From e82d04b37415974cfd85be881f50656610890daf Mon Sep 17 00:00:00 2001 From: Vladimir Marko Date: Mon, 17 Feb 2025 08:55:37 +0000 Subject: Optimizing: Speed up `HInstruction::Add{,Env}UseAt()`. Avoid three dependent loads to fetch the allocator on the hot paths. Inline the `FixupUserRecordsAfter*UseInsertion()` loop and use the fact that it's known to execute exactly one or two iterations. Test: m test-art-host-gtest Test: testrunner.py --host --optimizing Bug: 181943478 Change-Id: I7fd4d48caebc6aeb13fb9a9f8146a06129c72b2e --- compiler/optimizing/instruction_builder.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'compiler/optimizing/instruction_builder.cc') diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 1f2628c8ec..74880463c3 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -305,7 +305,7 @@ void HInstructionBuilder::InitializeInstruction(HInstruction* instruction) { graph_->GetArtMethod(), instruction->GetDexPc(), instruction); - environment->CopyFrom(ArrayRef(*current_locals_)); + environment->CopyFrom(allocator_, ArrayRef(*current_locals_)); instruction->SetRawEnvironment(environment); } } -- cgit v1.2.3-59-g8ed1b From b03ab575b9acb3fd73861d5d0a7719dcd0a6322a Mon Sep 17 00:00:00 2001 From: Nicolas Geoffray Date: Mon, 17 Feb 2025 14:18:17 +0000 Subject: Only locking error and runtime throws should retrigger verification. This ensures the stability of the vdex file. Test: 412-new-array Change-Id: I73a6be0a46b6eb184ea127de720bfaf7104f3777 --- compiler/optimizing/instruction_builder.cc | 2 -- runtime/verifier/method_verifier.cc | 25 +++++-------------------- runtime/verifier/verifier_compiler_binding.h | 19 ++++++++----------- 3 files changed, 13 insertions(+), 33 deletions(-) (limited to 'compiler/optimizing/instruction_builder.cc') diff --git a/compiler/optimizing/instruction_builder.cc b/compiler/optimizing/instruction_builder.cc index 74880463c3..8cc79c2424 100644 --- a/compiler/optimizing/instruction_builder.cc +++ b/compiler/optimizing/instruction_builder.cc @@ -2554,8 +2554,6 @@ bool HInstructionBuilder::BuildFilledNewArray(uint32_t dex_pc, char primitive = descriptor[1]; if (primitive != 'I' && primitive != 'L' && primitive != '[') { DCHECK(primitive != 'J' && primitive != 'D'); // Rejected by the verifier. - // FIXME: Why do we JIT compile a method with `VERIFY_ERROR_FILLED_NEW_ARRAY` when - // `CanCompilerHandleVerificationFailure(VERIFY_ERROR_FILLED_NEW_ARRAY)` returns false? MaybeRecordStat(compilation_stats_, MethodCompilationStat::kNotCompiledMalformedOpcode); return false; } diff --git a/runtime/verifier/method_verifier.cc b/runtime/verifier/method_verifier.cc index fce0b2b374..91e46365cf 100644 --- a/runtime/verifier/method_verifier.cc +++ b/runtime/verifier/method_verifier.cc @@ -65,6 +65,7 @@ #include "stack.h" #include "vdex_file.h" #include "verifier/method_verifier.h" +#include "verifier_compiler_binding.h" #include "verifier_deps.h" namespace art HIDDEN { @@ -5587,25 +5588,6 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, } } -// Return whether the runtime knows how to execute a method without needing to -// re-verify it at runtime (and therefore save on first use of the class). -// The AOT/JIT compiled code is not affected. -static inline bool CanRuntimeHandleVerificationFailure(uint32_t encountered_failure_types) { - constexpr uint32_t unresolved_mask = - verifier::VerifyError::VERIFY_ERROR_UNRESOLVED_TYPE_CHECK | - verifier::VerifyError::VERIFY_ERROR_NO_CLASS | - verifier::VerifyError::VERIFY_ERROR_CLASS_CHANGE | - verifier::VerifyError::VERIFY_ERROR_INSTANTIATION | - verifier::VerifyError::VERIFY_ERROR_FILLED_NEW_ARRAY | - verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS | - verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD | - verifier::VerifyError::VERIFY_ERROR_NO_METHOD | - verifier::VerifyError::VERIFY_ERROR_NO_FIELD | - verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD | - verifier::VerifyError::VERIFY_ERROR_RUNTIME_THROW; - return (encountered_failure_types & (~unresolved_mask)) == 0; -} - template MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, ArenaPool* arena_pool, @@ -5650,13 +5632,16 @@ MethodVerifier::FailureData MethodVerifier::VerifyMethod(Thread* self, LOG(INFO) << verifier.InfoMessages().view(); verifier.Dump(LOG_STREAM(INFO)); } - if (CanRuntimeHandleVerificationFailure(verifier.encountered_failure_types_)) { + if (CanCompilerHandleVerificationFailure(verifier.encountered_failure_types_)) { if (verifier.encountered_failure_types_ & VERIFY_ERROR_UNRESOLVED_TYPE_CHECK) { result.kind = FailureKind::kTypeChecksFailure; } else { result.kind = FailureKind::kAccessChecksFailure; } } else { + // If the compiler cannot handle the failure, force a soft failure to + // ensure the class will be re-verified at runtime and the method marked + // as not compilable. result.kind = FailureKind::kSoftFailure; } } diff --git a/runtime/verifier/verifier_compiler_binding.h b/runtime/verifier/verifier_compiler_binding.h index dd96a75975..d492751e64 100644 --- a/runtime/verifier/verifier_compiler_binding.h +++ b/runtime/verifier/verifier_compiler_binding.h @@ -27,17 +27,14 @@ namespace verifier { ALWAYS_INLINE static inline bool CanCompilerHandleVerificationFailure(uint32_t encountered_failure_types) { - constexpr uint32_t unresolved_mask = - verifier::VerifyError::VERIFY_ERROR_NO_CLASS | - verifier::VerifyError::VERIFY_ERROR_UNRESOLVED_TYPE_CHECK | - verifier::VerifyError::VERIFY_ERROR_CLASS_CHANGE | - verifier::VerifyError::VERIFY_ERROR_NO_METHOD | - verifier::VerifyError::VERIFY_ERROR_NO_FIELD | - verifier::VerifyError::VERIFY_ERROR_INSTANTIATION | - verifier::VerifyError::VERIFY_ERROR_ACCESS_CLASS | - verifier::VerifyError::VERIFY_ERROR_ACCESS_FIELD | - verifier::VerifyError::VERIFY_ERROR_ACCESS_METHOD; - return (encountered_failure_types & (~unresolved_mask)) == 0; + // These are and should remain the only two reasons a verified method cannot + // be compiled. The vdex file will mark classes where those methods are defined + // as verify-at-runtime and we should ideally not break that format in adding + // a new kind of failure. + constexpr uint32_t errors_needing_reverification = + verifier::VerifyError::VERIFY_ERROR_RUNTIME_THROW | + verifier::VerifyError::VERIFY_ERROR_LOCKING; + return (encountered_failure_types & errors_needing_reverification) == 0; } } // namespace verifier -- cgit v1.2.3-59-g8ed1b