diff options
| author | 2012-01-12 17:40:06 -0800 | |
|---|---|---|
| committer | 2012-01-12 17:40:06 -0800 | |
| commit | d9c37b307713572b6ea32e9f6ff965d15b3f4b88 (patch) | |
| tree | 342771fa27cc985ee7ce468db7797bce1c1fa129 /src/class_linker.cc | |
| parent | 9f23e24937efe175d24bb712010690a2358e61ca (diff) | |
| parent | b52b01ac70ccc5a56e108d81451beda0e1d320a0 (diff) | |
Merge "Don't duplicate interfaces in iftable" into dalvik-dev
Diffstat (limited to 'src/class_linker.cc')
| -rw-r--r-- | src/class_linker.cc | 43 |
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*/) { |