summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc137
1 files changed, 90 insertions, 47 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f778bc5b1c..7549c04b6f 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -79,7 +79,7 @@
#include "image-inl.h"
#include "imt_conflict_table.h"
#include "imtable-inl.h"
-#include "intern_table.h"
+#include "intern_table-inl.h"
#include "interpreter/interpreter.h"
#include "jit/debugger_interface.h"
#include "jit/jit.h"
@@ -1279,7 +1279,7 @@ bool VerifyStringInterning(gc::space::ImageSpace& space) REQUIRES_SHARED(Locks::
// new_class_set is the set of classes that were read from the class table section in the image.
// If there was no class table section, it is null.
// Note: using a class here to avoid having to make ClassLinker internals public.
-class AppImageClassLoadersAndDexCachesHelper {
+class AppImageLoadingHelper {
public:
static void Update(
ClassLinker* class_linker,
@@ -1289,9 +1289,17 @@ class AppImageClassLoadersAndDexCachesHelper {
ClassTable::ClassSet* new_class_set)
REQUIRES(!Locks::dex_lock_)
REQUIRES_SHARED(Locks::mutator_lock_);
+
+ static void AddImageInternTable(gc::space::ImageSpace* space)
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
+ static void UpdateInternStrings(
+ gc::space::ImageSpace* space,
+ const SafeMap<mirror::String*, mirror::String*>& intern_remap)
+ REQUIRES_SHARED(Locks::mutator_lock_);
};
-void AppImageClassLoadersAndDexCachesHelper::Update(
+void AppImageLoadingHelper::Update(
ClassLinker* class_linker,
gc::space::ImageSpace* space,
Handle<mirror::ClassLoader> class_loader,
@@ -1366,57 +1374,96 @@ void AppImageClassLoadersAndDexCachesHelper::Update(
}
if (ClassLinker::kAppImageMayContainStrings) {
- // Iterate over the string reference offsets stored in the image and intern
- // the strings they point to.
+ AddImageInternTable(space);
+ DCHECK(VerifyStringInterning(*space));
+ }
- ScopedTrace timing("AppImage:InternString");
- const auto& image_header = space->GetImageHeader();
- const uint8_t* target_base = space->GetMemMap()->Begin();
- const ImageSection& sro_section = image_header.GetImageStringReferenceOffsetsSection();
+ if (kVerifyArtMethodDeclaringClasses) {
+ ScopedTrace timing("AppImage:VerifyDeclaringClasses");
+ ReaderMutexLock rmu(self, *Locks::heap_bitmap_lock_);
+ VerifyDeclaringClassVisitor visitor;
+ header.VisitPackedArtMethods(&visitor, space->Begin(), kRuntimePointerSize);
+ }
+}
- size_t num_string_offsets = sro_section.Size() / sizeof(uint32_t);
+void AppImageLoadingHelper::UpdateInternStrings(
+ gc::space::ImageSpace* space,
+ const SafeMap<mirror::String*, mirror::String*>& intern_remap) {
+ const uint8_t* target_base = space->Begin();
+ const ImageSection& sro_section = space->GetImageHeader().GetImageStringReferenceOffsetsSection();
+ const size_t num_string_offsets = sro_section.Size() / sizeof(uint32_t);
+
+ VLOG(image)
+ << "ClassLinker:AppImage:InternStrings:imageStringReferenceOffsetCount = "
+ << num_string_offsets;
+
+ const uint32_t* sro_base =
+ reinterpret_cast<const uint32_t*>(target_base + sro_section.Offset());
+
+ for (size_t offset_index = 0; offset_index < num_string_offsets; ++offset_index) {
+ if (HasNativeRefTag(sro_base[offset_index])) {
+ void* raw_field_addr = space->Begin() + ClearNativeRefTag(sro_base[offset_index]);
+ mirror::CompressedReference<mirror::Object>* objref_addr =
+ reinterpret_cast<mirror::CompressedReference<mirror::Object>*>(raw_field_addr);
+ mirror::String* referred_string = objref_addr->AsMirrorPtr()->AsString();
+ DCHECK(referred_string != nullptr);
+
+ auto it = intern_remap.find(referred_string);
+ if (it != intern_remap.end()) {
+ objref_addr->Assign(it->second);
+ }
+ } else {
+ void* raw_field_addr = space->Begin() + sro_base[offset_index];
+ mirror::HeapReference<mirror::Object>* objref_addr =
+ reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_field_addr);
+ mirror::String* referred_string = objref_addr->AsMirrorPtr()->AsString();
+ DCHECK(referred_string != nullptr);
- if (kIsDebugBuild) {
- LOG(INFO)
- << "ClassLinker:AppImage:InternStrings:imageStringReferenceOffsetCount = "
- << num_string_offsets;
+ auto it = intern_remap.find(referred_string);
+ if (it != intern_remap.end()) {
+ objref_addr->Assign<false>(it->second);
+ }
}
+ }
+}
- DCHECK(Runtime::Current()->GetInternTable() != nullptr);
-
- InternTable& intern_table = *Runtime::Current()->GetInternTable();
- const uint32_t* sro_base =
- reinterpret_cast<const uint32_t*>(target_base + sro_section.Offset());
-
- for (size_t offset_index = 0; offset_index < num_string_offsets; ++offset_index) {
- if (HasNativeRefTag(sro_base[offset_index])) {
- void* raw_field_addr = space->Begin() + ClearNativeRefTag(sro_base[offset_index]);
- mirror::CompressedReference<mirror::Object>* objref_addr =
- reinterpret_cast<mirror::CompressedReference<mirror::Object>*>(raw_field_addr);
- mirror::String* referred_string = objref_addr->AsMirrorPtr()->AsString();
- DCHECK(referred_string != nullptr);
+void AppImageLoadingHelper::AddImageInternTable(gc::space::ImageSpace* space) {
+ // Iterate over the string reference offsets stored in the image and intern
+ // the strings they point to.
+ ScopedTrace timing("AppImage:InternString");
- objref_addr->Assign(intern_table.InternStrong(referred_string));
+ Thread* const self = Thread::Current();
+ Runtime* const runtime = Runtime::Current();
+ InternTable* const intern_table = runtime->GetInternTable();
+ // Add the intern table, removing any conflicts. For conflicts, store the new address in a map
+ // for faster lookup.
+ // TODO: Optimize with a bitmap or bloom filter
+ SafeMap<mirror::String*, mirror::String*> intern_remap;
+ intern_table->AddImageStringsToTable(space, [&](InternTable::UnorderedSet& interns)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ VLOG(image) << "AppImage:StringsInInternTable = " << interns.size();
+ for (auto it = interns.begin(); it != interns.end(); ) {
+ ObjPtr<mirror::String> string = it->Read();
+ ObjPtr<mirror::String> existing = intern_table->LookupWeak(self, string);
+ if (existing == nullptr) {
+ existing = intern_table->LookupStrong(self, string);
+ }
+ if (existing != nullptr) {
+ intern_remap.Put(string.Ptr(), existing.Ptr());
+ it = interns.erase(it);
} else {
- void* raw_field_addr = space->Begin() + sro_base[offset_index];
- mirror::HeapReference<mirror::Object>* objref_addr =
- reinterpret_cast<mirror::HeapReference<mirror::Object>*>(raw_field_addr);
- mirror::String* referred_string = objref_addr->AsMirrorPtr()->AsString();
- DCHECK(referred_string != nullptr);
-
- objref_addr->Assign<false>(intern_table.InternStrong(referred_string));
+ ++it;
}
}
+ });
- DCHECK(VerifyStringInterning(*space));
- }
+ VLOG(image) << "AppImage:ConflictingInternStrings = " << intern_remap.size();
- if (kVerifyArtMethodDeclaringClasses) {
- ScopedTrace timing("AppImage:VerifyDeclaringClasses");
- ReaderMutexLock rmu(self, *Locks::heap_bitmap_lock_);
- VerifyDeclaringClassVisitor visitor;
- header.VisitPackedArtMethods(&visitor, space->Begin(), kRuntimePointerSize);
+ // For debug builds, always run the code below to get coverage.
+ if (kIsDebugBuild || !intern_remap.empty()) {
+ // Slow path case is when there are conflicting intern strings to fix up.
+ UpdateInternStrings(space, intern_remap);
}
}
@@ -1907,11 +1954,7 @@ bool ClassLinker::AddImageSpace(
VLOG(image) << "Adding class table classes took " << PrettyDuration(NanoTime() - start_time2);
}
if (app_image) {
- AppImageClassLoadersAndDexCachesHelper::Update(this,
- space,
- class_loader,
- dex_caches,
- &temp_set);
+ AppImageLoadingHelper::Update(this, space, class_loader, dex_caches, &temp_set);
// Update class loader and resolved strings. If added_class_table is false, the resolved
// strings were forwarded UpdateAppImageClassLoadersAndDexCaches.
UpdateClassLoaderVisitor visitor(space, class_loader.Get());