Cache hashes of virtual methods in j.l.Object.
Avoid calculating them in ClassLinker::LinkVirtualMethods()
for each class that declares new virtual methods.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: boots.
Bug: 175869411
Change-Id: Iae75b1794a6d6ab5073a18c9000ec22550feebf0
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 8080eca..3155346 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1133,6 +1133,18 @@
}
}
+static void InitializeObjectVirtualMethodHashes(ObjPtr<mirror::Class> java_lang_Object,
+ PointerSize pointer_size,
+ /*out*/ ArrayRef<uint32_t> virtual_method_hashes)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ ArraySlice<ArtMethod> virtual_methods = java_lang_Object->GetVirtualMethods(pointer_size);
+ DCHECK_EQ(virtual_method_hashes.size(), virtual_methods.size());
+ for (size_t i = 0; i != virtual_method_hashes.size(); ++i) {
+ const char* name = virtual_methods[i].GetName();
+ virtual_method_hashes[i] = ComputeModifiedUtf8Hash(name);
+ }
+}
+
struct TrampolineCheckData {
const void* quick_resolution_trampoline;
const void* quick_imt_conflict_trampoline;
@@ -1299,6 +1311,9 @@
for (const std::unique_ptr<const DexFile>& dex_file : boot_dex_files_) {
OatDexFile::MadviseDexFile(*dex_file, MadviseState::kMadviseStateAtLoad);
}
+ InitializeObjectVirtualMethodHashes(GetClassRoot<mirror::Object>(this),
+ image_pointer_size_,
+ ArrayRef<uint32_t>(object_virtual_method_hashes_));
FinishInit(self);
VLOG(startup) << __FUNCTION__ << " exiting";
@@ -6331,10 +6346,9 @@
hash_table_[index] = virtual_method_index;
}
- uint32_t FindAndRemove(MethodNameAndSignatureComparator* comparator)
+ uint32_t FindAndRemove(MethodNameAndSignatureComparator* comparator, uint32_t hash)
REQUIRES_SHARED(Locks::mutator_lock_) {
- const char* name = comparator->GetName();
- uint32_t hash = ComputeModifiedUtf8Hash(name);
+ DCHECK_EQ(hash, ComputeModifiedUtf8Hash(comparator->GetName()));
size_t index = hash % hash_size_;
while (true) {
const uint32_t value = hash_table_[index];
@@ -6504,7 +6518,10 @@
super_method->GetInterfaceMethodIfProxy(image_pointer_size_));
// We remove the method so that subsequent lookups will be faster by making the hash-map
// smaller as we go on.
- uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator);
+ uint32_t hash = (j < mirror::Object::kVTableLength)
+ ? object_virtual_method_hashes_[j]
+ : ComputeModifiedUtf8Hash(super_method_name_comparator.GetName());
+ uint32_t hash_index = hash_table.FindAndRemove(&super_method_name_comparator, hash);
if (hash_index != hash_table.GetNotFoundIndex()) {
ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(
hash_index, image_pointer_size_);
@@ -6615,6 +6632,9 @@
virtual_method->SetMethodIndex(i & 0xFFFF);
}
klass->SetVTable(vtable);
+ InitializeObjectVirtualMethodHashes(klass.Get(),
+ image_pointer_size_,
+ ArrayRef<uint32_t>(object_virtual_method_hashes_));
}
return true;
}