Support for unresolved types in new-instance during verification.

Also, ensure that classes that don't load are erroneous, warn early
about exceptions left on a thread by the verifier/compiler, factor out
slowpath checks for the compiler and fix the slowpath selector for
const-class.

This change causes more dex cache misses at runtime (more slowpath
execution). It also requires a "mm clean-oat".

Change-Id: I014b49ebdd7d8f7dd2e39cc0958fc0b708d58c4c
diff --git a/src/thread.cc b/src/thread.cc
index 841ea9b..a8c58bf 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -91,7 +91,7 @@
   pLmul = __aeabi_lmul;
   pAllocArrayFromCode = art_alloc_array_from_code;
   pAllocObjectFromCode = art_alloc_object_from_code;
-  pAllocObjectFromCodeSlowPath = art_alloc_object_from_code_slow_path;
+  pAllocObjectFromCodeWithAccessCheck = art_alloc_object_from_code_with_access_check;
   pCanPutArrayElementFromCode = art_can_put_array_element_from_code;
   pCheckAndAllocArrayFromCode = art_check_and_alloc_array_from_code;
   pCheckCastFromCode = art_check_cast_from_code;
@@ -101,6 +101,7 @@
   pGetObjStatic = art_get_obj_static_from_code;
   pHandleFillArrayDataFromCode = art_handle_fill_data_from_code;
   pInitializeStaticStorage = art_initialize_static_storage_from_code;
+  pInitializeTypeFromCode = art_initialize_type_from_code;
   pInvokeInterfaceTrampoline = art_invoke_interface_trampoline;
   pLockObjectFromCode = art_lock_object_from_code;
   pObjectInit = art_object_init_from_code;
@@ -126,7 +127,6 @@
   pDecodeJObjectInThread = DecodeJObjectInThread;
   pDeliverException = art_deliver_exception_from_code;
   pFindNativeMethod = FindNativeMethod;
-  pInitializeTypeFromCode = InitializeTypeFromCode;
   pInstanceofNonTrivialFromCode = IsAssignableFromCode;
   pResolveMethodFromCode = ResolveMethodFromCode;
   pThrowAbstractMethodErrorFromCode = ThrowAbstractMethodErrorFromCode;
@@ -482,7 +482,8 @@
 
 struct StackDumpVisitor : public Thread::StackVisitor {
   StackDumpVisitor(std::ostream& os, const Thread* thread)
-      : os(os), thread(thread), frame_count(0) {
+      : last_method(NULL), last_line_number(0), repetition_count(0), os(os), thread(thread),
+        frame_count(0) {
   }
 
   virtual ~StackDumpVisitor() {
@@ -492,28 +493,41 @@
     if (!frame.HasMethod()) {
       return;
     }
-
+    const int kMaxRepetition = 3;
     Method* m = frame.GetMethod();
     Class* c = m->GetDeclaringClass();
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     const DexFile& dex_file = class_linker->FindDexFile(c->GetDexCache());
-
-    os << "  at " << PrettyMethod(m, false);
-    if (m->IsNative()) {
-      os << "(Native method)";
+    int line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc));
+    if (line_number == last_line_number && last_method == m) {
+      repetition_count++;
     } else {
-      int line_number = dex_file.GetLineNumFromPC(m, m->ToDexPC(pc));
-      SirtRef<String> source_file(c->GetSourceFile());
-      os << "(" << (source_file.get() != NULL ? source_file->ToModifiedUtf8() : "unavailable")
-         << ":" << line_number << ")";
+      if (repetition_count >= kMaxRepetition) {
+        os << "  ... repeated " << (repetition_count - kMaxRepetition) << " times\n";
+      }
+      repetition_count = 0;
+      last_line_number = line_number;
+      last_method = m;
     }
-    os << "\n";
+    if (repetition_count < kMaxRepetition) {
+      os << "  at " << PrettyMethod(m, false);
+      if (m->IsNative()) {
+        os << "(Native method)";
+      } else {
+        SirtRef<String> source_file(c->GetSourceFile());
+        os << "(" << (source_file.get() != NULL ? source_file->ToModifiedUtf8() : "unavailable")
+           << ":" << line_number << ")";
+      }
+      os << "\n";
+    }
 
     if (frame_count++ == 0) {
       Monitor::DescribeWait(os, thread);
     }
   }
-
+  Method* last_method;
+  int last_line_number;
+  int repetition_count;
   std::ostream& os;
   const Thread* thread;
   int frame_count;
@@ -1316,13 +1330,35 @@
 };
 
 void Thread::DeliverException() {
-  Throwable *exception = GetException();  // Set exception on thread
+  const bool kDebugExceptionDelivery = false;
+  Throwable *exception = GetException();  // Get exception from thread
   CHECK(exception != NULL);
+  // Don't leave exception visible while we try to find the handler, which may cause class
+  // resolution
+  ClearException();
+  if (kDebugExceptionDelivery) {
+    DumpStack(LOG(INFO) << "Delivering exception: " << PrettyTypeOf(exception) << std::endl);
+  }
 
   Context* long_jump_context = GetLongJumpContext();
   CatchBlockStackVisitor catch_finder(exception->GetClass(), long_jump_context);
   WalkStackUntilUpCall(&catch_finder, true);
 
+  if (kDebugExceptionDelivery) {
+    Method* handler_method = catch_finder.handler_frame_.GetMethod();
+    if (handler_method == NULL) {
+      LOG(INFO) << "Handler is upcall";
+    } else {
+      ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+      const DexFile& dex_file =
+          class_linker->FindDexFile(handler_method->GetDeclaringClass()->GetDexCache());
+      int line_number = dex_file.GetLineNumFromPC(handler_method,
+                                                handler_method->ToDexPC(catch_finder.handler_pc_));
+      LOG(INFO) << "Handler: " << PrettyMethod(handler_method)
+          << " (line: " << line_number << ")";
+    }
+  }
+  SetException(exception);
   long_jump_context->SetSP(reinterpret_cast<intptr_t>(catch_finder.handler_frame_.GetSP()));
   long_jump_context->SetPC(catch_finder.handler_pc_);
   long_jump_context->DoLongJump();