summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2018-11-01 14:21:33 -0700
committer Mathieu Chartier <mathieuc@google.com> 2018-11-02 10:02:18 -0700
commit8fc755804bc3eb7b55e4de0ac3b335efd5ca0309 (patch)
tree440b4c164ba6a506ed44e8ae31f5bb028dec2c88 /runtime/class_linker.cc
parent81ac31ded4df5d597aa603c53122fa1d74413b78 (diff)
Smarter set intersection between app image and non boot image strings
If there are fewer non boot image strings in the runtime, iterate over those strings instead of the set being newly added. On AOSP, nonBootImageInternStrings is around 500. Test: test-art-host Bug: 116059983 Change-Id: I76b49f2090971cf593ba487889b35dfc1fa8cf13
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc48
1 files changed, 37 insertions, 11 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index e3dfdb3256..6a5e8b6d65 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1495,18 +1495,44 @@ void AppImageLoadingHelper::HandleAppImageStrings(gc::space::ImageSpace* space)
intern_table->AddImageStringsToTable(space, [&](InternTable::UnorderedSet& interns)
REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(Locks::intern_table_lock_) {
+ const size_t non_boot_image_strings = intern_table->CountInterns(
+ /*visit_boot_images=*/false,
+ /*visit_non_boot_images=*/true);
VLOG(image) << "AppImage:stringsInInternTableSize = " << interns.size();
- for (auto it = interns.begin(); it != interns.end(); ) {
- ObjPtr<mirror::String> string = it->Read();
- ObjPtr<mirror::String> existing = intern_table->LookupWeakLocked(string);
- if (existing == nullptr) {
- existing = intern_table->LookupStrongLocked(string);
- }
- if (existing != nullptr) {
- intern_remap.Put(string.Ptr(), existing.Ptr());
- it = interns.erase(it);
- } else {
- ++it;
+ VLOG(image) << "AppImage:nonBootImageInternStrings = " << non_boot_image_strings;
+ // Visit the smaller of the two sets to compute the intersection.
+ if (interns.size() < non_boot_image_strings) {
+ for (auto it = interns.begin(); it != interns.end(); ) {
+ ObjPtr<mirror::String> string = it->Read();
+ ObjPtr<mirror::String> existing = intern_table->LookupWeakLocked(string);
+ if (existing == nullptr) {
+ existing = intern_table->LookupStrongLocked(string);
+ }
+ if (existing != nullptr) {
+ intern_remap.Put(string.Ptr(), existing.Ptr());
+ it = interns.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ } else {
+ intern_table->VisitInterns([&](const GcRoot<mirror::String>& root)
+ REQUIRES_SHARED(Locks::mutator_lock_)
+ REQUIRES(Locks::intern_table_lock_) {
+ auto it = interns.find(root);
+ if (it != interns.end()) {
+ ObjPtr<mirror::String> existing = root.Read();
+ intern_remap.Put(it->Read(), existing.Ptr());
+ it = interns.erase(it);
+ }
+ }, /*visit_boot_images=*/false, /*visit_non_boot_images=*/true);
+ }
+ // Sanity check to ensure correctness.
+ if (kIsDebugBuild) {
+ for (GcRoot<mirror::String>& root : interns) {
+ ObjPtr<mirror::String> string = root.Read();
+ CHECK(intern_table->LookupWeakLocked(string) == nullptr) << string->ToModifiedUtf8();
+ CHECK(intern_table->LookupStrongLocked(string) == nullptr) << string->ToModifiedUtf8();
}
}
});