Classes that hard fail compile-time verification are now marked error.

They were being marked "not ready" before, which would still cause the
verifier to check them at runtime, even though they were never compiled.

Change-Id: Ic29cc4239cb163e5093b3fb22afa6970205caea4
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 3c52370..2ee8bd8 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2066,14 +2066,20 @@
   Class::Status oat_file_class_status(Class::kStatusNotReady);
   bool preverified = VerifyClassUsingOatFile(dex_file, klass, oat_file_class_status);
   verifier::MethodVerifier::FailureKind verifier_failure = verifier::MethodVerifier::kNoFailure;
+  if (oat_file_class_status == Class::kStatusError) {
+    LOG(WARNING) << "Skipping runtime verification of erroneous class " << PrettyDescriptor(klass)
+                 << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8();
+    error_msg = "Rejecting class ";
+    error_msg += PrettyDescriptor(klass);
+    error_msg += " because it failed compile-time verification";
+    Thread::Current()->ThrowNewException("Ljava/lang/VerifyError;", error_msg.c_str());
+    klass->SetStatus(Class::kStatusError);
+    return;
+  }
   if (!preverified) {
     verifier_failure = verifier::MethodVerifier::VerifyClass(klass, error_msg);
   }
   if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
-    if (!preverified && oat_file_class_status == Class::kStatusError) {
-      LOG(FATAL) << "Verification failed hard on class " << PrettyDescriptor(klass)
-                 << " at compile time, but succeeded at runtime! The verifier must be broken.";
-    }
     if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
       LOG(WARNING) << "Soft verification failure in class " << PrettyDescriptor(klass)
           << " in " << klass->GetDexCache()->GetLocation()->ToModifiedUtf8()
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index ce15368..a7951f3 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -26,6 +26,7 @@
 #include "scoped_thread_state_change.h"
 #include "space.h"
 #include "stl_util.h"
+#include "verifier/method_verifier.h"
 
 namespace art {
 
@@ -129,10 +130,16 @@
         num_methods = num_direct_methods + num_virtual_methods;
       }
 
-      CompiledClass* compiled_class =
-          compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
-      Class::Status status =
-          (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
+      Compiler::ClassReference class_ref = Compiler::ClassReference(dex_file, class_def_index);
+      CompiledClass* compiled_class = compiler_->GetCompiledClass(class_ref);
+      Class::Status status;
+      if (compiled_class != NULL) {
+        status = compiled_class->GetStatus();
+      } else if (verifier::MethodVerifier::IsClassRejected(class_ref)) {
+        status = Class::kStatusError;
+      } else {
+        status = Class::kStatusNotReady;
+      }
 
       OatClass* oat_class = new OatClass(status, num_methods);
       oat_classes_.push_back(oat_class);
@@ -296,10 +303,16 @@
 
 #if !defined(NDEBUG) && !defined(ART_USE_LLVM_COMPILER)
     // We expect GC maps except when the class hasn't been verified or the method is native
-    CompiledClass* compiled_class =
-        compiler_->GetCompiledClass(Compiler::MethodReference(dex_file, class_def_index));
-    Class::Status status =
-        (compiled_class != NULL) ? compiled_class->GetStatus() : Class::kStatusNotReady;
+    Compiler::ClassReference class_ref = Compiler::ClassReference(dex_file, class_def_index);
+    CompiledClass* compiled_class = compiler_->GetCompiledClass(class_ref);
+    Class::Status status;
+    if (compiled_class != NULL) {
+      status = compiled_class->GetStatus();
+    } else if (verifier::MethodVerifier::IsClassRejected(class_ref)) {
+      status = Class::kStatusError;
+    } else {
+      status = Class::kStatusNotReady;
+    }
     CHECK(gc_map_size != 0 || is_native || status < Class::kStatusVerified)
         << &gc_map << " " << gc_map_size << " " << (is_native ? "true" : "false") << " " << (status < Class::kStatusVerified) << " " << status << " " << PrettyMethod(method_idx, *dex_file);
 #endif