summaryrefslogtreecommitdiff
path: root/src/class_linker.cc
diff options
context:
space:
mode:
author Ian Rogers <irogers@google.com> 2012-01-12 17:01:38 -0800
committer Ian Rogers <irogers@google.com> 2012-01-12 17:01:38 -0800
commitb52b01ac70ccc5a56e108d81451beda0e1d320a0 (patch)
tree13702b538f5ee819273c2e56a59aaac7b9476303 /src/class_linker.cc
parentec9822908b052272f4a7035dfdf6e639fd4535ca (diff)
Don't duplicate interfaces in iftable
Mirroring AOSP Change Idb4a13ca https://android-review.googlesource.com//#/c/30900/ Change-Id: I5d5a7b2993f8a9b2d96cb3e80c1d47d3b994c1ae
Diffstat (limited to 'src/class_linker.cc')
-rw-r--r--src/class_linker.cc43
1 files changed, 36 insertions, 7 deletions
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 045974f8c3..8c46a7e403 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2537,7 +2537,8 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>
if (super_ifcount != 0) {
ObjectArray<InterfaceEntry>* super_iftable = klass->GetSuperClass()->GetIfTable();
for (size_t i = 0; i < super_ifcount; i++) {
- iftable->Set(i, AllocInterfaceEntry(super_iftable->Get(i)->GetInterface()));
+ Class* super_interface = super_iftable->Get(i)->GetInterface();
+ iftable->Set(i, AllocInterfaceEntry(super_interface));
}
}
// Flatten the interface inheritance hierarchy.
@@ -2555,15 +2556,43 @@ bool ClassLinker::LinkInterfaceMethods(SirtRef<Class>& klass, ObjectArray<Class>
klass->SetVerifyErrorClass(thread->GetException()->GetClass());
return false;
}
- // Add this interface.
- iftable->Set(idx++, AllocInterfaceEntry(interface));
- // Add this interface's superinterfaces.
- for (int32_t j = 0; j < interface->GetIfTableCount(); j++) {
- iftable->Set(idx++, AllocInterfaceEntry(interface->GetIfTable()->Get(j)->GetInterface()));
+ // Check if interface is already in iftable
+ bool duplicate = false;
+ for (size_t j = 0; j < idx; j++) {
+ Class* existing_interface = iftable->Get(j)->GetInterface();
+ if (existing_interface == interface) {
+ duplicate = true;
+ break;
+ }
}
+ if (!duplicate) {
+ // Add this non-duplicate interface.
+ iftable->Set(idx++, AllocInterfaceEntry(interface));
+ // Add this interface's non-duplicate super-interfaces.
+ for (int32_t j = 0; j < interface->GetIfTableCount(); j++) {
+ Class* super_interface = interface->GetIfTable()->Get(j)->GetInterface();
+ bool super_duplicate = false;
+ for (size_t k = 0; k < idx; k++) {
+ Class* existing_interface = iftable->Get(k)->GetInterface();
+ if (existing_interface == super_interface) {
+ super_duplicate = true;
+ break;
+ }
+ }
+ if (!super_duplicate) {
+ iftable->Set(idx++, AllocInterfaceEntry(super_interface));
+ }
+ }
+ }
+ }
+ // Shrink iftable in case duplicates were found
+ if (idx < ifcount) {
+ iftable.reset(iftable->CopyOf(idx));
+ ifcount = idx;
+ } else {
+ CHECK_EQ(idx, ifcount);
}
klass->SetIfTable(iftable.get());
- CHECK_EQ(idx, ifcount);
// If we're an interface, we don't need the vtable pointers, so we're done.
if (klass->IsInterface() /*|| super_ifcount == ifcount*/) {