diff options
author | 2019-07-25 14:13:23 -0700 | |
---|---|---|
committer | 2019-07-29 20:10:20 +0000 | |
commit | fef91cc973f193d5b3a5a554b4910f0c548c08ad (patch) | |
tree | 6aa735be1e7ff51073eeb15b70a67a2f1c4037d8 | |
parent | e0bbab9fe1b073fecae78ca5d269bd0b2a177b4f (diff) |
ART: Verifier cleanup
Start making the method verifier more independent of externalities.
This will be implemented as incremental changes.
In this CL, replace querrying Runtime::Current() for AoT status
with a flag.
Test: m test-art-host
Change-Id: I91a3ad0208b544f47bb83db96edca6b4f86e5ce5
-rw-r--r-- | runtime/verifier/class_verifier.cc | 1 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.cc | 35 | ||||
-rw-r--r-- | runtime/verifier/method_verifier.h | 12 | ||||
-rw-r--r-- | runtime/verifier/reg_type.cc | 2 |
4 files changed, 37 insertions, 13 deletions
diff --git a/runtime/verifier/class_verifier.cc b/runtime/verifier/class_verifier.cc index aa1b7bd394..ca1e233a4a 100644 --- a/runtime/verifier/class_verifier.cc +++ b/runtime/verifier/class_verifier.cc @@ -154,6 +154,7 @@ FailureKind ClassVerifier::VerifyClass(Thread* self, log_level, /*need_precise_constants=*/ false, api_level, + Runtime::Current()->IsAotCompiler(), &hard_failure_msg); if (result.kind == FailureKind::kHardFailure) { if (failure_data.kind == FailureKind::kHardFailure) { diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index 01be7565c7..75a0a11ec2 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -166,6 +166,7 @@ class MethodVerifier final : public ::art::verifier::MethodVerifier { bool verify_to_dump, bool allow_thread_suspension, bool fill_register_lines_, + bool aot_mode, uint32_t api_level) REQUIRES_SHARED(Locks::mutator_lock_); @@ -716,6 +717,7 @@ MethodVerifier<kVerifierDebug>::MethodVerifier(Thread* self, bool verify_to_dump, bool allow_thread_suspension, bool fill_register_lines, + bool aot_mode, uint32_t api_level) : art::verifier::MethodVerifier(self, class_linker, @@ -724,7 +726,8 @@ MethodVerifier<kVerifierDebug>::MethodVerifier(Thread* self, dex_method_idx, can_load_classes, allow_thread_suspension, - allow_soft_failures), + allow_soft_failures, + aot_mode), method_being_verified_(method), method_access_flags_(method_access_flags), return_type_(nullptr), @@ -916,7 +919,7 @@ bool MethodVerifier<kVerifierDebug>::Verify() { InstructionFlags()); // Run through the instructions and see if the width checks out. bool result = ComputeWidthsAndCountOps(); - bool allow_runtime_only_instructions = !Runtime::Current()->IsAotCompiler() || verify_to_dump_; + bool allow_runtime_only_instructions = !IsAotMode() || verify_to_dump_; // Flag instructions guarded by a "try" block and check exception handlers. result = result && ScanTryCatchBlocks(); // Perform static instruction verification. @@ -1590,7 +1593,7 @@ bool MethodVerifier<kVerifierDebug>::VerifyCodeFlow() { const uint16_t registers_size = code_item_accessor_.RegistersSize(); /* Create and initialize table holding register status */ - RegisterTrackingMode base_mode = Runtime::Current()->IsAotCompiler() + RegisterTrackingMode base_mode = IsAotMode() ? kTrackCompilerInterestPoints : kTrackRegsBranches; reg_table_.Init(fill_register_lines_ ? kTrackRegsAll : base_mode, @@ -3478,7 +3481,7 @@ bool MethodVerifier<kVerifierDebug>::CodeFlowVerifyInstruction(uint32_t* start_g } // end - switch (dec_insn.opcode) if (flags_.have_pending_hard_failure_) { - if (Runtime::Current()->IsAotCompiler()) { + if (IsAotMode()) { /* When AOT compiling, check that the last failure is a hard failure */ if (failures_[failures_.size() - 1] != VERIFY_ERROR_BAD_CLASS_HARD) { LOG(ERROR) << "Pending failures:"; @@ -3843,7 +3846,7 @@ bool MethodVerifier<kVerifierDebug>::HandleMoveException(const Instruction* inst handlers_ptr = iterator.EndDataPointer(); } if (unresolved != nullptr) { - if (!Runtime::Current()->IsAotCompiler() && common_super == nullptr) { + if (!IsAotMode() && common_super == nullptr) { // This is an unreachable handler. // We need to post a failure. The compiler currently does not handle unreachable @@ -4805,7 +4808,7 @@ ArtField* MethodVerifier<kVerifierDebug>::GetInstanceField(const RegType& obj_ty // of C1. For resolution to occur the declared class of the field must be compatible with // obj_type, we've discovered this wasn't so, so report the field didn't exist. VerifyError type; - bool is_aot = Runtime::Current()->IsAotCompiler(); + bool is_aot = IsAotMode(); if (is_aot && (field_klass.IsUnresolvedTypes() || obj_type.IsUnresolvedTypes())) { // Compiler & unresolved types involved, retry at runtime. type = VerifyError::VERIFY_ERROR_NO_CLASS; @@ -5142,7 +5145,8 @@ MethodVerifier::MethodVerifier(Thread* self, uint32_t dex_method_idx, bool can_load_classes, bool allow_thread_suspension, - bool allow_soft_failures) + bool allow_soft_failures, + bool aot_mode) : self_(self), arena_stack_(Runtime::Current()->GetArenaPool()), allocator_(&arena_stack_), @@ -5152,7 +5156,8 @@ MethodVerifier::MethodVerifier(Thread* self, dex_method_idx_(dex_method_idx), dex_file_(dex_file), code_item_accessor_(*dex_file, code_item), - flags_({false, false, false, false}), + // TODO: make it designated initialization when we compile as C++20. + flags_({false, false, false, false, aot_mode}), encountered_failure_types_(0), can_load_classes_(can_load_classes), allow_soft_failures_(allow_soft_failures), @@ -5182,6 +5187,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, HardFailLogMode log_level, bool need_precise_constants, uint32_t api_level, + bool aot_mode, std::string* hard_failure_msg) { if (VLOG_IS_ON(verifier_debug)) { return VerifyMethod<true>(self, @@ -5199,6 +5205,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, log_level, need_precise_constants, api_level, + aot_mode, hard_failure_msg); } else { return VerifyMethod<false>(self, @@ -5216,6 +5223,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, log_level, need_precise_constants, api_level, + aot_mode, hard_failure_msg); } } @@ -5236,6 +5244,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, HardFailLogMode log_level, bool need_precise_constants, uint32_t api_level, + bool aot_mode, std::string* hard_failure_msg) { MethodVerifier::FailureData result; uint64_t start_ns = kTimeVerifyMethod ? NanoTime() : 0; @@ -5256,6 +5265,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, /* verify to dump */ false, /* allow_thread_suspension= */ true, /* fill_register_lines= */ false, + aot_mode, api_level); if (verifier.Verify()) { // Verification completed, however failures may be pending that didn't cause the verification @@ -5285,8 +5295,7 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, if (method != nullptr) { if (verifier.HasInstructionThatWillThrow()) { method->SetDontCompile(); - if (Runtime::Current()->IsAotCompiler() && - (callbacks != nullptr) && !callbacks->IsBootImage()) { + if (aot_mode && (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 @@ -5402,6 +5411,7 @@ MethodVerifier* MethodVerifier::CalculateVerificationInfo( /* verify_to_dump= */ false, /* allow_thread_suspension= */ false, /* fill_register_lines= */ true, + Runtime::Current()->IsAotCompiler(), // Just use the verifier at the current skd-version. // This might affect what soft-verifier errors are reported. // Callers can then filter out relevant errors if needed. @@ -5447,6 +5457,7 @@ MethodVerifier* MethodVerifier::VerifyMethodAndDump(Thread* self, /* verify_to_dump= */ true, /* allow_thread_suspension= */ true, /* fill_register_lines= */ false, + Runtime::Current()->IsAotCompiler(), api_level); verifier->Verify(); verifier->DumpFailures(vios->Stream()); @@ -5486,6 +5497,7 @@ void MethodVerifier::FindLocksAtDexPc( /* verify_to_dump= */ false, /* allow_thread_suspension= */ false, /* fill_register_lines= */ false, + Runtime::Current()->IsAotCompiler(), api_level); verifier.interesting_dex_pc_ = dex_pc; verifier.monitor_enter_dex_pcs_ = monitor_enter_dex_pcs; @@ -5523,6 +5535,7 @@ MethodVerifier* MethodVerifier::CreateVerifier(Thread* self, verify_to_dump, allow_thread_suspension, /* fill_register_lines= */ false, + Runtime::Current()->IsAotCompiler(), api_level); } @@ -5558,7 +5571,7 @@ std::ostream& MethodVerifier::Fail(VerifyError error, bool pending_exc) { case VERIFY_ERROR_CLASS_CHANGE: case VERIFY_ERROR_FORCE_INTERPRETER: case VERIFY_ERROR_LOCKING: - if (Runtime::Current()->IsAotCompiler() || !can_load_classes_) { + if (IsAotMode() || !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 diff --git a/runtime/verifier/method_verifier.h b/runtime/verifier/method_verifier.h index f77fa1fca8..14f5b746dc 100644 --- a/runtime/verifier/method_verifier.h +++ b/runtime/verifier/method_verifier.h @@ -198,6 +198,10 @@ class MethodVerifier { return class_linker_; } + bool IsAotMode() const { + return flags_.aot_mode_; + } + protected: MethodVerifier(Thread* self, ClassLinker* class_linker, @@ -206,7 +210,8 @@ class MethodVerifier { uint32_t dex_method_idx, bool can_load_classes, bool allow_thread_suspension, - bool allow_soft_failures) + bool allow_soft_failures, + bool aot_mode) REQUIRES_SHARED(Locks::mutator_lock_); // Verification result for method(s). Includes a (maximum) failure kind, and (the union of) @@ -245,6 +250,7 @@ class MethodVerifier { HardFailLogMode log_level, bool need_precise_constants, uint32_t api_level, + bool aot_mode, std::string* hard_failure_msg) REQUIRES_SHARED(Locks::mutator_lock_); @@ -264,6 +270,7 @@ class MethodVerifier { HardFailLogMode log_level, bool need_precise_constants, uint32_t api_level, + bool aot_mode, std::string* hard_failure_msg) REQUIRES_SHARED(Locks::mutator_lock_); @@ -339,6 +346,9 @@ class MethodVerifier { // A version of the above that is not reset and thus captures if there were *any* throw // failures. bool have_any_pending_runtime_throw_failure_ : 1; + + // Verify in AoT mode? + bool aot_mode_ : 1; } flags_; // Info message log use primarily for verifier diagnostics. diff --git a/runtime/verifier/reg_type.cc b/runtime/verifier/reg_type.cc index b6e05b5db1..2d170307a2 100644 --- a/runtime/verifier/reg_type.cc +++ b/runtime/verifier/reg_type.cc @@ -887,7 +887,7 @@ const RegType& RegType::Merge(const RegType& incoming_type, // When compiling on the host, we rather want to abort to ensure determinism for preopting. // (In that case, it is likely a misconfiguration of dex2oat.) - if (!kIsTargetBuild && Runtime::Current()->IsAotCompiler()) { + if (!kIsTargetBuild && (verifier != nullptr && verifier->IsAotMode())) { LOG(FATAL) << "Could not create class join of " << GetClass()->PrettyClass() << " & " |