Optimize method linking
Added more inlining, removed imt array allocation and replaced it
with a handle scope. Removed some un-necessary handle scopes.
Added logic to base interface method tables from the superclass so
that we dont need to reconstruct for every interface (large win).
Facebook launch Dalvik KK MR2:
TotalTime: 3165
TotalTime: 3652
TotalTime: 3143
TotalTime: 3298
TotalTime: 3212
TotalTime: 3211
Facebook launch TOT before:
WaitTime: 3702
WaitTime: 3616
WaitTime: 3616
WaitTime: 3687
WaitTime: 3742
WaitTime: 3767
After optimizations:
WaitTime: 2903
WaitTime: 2953
WaitTime: 2918
WaitTime: 2940
WaitTime: 2879
WaitTime: 2792
LinkInterfaceMethods no longer one of the hottest methods, new list:
4.73% art::ClassLinker::LinkVirtualMethods(art::Thread*, art::Handle<art::mirror::Class>)
3.07% art::DexFile::FindClassDef(char const*) const
2.94% art::mirror::Class::FindDeclaredStaticField(art::mirror::DexCache const*, unsigned int)
2.90% art::DexFile::FindStringId(char const*) const
Bug: 18054905
Bug: 16828525
(cherry picked from commit 1fb463e42cf1d67595cff66d19c0f99e3046f4c4)
Change-Id: I27cc70178fd3655fbe5a3178887fcba189d21321
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 854effd..0af8bd2 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -435,6 +435,7 @@
Runtime* runtime = Runtime::Current();
runtime->SetResolutionMethod(runtime->CreateResolutionMethod());
runtime->SetImtConflictMethod(runtime->CreateImtConflictMethod());
+ runtime->SetImtUnimplementedMethod(runtime->CreateImtConflictMethod());
runtime->SetDefaultImt(runtime->CreateDefaultImt(this));
// Set up GenericJNI entrypoint. That is mainly a hack for common_compiler_test.h so that
@@ -3211,7 +3212,11 @@
new_class->SetPrimitiveType(Primitive::kPrimNot);
new_class->SetClassLoader(component_type->GetClassLoader());
new_class->SetStatus(mirror::Class::kStatusLoaded, self);
- new_class->PopulateEmbeddedImtAndVTable();
+ {
+ StackHandleScope<mirror::Class::kImtSize> hs(self,
+ Runtime::Current()->GetImtUnimplementedMethod());
+ new_class->PopulateEmbeddedImtAndVTable(&hs);
+ }
new_class->SetStatus(mirror::Class::kStatusInitialized, self);
// don't need to set new_class->SetObjectSize(..)
// because Object::SizeOf delegates to Array::SizeOf
@@ -4423,7 +4428,9 @@
if (!LinkSuperClass(klass)) {
return false;
}
- if (!LinkMethods(self, klass, interfaces)) {
+ StackHandleScope<mirror::Class::kImtSize> imt_handle_scope(
+ self, Runtime::Current()->GetImtUnimplementedMethod());
+ if (!LinkMethods(self, klass, interfaces, &imt_handle_scope)) {
return false;
}
if (!LinkInstanceFields(self, klass)) {
@@ -4442,7 +4449,7 @@
CHECK_EQ(klass->GetClassSize(), class_size) << PrettyDescriptor(klass.Get());
if (klass->ShouldHaveEmbeddedImtAndVTable()) {
- klass->PopulateEmbeddedImtAndVTable();
+ klass->PopulateEmbeddedImtAndVTable(&imt_handle_scope);
}
// This will notify waiters on klass that saw the not yet resolved
@@ -4452,7 +4459,7 @@
} else {
CHECK(!klass->IsResolved());
// Retire the temporary class and create the correctly sized resolved class.
- *new_class = klass->CopyOf(self, class_size);
+ *new_class = klass->CopyOf(self, class_size, &imt_handle_scope);
if (UNLIKELY(*new_class == nullptr)) {
CHECK(self->IsExceptionPending()); // Expect an OOME.
klass->SetStatus(mirror::Class::kStatusError, self);
@@ -4586,7 +4593,8 @@
// Populate the class vtable and itable. Compute return type indices.
bool ClassLinker::LinkMethods(Thread* self, Handle<mirror::Class> klass,
- Handle<mirror::ObjectArray<mirror::Class>> interfaces) {
+ Handle<mirror::ObjectArray<mirror::Class>> interfaces,
+ StackHandleScope<mirror::Class::kImtSize>* out_imt) {
self->AllowThreadSuspension();
if (klass->IsInterface()) {
// No vtable.
@@ -4598,22 +4606,19 @@
for (size_t i = 0; i < count; ++i) {
klass->GetVirtualMethodDuringLinking(i)->SetMethodIndex(i);
}
- // Link interface method tables
- return LinkInterfaceMethods(klass, interfaces);
- } else {
- // Link virtual and interface method tables
- return LinkVirtualMethods(self, klass) && LinkInterfaceMethods(klass, interfaces);
+ } else if (!LinkVirtualMethods(self, klass)) { // Link virtual methods first.
+ return false;
}
- return true;
+ return LinkInterfaceMethods(self, klass, interfaces, out_imt); // Link interface method last.
}
bool ClassLinker::LinkVirtualMethods(Thread* self, Handle<mirror::Class> klass) {
+ const size_t num_virtual_methods = klass->NumVirtualMethods();
if (klass->HasSuperClass()) {
- uint32_t max_count = klass->NumVirtualMethods() +
- klass->GetSuperClass()->GetVTableLength();
- size_t actual_count = klass->GetSuperClass()->GetVTableLength();
- CHECK_LE(actual_count, max_count);
- StackHandleScope<4> hs(self);
+ const size_t super_vtable_length = klass->GetSuperClass()->GetVTableLength();
+ const size_t max_count = num_virtual_methods + super_vtable_length;
+ size_t actual_count = super_vtable_length;
+ StackHandleScope<2> hs(self);
Handle<mirror::Class> super_class(hs.NewHandle(klass->GetSuperClass()));
MutableHandle<mirror::ObjectArray<mirror::ArtMethod>> vtable;
if (super_class->ShouldHaveEmbeddedImtAndVTable()) {
@@ -4622,9 +4627,8 @@
CHECK(self->IsExceptionPending()); // OOME.
return false;
}
- int len = super_class->GetVTableLength();
- for (int i = 0; i < len; i++) {
- vtable->Set<false>(i, super_class->GetVTableEntry(i));
+ for (size_t i = 0; i < super_vtable_length; i++) {
+ vtable->SetWithoutChecks<false>(i, super_class->GetEmbeddedVTableEntry(i));
}
} else {
CHECK(super_class->GetVTable() != nullptr) << PrettyClass(super_class.Get());
@@ -4636,16 +4640,14 @@
}
// See if any of our virtual methods override the superclass.
- MutableMethodHelper local_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
- MutableMethodHelper super_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
- for (size_t i = 0; i < klass->NumVirtualMethods(); ++i) {
+ for (size_t i = 0; i < num_virtual_methods; ++i) {
mirror::ArtMethod* local_method = klass->GetVirtualMethodDuringLinking(i);
- local_mh.ChangeMethod(local_method);
+ MethodProtoHelper local_helper(local_method);
size_t j = 0;
for (; j < actual_count; ++j) {
- mirror::ArtMethod* super_method = vtable->Get(j);
- super_mh.ChangeMethod(super_method);
- if (local_mh.HasSameNameAndSignature(&super_mh)) {
+ mirror::ArtMethod* super_method = vtable->GetWithoutChecks(j);
+ MethodProtoHelper super_helper(super_method);
+ if (local_helper.HasSameNameAndSignature(super_helper)) {
if (klass->CanAccessMember(super_method->GetDeclaringClass(),
super_method->GetAccessFlags())) {
if (super_method->IsFinal()) {
@@ -4654,21 +4656,20 @@
super_method->GetDeclaringClassDescriptor());
return false;
}
- vtable->Set<false>(j, local_method);
+ vtable->SetWithoutChecks<false>(j, local_method);
local_method->SetMethodIndex(j);
break;
- } else {
- LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(local_method)
- << " would have incorrectly overridden the package-private method in "
- << PrettyDescriptor(super_method->GetDeclaringClassDescriptor());
}
+ LOG(WARNING) << "Before Android 4.1, method " << PrettyMethod(local_method)
+ << " would have incorrectly overridden the package-private method in "
+ << PrettyDescriptor(super_method->GetDeclaringClassDescriptor());
}
}
if (j == actual_count) {
// Not overriding, append.
- vtable->Set<false>(actual_count, local_method);
+ vtable->SetWithoutChecks<false>(actual_count, local_method);
local_method->SetMethodIndex(actual_count);
- actual_count += 1;
+ ++actual_count;
}
}
if (!IsUint(16, actual_count)) {
@@ -4687,72 +4688,76 @@
klass->SetVTable(vtable.Get());
} else {
CHECK_EQ(klass.Get(), GetClassRoot(kJavaLangObject));
- uint32_t num_virtual_methods = klass->NumVirtualMethods();
if (!IsUint(16, num_virtual_methods)) {
- ThrowClassFormatError(klass.Get(), "Too many methods: %d", num_virtual_methods);
+ ThrowClassFormatError(klass.Get(), "Too many methods: %d",
+ static_cast<int>(num_virtual_methods));
return false;
}
- StackHandleScope<1> hs(self);
- Handle<mirror::ObjectArray<mirror::ArtMethod>>
- vtable(hs.NewHandle(AllocArtMethodArray(self, num_virtual_methods)));
- if (UNLIKELY(vtable.Get() == nullptr)) {
+ mirror::ObjectArray<mirror::ArtMethod>* vtable = AllocArtMethodArray(self, num_virtual_methods);
+ if (UNLIKELY(vtable == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return false;
}
for (size_t i = 0; i < num_virtual_methods; ++i) {
mirror::ArtMethod* virtual_method = klass->GetVirtualMethodDuringLinking(i);
- vtable->Set<false>(i, virtual_method);
+ vtable->SetWithoutChecks<false>(i, virtual_method);
virtual_method->SetMethodIndex(i & 0xFFFF);
}
- klass->SetVTable(vtable.Get());
+ klass->SetVTable(vtable);
}
return true;
}
-bool ClassLinker::LinkInterfaceMethods(Handle<mirror::Class> klass,
- Handle<mirror::ObjectArray<mirror::Class>> interfaces) {
- Thread* const self = Thread::Current();
+bool ClassLinker::LinkInterfaceMethods(Thread* self, Handle<mirror::Class> klass,
+ Handle<mirror::ObjectArray<mirror::Class>> interfaces,
+ StackHandleScope<mirror::Class::kImtSize>* out_imt) {
+ static constexpr size_t kInterfaceCacheSize = 8;
+ StackHandleScope<3 + kInterfaceCacheSize> hs(self);
Runtime* const runtime = Runtime::Current();
- // Set the imt table to be all conflicts by default.
- klass->SetImTable(runtime->GetDefaultImt());
- size_t super_ifcount;
- if (klass->HasSuperClass()) {
- super_ifcount = klass->GetSuperClass()->GetIfTableCount();
- } else {
- super_ifcount = 0;
- }
- uint32_t num_interfaces =
- interfaces.Get() == nullptr ? klass->NumDirectInterfaces() : interfaces->GetLength();
- size_t ifcount = super_ifcount + num_interfaces;
- for (size_t i = 0; i < num_interfaces; i++) {
- mirror::Class* interface =
- interfaces.Get() == nullptr ? mirror::Class::GetDirectInterface(self, klass, i) :
- interfaces->Get(i);
- ifcount += interface->GetIfTableCount();
- }
- if (ifcount == 0) {
- // Class implements no interfaces.
- DCHECK_EQ(klass->GetIfTableCount(), 0);
- DCHECK(klass->GetIfTable() == nullptr);
- return true;
- }
- if (ifcount == super_ifcount) {
+ const bool has_superclass = klass->HasSuperClass();
+ const size_t super_ifcount = has_superclass ? klass->GetSuperClass()->GetIfTableCount() : 0U;
+ const bool have_interfaces = interfaces.Get() != nullptr;
+ const size_t num_interfaces =
+ have_interfaces ? interfaces->GetLength() : klass->NumDirectInterfaces();
+ if (num_interfaces == 0) {
+ if (super_ifcount == 0) {
+ // Class implements no interfaces.
+ DCHECK_EQ(klass->GetIfTableCount(), 0);
+ DCHECK(klass->GetIfTable() == nullptr);
+ return true;
+ }
// Class implements same interfaces as parent, are any of these not marker interfaces?
bool has_non_marker_interface = false;
mirror::IfTable* super_iftable = klass->GetSuperClass()->GetIfTable();
- for (size_t i = 0; i < ifcount; ++i) {
+ for (size_t i = 0; i < super_ifcount; ++i) {
if (super_iftable->GetMethodArrayCount(i) > 0) {
has_non_marker_interface = true;
break;
}
}
+ // Class just inherits marker interfaces from parent so recycle parent's iftable.
if (!has_non_marker_interface) {
- // Class just inherits marker interfaces from parent so recycle parent's iftable.
klass->SetIfTable(super_iftable);
return true;
}
}
- StackHandleScope<5> hs(self);
+ size_t ifcount = super_ifcount + num_interfaces;
+ for (size_t i = 0; i < num_interfaces; i++) {
+ mirror::Class* interface = have_interfaces ?
+ interfaces->GetWithoutChecks(i) : mirror::Class::GetDirectInterface(self, klass, i);
+ DCHECK(interface != nullptr);
+ if (i < kInterfaceCacheSize) {
+ hs.NewHandle(interface);
+ }
+ if (UNLIKELY(!interface->IsInterface())) {
+ std::string temp;
+ ThrowIncompatibleClassChangeError(klass.Get(), "Class %s implements non-interface class %s",
+ PrettyDescriptor(klass.Get()).c_str(),
+ PrettyDescriptor(interface->GetDescriptor(&temp)).c_str());
+ return false;
+ }
+ ifcount += interface->GetIfTableCount();
+ }
MutableHandle<mirror::IfTable> iftable(hs.NewHandle(AllocIfTable(self, ifcount)));
if (UNLIKELY(iftable.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
@@ -4769,16 +4774,12 @@
// Flatten the interface inheritance hierarchy.
size_t idx = super_ifcount;
for (size_t i = 0; i < num_interfaces; i++) {
- mirror::Class* interface =
- interfaces.Get() == nullptr ? mirror::Class::GetDirectInterface(self, klass, i) :
- interfaces->Get(i);
- DCHECK(interface != nullptr);
- if (!interface->IsInterface()) {
- std::string temp;
- ThrowIncompatibleClassChangeError(klass.Get(), "Class %s implements non-interface class %s",
- PrettyDescriptor(klass.Get()).c_str(),
- PrettyDescriptor(interface->GetDescriptor(&temp)).c_str());
- return false;
+ mirror::Class* interface;
+ if (i < kInterfaceCacheSize) {
+ interface = hs.GetReference(i)->AsClass();
+ } else {
+ interface = have_interfaces ? interfaces->Get(i) :
+ mirror::Class::GetDirectInterface(self, klass, i);
}
// Check if interface is already in iftable
bool duplicate = false;
@@ -4812,6 +4813,7 @@
self->AllowThreadSuspension();
// Shrink iftable in case duplicates were found
if (idx < ifcount) {
+ DCHECK_NE(num_interfaces, 0U);
iftable.Assign(down_cast<mirror::IfTable*>(iftable->CopyOf(self, idx * mirror::IfTable::kMax)));
if (UNLIKELY(iftable.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
@@ -4819,48 +4821,100 @@
}
ifcount = idx;
} else {
- CHECK_EQ(idx, ifcount);
+ DCHECK_EQ(idx, ifcount);
}
klass->SetIfTable(iftable.Get());
-
// If we're an interface, we don't need the vtable pointers, so we're done.
if (klass->IsInterface()) {
return true;
}
- self->AllowThreadSuspension();
- // Allocate imtable
- bool imtable_changed = false;
- Handle<mirror::ObjectArray<mirror::ArtMethod>> imtable(
- hs.NewHandle(AllocArtMethodArray(self, mirror::Class::kImtSize)));
- if (UNLIKELY(imtable.Get() == nullptr)) {
- CHECK(self->IsExceptionPending()); // OOME.
- return false;
- }
- MutableMethodHelper interface_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
- MutableMethodHelper vtable_mh(hs.NewHandle<mirror::ArtMethod>(nullptr));
+ size_t miranda_list_size = 0;
size_t max_miranda_methods = 0; // The max size of miranda_list.
for (size_t i = 0; i < ifcount; ++i) {
max_miranda_methods += iftable->GetInterface(i)->NumVirtualMethods();
}
- Handle<mirror::ObjectArray<mirror::ArtMethod>>
+ MutableHandle<mirror::ObjectArray<mirror::ArtMethod>>
miranda_list(hs.NewHandle(AllocArtMethodArray(self, max_miranda_methods)));
- size_t miranda_list_size = 0; // The current size of miranda_list.
+ MutableHandle<mirror::ObjectArray<mirror::ArtMethod>> vtable(
+ hs.NewHandle(klass->GetVTableDuringLinking()));
+ // Copy the IMT from the super class if possible.
+ bool extend_super_iftable = false;
+ if (has_superclass) {
+ mirror::Class* super_class = klass->GetSuperClass();
+ extend_super_iftable = true;
+ if (super_class->ShouldHaveEmbeddedImtAndVTable()) {
+ for (size_t i = 0; i < mirror::Class::kImtSize; ++i) {
+ out_imt->SetReference(i, super_class->GetEmbeddedImTableEntry(i));
+ }
+ } else {
+ // No imt in the super class, need to reconstruct from the iftable.
+ mirror::IfTable* if_table = super_class->GetIfTable();
+ mirror::ArtMethod* conflict_method = runtime->GetImtConflictMethod();
+ const size_t length = super_class->GetIfTableCount();
+ for (size_t i = 0; i < length; ++i) {
+ mirror::Class* interface = iftable->GetInterface(i);
+ const size_t num_virtuals = interface->NumVirtualMethods();
+ const size_t method_array_count = if_table->GetMethodArrayCount(i);
+ DCHECK_EQ(num_virtuals, method_array_count);
+ if (method_array_count == 0) {
+ continue;
+ }
+ mirror::ObjectArray<mirror::ArtMethod>* method_array = if_table->GetMethodArray(i);
+ for (size_t j = 0; j < num_virtuals; ++j) {
+ mirror::ArtMethod* method = method_array->GetWithoutChecks(j);
+ if (method->IsMiranda()) {
+ continue;
+ }
+ mirror::ArtMethod* interface_method = interface->GetVirtualMethod(j);
+ uint32_t imt_index = interface_method->GetDexMethodIndex() % mirror::Class::kImtSize;
+ mirror::ArtMethod* imt_ref = out_imt->GetReference(imt_index)->AsArtMethod();
+ if (imt_ref == runtime->GetImtUnimplementedMethod()) {
+ out_imt->SetReference(imt_index, method);
+ } else if (imt_ref != conflict_method) {
+ out_imt->SetReference(imt_index, conflict_method);
+ }
+ }
+ }
+ }
+ }
for (size_t i = 0; i < ifcount; ++i) {
self->AllowThreadSuspension();
size_t num_methods = iftable->GetInterface(i)->NumVirtualMethods();
if (num_methods > 0) {
StackHandleScope<2> hs(self);
- Handle<mirror::ObjectArray<mirror::ArtMethod>>
- method_array(hs.NewHandle(AllocArtMethodArray(self, num_methods)));
+ const bool is_super = i < super_ifcount;
+ const bool super_interface = is_super && extend_super_iftable;
+ Handle<mirror::ObjectArray<mirror::ArtMethod>> method_array;
+ Handle<mirror::ObjectArray<mirror::ArtMethod>> input_array;
+ if (super_interface) {
+ mirror::IfTable* if_table = klass->GetSuperClass()->GetIfTable();
+ DCHECK(if_table != nullptr);
+ DCHECK(if_table->GetMethodArray(i) != nullptr);
+ // If we are working on a super interface, try extending the existing method array.
+ method_array = hs.NewHandle(if_table->GetMethodArray(i)->Clone(self)->
+ AsObjectArray<mirror::ArtMethod>());
+ // We are overwriting a super class interface, try to only virtual methods instead of the
+ // whole vtable.
+ input_array = hs.NewHandle(klass->GetVirtualMethods());
+ } else {
+ method_array = hs.NewHandle(AllocArtMethodArray(self, num_methods));
+ // A new interface, we need the whole vtable incase a new interface method is implemented
+ // in the whole superclass.
+ input_array = vtable;
+ }
if (UNLIKELY(method_array.Get() == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return false;
}
iftable->SetMethodArray(i, method_array.Get());
- Handle<mirror::ObjectArray<mirror::ArtMethod>> vtable(
- hs.NewHandle(klass->GetVTableDuringLinking()));
+ if (input_array.Get() == nullptr) {
+ // If the added virtual methods is empty, do nothing.
+ DCHECK(super_interface);
+ continue;
+ }
for (size_t j = 0; j < num_methods; ++j) {
- interface_mh.ChangeMethod(iftable->GetInterface(i)->GetVirtualMethod(j));
+ mirror::ArtMethod* interface_method = iftable->GetInterface(i)->GetVirtualMethod(j);
+ MethodProtoHelper interface_helper(interface_method);
int32_t k;
// For each method listed in the interface's method list, find the
// matching method in our class's method list. We want to favor the
@@ -4870,66 +4924,62 @@
// it -- otherwise it would use the same vtable slot. In .dex files
// those don't end up in the virtual method table, so it shouldn't
// matter which direction we go. We walk it backward anyway.)
- for (k = vtable->GetLength() - 1; k >= 0; --k) {
- vtable_mh.ChangeMethod(vtable->Get(k));
- if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
- if (!vtable_mh.Get()->IsAbstract() && !vtable_mh.Get()->IsPublic()) {
+ for (k = input_array->GetLength() - 1; k >= 0; --k) {
+ mirror::ArtMethod* vtable_method = input_array->GetWithoutChecks(k);
+ MethodProtoHelper vtable_helper(vtable_method);
+ if (interface_helper.HasSameNameAndSignature(vtable_helper)) {
+ if (!vtable_method->IsAbstract() && !vtable_method->IsPublic()) {
ThrowIllegalAccessError(
klass.Get(),
"Method '%s' implementing interface method '%s' is not public",
- PrettyMethod(vtable_mh.Get()).c_str(),
- PrettyMethod(interface_mh.Get()).c_str());
+ PrettyMethod(vtable_method).c_str(),
+ PrettyMethod(interface_method).c_str());
return false;
}
- method_array->Set<false>(j, vtable_mh.Get());
+ method_array->SetWithoutChecks<false>(j, vtable_method);
// Place method in imt if entry is empty, place conflict otherwise.
- uint32_t imt_index = interface_mh.Get()->GetDexMethodIndex() % mirror::Class::kImtSize;
- if (imtable->Get(imt_index) == nullptr) {
- imtable->Set<false>(imt_index, vtable_mh.Get());
- imtable_changed = true;
- } else {
- imtable->Set<false>(imt_index, runtime->GetImtConflictMethod());
+ uint32_t imt_index = interface_method->GetDexMethodIndex() % mirror::Class::kImtSize;
+ mirror::ArtMethod* imt_ref = out_imt->GetReference(imt_index)->AsArtMethod();
+ mirror::ArtMethod* conflict_method = runtime->GetImtConflictMethod();
+ if (imt_ref == runtime->GetImtUnimplementedMethod()) {
+ out_imt->SetReference(imt_index, vtable_method);
+ } else if (imt_ref != conflict_method) {
+ // If we are not a conflict and we have the same signature and name as the imt entry,
+ // it must be that we overwrote a superclass vtable entry.
+ if (MethodProtoHelper(imt_ref).HasSameNameAndSignature(vtable_helper)) {
+ out_imt->SetReference(imt_index, vtable_method);
+ } else {
+ out_imt->SetReference(imt_index, conflict_method);
+ }
}
break;
}
}
- if (k < 0) {
- StackHandleScope<1> hs(self);
- auto miranda_method = hs.NewHandle<mirror::ArtMethod>(nullptr);
+ if (k < 0 && !super_interface) {
+ mirror::ArtMethod* miranda_method = nullptr;
for (size_t l = 0; l < miranda_list_size; ++l) {
mirror::ArtMethod* mir_method = miranda_list->Get(l);
- DCHECK(mir_method != nullptr);
- vtable_mh.ChangeMethod(mir_method);
- if (interface_mh.HasSameNameAndSignature(&vtable_mh)) {
- miranda_method.Assign(mir_method);
+ MethodProtoHelper vtable_helper(mir_method);
+ if (interface_helper.HasSameNameAndSignature(vtable_helper)) {
+ miranda_method = mir_method;
break;
}
}
- if (miranda_method.Get() == nullptr) {
+ if (miranda_method == nullptr) {
// Point the interface table at a phantom slot.
- miranda_method.Assign(down_cast<mirror::ArtMethod*>(interface_mh.Get()->Clone(self)));
- if (UNLIKELY(miranda_method.Get() == nullptr)) {
+ miranda_method = interface_method->Clone(self)->AsArtMethod();
+ if (UNLIKELY(miranda_method == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
return false;
}
DCHECK_LT(miranda_list_size, max_miranda_methods);
- miranda_list->Set<false>(miranda_list_size++, miranda_method.Get());
+ miranda_list->Set<false>(miranda_list_size++, miranda_method);
}
- method_array->Set<false>(j, miranda_method.Get());
+ method_array->SetWithoutChecks<false>(j, miranda_method);
}
}
}
}
- if (imtable_changed) {
- // Fill in empty entries in interface method table with conflict.
- mirror::ArtMethod* imt_conflict_method = runtime->GetImtConflictMethod();
- for (size_t i = 0; i < mirror::Class::kImtSize; i++) {
- if (imtable->Get(i) == nullptr) {
- imtable->Set<false>(i, imt_conflict_method);
- }
- }
- klass->SetImTable(imtable.Get());
- }
if (miranda_list_size > 0) {
int old_method_count = klass->NumVirtualMethods();
int new_method_count = old_method_count + miranda_list_size;
@@ -4945,10 +4995,6 @@
}
klass->SetVirtualMethods(virtuals);
- StackHandleScope<1> hs(self);
- MutableHandle<mirror::ObjectArray<mirror::ArtMethod>> vtable(
- hs.NewHandle(klass->GetVTableDuringLinking()));
- CHECK(vtable.Get() != nullptr);
int old_vtable_count = vtable->GetLength();
int new_vtable_count = old_vtable_count + miranda_list_size;
vtable.Assign(vtable->CopyOf(self, new_vtable_count));
@@ -4962,19 +5008,20 @@
method->SetAccessFlags(method->GetAccessFlags() | kAccMiranda);
method->SetMethodIndex(0xFFFF & (old_vtable_count + i));
klass->SetVirtualMethod(old_method_count + i, method);
- vtable->Set<false>(old_vtable_count + i, method);
+ vtable->SetWithoutChecks<false>(old_vtable_count + i, method);
}
// TODO: do not assign to the vtable field until it is fully constructed.
klass->SetVTable(vtable.Get());
}
- mirror::ObjectArray<mirror::ArtMethod>* vtable = klass->GetVTableDuringLinking();
- for (int i = 0; i < vtable->GetLength(); ++i) {
- CHECK(vtable->Get(i) != nullptr);
+ if (kIsDebugBuild) {
+ mirror::ObjectArray<mirror::ArtMethod>* vtable = klass->GetVTableDuringLinking();
+ for (int i = 0; i < vtable->GetLength(); ++i) {
+ CHECK(vtable->GetWithoutChecks(i) != nullptr);
+ }
}
self->AllowThreadSuspension();
-
return true;
}