diff options
author | 2019-07-10 04:57:58 +0000 | |
---|---|---|
committer | 2019-07-10 04:57:58 +0000 | |
commit | 4a30f89d65efa9b85c34bbd7aa23ea4cd38b920d (patch) | |
tree | 95ad8586ef841a3a5750c24a7780b58bf12cac3c | |
parent | 7a82acc7ee79b198f7b4638a15cb1c3d1625ab6c (diff) |
Revert "ART: Remove VERIFY_ERROR_UNRESOLVED_CATCH"
This reverts commit 7a82acc7ee79b198f7b4638a15cb1c3d1625ab6c.
Reason for revert: NO_CLASS doesn't have the right semantics for the compiler
Bug: 121245951
Change-Id: I8dbeb7fbd6a697fe536535f1c696187041d7fcab
Test: m test-art-host
-rw-r--r-- | runtime/verifier/method_verifier.cc | 115 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 2 | ||||
-rw-r--r-- | runtime/verifier/verifier_enums.h | 3 |
3 files changed, 60 insertions, 60 deletions
diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 8396fe99ef..b644dbae80 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -3829,13 +3829,12 @@ bool MethodVerifier<kVerifierDebug>::HandleMoveException(const Instruction* inst // We need to post a failure. The compiler currently does not handle unreachable // code correctly. - Fail(VERIFY_ERROR_NO_CLASS, /*pending_exc=*/ false) - << "Unresolved catch handler, fail for compiler"; + Fail(VERIFY_ERROR_UNRESOLVED_CATCH) << "Unresolved catch handler, fail for compiler"; return std::make_pair(false, unresolved); } // Soft-fail, but do not handle this with a synthetic throw. - Fail(VERIFY_ERROR_NO_CLASS, /*pending_exc=*/ false) << "Unresolved catch handler"; + Fail(VERIFY_ERROR_UNRESOLVED_CATCH) << "Unresolved catch handler"; if (common_super != nullptr) { unresolved = &unresolved->Merge(*common_super, ®_types_, this); } @@ -5514,72 +5513,70 @@ void MethodVerifier::VisitRoots(RootVisitor* visitor, const RootInfo& root_info) reg_types_.VisitRoots(visitor, root_info); } -std::ostream& MethodVerifier::Fail(VerifyError error, bool pending_exc) { +std::ostream& MethodVerifier::Fail(VerifyError error) { // Mark the error type as encountered. encountered_failure_types_ |= static_cast<uint32_t>(error); - if (pending_exc) { - switch (error) { - case VERIFY_ERROR_NO_CLASS: - case VERIFY_ERROR_NO_FIELD: - case VERIFY_ERROR_NO_METHOD: - case VERIFY_ERROR_ACCESS_CLASS: - case VERIFY_ERROR_ACCESS_FIELD: - case VERIFY_ERROR_ACCESS_METHOD: - case VERIFY_ERROR_INSTANTIATION: - case VERIFY_ERROR_CLASS_CHANGE: - case VERIFY_ERROR_FORCE_INTERPRETER: - case VERIFY_ERROR_LOCKING: - if (Runtime::Current()->IsAotCompiler() || !can_load_classes_) { - // 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 { - // If we fail again at runtime, mark that this instruction would throw and force this - // method to be executed using the interpreter with checks. - flags_.have_pending_runtime_throw_failure_ = true; - - // We need to save the work_line if the instruction wasn't throwing before. Otherwise - // we'll try to merge garbage. - // Note: this assumes that Fail is called before we do any work_line modifications. - // Note: this can fail before we touch any instruction, for the signature of a method. So - // add a check. - if (work_insn_idx_ < dex::kDexNoIndex) { - const Instruction& inst = code_item_accessor_.InstructionAt(work_insn_idx_); - int opcode_flags = Instruction::FlagsOf(inst.Opcode()); - - if ((opcode_flags & Instruction::kThrow) == 0 && - GetInstructionFlags(work_insn_idx_).IsInTry()) { - saved_line_->CopyFromLine(work_line_.get()); - } + switch (error) { + case VERIFY_ERROR_NO_CLASS: + case VERIFY_ERROR_NO_FIELD: + case VERIFY_ERROR_NO_METHOD: + case VERIFY_ERROR_ACCESS_CLASS: + case VERIFY_ERROR_ACCESS_FIELD: + case VERIFY_ERROR_ACCESS_METHOD: + case VERIFY_ERROR_INSTANTIATION: + case VERIFY_ERROR_CLASS_CHANGE: + case VERIFY_ERROR_FORCE_INTERPRETER: + case VERIFY_ERROR_LOCKING: + if (Runtime::Current()->IsAotCompiler() || !can_load_classes_) { + // 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 { + // If we fail again at runtime, mark that this instruction would throw and force this + // method to be executed using the interpreter with checks. + flags_.have_pending_runtime_throw_failure_ = true; + + // We need to save the work_line if the instruction wasn't throwing before. Otherwise we'll + // try to merge garbage. + // Note: this assumes that Fail is called before we do any work_line modifications. + // Note: this can fail before we touch any instruction, for the signature of a method. So + // add a check. + if (work_insn_idx_ < dex::kDexNoIndex) { + const Instruction& inst = code_item_accessor_.InstructionAt(work_insn_idx_); + int opcode_flags = Instruction::FlagsOf(inst.Opcode()); + + if ((opcode_flags & Instruction::kThrow) == 0 && + GetInstructionFlags(work_insn_idx_).IsInTry()) { + saved_line_->CopyFromLine(work_line_.get()); } } - break; - - // Indication that verification should be retried at runtime. - case VERIFY_ERROR_BAD_CLASS_SOFT: - if (!allow_soft_failures_) { - flags_.have_pending_hard_failure_ = true; - } - break; + } + break; - // Hard verification failures at compile time will still fail at runtime, so the class is - // marked as rejected to prevent it from being compiled. - case VERIFY_ERROR_BAD_CLASS_HARD: { + // Indication that verification should be retried at runtime. + case VERIFY_ERROR_BAD_CLASS_SOFT: + if (!allow_soft_failures_) { flags_.have_pending_hard_failure_ = true; - break; } + break; + + // Hard verification failures at compile time will still fail at runtime, so the class is + // marked as rejected to prevent it from being compiled. + case VERIFY_ERROR_BAD_CLASS_HARD: { + flags_.have_pending_hard_failure_ = true; + break; } - } else if (kIsDebugBuild) { - CHECK_NE(error, VERIFY_ERROR_BAD_CLASS_SOFT); - CHECK_NE(error, VERIFY_ERROR_BAD_CLASS_HARD); - } + case VERIFY_ERROR_UNRESOLVED_CATCH: + // Nothing to do, just remember the failure type. + break; + } failures_.push_back(error); std::string location(StringPrintf("%s: [0x%X] ", dex_file_->PrettyMethod(dex_method_idx_).c_str(), work_insn_idx_)); diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index 2b9a4bc64a..e3d0901d3f 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -138,7 +138,7 @@ class MethodVerifier { } // Log a verification failure. - std::ostream& Fail(VerifyError error, bool pending_exc = true); + std::ostream& Fail(VerifyError error); // Log for verification information. ScopedNewLine LogVerifyInfo(); diff --git a/runtime/verifier/verifier_enums.h b/runtime/verifier/verifier_enums.h index 96c98f9924..0e968828f5 100644 --- a/runtime/verifier/verifier_enums.h +++ b/runtime/verifier/verifier_enums.h @@ -94,6 +94,9 @@ enum VerifyError : uint32_t { // (sets a soft fail at compile time). VERIFY_ERROR_LOCKING = 1 << 11, // Could not guarantee balanced locking. This should be // punted to the interpreter with access checks. + VERIFY_ERROR_UNRESOLVED_CATCH = 1 << 12, // Error code necessary to have a synthetic soft fail + // that is not an exception, to let the compiler know + // that there is (unreachable) unverified code. }; std::ostream& operator<<(std::ostream& os, const VerifyError& rhs); |