ART: Add option to abort dex2oat on hard failure

Add an option that aborts dex2oat when a hard verifier failure occurs.

Bug: 19606409
Change-Id: I53195284e22fe6207274101e85745af763c06271
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index a52a83a..df2b520 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -358,6 +358,7 @@
       image_(image),
       image_classes_(image_classes),
       classes_to_compile_(compiled_classes),
+      had_hard_verifier_failure_(false),
       thread_count_(thread_count),
       stats_(new AOTCompilationStats),
       dedupe_enabled_(true),
@@ -616,6 +617,11 @@
   Verify(class_loader, dex_files, thread_pool, timings);
   VLOG(compiler) << "Verify: " << GetMemoryUsageString(false);
 
+  if (had_hard_verifier_failure_ && GetCompilerOptions().AbortOnHardVerifierFailure()) {
+    LOG(FATAL) << "Had a hard failure verifying all classes, and was asked to abort in such "
+               << "situations. Please check the log.";
+  }
+
   InitializeClasses(class_loader, dex_files, thread_pool, timings);
   VLOG(compiler) << "InitializeClasses: " << GetMemoryUsageString(false);
 
@@ -1839,6 +1845,7 @@
                                                   verifier::MethodVerifier::kHardFailure) {
       LOG(ERROR) << "Verification failed on class " << PrettyDescriptor(descriptor)
                  << " because: " << error_msg;
+      manager->GetCompiler()->SetHadHardVerifierFailure();
     }
   } else if (!SkipClass(jclass_loader, dex_file, klass.Get())) {
     CHECK(klass->IsResolved()) << PrettyClass(klass.Get());
@@ -1848,6 +1855,7 @@
       // ClassLinker::VerifyClass throws, which isn't useful in the compiler.
       CHECK(soa.Self()->IsExceptionPending());
       soa.Self()->ClearException();
+      manager->GetCompiler()->SetHadHardVerifierFailure();
     }
 
     CHECK(klass->IsCompileTimeVerified() || klass->IsErroneous())
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 24b6f17..f949667 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -437,6 +437,10 @@
   // Get memory usage during compilation.
   std::string GetMemoryUsageString(bool extended) const;
 
+  void SetHadHardVerifierFailure() {
+    had_hard_verifier_failure_ = true;
+  }
+
  private:
   // These flags are internal to CompilerDriver for collecting INVOKE resolution statistics.
   // The only external contract is that unresolved method has flags 0 and resolved non-0.
@@ -575,6 +579,8 @@
   // included in the image.
   std::unique_ptr<std::set<std::string>> classes_to_compile_;
 
+  bool had_hard_verifier_failure_;
+
   size_t thread_count_;
 
   class AOTCompilationStats;
diff --git a/compiler/driver/compiler_options.cc b/compiler/driver/compiler_options.cc
index 067e1bd..e436f52 100644
--- a/compiler/driver/compiler_options.cc
+++ b/compiler/driver/compiler_options.cc
@@ -38,6 +38,7 @@
       compile_pic_(false),
       verbose_methods_(nullptr),
       pass_manager_options_(new PassManagerOptions),
+      abort_on_hard_verifier_failure_(false),
       init_failure_output_(nullptr) {
 }
 
@@ -58,7 +59,8 @@
                                  bool compile_pic,
                                  const std::vector<std::string>* verbose_methods,
                                  PassManagerOptions* pass_manager_options,
-                                 std::ostream* init_failure_output
+                                 std::ostream* init_failure_output,
+                                 bool abort_on_hard_verifier_failure
                                  ) :  // NOLINT(whitespace/parens)
     compiler_filter_(compiler_filter),
     huge_method_threshold_(huge_method_threshold),
@@ -77,6 +79,7 @@
     compile_pic_(compile_pic),
     verbose_methods_(verbose_methods),
     pass_manager_options_(pass_manager_options),
+    abort_on_hard_verifier_failure_(abort_on_hard_verifier_failure),
     init_failure_output_(init_failure_output) {
 }
 
diff --git a/compiler/driver/compiler_options.h b/compiler/driver/compiler_options.h
index fecc600..5042c75 100644
--- a/compiler/driver/compiler_options.h
+++ b/compiler/driver/compiler_options.h
@@ -70,7 +70,8 @@
                   bool compile_pic,
                   const std::vector<std::string>* verbose_methods,
                   PassManagerOptions* pass_manager_options,
-                  std::ostream* init_failure_output);
+                  std::ostream* init_failure_output,
+                  bool abort_on_hard_verifier_failure);
 
   CompilerFilter GetCompilerFilter() const {
     return compiler_filter_;
@@ -183,6 +184,10 @@
     return pass_manager_options_.get();
   }
 
+  bool AbortOnHardVerifierFailure() const {
+    return abort_on_hard_verifier_failure_;
+  }
+
  private:
   CompilerFilter compiler_filter_;
   const size_t huge_method_threshold_;
@@ -206,6 +211,10 @@
 
   std::unique_ptr<PassManagerOptions> pass_manager_options_;
 
+  // Abort compilation with an error if we find a class that fails verification with a hard
+  // failure.
+  const bool abort_on_hard_verifier_failure_;
+
   // Log initialization of initialization failures to this stream if not null.
   std::ostream* const init_failure_output_;