From faf459e5decdfcf6dd7844947898beefe31e6435 Mon Sep 17 00:00:00 2001 From: jeffhao Date: Fri, 31 Aug 2012 15:32:47 -0700 Subject: Verifier no longer checks dead code after failing instruction at runtime. When a failure is detected by the verifier at runtime, the code following the failing instruction is unreachable, and is no longer checked. This prevents further failures from causing the whole class to be thrown out. OTP is working again. Change-Id: I143a76370a2bc9998df526b03219b3ae40a77093 --- src/verifier/method_verifier.cc | 24 ++++++++++++++++-------- src/verifier/method_verifier.h | 5 +++++ 2 files changed, 21 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc index 30bee66d1d..55d537c81c 100644 --- a/src/verifier/method_verifier.cc +++ b/src/verifier/method_verifier.cc @@ -333,6 +333,7 @@ MethodVerifier::MethodVerifier(const DexFile* dex_file, DexCache* dex_cache, interesting_dex_pc_(-1), monitor_enter_dex_pcs_(NULL), have_pending_hard_failure_(false), + have_pending_runtime_throw_failure_(false), new_instance_count_(0), monitor_enter_count_(0) { } @@ -396,14 +397,18 @@ std::ostream& MethodVerifier::Fail(VerifyError error) { case VERIFY_ERROR_ACCESS_METHOD: case VERIFY_ERROR_INSTANTIATION: case VERIFY_ERROR_CLASS_CHANGE: - // If we're optimistically running verification at compile time, turn NO_xxx, ACCESS_xxx, - // class change and instantiation errors into soft verification errors so that we re-verify - // at runtime. We may fail to find or to agree on access because of not yet available class - // loaders, or class loaders that will differ at runtime. In these cases, we don't want to - // affect the soundness of the code being compiled. Instead, the generated code runs "slow - // paths" that dynamically perform the verification and cause the behavior to be that akin - // to an interpreter. - error = VERIFY_ERROR_BAD_CLASS_SOFT; + if (Runtime::Current()->IsCompiler()) { + // If we're optimistically running verification at compile time, turn NO_xxx, ACCESS_xxx, + // class change and instantiation errors into soft verification errors so that we re-verify + // at runtime. We may fail to find or to agree on access because of not yet available class + // loaders, or class loaders that will differ at runtime. In these cases, we don't want to + // affect the soundness of the code being compiled. Instead, the generated code runs "slow + // paths" that dynamically perform the verification and cause the behavior to be that akin + // to an interpreter. + error = VERIFY_ERROR_BAD_CLASS_SOFT; + } else { + have_pending_runtime_throw_failure_ = true; + } break; // Indication that verification should be retried at runtime. case VERIFY_ERROR_BAD_CLASS_SOFT: @@ -2265,6 +2270,9 @@ bool MethodVerifier::CodeFlowVerifyInstruction(uint32_t* start_guess) { /* immediate failure, reject class */ info_messages_ << "Rejecting opcode " << inst->DumpString(dex_file_); return false; + } else if (have_pending_runtime_throw_failure_) { + /* slow path will throw, mark following code as unreachable */ + opcode_flags = Instruction::kThrow; } /* * If we didn't just set the result register, clear it out. This ensures that you can only use diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h index 3e3154b773..244f1f8720 100644 --- a/src/verifier/method_verifier.h +++ b/src/verifier/method_verifier.h @@ -649,6 +649,11 @@ class MethodVerifier { std::vector failure_messages_; // Is there a pending hard failure? bool have_pending_hard_failure_; + // Is there a pending runtime throw failure? A runtime throw failure is when an instruction + // would fail at runtime throwing an exception. Such an instruction causes the following code + // to be unreachable. This is set by Fail and used to ensure we don't process unreachable + // instructions that would hard fail the verification. + bool have_pending_runtime_throw_failure_; // Info message log use primarily for verifier diagnostics. std::ostringstream info_messages_; -- cgit v1.2.3-59-g8ed1b