Fix JIT crash due to unverified dead code

The JIT compiler assumes that it only gets completely verified code. To
work around potential unverified dead code it uses kAccDontBotherCompile
flag set during runtime verification. However, if a class is verified
during a prior dex2oat the flag is not persisted and JIT happily things
that everything is ok.

The simplest fix is to mark classes with potential unverified dex code
as verify at runtime. We only do this for apps and assume that
everything in the boot image is well formed.

Test: m test-art-host
Bug: 31000839
Change-Id: I092d2e9553cd1c577036d78e8563a7a39d6cb7b9
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc
index 7e23c8b..715b237 100644
--- a/runtime/verifier/method_verifier.cc
+++ b/runtime/verifier/method_verifier.cc
@@ -421,6 +421,19 @@
     if (method != nullptr) {
       if (verifier.HasInstructionThatWillThrow()) {
         method->AddAccessFlags(kAccCompileDontBother);
+        if (Runtime::Current()->IsAotCompiler() &&
+            (callbacks != nullptr) && !callbacks->IsBootImage()) {
+          // When compiling apps, make HasInstructionThatWillThrow a soft error to trigger
+          // re-verification at runtime.
+          // The dead code after the throw is not verified and might be invalid. This may cause
+          // the JIT compiler to crash since it assumes that all the code is valid.
+          //
+          // There's a strong assumption that the entire boot image is verified and all its dex
+          // code is valid (even the dead and unverified one). As such this is done only for apps.
+          // (CompilerDriver DCHECKs in VerifyClassVisitor that methods from boot image are
+          // fully verified).
+          result.kind = kSoftFailure;
+        }
       }
       if ((verifier.encountered_failure_types_ & VerifyError::VERIFY_ERROR_LOCKING) != 0) {
         method->AddAccessFlags(kAccMustCountLocks);