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