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/native/dalvik_system_DexFile.cc b/src/native/dalvik_system_DexFile.cc
index 7c6fbd9..d703f83 100644
--- a/src/native/dalvik_system_DexFile.cc
+++ b/src/native/dalvik_system_DexFile.cc
@@ -18,6 +18,7 @@
 
 #include "base/logging.h"
 #include "class_linker.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "gc/space.h"
 #include "image.h"
@@ -103,18 +104,18 @@
   }
   if (dex_file == NULL) {
     LOG(WARNING) << "Failed to open dex file: " << source;
-    Thread::Current()->ThrowNewExceptionF("Ljava/io/IOException;", "Unable to open dex file: %s",
-                                          source.c_str());
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/io/IOException;",
+                                   "Unable to open dex file: %s", source.c_str());
     return 0;
   }
   return static_cast<jint>(reinterpret_cast<uintptr_t>(dex_file));
 }
 
-static const DexFile* toDexFile(int dex_file_address)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+static const DexFile* toDexFile(int dex_file_address) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   const DexFile* dex_file = reinterpret_cast<const DexFile*>(static_cast<uintptr_t>(dex_file_address));
   if (dex_file == NULL) {
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;", "dex_file == null");
+    ThrowNullPointerException(NULL, "dex_file == null");
   }
   return dex_file;
 }
@@ -188,7 +189,9 @@
   if (!OS::FileExists(filename.c_str())) {
     LOG(ERROR) << "DexFile_isDexOptNeeded file '" << filename.c_str() << "' does not exist";
     ScopedObjectAccess soa(env);
-    Thread::Current()->ThrowNewExceptionF("Ljava/io/FileNotFoundException;", "%s", filename.c_str());
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/io/FileNotFoundException;",
+                                   "%s", filename.c_str());
     return JNI_TRUE;
   }
 
diff --git a/src/native/dalvik_system_VMDebug.cc b/src/native/dalvik_system_VMDebug.cc
index dc07a31..992998e 100644
--- a/src/native/dalvik_system_VMDebug.cc
+++ b/src/native/dalvik_system_VMDebug.cc
@@ -18,6 +18,7 @@
 #include <unistd.h>
 
 #include "class_linker.h"
+#include "common_throws.h"
 #include "debugger.h"
 #include "hprof/hprof.h"
 #include "jni_internal.h"
@@ -68,8 +69,9 @@
   int fd = dup(originalFd);
   if (fd < 0) {
     ScopedObjectAccess soa(env);
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
-                                          "dup(%d) failed: %s", originalFd, strerror(errno));
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/RuntimeException;",
+                                   "dup(%d) failed: %s", originalFd, strerror(errno));
     return;
   }
 
@@ -90,7 +92,7 @@
 }
 
 static jboolean VMDebug_isMethodTracingActive(JNIEnv*, jclass) {
-  return Runtime::Current()->IsMethodTracingActive();
+  return Trace::IsMethodTracingActive();
 }
 
 static void VMDebug_stopMethodTracing(JNIEnv*, jclass) {
@@ -119,24 +121,26 @@
   return Dbg::LastDebuggerActivity();
 }
 
-static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
+static void ThrowUnsupportedOperationException(JNIEnv* env) {
   ScopedObjectAccess soa(env);
-  Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
+  ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+  soa.Self()->ThrowNewException(throw_location, "Ljava/lang/UnsupportedOperationException;", NULL);
+}
+
+static void VMDebug_startInstructionCounting(JNIEnv* env, jclass) {
+  ThrowUnsupportedOperationException(env);
 }
 
 static void VMDebug_stopInstructionCounting(JNIEnv* env, jclass) {
-  ScopedObjectAccess soa(env);
-  Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
+  ThrowUnsupportedOperationException(env);
 }
 
 static void VMDebug_getInstructionCount(JNIEnv* env, jclass, jintArray /*javaCounts*/) {
-  ScopedObjectAccess soa(env);
-  Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
+  ThrowUnsupportedOperationException(env);
 }
 
 static void VMDebug_resetInstructionCount(JNIEnv* env, jclass) {
-  ScopedObjectAccess soa(env);
-  Thread::Current()->ThrowNewException("Ljava/lang/UnsupportedOperationException;", "");
+  ThrowUnsupportedOperationException(env);
 }
 
 static void VMDebug_printLoadedClasses(JNIEnv* env, jclass, jint flags) {
@@ -166,8 +170,7 @@
   // Only one of these may be NULL.
   if (javaFilename == NULL && javaFd == NULL) {
     ScopedObjectAccess soa(env);
-    Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;",
-                                         "fileName == null && fd == null");
+    ThrowNullPointerException(NULL, "fileName == null && fd == null");
     return;
   }
 
@@ -187,8 +190,7 @@
     fd = jniGetFDFromFileDescriptor(env, javaFd);
     if (fd < 0) {
       ScopedObjectAccess soa(env);
-      Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;",
-                                           "Invalid file descriptor");
+      ThrowRuntimeException("Invalid file descriptor");
       return;
     }
   }
diff --git a/src/native/dalvik_system_VMRuntime.cc b/src/native/dalvik_system_VMRuntime.cc
index a13d07a..d2ef43c 100644
--- a/src/native/dalvik_system_VMRuntime.cc
+++ b/src/native/dalvik_system_VMRuntime.cc
@@ -17,6 +17,7 @@
 #include <limits.h>
 
 #include "class_linker.h"
+#include "common_throws.h"
 #include "debugger.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
@@ -57,11 +58,11 @@
 
   mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
   if (element_class == NULL) {
-    soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "element class == null");
+    ThrowNullPointerException(NULL, "element class == null");
     return NULL;
   }
   if (length < 0) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length);
+    ThrowNegativeArraySizeException(length);
     return NULL;
   }
 
@@ -84,7 +85,7 @@
   ScopedObjectAccess soa(env);
   mirror::Array* array = soa.Decode<mirror::Array*>(javaArray);
   if (!array->IsArrayInstance()) {
-    soa.Self()->ThrowNewException("Ljava/lang/IllegalArgumentException;", "not an array");
+    ThrowIllegalArgumentException(NULL, "not an array");
     return 0;
   }
   // TODO: we should also check that this is a non-movable array.
diff --git a/src/native/java_lang_Class.cc b/src/native/java_lang_Class.cc
index 72f4c18..a729699 100644
--- a/src/native/java_lang_Class.cc
+++ b/src/native/java_lang_Class.cc
@@ -53,8 +53,9 @@
   // is especially handy for array types, since we want to avoid
   // auto-generating bogus array classes.
   if (!IsValidBinaryClassName(name.c_str())) {
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassNotFoundException;",
-        "Invalid name: %s", name.c_str());
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ClassNotFoundException;",
+                                   "Invalid name: %s", name.c_str());
     return NULL;
   }
 
diff --git a/src/native/java_lang_String.cc b/src/native/java_lang_String.cc
index 44ab1ca..3e9c3f3 100644
--- a/src/native/java_lang_String.cc
+++ b/src/native/java_lang_String.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "common_throws.h"
 #include "jni_internal.h"
 #include "mirror/string.h"
 #include "scoped_thread_state_change.h"
@@ -22,12 +23,11 @@
 namespace art {
 
 static jint String_compareTo(JNIEnv* env, jobject javaThis, jobject javaRhs) {
+  ScopedObjectAccess soa(env);
   if (UNLIKELY(javaRhs == NULL)) {
-    ScopedLocalRef<jclass> npe(env, env->FindClass("java/lang/NullPointerException"));
-    env->ThrowNew(npe.get(), "rhs == null");
+    ThrowNullPointerException(NULL, "rhs == null");
     return -1;
   } else {
-    ScopedObjectAccess soa(env);
     return soa.Decode<mirror::String*>(javaThis)->CompareTo(soa.Decode<mirror::String*>(javaRhs));
   }
 }
diff --git a/src/native/java_lang_System.cc b/src/native/java_lang_System.cc
index 5572623..d8df9d9 100644
--- a/src/native/java_lang_System.cc
+++ b/src/native/java_lang_System.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "common_throws.h"
 #include "gc/card_table-inl.h"
 #include "jni_internal.h"
 #include "mirror/array.h"
@@ -171,31 +172,33 @@
 static void ThrowArrayStoreException_NotAnArray(const char* identifier, mirror::Object* array)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   std::string actualType(PrettyTypeOf(array));
-  Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-      "%s of type %s is not an array", identifier, actualType.c_str());
+  Thread* self = Thread::Current();
+  ThrowLocation throw_location = self->GetCurrentLocationForThrow();
+  self->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
+                           "%s of type %s is not an array", identifier, actualType.c_str());
 }
 
 static void System_arraycopy(JNIEnv* env, jclass, jobject javaSrc, jint srcPos, jobject javaDst, jint dstPos, jint length) {
   ScopedObjectAccess soa(env);
 
   // Null pointer checks.
-  if (javaSrc == NULL) {
-    soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "src == null");
+  if (UNLIKELY(javaSrc == NULL)) {
+    ThrowNullPointerException(NULL, "src == null");
     return;
   }
-  if (javaDst == NULL) {
-    soa.Self()->ThrowNewException("Ljava/lang/NullPointerException;", "dst == null");
+  if (UNLIKELY(javaDst == NULL)) {
+    ThrowNullPointerException(NULL, "dst == null");
     return;
   }
 
   // Make sure source and destination are both arrays.
   mirror::Object* srcObject = soa.Decode<mirror::Object*>(javaSrc);
   mirror::Object* dstObject = soa.Decode<mirror::Object*>(javaDst);
-  if (!srcObject->IsArrayInstance()) {
+  if (UNLIKELY(!srcObject->IsArrayInstance())) {
     ThrowArrayStoreException_NotAnArray("source", srcObject);
     return;
   }
-  if (!dstObject->IsArrayInstance()) {
+  if (UNLIKELY(!dstObject->IsArrayInstance())) {
     ThrowArrayStoreException_NotAnArray("destination", dstObject);
     return;
   }
@@ -205,21 +208,24 @@
   mirror::Class* dstComponentType = dstArray->GetClass()->GetComponentType();
 
   // Bounds checking.
-  if (srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
-        "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
-        srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
+  if (UNLIKELY(srcPos < 0 || dstPos < 0 || length < 0 || srcPos > srcArray->GetLength() - length || dstPos > dstArray->GetLength() - length)) {
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayIndexOutOfBoundsException;",
+                                   "src.length=%d srcPos=%d dst.length=%d dstPos=%d length=%d",
+                                   srcArray->GetLength(), srcPos, dstArray->GetLength(), dstPos, length);
     return;
   }
 
   // Handle primitive arrays.
   if (srcComponentType->IsPrimitive() || dstComponentType->IsPrimitive()) {
     // If one of the arrays holds a primitive type the other array must hold the exact same type.
-    if (srcComponentType->IsPrimitive() != dstComponentType->IsPrimitive() || srcComponentType != dstComponentType) {
+    if (UNLIKELY(srcComponentType != dstComponentType)) {
       std::string srcType(PrettyTypeOf(srcArray));
       std::string dstType(PrettyTypeOf(dstArray));
-      soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-          "Incompatible types: src=%s, dst=%s", srcType.c_str(), dstType.c_str());
+      ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+      soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
+                                     "Incompatible types: src=%s, dst=%s",
+                                     srcType.c_str(), dstType.c_str());
       return;
     }
 
@@ -299,12 +305,13 @@
   }
 
   Runtime::Current()->GetHeap()->WriteBarrierArray(dstArray, dstPos, length);
-  if (i != length) {
+  if (UNLIKELY(i != length)) {
     std::string actualSrcType(PrettyTypeOf(o));
     std::string dstType(PrettyTypeOf(dstArray));
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-        "source[%d] of type %s cannot be stored in destination array of type %s",
-        srcPos + i, actualSrcType.c_str(), dstType.c_str());
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/ArrayStoreException;",
+                                   "source[%d] of type %s cannot be stored in destination array of type %s",
+                                   srcPos + i, actualSrcType.c_str(), dstType.c_str());
     return;
   }
 }
diff --git a/src/native/java_lang_Thread.cc b/src/native/java_lang_Thread.cc
index ca4be9d..7ccfaaa 100644
--- a/src/native/java_lang_Thread.cc
+++ b/src/native/java_lang_Thread.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "common_throws.h"
 #include "debugger.h"
 #include "jni_internal.h"
 #include "monitor.h"
@@ -90,7 +91,7 @@
   ScopedObjectAccess soa(env);
   mirror::Object* object = soa.Decode<mirror::Object*>(java_object);
   if (object == NULL) {
-    Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;", "object == null");
+    ThrowNullPointerException(NULL, "object == null");
     return JNI_FALSE;
   }
   MutexLock mu(soa.Self(), *Locks::thread_list_lock_);
diff --git a/src/native/java_lang_reflect_Array.cc b/src/native/java_lang_reflect_Array.cc
index af7a77a..45ec0ad 100644
--- a/src/native/java_lang_reflect_Array.cc
+++ b/src/native/java_lang_reflect_Array.cc
@@ -15,6 +15,7 @@
  */
 
 #include "class_linker.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
 #include "mirror/class-inl.h"
@@ -44,7 +45,7 @@
   DCHECK(javaElementClass != NULL);
   mirror::Class* element_class = soa.Decode<mirror::Class*>(javaElementClass);
   if (UNLIKELY(length < 0)) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", length);
+    ThrowNegativeArraySizeException(length);
     return NULL;
   }
   std::string descriptor("[");
diff --git a/src/native/java_lang_reflect_Constructor.cc b/src/native/java_lang_reflect_Constructor.cc
index fb84dfd..9180217 100644
--- a/src/native/java_lang_reflect_Constructor.cc
+++ b/src/native/java_lang_reflect_Constructor.cc
@@ -37,9 +37,12 @@
   ScopedObjectAccess soa(env);
   mirror::AbstractMethod* m = soa.Decode<mirror::Object*>(javaMethod)->AsMethod();
   mirror::Class* c = m->GetDeclaringClass();
-  if (c->IsAbstract()) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/InstantiationException;",
-        "Can't instantiate abstract class %s", PrettyDescriptor(c).c_str());
+  if (UNLIKELY(c->IsAbstract())) {
+    ThrowLocation throw_location = soa.Self()->GetCurrentLocationForThrow();
+    soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/InstantiationException;",
+                                   "Can't instantiate %s %s",
+                                   c->IsInterface() ? "interface" : "abstract class",
+                                   PrettyDescriptor(c).c_str());
     return NULL;
   }
 
diff --git a/src/native/java_lang_reflect_Field.cc b/src/native/java_lang_reflect_Field.cc
index 922fe00..b0daa91 100644
--- a/src/native/java_lang_reflect_Field.cc
+++ b/src/native/java_lang_reflect_Field.cc
@@ -16,6 +16,7 @@
 
 #include "class_linker.h"
 #include "class_linker-inl.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
 #include "mirror/class-inl.h"
@@ -71,22 +72,23 @@
     // Never okay.
     break;
   }
-  soa.Self()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
-      "Not a primitive field: %s", PrettyField(f).c_str());
+  ThrowIllegalArgumentException(NULL,
+                                StringPrintf("Not a primitive field: %s",
+                                             PrettyField(f).c_str()).c_str());
   return false;
 }
 
-static bool CheckReceiver(const ScopedObjectAccess& soa, jobject javaObj, mirror::Field* f,
-                          mirror::Object*& o)
+static bool CheckReceiver(const ScopedObjectAccess& soa, jobject j_rcvr, mirror::Field* f,
+                          mirror::Object*& class_or_rcvr)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   if (f->IsStatic()) {
-    o = f->GetDeclaringClass();
+    class_or_rcvr = f->GetDeclaringClass();
     return true;
   }
 
-  o = soa.Decode<mirror::Object*>(javaObj);
+  class_or_rcvr = soa.Decode<mirror::Object*>(j_rcvr);
   mirror::Class* declaringClass = f->GetDeclaringClass();
-  if (!VerifyObjectInClass(o, declaringClass)) {
+  if (!VerifyObjectInClass(class_or_rcvr, declaringClass)) {
     return false;
   }
   return true;
@@ -126,8 +128,8 @@
   // Widen it if necessary (and possible).
   JValue wide_value;
   mirror::Class* dst_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(dst_descriptor);
-  if (!ConvertPrimitiveValue(FieldHelper(f).GetTypeAsPrimitiveType(), dst_type->GetPrimitiveType(),
-                             field_value, wide_value)) {
+  if (!ConvertPrimitiveValue(NULL, false, FieldHelper(f).GetTypeAsPrimitiveType(),
+                             dst_type->GetPrimitiveType(), field_value, wide_value)) {
     return JValue();
   }
   return wide_value;
@@ -205,8 +207,8 @@
     // Else fall through to report an error.
   case Primitive::kPrimVoid:
     // Never okay.
-    Thread::Current()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
-        "Not a primitive field: %s", PrettyField(f).c_str());
+    ThrowIllegalArgumentException(NULL, StringPrintf("Not a primitive field: %s",
+                                                     PrettyField(f).c_str()).c_str());
     return;
   }
 
@@ -247,15 +249,15 @@
   }
   FieldHelper fh(f);
   if (!fh.IsPrimitiveType()) {
-    soa.Self()->ThrowNewExceptionF("Ljava/lang/IllegalArgumentException;",
-        "Not a primitive field: %s", PrettyField(f).c_str());
+    ThrowIllegalArgumentException(NULL, StringPrintf("Not a primitive field: %s",
+                                                     PrettyField(f).c_str()).c_str());
     return;
   }
 
   // Widen the value if necessary (and possible).
   JValue wide_value;
   mirror::Class* src_type = Runtime::Current()->GetClassLinker()->FindPrimitiveClass(src_descriptor);
-  if (!ConvertPrimitiveValue(src_type->GetPrimitiveType(), fh.GetTypeAsPrimitiveType(),
+  if (!ConvertPrimitiveValue(NULL, false, src_type->GetPrimitiveType(), fh.GetTypeAsPrimitiveType(),
                              new_value, wide_value)) {
     return;
   }