Add class status for resolved erroneous classes.

Split the old ambiguous status mirror::Class::kStatusError
into kStatusErrorUnresolved and kStatusErrorResolved. Once
a class has been resolved, IsResolved() shall return true
even if the class later becomes erroneous. Allow returning
erroneous class from ClassLinker::EnsureResolved() if it has
been previously resolved. This allows consistent behavior
for retrieving classes, immune to multi-threaded races and
multi-dex weirdness. It also allows JVMTI to properly report
"prepared" (i.e. resolved) classes that are also erroneous.

The new behavior is consistent with the RI.

Add regression tests to 008-exceptions for inconsistent
behavior for multi-dex retrieval of erroneous resolved class
(wrapping or not wrapping the old exception based on which
dex file is used for lookup) and for a CHECK(IsResolved())
crash in ClassLinker::LoadSuperAndInterfaces() (without any
tests for similar checks that could have previously failed
only due to extremely unlikely race conditions; these should
now also be fixed).

Inconsistency still remains for class verification as shown
by the new exceptionsForSuperClassInitFailure() test in
008-exceptions, where interpreter and Optimizing still
cause different exceptions to be thrown.

Note: This is partially changing behavior implemented for
bug 28787733. Since we allow the class loader to retrieve an
erroneous resolved class, the ExceptionInInitializerError is
not thrown at all from VMClassLoader_findLoadedClass(), so
there is nothing to wrap in ClassNotFoundException.

Test: m test-art-host
Bug: 30627598
Bug: 28787733
Change-Id: I86cdca00f35a0d6221d2559e3026ac0428a3613c
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 9964b73..f08d4da 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -115,7 +115,9 @@
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   bool class_linker_initialized = class_linker != nullptr && class_linker->IsInitialized();
   if (LIKELY(class_linker_initialized)) {
-    if (UNLIKELY(new_status <= old_status && new_status != kStatusError &&
+    if (UNLIKELY(new_status <= old_status &&
+                 new_status != kStatusErrorUnresolved &&
+                 new_status != kStatusErrorResolved &&
                  new_status != kStatusRetired)) {
       LOG(FATAL) << "Unexpected change back of class status for " << h_this->PrettyClass()
                  << " " << old_status << " -> " << new_status;
@@ -127,10 +129,12 @@
             << h_this->PrettyClass() << " " << old_status << " -> " << new_status;
     }
   }
-  if (UNLIKELY(new_status == kStatusError)) {
-    CHECK_NE(h_this->GetStatus(), kStatusError)
+  if (UNLIKELY(IsErroneous(new_status))) {
+    CHECK(!h_this->IsErroneous())
         << "Attempt to set as erroneous an already erroneous class "
-        << h_this->PrettyClass();
+        << h_this->PrettyClass()
+        << " old_status: " << old_status << " new_status: " << new_status;
+    CHECK_EQ(new_status == kStatusErrorResolved, old_status >= kStatusResolved);
     if (VLOG_IS_ON(class_linker)) {
       LOG(ERROR) << "Setting " << h_this->PrettyDescriptor() << " to erroneous.";
       if (self->IsExceptionPending()) {
@@ -177,7 +181,7 @@
       // Class is a temporary one, ensure that waiters for resolution get notified of retirement
       // so that they can grab the new version of the class from the class linker's table.
       CHECK_LT(new_status, kStatusResolved) << h_this->PrettyDescriptor();
-      if (new_status == kStatusRetired || new_status == kStatusError) {
+      if (new_status == kStatusRetired || new_status == kStatusErrorUnresolved) {
         h_this->NotifyAll(self);
       }
     } else {
@@ -305,7 +309,7 @@
     }
     if (h_this->NumStaticFields() > 0) {
       os << "  static fields (" << h_this->NumStaticFields() << " entries):\n";
-      if (h_this->IsResolved() || h_this->IsErroneous()) {
+      if (h_this->IsResolved()) {
         for (size_t i = 0; i < h_this->NumStaticFields(); ++i) {
           os << StringPrintf("    %2zd: %s\n", i,
                              ArtField::PrettyField(h_this->GetStaticField(i)).c_str());
@@ -316,7 +320,7 @@
     }
     if (h_this->NumInstanceFields() > 0) {
       os << "  instance fields (" << h_this->NumInstanceFields() << " entries):\n";
-      if (h_this->IsResolved() || h_this->IsErroneous()) {
+      if (h_this->IsResolved()) {
         for (size_t i = 0; i < h_this->NumInstanceFields(); ++i) {
           os << StringPrintf("    %2zd: %s\n", i,
                              ArtField::PrettyField(h_this->GetInstanceField(i)).c_str());