Fix exception throwing to support no detail message.

(The empty string as a detail message is distinct from a NULL detail message,
and is treated differently by Throwable.printStackTrace.)

Change-Id: I8c65deac9f18c5782dcf6e72e4c37e6dd4174fe9
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index e5fbfd2..ca1fdea 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -83,7 +83,7 @@
   // Place a special frame at the TOS that will save all callee saves
   *sp = Runtime::Current()->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
-  thread->ThrowNewException("Ljava/lang/NullPointerException;", "unexpected null reference");
+  thread->ThrowNewException("Ljava/lang/NullPointerException;", NULL);
   thread->DeliverException();
 }
 
@@ -101,8 +101,8 @@
   // Place a special frame at the TOS that will save all callee saves
   *sp = Runtime::Current()->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
-  thread->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
-                            "length=%d; index=%d", limit, index);
+  thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;", "length=%d; index=%d",
+      limit, index);
   thread->DeliverException();
 }
 
@@ -110,9 +110,8 @@
 extern void ThrowAbstractMethodErrorFromCode(Method* method, Thread* thread, Method** sp) {
   *sp = Runtime::Current()->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
-  thread->ThrowNewException("Ljava/lang/AbstractMethodError;",
-                            "abstract method \"%s\"",
-                            PrettyMethod(method).c_str());
+  thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;", "abstract method \"%s\"",
+      PrettyMethod(method).c_str());
   thread->DeliverException();
 }
 
@@ -122,9 +121,9 @@
   *sp = runtime->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
   thread->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute
-  thread->ThrowNewException("Ljava/lang/StackOverflowError;",
-                            "stack size %zdkb; default stack size: %zdkb",
-                            thread->GetStackSize() / KB, runtime->GetDefaultStackSize() / KB);
+  thread->ThrowNewExceptionF("Ljava/lang/StackOverflowError;",
+      "stack size %zdkb; default stack size: %zdkb",
+      thread->GetStackSize() / KB, runtime->GetDefaultStackSize() / KB);
   thread->ResetDefaultStackEnd();  // Return to default stack size
   thread->DeliverException();
 }
@@ -135,8 +134,8 @@
   *sp = runtime->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
   LOG(WARNING) << "TODO: verifcation error detail message. src1=" << src1 << " ref=" << ref;
-  thread->ThrowNewException("Ljava/lang/VerifyError;",
-                            "TODO: verifcation error detail message. src1=%d; ref=%d", src1, ref);
+  thread->ThrowNewExceptionF("Ljava/lang/VerifyError;",
+      "TODO: verification error detail message. src1=%d; ref=%d", src1, ref);
   thread->DeliverException();
 }
 
@@ -146,7 +145,7 @@
   *sp = runtime->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
   LOG(WARNING) << "TODO: internal error detail message. errnum=" << errnum;
-  thread->ThrowNewException("Ljava/lang/InternalError;", "errnum=%d", errnum);
+  thread->ThrowNewExceptionF("Ljava/lang/InternalError;", "errnum=%d", errnum);
   thread->DeliverException();
 }
 
@@ -156,7 +155,7 @@
   *sp = runtime->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
   LOG(WARNING) << "TODO: runtime exception detail message. errnum=" << errnum;
-  thread->ThrowNewException("Ljava/lang/RuntimeException;", "errnum=%d", errnum);
+  thread->ThrowNewExceptionF("Ljava/lang/RuntimeException;", "errnum=%d", errnum);
   thread->DeliverException();
 }
 
@@ -166,7 +165,7 @@
   *sp = runtime->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
   LOG(WARNING) << "TODO: no such method exception detail message. method_idx=" << method_idx;
-  thread->ThrowNewException("Ljava/lang/NoSuchMethodError;", "method_idx=%d", method_idx);
+  thread->ThrowNewExceptionF("Ljava/lang/NoSuchMethodError;", "method_idx=%d", method_idx);
   thread->DeliverException();
 }
 
@@ -176,7 +175,7 @@
   Runtime* runtime = Runtime::Current();
   *sp = runtime->GetCalleeSaveMethod();
   thread->SetTopOfStack(sp, 0);
-  thread->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d", size);
+  thread->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d", size);
   thread->DeliverException();
 }
 
@@ -226,7 +225,7 @@
 extern "C" Array* artCheckAndArrayAllocFromCode(uint32_t type_idx, Method* method,
                                                 int32_t component_count) {
   if (component_count < 0) {
-    Thread::Current()->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d",
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
                                          component_count);
     return NULL;  // Failure
   }
@@ -240,11 +239,11 @@
   }
   if (klass->IsPrimitive() && !klass->IsPrimitiveInt()) {
     if (klass->IsPrimitiveLong() || klass->IsPrimitiveDouble()) {
-      Thread::Current()->ThrowNewException("Ljava/lang/RuntimeException;",
+      Thread::Current()->ThrowNewExceptionF("Ljava/lang/RuntimeException;",
           "Bad filled array request for type %s",
           PrettyDescriptor(klass->GetDescriptor()).c_str());
     } else {
-      Thread::Current()->ThrowNewException("Ljava/lang/InternalError;",
+      Thread::Current()->ThrowNewExceptionF("Ljava/lang/InternalError;",
           "Found type %s; filled-new-array not implemented for anything but \'int\'",
           PrettyDescriptor(klass->GetDescriptor()).c_str());
     }
@@ -259,7 +258,7 @@
 // it cannot be resolved, throw an error. If it can, use it to create an array.
 extern "C" Array* artArrayAllocFromCode(uint32_t type_idx, Method* method, int32_t component_count) {
   if (component_count < 0) {
-    Thread::Current()->ThrowNewException("Ljava/lang/NegativeArraySizeException;", "%d",
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NegativeArraySizeException;", "%d",
                                          component_count);
     return NULL;  // Failure
   }
@@ -282,7 +281,7 @@
   if (b->IsAssignableFrom(a)) {
     return 0;  // Success
   } else {
-    Thread::Current()->ThrowNewException("Ljava/lang/ClassCastException;",
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ClassCastException;",
         "%s cannot be cast to %s",
         PrettyDescriptor(a->GetDescriptor()).c_str(),
         PrettyDescriptor(b->GetDescriptor()).c_str());
@@ -300,7 +299,7 @@
   if (component_type->IsAssignableFrom(element_class)) {
     return 0;  // Success
   } else {
-    Thread::Current()->ThrowNewException("Ljava/lang/ArrayStoreException;",
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
         "Cannot store an object of type %s in to an array of type %s",
         PrettyDescriptor(element_class->GetDescriptor()).c_str(),
         PrettyDescriptor(array_class->GetDescriptor()).c_str());
@@ -343,16 +342,15 @@
 extern "C" int artHandleFillArrayDataFromCode(Array* array, const uint16_t* table) {
   DCHECK_EQ(table[0], 0x0300);
   if (array == NULL) {
-    Thread::Current()->ThrowNewException("Ljava/lang/NullPointerException;",
-                                         "null array in fill array");
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
+        "null array in fill array");
     return -1;  // Error
   }
   DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
   uint32_t size = (uint32_t)table[2] | (((uint32_t)table[3]) << 16);
   if (static_cast<int32_t>(size) > array->GetLength()) {
-    Thread::Current()->ThrowNewException("Ljava/lang/ArrayIndexOutOfBoundsException;",
-                                         "failed array fill. length=%d; index=%d",
-                                         array->GetLength(), size);
+    Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
+        "failed array fill. length=%d; index=%d", array->GetLength(), size);
     return -1;  // Error
   }
   uint16_t width = table[1];
@@ -367,8 +365,8 @@
                                                           Method* caller_method) {
   Thread* thread = Thread::Current();
   if (this_object == NULL) {
-    thread->ThrowNewException("Ljava/lang/NullPointerException;",
-                              "null receiver during interface dispatch");
+    thread->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
+        "null receiver during interface dispatch");
     return 0;
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();