diff options
Diffstat (limited to 'runtime/intern_table.cc')
-rw-r--r-- | runtime/intern_table.cc | 85 |
1 files changed, 59 insertions, 26 deletions
diff --git a/runtime/intern_table.cc b/runtime/intern_table.cc index d7398ca..e3a75cf 100644 --- a/runtime/intern_table.cc +++ b/runtime/intern_table.cc @@ -16,6 +16,10 @@ #include "intern_table.h" +#include "gc/space/image_space.h" +#include "mirror/dex_cache.h" +#include "mirror/object_array-inl.h" +#include "mirror/object-inl.h" #include "mirror/string.h" #include "thread.h" #include "UniquePtr.h" @@ -23,8 +27,8 @@ namespace art { -InternTable::InternTable() : intern_table_lock_("InternTable lock"), is_dirty_(false) { -} +InternTable::InternTable() + : intern_table_lock_("InternTable lock"), is_dirty_(false) {} size_t InternTable::Size() const { MutexLock mu(Thread::Current(), intern_table_lock_); @@ -34,11 +38,11 @@ size_t InternTable::Size() const { void InternTable::DumpForSigQuit(std::ostream& os) const { MutexLock mu(Thread::Current(), intern_table_lock_); os << "Intern table: " << strong_interns_.size() << " strong; " - << weak_interns_.size() << " weak; " - << image_strong_interns_.size() << " image strong\n"; + << weak_interns_.size() << " weak\n"; } -void InternTable::VisitRoots(RootVisitor* visitor, void* arg, bool clean_dirty) { +void InternTable::VisitRoots(RootVisitor* visitor, void* arg, + bool clean_dirty) { MutexLock mu(Thread::Current(), intern_table_lock_); for (const auto& strong_intern : strong_interns_) { visitor(strong_intern.second, arg); @@ -46,10 +50,12 @@ void InternTable::VisitRoots(RootVisitor* visitor, void* arg, bool clean_dirty) if (clean_dirty) { is_dirty_ = false; } - // Note: we deliberately don't visit the weak_interns_ table and the immutable image roots. + // Note: we deliberately don't visit the weak_interns_ table and the immutable + // image roots. } -mirror::String* InternTable::Lookup(Table& table, mirror::String* s, uint32_t hash_code) { +mirror::String* InternTable::Lookup(Table& table, mirror::String* s, + uint32_t hash_code) { intern_table_lock_.AssertHeld(Thread::Current()); for (auto it = table.find(hash_code), end = table.end(); it != end; ++it) { mirror::String* existing_string = it->second; @@ -60,18 +66,15 @@ mirror::String* InternTable::Lookup(Table& table, mirror::String* s, uint32_t ha return NULL; } -mirror::String* InternTable::Insert(Table& table, mirror::String* s, uint32_t hash_code) { +mirror::String* InternTable::Insert(Table& table, mirror::String* s, + uint32_t hash_code) { intern_table_lock_.AssertHeld(Thread::Current()); table.insert(std::make_pair(hash_code, s)); return s; } -void InternTable::RegisterStrong(mirror::String* s) { - MutexLock mu(Thread::Current(), intern_table_lock_); - Insert(image_strong_interns_, s, s->GetHashCode()); -} - -void InternTable::Remove(Table& table, const mirror::String* s, uint32_t hash_code) { +void InternTable::Remove(Table& table, const mirror::String* s, + uint32_t hash_code) { intern_table_lock_.AssertHeld(Thread::Current()); for (auto it = table.find(hash_code), end = table.end(); it != end; ++it) { if (it->second == s) { @@ -81,6 +84,31 @@ void InternTable::Remove(Table& table, const mirror::String* s, uint32_t hash_co } } +static mirror::String* LookupStringFromImage(mirror::String* s) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + gc::space::ImageSpace* image = Runtime::Current()->GetHeap()->GetImageSpace(); + if (image == NULL) { + return NULL; // No image present. + } + mirror::Object* root = image->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches); + mirror::ObjectArray<mirror::DexCache>* dex_caches = root->AsObjectArray<mirror::DexCache>(); + const std::string utf8 = s->ToModifiedUtf8(); + for (int32_t i = 0; i < dex_caches->GetLength(); ++i) { + mirror::DexCache* dex_cache = dex_caches->Get(i); + const DexFile* dex_file = dex_cache->GetDexFile(); + // Binary search the dex file for the string index. + const DexFile::StringId* string_id = dex_file->FindStringId(utf8.c_str()); + if (string_id != NULL) { + uint32_t string_idx = dex_file->GetIndexForStringId(*string_id); + mirror::String* image = dex_cache->GetResolvedString(string_idx); + if (image != NULL) { + return image; + } + } + } + return NULL; +} + mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) { MutexLock mu(Thread::Current(), intern_table_lock_); @@ -93,15 +121,16 @@ mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) { if (strong != NULL) { return strong; } - // Check the image table for a match. - mirror::String* image = Lookup(image_strong_interns_, s, hash_code); - if (image != NULL) { - return image; - } // Mark as dirty so that we rescan the roots. Dirty(); + // Check the image for a match. + mirror::String* image = LookupStringFromImage(s); + if (image != NULL) { + return Insert(strong_interns_, image, hash_code); + } + // There is no match in the strong table, check the weak table. mirror::String* weak = Lookup(weak_interns_, s, hash_code); if (weak != NULL) { @@ -110,7 +139,8 @@ mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) { return Insert(strong_interns_, weak, hash_code); } - // No match in the strong table or the weak table. Insert into the strong table. + // No match in the strong table or the weak table. Insert into the strong + // table. return Insert(strong_interns_, s, hash_code); } @@ -119,10 +149,10 @@ mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) { if (strong != NULL) { return strong; } - // Check the image table for a match. - mirror::String* image = Lookup(image_strong_interns_, s, hash_code); + // Check the image for a match. + mirror::String* image = LookupStringFromImage(s); if (image != NULL) { - return image; + return Insert(weak_interns_, image, hash_code); } // Check the weak table for a match. mirror::String* weak = Lookup(weak_interns_, s, hash_code); @@ -133,12 +163,15 @@ mirror::String* InternTable::Insert(mirror::String* s, bool is_strong) { return Insert(weak_interns_, s, hash_code); } -mirror::String* InternTable::InternStrong(int32_t utf16_length, const char* utf8_data) { - return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf16_length, utf8_data)); +mirror::String* InternTable::InternStrong(int32_t utf16_length, + const char* utf8_data) { + return InternStrong(mirror::String::AllocFromModifiedUtf8( + Thread::Current(), utf16_length, utf8_data)); } mirror::String* InternTable::InternStrong(const char* utf8_data) { - return InternStrong(mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf8_data)); + return InternStrong( + mirror::String::AllocFromModifiedUtf8(Thread::Current(), utf8_data)); } mirror::String* InternTable::InternStrong(mirror::String* s) { |