Class::SetStatus(kStatusError) now checks that an exception is pending and uses it to SetVerifyErrorClass

Change-Id: I02f4adc51ac6da88d4969655fa828f93941c4c0a
diff --git a/src/class_linker.cc b/src/class_linker.cc
index ac2f4f1..5687453 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -121,6 +121,7 @@
    */
   LOG(INFO) << "Rejecting re-init on previously-failed class " << PrettyClass(c);
 
+  CHECK(c->IsErroneous()) << PrettyClass(c);
   if (c->GetVerifyErrorClass() != NULL) {
     // TODO: change the verifier to store an _instance_, with a useful detail message?
     ClassHelper ve_ch(c->GetVerifyErrorClass());
@@ -1079,6 +1080,7 @@
     if (!klass->IsResolved() && klass->GetClinitThreadId() == self->GetTid()) {
       self->ThrowNewException("Ljava/lang/ClassCircularityError;",
           PrettyDescriptor(klass).c_str());
+      klass->SetStatus(Class::kStatusError);
       return NULL;
     }
     // Wait for the pending initialization to complete.
@@ -1159,7 +1161,7 @@
     ScopedLocalRef<jobject> class_loader_object(env, AddLocalReference<jobject>(env, class_loader));
     ScopedLocalRef<jobject> result(env, env->CallObjectMethod(class_loader_object.get(), mid,
                                                               class_name_object.get()));
-    if (env->ExceptionOccurred()) {
+    if (env->ExceptionCheck()) {
       // If the ClassLoader threw, pass that exception up.
       return NULL;
     } else if (result.get() == NULL) {
@@ -1208,6 +1210,7 @@
   // Check for a pending exception during load
   Thread* self = Thread::Current();
   if (self->IsExceptionPending()) {
+    klass->SetStatus(Class::kStatusError);
     return NULL;
   }
   ObjectLock lock(klass.get());
@@ -1224,7 +1227,6 @@
   CHECK(!klass->IsLoaded());
   if (!LoadSuperAndInterfaces(klass, dex_file)) {
     // Loading failed.
-    CHECK(self->IsExceptionPending());
     klass->SetStatus(Class::kStatusError);
     lock.NotifyAll();
     return NULL;
@@ -1234,7 +1236,6 @@
   CHECK(!klass->IsResolved());
   if (!LinkClass(klass, NULL)) {
     // Linking failed.
-    CHECK(self->IsExceptionPending());
     klass->SetStatus(Class::kStatusError);
     lock.NotifyAll();
     return NULL;
@@ -1902,8 +1903,9 @@
   CHECK(oat_class.get() != NULL) << descriptor;
   Class::Status status = oat_class->GetStatus();
   if (status == Class::kStatusError) {
-    ThrowEarlierClassFailure(klass);
-    klass->SetVerifyErrorClass(Thread::Current()->GetException()->GetClass());
+    // TODO: include appropriate verify_error_class_ information in oat file for use here.
+    ThrowNoClassDefFoundError("Class failed compile-time verification: %s",
+                              PrettyDescriptor(klass).c_str());
     klass->SetStatus(Class::kStatusError);
     return true;
   }
@@ -2002,7 +2004,7 @@
 
   // Link the fields and virtual methods, creating vtable and iftables
   if (!LinkClass(klass, interfaces)) {
-    DCHECK(Thread::Current()->IsExceptionPending());
+    klass->SetStatus(Class::kStatusError);
     return NULL;
   }
   sfield->SetObject(NULL, throws);    // initialize throws field
@@ -2156,7 +2158,6 @@
     }
 
     if (!ValidateSuperClassDescriptors(klass)) {
-      CHECK(self->IsExceptionPending());
       klass->SetStatus(Class::kStatusError);
       return false;
     }
@@ -2170,7 +2171,7 @@
   uint64_t t0 = NanoTime();
 
   if (!InitializeSuperClass(klass, can_run_clinit)) {
-    CHECK(self->IsExceptionPending());
+    CHECK(klass->IsErroneous());
     return false;
   }
 
@@ -2346,10 +2347,10 @@
       // TODO: check for a pending exception
       if (!super_initialized) {
         if (!can_run_clinit) {
-         // Don't set status to error when we can't run <clinit>.
-         CHECK_EQ(klass->GetStatus(), Class::kStatusInitializing) << PrettyClass(klass);
-         klass->SetStatus(Class::kStatusVerified);
-         return false;
+          // Don't set status to error when we can't run <clinit>.
+          CHECK_EQ(klass->GetStatus(), Class::kStatusInitializing) << PrettyClass(klass);
+          klass->SetStatus(Class::kStatusVerified);
+          return false;
         }
         klass->SetStatus(Class::kStatusError);
         klass->NotifyAll();
@@ -2370,7 +2371,7 @@
   ScopedThreadStateChange tsc(self, Thread::kRunnable);
   bool success = InitializeClass(c, can_run_clinit);
   if (!success) {
-    CHECK(self->IsExceptionPending());
+    CHECK(self->IsExceptionPending()) << PrettyClass(c);
   }
   return success;
 }
@@ -2496,13 +2497,12 @@
   }
   // Verify
   if (super->IsFinal() || super->IsInterface()) {
-    Thread* thread = Thread::Current();
-    thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+    Thread* self = Thread::Current();
+    self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
         "Superclass %s of %s is %s",
         PrettyDescriptor(super).c_str(),
         PrettyDescriptor(klass.get()).c_str(),
         super->IsFinal() ? "declared final" : "an interface");
-    klass->SetVerifyErrorClass(thread->GetException()->GetClass());
     return false;
   }
   if (!klass->CanAccess(super)) {
@@ -2663,12 +2663,11 @@
     DCHECK(interface != NULL);
     if (!interface->IsInterface()) {
       ClassHelper ih(interface);
-      Thread* thread = Thread::Current();
-      thread->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
+      Thread* self = Thread::Current();
+      self->ThrowNewExceptionF("Ljava/lang/IncompatibleClassChangeError;",
           "Class %s implements non-interface class %s",
           PrettyDescriptor(klass.get()).c_str(),
           PrettyDescriptor(ih.GetDescriptor()).c_str());
-      klass->SetVerifyErrorClass(thread->GetException()->GetClass());
       return false;
     }
     // Check if interface is already in iftable