Fix ClassLinker::LinkInterfaceMethods bug
Also:
- Expanded class_linker_test with additional vtable and iftable coverage
- Added -fkeep-inline-functions where it works on host for debugging
- Added disabled test for running command line Fibonacci with oatexec
Change-Id: Ie295551e42493c7cca05684e71e56bf55bd362a4
diff --git a/src/class_linker.cc b/src/class_linker.cc
index f25bac0..dde29cf 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -1718,7 +1718,7 @@
}
klass->SetIfTable(iftable);
CHECK_EQ(idx, ifcount);
- if (klass->IsInterface() || super_ifcount == ifcount) {
+ if (klass->IsInterface()) {
return true;
}
std::vector<Method*> miranda_list;
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index eab184e..4b48892 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -54,6 +54,9 @@
EXPECT_EQ(0U, primitive->NumInstanceFields());
EXPECT_EQ(0U, primitive->NumStaticFields());
EXPECT_EQ(0U, primitive->NumInterfaces());
+ EXPECT_TRUE(primitive->GetVTable() == NULL);
+ EXPECT_EQ(0, primitive->GetIfTableCount());
+ EXPECT_TRUE(primitive->GetIfTable() == NULL);
}
void AssertArrayClass(const StringPiece& array_descriptor,
@@ -95,6 +98,12 @@
EXPECT_EQ(0U, array->NumInstanceFields());
EXPECT_EQ(0U, array->NumStaticFields());
EXPECT_EQ(2U, array->NumInterfaces());
+ EXPECT_TRUE(array->GetVTable() != NULL);
+ EXPECT_EQ(2, array->GetIfTableCount());
+ ObjectArray<InterfaceEntry>* iftable = array->GetIfTable();
+ ASSERT_TRUE(iftable != NULL);
+ EXPECT_TRUE(iftable->Get(0)->GetInterface()->GetDescriptor()->Equals("Ljava/lang/Cloneable;"));
+ EXPECT_TRUE(iftable->Get(1)->GetInterface()->GetDescriptor()->Equals("Ljava/io/Serializable;"));
}
void AssertMethod(Class* klass, Method* method) {
@@ -159,6 +168,20 @@
EXPECT_NE(0U, klass->NumDirectMethods());
}
}
+ EXPECT_EQ(klass->IsInterface(), klass->GetVTable() == NULL);
+ for (int i = 0; i < klass->GetIfTableCount(); i++) {
+ const InterfaceEntry* interface_entry = klass->GetIfTable()->Get(i);
+ ASSERT_TRUE(interface_entry != NULL);
+ Class* interface = interface_entry->GetInterface();
+ ASSERT_TRUE(interface != NULL);
+ EXPECT_TRUE(interface_entry->GetInterface() != NULL);
+ if (klass->IsInterface()) {
+ EXPECT_EQ(0U, interface_entry->GetMethodArrayCount());
+ } else {
+ CHECK_EQ(interface->NumVirtualMethods(), interface_entry->GetMethodArrayCount());
+ EXPECT_EQ(interface->NumVirtualMethods(), interface_entry->GetMethodArrayCount());
+ }
+ }
if (klass->IsAbstract()) {
EXPECT_FALSE(klass->IsFinal());
} else {
diff --git a/src/object.h b/src/object.h
index 2f9ea33..5e09f2e 100644
--- a/src/object.h
+++ b/src/object.h
@@ -2683,6 +2683,14 @@
Set(kInterface, interface);
}
+ size_t GetMethodArrayCount() const {
+ ObjectArray<Method>* method_array = down_cast<ObjectArray<Method>*>(Get(kMethodArray));
+ if (method_array == 0) {
+ return 0;
+ }
+ return method_array->GetLength();
+ }
+
ObjectArray<Method>* GetMethodArray() const {
ObjectArray<Method>* method_array = down_cast<ObjectArray<Method>*>(Get(kMethodArray));
DCHECK(method_array != NULL);