Tolerant compilation of classes with missing super classes

Change-Id: If64f25ae36204ab2ea5499f27601696dea9d4016
diff --git a/src/compiler.cc b/src/compiler.cc
index 54793ba..d29e8ca 100644
--- a/src/compiler.cc
+++ b/src/compiler.cc
@@ -105,7 +105,13 @@
       for (size_t i = 0; i < num_static_fields; ++i) {
         DexFile::Field dex_field;
         dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-        class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache, class_loader, true);
+        Field* field = class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache,
+                                                  class_loader, true);
+        if (field == NULL) {
+          Thread* self = Thread::Current();
+          CHECK(self->IsExceptionPending());
+          self->ClearException();
+        }
       }
     }
     if (num_instance_fields != 0) {
@@ -113,7 +119,13 @@
       for (size_t i = 0; i < num_instance_fields; ++i) {
         DexFile::Field dex_field;
         dex_file.dexReadClassDataField(&class_data, &dex_field, &last_idx);
-        class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache, class_loader, false);
+        Field* field = class_linker->ResolveField(dex_file, dex_field.field_idx_, dex_cache,
+                                                  class_loader, false);
+        if (field == NULL) {
+          Thread* self = Thread::Current();
+          CHECK(self->IsExceptionPending());
+          self->ClearException();
+        }
       }
     }
     if (num_direct_methods != 0) {
@@ -121,8 +133,13 @@
       for (size_t i = 0; i < num_direct_methods; ++i) {
         DexFile::Method dex_method;
         dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-        class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache, class_loader,
-                                    true);
+        Method* method = class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache,
+                                                     class_loader, true);
+        if (method == NULL) {
+          Thread* self = Thread::Current();
+          CHECK(self->IsExceptionPending());
+          self->ClearException();
+        }
       }
     }
     if (num_virtual_methods != 0) {
@@ -130,8 +147,13 @@
       for (size_t i = 0; i < num_virtual_methods; ++i) {
         DexFile::Method dex_method;
         dex_file.dexReadClassDataMethod(&class_data, &dex_method, &last_idx);
-        class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache, class_loader,
-                                    false);
+        Method* method = class_linker->ResolveMethod(dex_file, dex_method.method_idx_, dex_cache,
+                                                     class_loader, false);
+        if (method == NULL) {
+          Thread* self = Thread::Current();
+          CHECK(self->IsExceptionPending());
+          self->ClearException();
+        }
       }
     }
   }
@@ -153,10 +175,23 @@
     const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
     const char* descriptor = dex_file.GetClassDescriptor(class_def);
     Class* klass = class_linker->FindClass(descriptor, class_loader);
-    CHECK(klass->IsResolved());
-    CHECK(klass != NULL);
+    if (klass == NULL) {
+      Thread* self = Thread::Current();
+      CHECK(self->IsExceptionPending());
+      self->ClearException();
+      continue;
+    }
+    CHECK(klass->IsResolved()) << PrettyClass(klass);
     class_linker->VerifyClass(klass);
-    CHECK(klass->IsVerified() || klass->IsErroneous());
+    CHECK(klass->IsVerified() || klass->IsErroneous()) << PrettyClass(klass);
+    //CHECK(!Thread::Current()->IsExceptionPending());
+    if (klass->IsErroneous()) {
+      Thread* self = Thread::Current();
+      if (self->IsExceptionPending()) {
+        UNIMPLEMENTED(WARNING) << "Verifier failed to cleanup exceptions internally";
+        self->ClearException();
+      }
+    }
   }
   dex_file.ChangePermissions(PROT_READ);
 }
@@ -212,8 +247,7 @@
     if (klass == NULL) {
       // previous verification error will cause FindClass to throw
       Thread* self = Thread::Current();
-      // CHECK(self->IsExceptionPending());
-      UNIMPLEMENTED(WARNING) << "CHECK for verification error after FindClass " << descriptor;
+      CHECK(self->IsExceptionPending());
       self->ClearException();
     } else {
       CompileClass(klass);