Add bool to verifier to allow soft failures.

When false, soft failures in the verifier become hard failures. It should
only be false when not compiling, and calling the verifier from the class
linker.

Change-Id: I664e5cbe491784b280aa5bfdb7e7fc0b771814f5
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 7dcd511..cee1881 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -2233,7 +2233,7 @@
   }
   std::string error_msg;
   if (!preverified) {
-    verifier_failure = verifier::MethodVerifier::VerifyClass(klass, error_msg);
+    verifier_failure = verifier::MethodVerifier::VerifyClass(klass, error_msg, Runtime::Current()->IsCompiler());
   }
   if (preverified || verifier_failure != verifier::MethodVerifier::kHardFailure) {
     if (!preverified && verifier_failure != verifier::MethodVerifier::kNoFailure) {
diff --git a/src/compiler/driver/compiler_driver.cc b/src/compiler/driver/compiler_driver.cc
index f08e629..9595ad9 100644
--- a/src/compiler/driver/compiler_driver.cc
+++ b/src/compiler/driver/compiler_driver.cc
@@ -1216,7 +1216,7 @@
     if (verifier::MethodVerifier::VerifyClass(manager->GetDexFile(),
                                               dex_cache,
                                               soa.Decode<mirror::ClassLoader*>(manager->GetClassLoader()),
-                                              class_def_index, error_msg) ==
+                                              class_def_index, error_msg, true) ==
                                                   verifier::MethodVerifier::kHardFailure) {
       const DexFile::ClassDef& class_def = manager->GetDexFile()->GetClassDef(class_def_index);
       LOG(ERROR) << "Verification failed on class "
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 12e93db..cba079a 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -584,7 +584,7 @@
       mirror::ClassLoader* class_loader = NULL;
       verifier.reset(new verifier::MethodVerifier(dex_file, dex_cache, class_loader, class_def_idx,
                                                   code_item, dex_method_idx, NULL,
-                                                  method_access_flags, true));
+                                                  method_access_flags, true, true));
       verifier->Verify();
       verified_dex_file = dex_file;
       verified_dex_method_idx = dex_method_idx;
diff --git a/src/thread.cc b/src/thread.cc
index 5eb7373..e6c32ca 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -1763,7 +1763,7 @@
     ShadowFrame* new_frame = ShadowFrame::Create(num_regs, NULL, m, new_dex_pc);
     verifier::MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
                                       mh.GetClassDefIndex(), code_item,
-                                      m->GetDexMethodIndex(), m, m->GetAccessFlags(), false);
+                                      m->GetDexMethodIndex(), m, m->GetAccessFlags(), false, true);
     verifier.Verify();
     std::vector<int32_t> kinds = verifier.DescribeVRegs(dex_pc);
     for(uint16_t reg = 0; reg < num_regs; reg++) {
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index 01f5466..2b70e26 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -72,7 +72,8 @@
 }
 
 MethodVerifier::FailureKind MethodVerifier::VerifyClass(const mirror::Class* klass,
-                                                        std::string& error) {
+                                                        std::string& error,
+                                                        bool allow_soft_failures) {
   if (klass->IsVerified()) {
     return kNoFailure;
   }
@@ -100,14 +101,15 @@
     error += dex_file.GetLocation();
     return kHardFailure;
   }
-  return VerifyClass(&dex_file, kh.GetDexCache(), klass->GetClassLoader(), class_def_idx, error);
+  return VerifyClass(&dex_file, kh.GetDexCache(), klass->GetClassLoader(), class_def_idx, error, allow_soft_failures);
 }
 
 MethodVerifier::FailureKind MethodVerifier::VerifyClass(const DexFile* dex_file,
                                                         mirror::DexCache* dex_cache,
                                                         mirror::ClassLoader* class_loader,
                                                         uint32_t class_def_idx,
-                                                        std::string& error) {
+                                                        std::string& error,
+                                                        bool allow_soft_failures) {
   const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_idx);
   const byte* class_data = dex_file->GetClassData(class_def);
   if (class_data == NULL) {
@@ -140,7 +142,7 @@
       Thread::Current()->ClearException();
     }
     MethodVerifier::FailureKind result = VerifyMethod(method_idx, dex_file, dex_cache, class_loader,
-        class_def_idx, it.GetMethodCodeItem(), method, it.GetMemberAccessFlags());
+        class_def_idx, it.GetMethodCodeItem(), method, it.GetMemberAccessFlags(), allow_soft_failures);
     if (result != kNoFailure) {
       if (result == kHardFailure) {
         hard_fail = true;
@@ -175,7 +177,7 @@
       Thread::Current()->ClearException();
     }
     MethodVerifier::FailureKind result = VerifyMethod(method_idx, dex_file, dex_cache, class_loader,
-        class_def_idx, it.GetMethodCodeItem(), method, it.GetMemberAccessFlags());
+        class_def_idx, it.GetMethodCodeItem(), method, it.GetMemberAccessFlags(), allow_soft_failures);
     if (result != kNoFailure) {
       if (result == kHardFailure) {
         hard_fail = true;
@@ -205,12 +207,13 @@
                                                          uint32_t class_def_idx,
                                                          const DexFile::CodeItem* code_item,
                                                          mirror::AbstractMethod* method,
-                                                         uint32_t method_access_flags) {
+                                                         uint32_t method_access_flags,
+                                                         bool allow_soft_failures) {
   MethodVerifier::FailureKind result = kNoFailure;
   uint64_t start_ns = NanoTime();
 
   MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item, method_idx,
-                          method, method_access_flags, true);
+                          method, method_access_flags, true, allow_soft_failures);
   if (verifier.Verify()) {
     // Verification completed, however failures may be pending that didn't cause the verification
     // to hard fail.
@@ -247,7 +250,7 @@
                                          mirror::AbstractMethod* method,
                                          uint32_t method_access_flags) {
   MethodVerifier verifier(dex_file, dex_cache, class_loader, class_def_idx, code_item,
-                          dex_method_idx, method, method_access_flags, true);
+                          dex_method_idx, method, method_access_flags, true, true);
   verifier.Verify();
   verifier.DumpFailures(os);
   os << verifier.info_messages_.str();
@@ -258,8 +261,8 @@
                                mirror::ClassLoader* class_loader, uint32_t class_def_idx,
                                const DexFile::CodeItem* code_item,
                                uint32_t dex_method_idx, mirror::AbstractMethod* method,
-                               uint32_t method_access_flags,
-    bool can_load_classes)
+                               uint32_t method_access_flags, bool can_load_classes,
+                               bool allow_soft_failures)
     : reg_types_(can_load_classes),
       work_insn_idx_(-1),
       dex_method_idx_(dex_method_idx),
@@ -276,7 +279,8 @@
       have_pending_runtime_throw_failure_(false),
       new_instance_count_(0),
       monitor_enter_count_(0),
-      can_load_classes_(can_load_classes) {
+      can_load_classes_(can_load_classes),
+      allow_soft_failures_(allow_soft_failures) {
 }
 
 void MethodVerifier::FindLocksAtDexPc(mirror::AbstractMethod* m, uint32_t dex_pc,
@@ -284,7 +288,7 @@
   MethodHelper mh(m);
   MethodVerifier verifier(&mh.GetDexFile(), mh.GetDexCache(), mh.GetClassLoader(),
                           mh.GetClassDefIndex(), mh.GetCodeItem(), m->GetDexMethodIndex(),
-                          m, m->GetAccessFlags(), false);
+                          m, m->GetAccessFlags(), false, true);
   verifier.interesting_dex_pc_ = dex_pc;
   verifier.monitor_enter_dex_pcs_ = &monitor_enter_dex_pcs;
   verifier.FindLocksAtDexPc();
@@ -354,8 +358,7 @@
       break;
       // Indication that verification should be retried at runtime.
     case VERIFY_ERROR_BAD_CLASS_SOFT:
-      if (!Runtime::Current()->IsCompiler()) {
-        // It is runtime so hard fail.
+      if (!allow_soft_failures_) {
         have_pending_hard_failure_ = true;
       }
       break;
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index ae43162..7570b50 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -144,11 +144,12 @@
   };
 
   /* Verify a class. Returns "kNoFailure" on success. */
-  static FailureKind VerifyClass(const mirror::Class* klass, std::string& error)
+  static FailureKind VerifyClass(const mirror::Class* klass, std::string& error,
+                                 bool allow_soft_failures)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static FailureKind VerifyClass(const DexFile* dex_file, mirror::DexCache* dex_cache,
                                  mirror::ClassLoader* class_loader, uint32_t class_def_idx,
-                                 std::string& error)
+                                 std::string& error, bool allow_soft_failures)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   static void VerifyMethodAndDump(std::ostream& os, uint32_t method_idx, const DexFile* dex_file,
@@ -206,7 +207,7 @@
                  mirror::ClassLoader* class_loader, uint32_t class_def_idx,
                  const DexFile::CodeItem* code_item,
                  uint32_t method_idx, mirror::AbstractMethod* method,
-                 uint32_t access_flags, bool can_load_classes)
+                 uint32_t access_flags, bool can_load_classes, bool allow_soft_failures)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Run verification on the method. Returns true if verification completes and false if the input
@@ -238,7 +239,8 @@
                                   mirror::DexCache* dex_cache,
                                   mirror::ClassLoader* class_loader, uint32_t class_def_idx,
                                   const DexFile::CodeItem* code_item,
-                                  mirror::AbstractMethod* method, uint32_t method_access_flags)
+                                  mirror::AbstractMethod* method, uint32_t method_access_flags,
+                                  bool allow_soft_failures)
           SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   void FindLocksAtDexPc() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
@@ -636,6 +638,10 @@
   size_t monitor_enter_count_;
 
   const bool can_load_classes_;
+
+  // Converts soft failures to hard failures when false. Only false when the compiler isn't
+  // running and the verifier is called from the class linker.
+  const bool allow_soft_failures_;
 };
 std::ostream& operator<<(std::ostream& os, const MethodVerifier::FailureKind& rhs);
 
diff --git a/src/verifier/method_verifier_test.cc b/src/verifier/method_verifier_test.cc
index 5cb3974..611b7c0 100644
--- a/src/verifier/method_verifier_test.cc
+++ b/src/verifier/method_verifier_test.cc
@@ -34,7 +34,7 @@
 
     // Verify the class
     std::string error_msg;
-    ASSERT_TRUE(MethodVerifier::VerifyClass(klass, error_msg) == MethodVerifier::kNoFailure) << error_msg;
+    ASSERT_TRUE(MethodVerifier::VerifyClass(klass, error_msg, true) == MethodVerifier::kNoFailure) << error_msg;
   }
 
   void VerifyDexFile(const DexFile* dex)