Fix for test 069.
Can't throw exception in fast interface lookup. Extra debugging that
methods look sane when creating native to managed records.
Change-Id: If0b970c418db5ff075334af8359541a94e8680b7
diff --git a/src/class_linker_test.cc b/src/class_linker_test.cc
index e604ca0..58f36f1 100644
--- a/src/class_linker_test.cc
+++ b/src/class_linker_test.cc
@@ -939,9 +939,9 @@
EXPECT_NE(Jj2, Aj2);
EXPECT_EQ(Kj1, Jj1);
EXPECT_EQ(Kj2, Jj2);
- EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii));
- EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1));
- EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2));
+ EXPECT_EQ(Ai, A->FindVirtualMethodForInterface(Ii, true));
+ EXPECT_EQ(Aj1, A->FindVirtualMethodForInterface(Jj1, true));
+ EXPECT_EQ(Aj2, A->FindVirtualMethodForInterface(Jj2, true));
EXPECT_EQ(Ai, A->FindVirtualMethodForVirtualOrInterface(Ii));
EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1));
EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2));
diff --git a/src/object.cc b/src/object.cc
index 558978c..281f685 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -990,7 +990,7 @@
new_class_loader, false);
}
-Method* Class::FindVirtualMethodForInterface(Method* method) {
+Method* Class::FindVirtualMethodForInterface(Method* method, bool can_throw) {
Class* declaring_class = method->GetDeclaringClass();
DCHECK(declaring_class != NULL) << PrettyClass(this);
DCHECK(declaring_class->IsInterface()) << PrettyMethod(method);
@@ -1003,10 +1003,12 @@
return interface_entry->GetMethodArray()->Get(method->GetMethodIndex());
}
}
- Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
- "Class %s does not implement interface %s",
- PrettyDescriptor(GetDescriptor()).c_str(),
- PrettyDescriptor(declaring_class->GetDescriptor()).c_str());
+ if (can_throw) {
+ Thread::Current()->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+ "Class %s does not implement interface %s",
+ PrettyDescriptor(GetDescriptor()).c_str(),
+ PrettyDescriptor(declaring_class->GetDescriptor()).c_str());
+ }
return NULL;
}
diff --git a/src/object.h b/src/object.h
index a93733c..c60f580 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1727,7 +1727,7 @@
// Given a method implemented by this class, but potentially from a
// super class or interface, return the specific implementation
// method for this class.
- Method* FindVirtualMethodForInterface(Method* method);
+ Method* FindVirtualMethodForInterface(Method* method, bool can_throw);
Method* FindInterfaceMethod(const StringPiece& name, const StringPiece& descriptor) const;
Method* FindInterfaceMethod(String* name, String* descriptor) const;
@@ -1737,7 +1737,7 @@
return method;
}
if (method->GetDeclaringClass()->IsInterface()) {
- return FindVirtualMethodForInterface(method);
+ return FindVirtualMethodForInterface(method, true);
}
return FindVirtualMethodForVirtual(method);
}
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index ccb8dcc..5550c2f 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -869,7 +869,7 @@
Method* interface_method = caller_method->GetDexCacheResolvedMethods()->Get(method_idx);
Method* found_method = NULL; // The found method
if (LIKELY(interface_method != NULL && this_object != NULL)) {
- found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
+ found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method, false);
}
if (UNLIKELY(found_method == NULL)) {
FinishCalleeSaveFrameSetup(thread, sp, Runtime::kRefsAndArgs);
@@ -887,7 +887,7 @@
return 0;
}
}
- found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
+ found_method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method, true);
if (found_method == NULL) {
CHECK(thread->IsExceptionPending());
return 0;
diff --git a/src/thread.cc b/src/thread.cc
index 79dbf81..e1a8841 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -451,6 +451,28 @@
<< " HZ=" << sysconf(_SC_CLK_TCK) << "\n";
}
+void Thread::PushNativeToManagedRecord(NativeToManagedRecord* record) {
+ Method **sp = top_of_managed_stack_.GetSP();
+#ifndef NDEBUG
+ if (sp != NULL) {
+ Method* m = *sp;
+ Heap::VerifyObject(m);
+ DCHECK((m == NULL) || m->IsMethod());
+ }
+#endif
+ record->last_top_of_managed_stack_ = reinterpret_cast<void*>(sp);
+ record->last_top_of_managed_stack_pc_ = top_of_managed_stack_pc_;
+ record->link_ = native_to_managed_record_;
+ native_to_managed_record_ = record;
+ top_of_managed_stack_.SetSP(NULL);
+}
+
+void Thread::PopNativeToManagedRecord(const NativeToManagedRecord& record) {
+ native_to_managed_record_ = record.link_;
+ top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(record.last_top_of_managed_stack_));
+ top_of_managed_stack_pc_ = record.last_top_of_managed_stack_pc_;
+}
+
struct StackDumpVisitor : public Thread::StackVisitor {
StackDumpVisitor(std::ostream& os, const Thread* thread)
: os(os), thread(thread), frame_count(0) {
diff --git a/src/thread.h b/src/thread.h
index 74e6f83..3a8b2a8 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -344,19 +344,8 @@
}
// Linked list recording transitions from native to managed code
- void PushNativeToManagedRecord(NativeToManagedRecord* record) {
- record->last_top_of_managed_stack_ = reinterpret_cast<void*>(top_of_managed_stack_.GetSP());
- record->last_top_of_managed_stack_pc_ = top_of_managed_stack_pc_;
- record->link_ = native_to_managed_record_;
- native_to_managed_record_ = record;
- top_of_managed_stack_.SetSP(NULL);
- }
-
- void PopNativeToManagedRecord(const NativeToManagedRecord& record) {
- native_to_managed_record_ = record.link_;
- top_of_managed_stack_.SetSP(reinterpret_cast<Method**>(record.last_top_of_managed_stack_));
- top_of_managed_stack_pc_ = record.last_top_of_managed_stack_pc_;
- }
+ void PushNativeToManagedRecord(NativeToManagedRecord* record);
+ void PopNativeToManagedRecord(const NativeToManagedRecord& record);
const ClassLoader* GetClassLoaderOverride() {
// TODO: need to place the class_loader_override_ in a handle