ART: Optimize array accesses
Optimize computation of the data offset of arrays by adding
a constant for the array payload field offset, and templatized
versions of the computation. Add a correctness check on runtime
creation.
Templatize CheckVTableHasNoDuplicates.
Decreases dex2oatd preopting of a big app from 165s to 151s.
Bug: 123888325
Test: m test-art-host
Change-Id: I8db9df545dc807a307aef8af7dad7a15757670b1
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index d29a6b7..cb1fbfe 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -7074,31 +7074,30 @@
// Check to make sure the vtable does not have duplicates. Duplicates could cause problems when a
// method is overridden in a subclass.
-static void CheckVTableHasNoDuplicates(Thread* self,
- Handle<mirror::Class> klass,
- PointerSize pointer_size)
+template <PointerSize kPointerSize>
+static void CheckVTableHasNoDuplicates(Thread* self, Handle<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_) {
StackHandleScope<1> hs(self);
Handle<mirror::PointerArray> vtable(hs.NewHandle(klass->GetVTableDuringLinking()));
int32_t num_entries = vtable->GetLength();
for (int32_t i = 0; i < num_entries; i++) {
- ArtMethod* vtable_entry = vtable->GetElementPtrSize<ArtMethod*>(i, pointer_size);
+ ArtMethod* vtable_entry = vtable->GetElementPtrSize<ArtMethod*, kPointerSize>(i);
// Don't bother if we cannot 'see' the vtable entry (i.e. it is a package-private member maybe).
if (!klass->CanAccessMember(vtable_entry->GetDeclaringClass(),
vtable_entry->GetAccessFlags())) {
continue;
}
MethodNameAndSignatureComparator name_comparator(
- vtable_entry->GetInterfaceMethodIfProxy(pointer_size));
+ vtable_entry->GetInterfaceMethodIfProxy(kPointerSize));
for (int32_t j = i + 1; j < num_entries; j++) {
- ArtMethod* other_entry = vtable->GetElementPtrSize<ArtMethod*>(j, pointer_size);
+ ArtMethod* other_entry = vtable->GetElementPtrSize<ArtMethod*, kPointerSize>(j);
if (!klass->CanAccessMember(other_entry->GetDeclaringClass(),
other_entry->GetAccessFlags())) {
continue;
}
if (vtable_entry == other_entry ||
name_comparator.HasSameNameAndSignature(
- other_entry->GetInterfaceMethodIfProxy(pointer_size))) {
+ other_entry->GetInterfaceMethodIfProxy(kPointerSize))) {
LOG(WARNING) << "vtable entries " << i << " and " << j << " are identical for "
<< klass->PrettyClass() << " in method " << vtable_entry->PrettyMethod()
<< " (0x" << std::hex << reinterpret_cast<uintptr_t>(vtable_entry) << ") and "
@@ -7108,6 +7107,19 @@
}
}
}
+static void CheckVTableHasNoDuplicates(Thread* self,
+ Handle<mirror::Class> klass,
+ PointerSize pointer_size)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ switch (pointer_size) {
+ case PointerSize::k64:
+ CheckVTableHasNoDuplicates<PointerSize::k64>(self, klass);
+ break;
+ case PointerSize::k32:
+ CheckVTableHasNoDuplicates<PointerSize::k32>(self, klass);
+ break;
+ }
+}
static void SanityCheckVTable(Thread* self, Handle<mirror::Class> klass, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_) {