More exception rework.

This includes banishing dvmThrowExceptionWithClassMessage(), in favor
of the "ByClass" version, as well as making the verification error
throwing code use class objects.

Bug: 3500987
Change-Id: I1d63cec0ffaf3a0ad17e9304ba6a21fe51072fc7
diff --git a/vm/Exception.c b/vm/Exception.c
index 02e0e2a..99db870 100644
--- a/vm/Exception.c
+++ b/vm/Exception.c
@@ -261,29 +261,13 @@
     dvmReleaseTrackedAlloc(exception, self);
 }
 
-/*
- * Throw the named exception using the human-readable form of the class
- * descriptor as the exception message, and with the specified cause.
- */
-void dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor,
-    const char* messageDescriptor, Object* cause)
-{
-    char* message = dvmHumanReadableDescriptor(messageDescriptor);
-
-    dvmThrowChainedException(exceptionDescriptor, message, cause);
-    free(message);
-}
-
-/*
- * Like dvmThrowException, but take a class object instead of a name
- * and turn the given message into the human-readable form for a descriptor.
- */
-void dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass,
-    const char* messageDescriptor)
+void dvmThrowChainedExceptionByClassWithClassMessage(
+    ClassObject* exceptionClass, const char* messageDescriptor,
+    Object* cause)
 {
     char* message = dvmDescriptorToName(messageDescriptor);
 
-    dvmThrowExceptionByClass(exceptionClass, message);
+    dvmThrowChainedExceptionByClass(exceptionClass, message, cause);
     free(message);
 }
 
@@ -1470,6 +1454,12 @@
             descriptor);
 }
 
+void dvmThrowChainedNoClassDefFoundError(const char* descriptor,
+        Object* cause) {
+    dvmThrowChainedExceptionByClassWithClassMessage(
+            gDvm.exNoClassDefFoundError, descriptor, cause);
+}
+
 void dvmThrowNoSuchFieldError(const char* msg) {
     dvmThrowExceptionByClass(gDvm.exNoSuchFieldError, msg);
 }
diff --git a/vm/Exception.h b/vm/Exception.h
index 6d27437..ccab18c 100644
--- a/vm/Exception.h
+++ b/vm/Exception.h
@@ -83,24 +83,23 @@
 }
 
 /*
- * Throw the named exception using the human-readable form of the class
- * descriptor as the exception message, and with the specified cause.
+ * Like dvmThrowChainedException, but take a class object instead of a name
+ * and turn the given message into the human-readable form for a descriptor.
  */
-void dvmThrowChainedExceptionWithClassMessage(const char* exceptionDescriptor,
-    const char* messageDescriptor, Object* cause);
-INLINE void dvmThrowExceptionWithClassMessage(const char* exceptionDescriptor,
-    const char* messageDescriptor)
-{
-    dvmThrowChainedExceptionWithClassMessage(exceptionDescriptor,
-        messageDescriptor, NULL);
-}
+void dvmThrowChainedExceptionByClassWithClassMessage(
+    ClassObject* exceptionClass, const char* messageDescriptor,
+    Object* cause);
 
 /*
  * Like dvmThrowException, but take a class object instead of a name
  * and turn the given message into the human-readable form for a descriptor.
  */
-void dvmThrowExceptionByClassWithClassMessage(ClassObject* exceptionClass,
-    const char* messageDescriptor);
+INLINE void dvmThrowExceptionByClassWithClassMessage(
+    ClassObject* exceptionClass, const char* messageDescriptor)
+{
+    dvmThrowChainedExceptionByClassWithClassMessage(exceptionClass,
+            messageDescriptor, NULL);
+}
 
 /*
  * Return the exception being thrown in the current thread, or NULL if
@@ -378,6 +377,14 @@
 void dvmThrowNoClassDefFoundError(const char* descriptor);
 
 /**
+ * Throw a NoClassDefFoundError in the current thread, with the given
+ * cause, and the human-readable form of the given descriptor as the
+ * detail message.
+ */
+void dvmThrowChainedNoClassDefFoundError(const char* descriptor,
+        Object* cause);
+
+/**
  * Throw a NoSuchFieldError in the current thread, with the given
  * detail message.
  */
diff --git a/vm/Globals.h b/vm/Globals.h
index a4b47a6..48e3f87 100644
--- a/vm/Globals.h
+++ b/vm/Globals.h
@@ -286,6 +286,7 @@
     ClassObject* exIllegalStateException;
     ClassObject* exIllegalThreadStateException;
     ClassObject* exIncompatibleClassChangeError;
+    ClassObject* exInstantiationError;
     ClassObject* exInstantiationException;
     ClassObject* exInternalError;
     ClassObject* exInterruptedException;
diff --git a/vm/Init.c b/vm/Init.c
index e4d05ee..b9039d8 100644
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -1191,11 +1191,11 @@
 
     ok &= initRef(&gDvm.classJavaLangClass, "Ljava/lang/Class;");
     ok &= initRef(&gDvm.classJavaLangObject, "Ljava/lang/Object;");
+    ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
 
     ok &= initRef(&gDvm.classJavaLangString, "Ljava/lang/String;");
     ok &= initRef(&gDvm.classJavaLangThread, "Ljava/lang/Thread;");
     ok &= initRef(&gDvm.classJavaLangThreadGroup, "Ljava/lang/ThreadGroup;");
-    ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
     ok &= initRef(&gDvm.classJavaLangVMThread, "Ljava/lang/VMThread;");
 
     /* Exception classes and related support classes */
@@ -1235,6 +1235,8 @@
             "Ljava/lang/IllegalThreadStateException;");
     ok &= initRef(&gDvm.exIncompatibleClassChangeError,
             "Ljava/lang/IncompatibleClassChangeError;");
+    ok &= initRef(&gDvm.exInstantiationError,
+            "Ljava/lang/InstantiationError;");
     ok &= initRef(&gDvm.exInstantiationException,
             "Ljava/lang/InstantiationException;");
     ok &= initRef(&gDvm.exInternalError,
@@ -1264,7 +1266,6 @@
             "Ldalvik/system/StaleDexCacheError;");
     ok &= initRef(&gDvm.exStringIndexOutOfBoundsException,
             "Ljava/lang/StringIndexOutOfBoundsException;");
-    ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
     ok &= initRef(&gDvm.exTypeNotPresentException,
             "Ljava/lang/TypeNotPresentException;");
     ok &= initRef(&gDvm.exUnsatisfiedLinkError,
diff --git a/vm/interp/Interp.c b/vm/interp/Interp.c
index 9e94449..a145034 100644
--- a/vm/interp/Interp.c
+++ b/vm/interp/Interp.c
@@ -1154,43 +1154,43 @@
     const int typeMask = 0xff << kVerifyErrorRefTypeShift;
     VerifyError errorKind = kind & ~typeMask;
     VerifyErrorRefType refType = kind >> kVerifyErrorRefTypeShift;
-    const char* exceptionName = "Ljava/lang/VerifyError;";
+    ClassObject* exceptionClass = gDvm.exVerifyError;
     char* msg = NULL;
 
     switch ((VerifyError) errorKind) {
     case VERIFY_ERROR_NO_CLASS:
-        exceptionName = "Ljava/lang/NoClassDefFoundError;";
+        exceptionClass = gDvm.exNoClassDefFoundError;
         msg = classNameFromIndex(method, ref, refType, 0);
         break;
     case VERIFY_ERROR_NO_FIELD:
-        exceptionName = "Ljava/lang/NoSuchFieldError;";
+        exceptionClass = gDvm.exNoSuchFieldError;
         msg = fieldNameFromIndex(method, ref, refType, 0);
         break;
     case VERIFY_ERROR_NO_METHOD:
-        exceptionName = "Ljava/lang/NoSuchMethodError;";
+        exceptionClass = gDvm.exNoSuchMethodError;
         msg = methodNameFromIndex(method, ref, refType, 0);
         break;
     case VERIFY_ERROR_ACCESS_CLASS:
-        exceptionName = "Ljava/lang/IllegalAccessError;";
+        exceptionClass = gDvm.exIllegalAccessError;
         msg = classNameFromIndex(method, ref, refType,
             kThrowShow_accessFromClass);
         break;
     case VERIFY_ERROR_ACCESS_FIELD:
-        exceptionName = "Ljava/lang/IllegalAccessError;";
+        exceptionClass = gDvm.exIllegalAccessError;
         msg = fieldNameFromIndex(method, ref, refType,
             kThrowShow_accessFromClass);
         break;
     case VERIFY_ERROR_ACCESS_METHOD:
-        exceptionName = "Ljava/lang/IllegalAccessError;";
+        exceptionClass = gDvm.exIllegalAccessError;
         msg = methodNameFromIndex(method, ref, refType,
             kThrowShow_accessFromClass);
         break;
     case VERIFY_ERROR_CLASS_CHANGE:
-        exceptionName = "Ljava/lang/IncompatibleClassChangeError;";
+        exceptionClass = gDvm.exIncompatibleClassChangeError;
         msg = classNameFromIndex(method, ref, refType, 0);
         break;
     case VERIFY_ERROR_INSTANTIATION:
-        exceptionName = "Ljava/lang/InstantiationError;";
+        exceptionClass = gDvm.exInstantiationError;
         msg = classNameFromIndex(method, ref, refType, 0);
         break;
 
@@ -1206,7 +1206,7 @@
     /* no default clause -- want warning if enum updated */
     }
 
-    dvmThrowException(exceptionName, msg);
+    dvmThrowExceptionByClass(exceptionClass, msg);
     free(msg);
 }
 
diff --git a/vm/mterp/c/OP_NEW_INSTANCE.c b/vm/mterp/c/OP_NEW_INSTANCE.c
index e7e2952..65a8cf7 100644
--- a/vm/mterp/c/OP_NEW_INSTANCE.c
+++ b/vm/mterp/c/OP_NEW_INSTANCE.c
@@ -32,7 +32,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
diff --git a/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c b/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
index b49adbf..6cb27b8 100644
--- a/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
+++ b/vm/mterp/c/OP_NEW_INSTANCE_JUMBO.c
@@ -32,7 +32,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
diff --git a/vm/mterp/out/InterpC-allstubs.c b/vm/mterp/out/InterpC-allstubs.c
index 632d62d..5d94cef 100644
--- a/vm/mterp/out/InterpC-allstubs.c
+++ b/vm/mterp/out/InterpC-allstubs.c
@@ -1802,7 +1802,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
@@ -3276,7 +3276,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
diff --git a/vm/mterp/out/InterpC-portdbg.c b/vm/mterp/out/InterpC-portdbg.c
index 090146f..e2b8e67 100644
--- a/vm/mterp/out/InterpC-portdbg.c
+++ b/vm/mterp/out/InterpC-portdbg.c
@@ -2165,7 +2165,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
@@ -3639,7 +3639,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
diff --git a/vm/mterp/out/InterpC-portstd.c b/vm/mterp/out/InterpC-portstd.c
index e71511e..8204e48 100644
--- a/vm/mterp/out/InterpC-portstd.c
+++ b/vm/mterp/out/InterpC-portstd.c
@@ -1915,7 +1915,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
@@ -3389,7 +3389,7 @@
          * Verifier now tests for interface/abstract class.
          */
         //if (dvmIsInterfaceClass(clazz) || dvmIsAbstractClass(clazz)) {
-        //    dvmThrowExceptionWithClassMessage("Ljava/lang/InstantiationError;",
+        //    dvmThrowExceptionByClassWithClassMessage(gDvm.exInstantiationError,
         //        clazz->descriptor);
         //    GOTO_exceptionThrown();
         //}
diff --git a/vm/oo/Class.c b/vm/oo/Class.c
index 3bd0298..358067e 100644
--- a/vm/oo/Class.c
+++ b/vm/oo/Class.c
@@ -1300,8 +1300,7 @@
 #endif
         dvmAddTrackedAlloc(excep, self);
         dvmClearException(self);
-        dvmThrowChainedExceptionWithClassMessage(
-            "Ljava/lang/NoClassDefFoundError;", descriptor, excep);
+        dvmThrowChainedNoClassDefFoundError(descriptor, excep);
         dvmReleaseTrackedAlloc(excep, self);
         clazz = NULL;
         goto bail;