Fixes to make all run-tests except 051-thread work.

- Moved exception delivery into common method DeliverException
- Renamed old DeliverException to QuickDeliverException since it is only
  used by quick
- Fixed null checks for arrays returned by GetReference
- Standardized ArrayStoreException error message
- Added additional sleeps to ensure threads stay alive long enough in
  051-thread, and that <clinit> is complete for 084-class-init

Change-Id: I9ca306896a4bd10f453150fcf3965d9750fa0cbd
diff --git a/src/compiler_llvm/runtime_support_llvm.cc b/src/compiler_llvm/runtime_support_llvm.cc
index 371b32a..f01ca9a 100644
--- a/src/compiler_llvm/runtime_support_llvm.cc
+++ b/src/compiler_llvm/runtime_support_llvm.cc
@@ -156,11 +156,7 @@
 void art_throw_exception_from_code(Object* exception)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   Thread* thread = art_get_current_thread_from_code();
-  if (exception == NULL) {
-    thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
-  } else {
-    thread->SetException(static_cast<Throwable*>(exception));
-  }
+  self->DeliverException(static_cast<Throwable*>(exception));
 }
 
 void* art_get_and_clear_exception(Thread* self)
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index e68896a..8c217c7 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -862,7 +862,7 @@
       }
       case Instruction::THROW: {
         Throwable* t = shadow_frame.GetReference(dec_insn.vA)->AsThrowable();
-        self->SetException(t);
+        self->DeliverException(t);
         break;
       }
       case Instruction::GOTO:
@@ -918,12 +918,13 @@
         break;
       }
       case Instruction::FILL_ARRAY_DATA: {
-        Array* array = shadow_frame.GetReference(dec_insn.vA)->AsArray();
-        if (UNLIKELY(array == NULL)) {
+        Object* obj = shadow_frame.GetReference(dec_insn.vA);
+        if (UNLIKELY(obj == NULL)) {
           Thread::Current()->ThrowNewExceptionF("Ljava/lang/NullPointerException;",
               "null array in FILL_ARRAY_DATA");
           break;
         }
+        Array* array = obj->AsArray();
         DCHECK(array->IsArrayInstance() && !array->IsObjectArray());
         uint32_t dex_pc = inst->GetDexPc(insns);
         const Instruction::ArrayDataPayload* payload =
@@ -1023,151 +1024,150 @@
         break;
       }
       case Instruction::AGET_BOOLEAN: {
-        BooleanArray* a = shadow_frame.GetReference(dec_insn.vB)->AsBooleanArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
+        shadow_frame.SetVReg(dec_insn.vA, a->AsBooleanArray()->Get(index));
         break;
       }
       case Instruction::AGET_BYTE: {
-        ByteArray* a = shadow_frame.GetReference(dec_insn.vB)->AsByteArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
+        shadow_frame.SetVReg(dec_insn.vA, a->AsByteArray()->Get(index));
         break;
       }
       case Instruction::AGET_CHAR: {
-        CharArray* a = shadow_frame.GetReference(dec_insn.vB)->AsCharArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
+        shadow_frame.SetVReg(dec_insn.vA, a->AsCharArray()->Get(index));
         break;
       }
       case Instruction::AGET_SHORT: {
-        ShortArray* a = shadow_frame.GetReference(dec_insn.vB)->AsShortArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
+        shadow_frame.SetVReg(dec_insn.vA, a->AsShortArray()->Get(index));
         break;
       }
       case Instruction::AGET: {
-        IntArray* a = shadow_frame.GetReference(dec_insn.vB)->AsIntArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVReg(dec_insn.vA, a->Get(index));
+        shadow_frame.SetVReg(dec_insn.vA, a->AsIntArray()->Get(index));
         break;
       }
       case Instruction::AGET_WIDE:  {
-        LongArray* a = shadow_frame.GetReference(dec_insn.vB)->AsLongArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        shadow_frame.SetVRegLong(dec_insn.vA, a->Get(index));
+        shadow_frame.SetVRegLong(dec_insn.vA, a->AsLongArray()->Get(index));
         break;
       }
       case Instruction::AGET_OBJECT: {
-        ObjectArray<Object>* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray<Object>();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        Object* o = a->Get(index);
-        shadow_frame.SetReferenceAndVReg(dec_insn.vA, o);
+        shadow_frame.SetReferenceAndVReg(dec_insn.vA, a->AsObjectArray<Object>()->Get(index));
         break;
       }
       case Instruction::APUT_BOOLEAN: {
         uint8_t val = shadow_frame.GetVReg(dec_insn.vA);
-        BooleanArray* a = shadow_frame.GetReference(dec_insn.vB)->AsBooleanArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsBooleanArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_BYTE: {
         int8_t val = shadow_frame.GetVReg(dec_insn.vA);
-        ByteArray* a = shadow_frame.GetReference(dec_insn.vB)->AsByteArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsByteArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_CHAR: {
         uint16_t val = shadow_frame.GetVReg(dec_insn.vA);
-        CharArray* a = shadow_frame.GetReference(dec_insn.vB)->AsCharArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsCharArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_SHORT: {
         int16_t val = shadow_frame.GetVReg(dec_insn.vA);
-        ShortArray* a = shadow_frame.GetReference(dec_insn.vB)->AsShortArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsShortArray()->Set(index, val);
         break;
       }
       case Instruction::APUT: {
         int32_t val = shadow_frame.GetVReg(dec_insn.vA);
-        IntArray* a = shadow_frame.GetReference(dec_insn.vB)->AsIntArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsIntArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_WIDE: {
         int64_t val = shadow_frame.GetVRegLong(dec_insn.vA);
-        LongArray* a = shadow_frame.GetReference(dec_insn.vB)->AsLongArray();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsLongArray()->Set(index, val);
         break;
       }
       case Instruction::APUT_OBJECT: {
         Object* val = shadow_frame.GetReference(dec_insn.vA);
-        ObjectArray<Object>* a = shadow_frame.GetReference(dec_insn.vB)->AsObjectArray<Object>();
+        Object* a = shadow_frame.GetReference(dec_insn.vB);
         if (UNLIKELY(a == NULL)) {
           ThrowNullPointerExceptionFromDexPC(shadow_frame.GetMethod(), inst->GetDexPc(insns));
           break;
         }
         int32_t index = shadow_frame.GetVReg(dec_insn.vC);
-        a->Set(index, val);
+        a->AsObjectArray<Object>()->Set(index, val);
         break;
       }
       case Instruction::IGET_BOOLEAN:
@@ -1787,8 +1787,11 @@
     shadow_frame->SetReferenceAndVReg(cur_reg, receiver);
     ++cur_reg;
   } else if (!method->GetDeclaringClass()->IsInitializing()) {
-    Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
-                                                            true, true);
+    if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(method->GetDeclaringClass(),
+                                                                 true, true)) {
+      DCHECK(Thread::Current()->IsExceptionPending());
+      return;
+    }
     CHECK(method->GetDeclaringClass()->IsInitializing());
   }
   const char* shorty = mh.GetShorty();
diff --git a/src/oat/runtime/support_stubs.cc b/src/oat/runtime/support_stubs.cc
index 9e33c43..ac188a8 100644
--- a/src/oat/runtime/support_stubs.cc
+++ b/src/oat/runtime/support_stubs.cc
@@ -347,7 +347,7 @@
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->ThrowNewExceptionF("Ljava/lang/AbstractMethodError;",
                              "abstract method \"%s\"", PrettyMethod(method).c_str());
-  thread->DeliverException();
+  thread->QuickDeliverException();
 }
 #else // ART_USE_LLVM_COMPILER
 extern void ThrowAbstractMethodErrorFromCode(AbstractMethod* method, Thread* thread, AbstractMethod**)
diff --git a/src/oat/runtime/support_throw.cc b/src/oat/runtime/support_throw.cc
index 21adc52..5bf48e4 100644
--- a/src/oat/runtime/support_throw.cc
+++ b/src/oat/runtime/support_throw.cc
@@ -35,7 +35,7 @@
 extern "C" void artDeliverPendingExceptionFromCode(Thread* thread, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  thread->DeliverException();
+  thread->QuickDeliverException();
 }
 
 // Called by generated call to throw an exception.
@@ -50,12 +50,8 @@
    * exception_ in thread and delivering the exception.
    */
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
-  if (exception == NULL) {
-    thread->ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
-  } else {
-    thread->SetException(exception);
-  }
-  thread->DeliverException();
+  thread->DeliverException(exception);
+  thread->QuickDeliverException();
 }
 
 // Called by generated call to throw a NPE exception.
@@ -66,7 +62,7 @@
   uint32_t dex_pc;
   AbstractMethod* throw_method = self->GetCurrentMethod(&dex_pc);
   ThrowNullPointerExceptionFromDexPC(throw_method, dex_pc);
-  self->DeliverException();
+  self->QuickDeliverException();
 }
 
 // Called by generated call to throw an arithmetic divide by zero exception.
@@ -75,7 +71,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->ThrowNewException("Ljava/lang/ArithmeticException;", "divide by zero");
-  thread->DeliverException();
+  thread->QuickDeliverException();
 }
 
 // Called by generated call to throw an array index out of bounds exception.
@@ -85,14 +81,14 @@
   FinishCalleeSaveFrameSetup(thread, sp, Runtime::kSaveAll);
   thread->ThrowNewExceptionF("Ljava/lang/ArrayIndexOutOfBoundsException;",
                              "length=%d; index=%d", limit, index);
-  thread->DeliverException();
+  thread->QuickDeliverException();
 }
 
 extern "C" void artThrowStackOverflowFromCode(Thread* self, AbstractMethod** sp)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
   ThrowStackOverflowError(self);
-  self->DeliverException();
+  self->QuickDeliverException();
 }
 
 extern "C" void artThrowNoSuchMethodFromCode(int32_t method_idx, Thread* self,
@@ -101,7 +97,7 @@
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kSaveAll);
   AbstractMethod* method = self->GetCurrentMethod();
   ThrowNoSuchMethodError(method_idx, method);
-  self->DeliverException();
+  self->QuickDeliverException();
 }
 
 }  // namespace art
diff --git a/src/object.cc b/src/object.cc
index 147b882..210c42d 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1480,7 +1480,7 @@
 
 bool Array::ThrowArrayStoreException(Object* object) const {
   Thread::Current()->ThrowNewExceptionF("Ljava/lang/ArrayStoreException;",
-      "Can't store an element of type %s into an array of type %s",
+      "%s cannot be stored in an array of type %s",
       PrettyTypeOf(object).c_str(), PrettyTypeOf(this).c_str());
   return false;
 }
diff --git a/src/thread.cc b/src/thread.cc
index 8037886..ca57f8a 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1770,7 +1770,7 @@
   const char* last_no_assert_suspension_cause_;
 };
 
-void Thread::DeliverException() {
+void Thread::QuickDeliverException() {
   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
diff --git a/src/thread.h b/src/thread.h
index 4e1f0e7..112db2d 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -319,8 +319,16 @@
     DCHECK(!IsExceptionPending());
   }
 
+  void DeliverException(Throwable* exception) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    if (exception == NULL) {
+      ThrowNewException("Ljava/lang/NullPointerException;", "throw with null exception");
+    } else {
+      SetException(exception);
+    }
+  }
+
   // Find catch block and perform long jump to appropriate exception handle
-  void DeliverException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  void QuickDeliverException() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   Context* GetLongJumpContext();
   void ReleaseLongJumpContext(Context* context) {
diff --git a/test/051-thread/src/Main.java b/test/051-thread/src/Main.java
index ea587af..911c739 100644
--- a/test/051-thread/src/Main.java
+++ b/test/051-thread/src/Main.java
@@ -67,6 +67,10 @@
             synchronized (MyThread.class) {
                 ++mCount;
             }
+            try {
+                sleep(1000);
+            } catch (Exception ex) {
+            }
         }
     }
 }
diff --git a/test/084-class-init/src/Main.java b/test/084-class-init/src/Main.java
index f551dc5..abad1f0 100644
--- a/test/084-class-init/src/Main.java
+++ b/test/084-class-init/src/Main.java
@@ -96,7 +96,7 @@
     static class FieldThread extends Thread {
         public void run() {
             /* allow SlowInit's <clinit> to start */
-            Main.sleep(1000);
+            Main.sleep(5000);
 
             /* collect fields; should delay until class init completes */
             int field0, field1, field2, field3;
@@ -115,7 +115,7 @@
     static class MethodThread extends Thread {
         public void run() {
             /* allow SlowInit's <clinit> to start */
-            Main.sleep(1000);
+            Main.sleep(5000);
 
             /* use a method that shouldn't be accessible yet */
             SlowInit.printMsg("MethodThread message");