Interpreter entries and instrumentation as a listener.

Make the instrumentation responsible for whether we want method entry/exit
stubs, and allow it to use interpreter entry stubs when instruction by
instruction instrumentation is required. Improve deoptimization so more JDWP
test cases are passing.

Refactor exception debug posting, in particular improve reporting in the
interpreter. Improve class linker exception throwing so that broken dex files
are more likely to be reported. Fixes the performance issue Bug: 8410519.

Fix some error reporting lock level errors for the large object space. Make
fast object verification faster.

Add some debug mode robustness to finding dex PCs in GC maps.

Add printf attributes to JniAbortF and fix errors.

Expand run-test 044 to test return behaviors and fix issues with not throwing
appropriate exceptions for proxies.

Ensure causes are reported with a class linker NoClassDefFoundError and JNI
NoSuchFieldError.

Remove unused debugMe and updateDebuggerFromCode.

There's a minor sizing tweak to the arg array builder, and an extra reference
array check in the interpreter.

Some clean-up of trace code.

Fix reg type cache destructor if it is called after the reg type cache is
shutdown (as is the case in oatdump).

Change-Id: I6519c7b35df77f978d011999354c864f4918e8ce
diff --git a/src/mirror/abstract_method-inl.h b/src/mirror/abstract_method-inl.h
index 2049748..fd02474 100644
--- a/src/mirror/abstract_method-inl.h
+++ b/src/mirror/abstract_method-inl.h
@@ -20,6 +20,7 @@
 #include "abstract_method.h"
 
 #include "dex_file.h"
+#include "oat/runtime/oat_support_entrypoints.h"
 #include "object_array.h"
 #include "runtime.h"
 
@@ -113,6 +114,9 @@
   if (IsNative() || IsRuntimeMethod() || IsProxyMethod()) {
     return;
   }
+  if (GetCode() == GetInterpreterEntryPoint()) {
+    return;
+  }
   Runtime* runtime = Runtime::Current();
   if (GetCode() == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
       return;
diff --git a/src/mirror/abstract_method.cc b/src/mirror/abstract_method.cc
index f74814c..3ab3a93 100644
--- a/src/mirror/abstract_method.cc
+++ b/src/mirror/abstract_method.cc
@@ -151,23 +151,9 @@
   return result;
 }
 
-static const void* GetOatCode(const AbstractMethod* m)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  Runtime* runtime = Runtime::Current();
-  const void* code = m->GetCode();
-  // Peel off any method tracing trampoline.
-  if (runtime->IsMethodTracingActive() && runtime->GetInstrumentation()->GetSavedCodeFromMap(m) != NULL) {
-    code = runtime->GetInstrumentation()->GetSavedCodeFromMap(m);
-  }
-  // Peel off any resolution stub.
-  if (code == runtime->GetResolutionStubArray(Runtime::kStaticMethod)->GetData()) {
-    code = runtime->GetClassLinker()->GetOatCodeFor(m);
-  }
-  return code;
-}
-
 uintptr_t AbstractMethod::NativePcOffset(const uintptr_t pc) const {
-  return pc - reinterpret_cast<uintptr_t>(GetOatCode(this));
+  const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
+  return pc - reinterpret_cast<uintptr_t>(code);
 }
 
 // Find the lowest-address native safepoint pc for a given dex pc
@@ -181,7 +167,8 @@
   size_t mapping_table_length = GetPcToDexMappingTableLength();
   for (size_t i = 0; i < mapping_table_length; i += 2) {
     if (mapping_table[i + 1] == dex_pc) {
-      return mapping_table[i] + reinterpret_cast<uintptr_t>(GetOatCode(this));
+      const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
+      return mapping_table[i] + reinterpret_cast<uintptr_t>(code);
     }
   }
   LOG(FATAL) << "Failed to find native offset for dex pc 0x" << std::hex << dex_pc
@@ -201,14 +188,16 @@
     return DexFile::kDexNoIndex;   // Special no mapping case
   }
   size_t mapping_table_length = GetPcToDexMappingTableLength();
-  uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(GetOatCode(this));
+  const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
+  uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(code);
   for (size_t i = 0; i < mapping_table_length; i += 2) {
     if (mapping_table[i] == sought_offset) {
       return mapping_table[i + 1];
     }
   }
-  LOG(ERROR) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset)
-             << "(PC " << reinterpret_cast<void*>(pc) << ") in " << PrettyMethod(this);
+  LOG(FATAL) << "Failed to find Dex offset for PC offset " << reinterpret_cast<void*>(sought_offset)
+             << "(PC " << reinterpret_cast<void*>(pc) << ", code=" << code
+             << ") in " << PrettyMethod(this);
   return DexFile::kDexNoIndex;
 #else
   // Compiler LLVM doesn't use the machine pc, we just use dex pc instead.
@@ -227,7 +216,8 @@
     uint32_t map_offset = mapping_table[i];
     uint32_t map_dex_offset = mapping_table[i + 1];
     if (map_dex_offset == dex_pc) {
-      return reinterpret_cast<uintptr_t>(GetOatCode(this)) + map_offset;
+      const void* code = Runtime::Current()->GetInstrumentation()->GetQuickCodeFor(this);
+      return reinterpret_cast<uintptr_t>(code) + map_offset;
     }
   }
   LOG(FATAL) << "Looking up Dex PC not contained in method, 0x" << std::hex << dex_pc
@@ -270,14 +260,16 @@
   ManagedStack fragment;
   self->PushManagedStackFragment(&fragment);
 
+  Runtime* runtime = Runtime::Current();
   // Call the invoke stub, passing everything as arguments.
-  if (UNLIKELY(!Runtime::Current()->IsStarted())){
+  if (UNLIKELY(!runtime->IsStarted())){
     LOG(INFO) << "Not invoking " << PrettyMethod(this) << " for a runtime that isn't started";
     if (result != NULL) {
       result->SetJ(0);
     }
   } else {
-    bool interpret = self->ReadFlag(kEnterInterpreter) && !IsNative() && !IsProxyMethod();
+    bool interpret = runtime->GetInstrumentation()->InterpretOnly() && !IsNative() &&
+        !IsProxyMethod();
     const bool kLogInvocationStartAndReturn = false;
     if (GetCode() != NULL) {
       if (!interpret) {
@@ -289,15 +281,15 @@
 #else
         (*art_quick_invoke_stub)(this, args, args_size, self, result, result_type);
 #endif
-        if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException()) == -1)) {
+        if (UNLIKELY(reinterpret_cast<int32_t>(self->GetException(NULL)) == -1)) {
           // Unusual case where we were running LLVM generated code and an
           // exception was thrown to force the activations to be removed from the
           // stack. Continue execution in the interpreter.
-          JValue value;
           self->ClearException();
-          ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(&value);
+          ShadowFrame* shadow_frame = self->GetAndClearDeoptimizationShadowFrame(result);
+          self->SetTopOfStack(NULL, 0);
           self->SetTopOfShadowStack(shadow_frame);
-          interpreter::EnterInterpreterFromLLVM(self, shadow_frame, result);
+          interpreter::EnterInterpreterFromDeoptimize(self, shadow_frame, result);
         }
         if (kLogInvocationStartAndReturn) {
           LOG(INFO) << StringPrintf("Returned '%s' code=%p", PrettyMethod(this).c_str(), GetCode());
diff --git a/src/mirror/abstract_method.h b/src/mirror/abstract_method.h
index d10031a..9440915 100644
--- a/src/mirror/abstract_method.h
+++ b/src/mirror/abstract_method.h
@@ -321,6 +321,11 @@
     return GetFrameSizeInBytes() - kPointerSize;
   }
 
+  size_t GetSirtOffsetInBytes() const {
+    CHECK(IsNative());
+    return kPointerSize;
+  }
+
   bool IsRegistered() const;
 
   void RegisterNative(Thread* self, const void* native_method)
diff --git a/src/mirror/array.cc b/src/mirror/array.cc
index d0b3838..84c2dc6 100644
--- a/src/mirror/array.cc
+++ b/src/mirror/array.cc
@@ -18,6 +18,7 @@
 
 #include "class.h"
 #include "class-inl.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "gc/card_table-inl.h"
 #include "object-inl.h"
@@ -43,10 +44,10 @@
 
   // Check for overflow and throw OutOfMemoryError if this was an unreasonable request.
   size_t component_shift = sizeof(size_t) * 8 - 1 - CLZ(component_size);
-  if (data_size >> component_shift != size_t(component_count) || size < data_size) {
-    self->ThrowNewExceptionF("Ljava/lang/OutOfMemoryError;",
-        "%s of length %d would overflow",
-        PrettyDescriptor(array_class).c_str(), component_count);
+  if (UNLIKELY(data_size >> component_shift != size_t(component_count) || size < data_size)) {
+    self->ThrowOutOfMemoryError(StringPrintf("%s of length %d would overflow",
+                                             PrettyDescriptor(array_class).c_str(),
+                                             component_count).c_str());
     return NULL;
   }
 
@@ -108,8 +109,7 @@
   for (int i = 0; i < num_dimensions; i++) {
     int dimension = dimensions->Get(i);
     if (UNLIKELY(dimension < 0)) {
-      self->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;",
-                               "Dimension %d: %d", i, dimension);
+      ThrowNegativeArraySizeException(StringPrintf("Dimension %d: %d", i, dimension).c_str());
       return NULL;
     }
   }
@@ -135,15 +135,12 @@
 }
 
 bool Array::ThrowArrayIndexOutOfBoundsException(int32_t index) const {
-  Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
-      "length=%i; index=%i", length_, index);
+  art::ThrowArrayIndexOutOfBoundsException(index, GetLength());
   return false;
 }
 
 bool Array::ThrowArrayStoreException(Object* object) const {
-  Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-      "%s cannot be stored in an array of type %s",
-      PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str());
+  art::ThrowArrayStoreException(object->GetClass(), this->GetClass());
   return false;
 }
 
diff --git a/src/mirror/class-inl.h b/src/mirror/class-inl.h
index ec92c19..d7afed6 100644
--- a/src/mirror/class-inl.h
+++ b/src/mirror/class-inl.h
@@ -24,7 +24,7 @@
 #include "dex_cache.h"
 #include "field.h"
 #include "iftable.h"
-#include "object_array.h"
+#include "object_array-inl.h"
 #include "runtime.h"
 #include "string.h"
 
diff --git a/src/mirror/class.cc b/src/mirror/class.cc
index ba3556e..15129ab 100644
--- a/src/mirror/class.cc
+++ b/src/mirror/class.cc
@@ -60,10 +60,22 @@
   if (new_status == kStatusError) {
     CHECK_NE(GetStatus(), kStatusError) << PrettyClass(this);
 
-    // stash current exception
+    // Stash current exception.
     Thread* self = Thread::Current();
-    SirtRef<Throwable> exception(self, self->GetException());
-    CHECK(exception.get() != NULL);
+    SirtRef<mirror::Object> old_throw_this_object(self, NULL);
+    SirtRef<mirror::AbstractMethod> old_throw_method(self, NULL);
+    SirtRef<mirror::Throwable> old_exception(self, NULL);
+    uint32_t old_throw_dex_pc;
+    {
+      ThrowLocation old_throw_location;
+      mirror::Throwable* old_exception_obj = self->GetException(&old_throw_location);
+      old_throw_this_object.reset(old_throw_location.GetThis());
+      old_throw_method.reset(old_throw_location.GetMethod());
+      old_exception.reset(old_exception_obj);
+      old_throw_dex_pc = old_throw_location.GetDexPc();
+      self->ClearException();
+    }
+    CHECK(old_exception.get() != NULL);
 
     // clear exception to call FindSystemClass
     self->ClearException();
@@ -71,15 +83,18 @@
     Class* eiie_class = class_linker->FindSystemClass("Ljava/lang/ExceptionInInitializerError;");
     CHECK(!self->IsExceptionPending());
 
-    // only verification errors, not initialization problems, should set a verify error.
-    // this is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case.
-    Class* exception_class = exception->GetClass();
+    // Only verification errors, not initialization problems, should set a verify error.
+    // This is to ensure that ThrowEarlierClassFailure will throw NoClassDefFoundError in that case.
+    Class* exception_class = old_exception->GetClass();
     if (!eiie_class->IsAssignableFrom(exception_class)) {
       SetVerifyErrorClass(exception_class);
     }
 
-    // restore exception
-    self->SetException(exception.get());
+    // Restore exception.
+    ThrowLocation gc_safe_throw_location(old_throw_this_object.get(), old_throw_method.get(),
+                                         old_throw_dex_pc);
+
+    self->SetException(gc_safe_throw_location, old_exception.get());
   }
   return SetField32(OFFSET_OF_OBJECT_MEMBER(Class, status_), new_status, false);
 }
diff --git a/src/mirror/object_test.cc b/src/mirror/object_test.cc
index eed96bd..5c7ec11 100644
--- a/src/mirror/object_test.cc
+++ b/src/mirror/object_test.cc
@@ -116,12 +116,12 @@
 
   EXPECT_TRUE(oa->Get(-1) == NULL);
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
-  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
   soa.Self()->ClearException();
 
   EXPECT_TRUE(oa->Get(2) == NULL);
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
-  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
   soa.Self()->ClearException();
 
   ASSERT_TRUE(oa->GetClass() != NULL);
@@ -166,12 +166,12 @@
 
   EXPECT_EQ(0, a->Get(-1));
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
-  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
   soa.Self()->ClearException();
 
   EXPECT_EQ(0, a->Get(2));
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
-  EXPECT_EQ(aioobe, soa.Self()->GetException()->GetClass());
+  EXPECT_EQ(aioobe, soa.Self()->GetException(NULL)->GetClass());
   soa.Self()->ClearException();
 }
 
@@ -231,7 +231,7 @@
   dims->Set(0, -1);
   multi = Array::CreateMultiArray(soa.Self(), c.get(), dims.get());
   EXPECT_TRUE(soa.Self()->IsExceptionPending());
-  EXPECT_EQ(PrettyDescriptor(soa.Self()->GetException()->GetClass()),
+  EXPECT_EQ(PrettyDescriptor(soa.Self()->GetException(NULL)->GetClass()),
             "java.lang.NegativeArraySizeException");
   soa.Self()->ClearException();
 
diff --git a/src/mirror/string.cc b/src/mirror/string.cc
index f571fb8..45a6779 100644
--- a/src/mirror/string.cc
+++ b/src/mirror/string.cc
@@ -103,8 +103,9 @@
   // bounds check itself.
   if (index < 0 || index >= count_) {
     Thread* self = Thread::Current();
-    self->ThrowNewExceptionF("Ljava/lang/StringIndexOutOfBoundsException;",
-        "length=%i; index=%i", count_, index);
+    ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+    self->ThrowNewExceptionF(throw_location, "Ljava/lang/StringIndexOutOfBoundsException;",
+                             "length=%i; index=%i", count_, index);
     return 0;
   }
   return GetCharArray()->Get(index + GetOffset());
diff --git a/src/mirror/throwable.cc b/src/mirror/throwable.cc
index d1192b0..bbff9c2 100644
--- a/src/mirror/throwable.cc
+++ b/src/mirror/throwable.cc
@@ -35,7 +35,9 @@
 void Throwable::SetCause(Throwable* cause) {
   CHECK(cause != NULL);
   CHECK(cause != this);
-  CHECK(GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), false) == NULL);
+  Throwable* current_cause = GetFieldObject<Throwable*>(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_),
+                                                        false);
+  CHECK(current_cause == NULL || current_cause == this);
   SetFieldObject(OFFSET_OF_OBJECT_MEMBER(Throwable, cause_), cause, false);
 }