Prevent exception bugs in class linker

There were some places that could throw exceptions but still succeed.
This caused the allocation entrypoints to occasionally allocate a
heap object with a pending exception.
Also added some additional AssertNoExceptionPending.

Bug: 17164348

Change-Id: Ic6dd3b0cce9955349176503dd7f6c3da7ab0a6f1
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index c2a3ab7..e7a645e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -2065,6 +2065,7 @@
     }
     return nullptr;
   }
+  self->AssertNoPendingException();
   CHECK(new_class != nullptr) << descriptor;
   CHECK(new_class->IsResolved()) << descriptor;
 
@@ -3808,6 +3809,8 @@
           CHECK_EQ(klass->GetStatus(), mirror::Class::kStatusRetryVerificationAtRuntime);
         }
         return false;
+      } else {
+        self->AssertNoPendingException();
       }
     }
 
@@ -3817,6 +3820,10 @@
     // invocation of InitializeClass will not be responsible for
     // running <clinit> and will return.
     if (klass->GetStatus() == mirror::Class::kStatusInitializing) {
+      // Could have got an exception during verification.
+      if (self->IsExceptionPending()) {
+        return false;
+      }
       // We caught somebody else in the act; was it us?
       if (klass->GetClinitThreadId() == self->GetTid()) {
         // Yes. That's fine. Return so we can continue initializing.
@@ -4018,9 +4025,17 @@
 bool ClassLinker::EnsureInitialized(Handle<mirror::Class> c, bool can_init_fields,
                                     bool can_init_parents) {
   DCHECK(c.Get() != nullptr);
-  const bool success = c->IsInitialized() || InitializeClass(c, can_init_fields, can_init_parents);
-  if (!success && can_init_fields && can_init_parents) {
-    CHECK(Thread::Current()->IsExceptionPending()) << PrettyClass(c.Get());
+  if (c->IsInitialized()) {
+    return true;
+  }
+  const bool success = InitializeClass(c, can_init_fields, can_init_parents);
+  Thread* self = Thread::Current();
+  if (!success) {
+    if (can_init_fields && can_init_parents) {
+      CHECK(self->IsExceptionPending()) << PrettyClass(c.Get());
+    }
+  } else {
+    self->AssertNoPendingException();
   }
   return success;
 }
diff --git a/runtime/entrypoints/entrypoint_utils-inl.h b/runtime/entrypoints/entrypoint_utils-inl.h
index af71c19..ccbedc0 100644
--- a/runtime/entrypoints/entrypoint_utils-inl.h
+++ b/runtime/entrypoints/entrypoint_utils-inl.h
@@ -47,6 +47,8 @@
     if (klass == NULL) {
       DCHECK(self->IsExceptionPending());
       return nullptr;  // Failure
+    } else {
+      DCHECK(!self->IsExceptionPending());
     }
   }
   if (kAccessCheck) {
@@ -79,6 +81,8 @@
     if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(h_klass, true, true)) {
       DCHECK(self->IsExceptionPending());
       return nullptr;  // Failure
+    } else {
+      DCHECK(!self->IsExceptionPending());
     }
     return h_klass.Get();
   }