diff options
author | 2025-02-12 10:25:46 +0000 | |
---|---|---|
committer | 2025-02-17 04:47:25 -0800 | |
commit | 474e99956e8be96e84404b5be6ad075bb5cb6b79 (patch) | |
tree | 9c0b2b1d686c906912cbe842b18a9100258d0c10 /runtime/class_linker.cc | |
parent | e7776615ea6b005051219845a143231b5bb1e4f8 (diff) |
Refactor `ArtMethod` entrypoint initialization.
Introduce `Instrumentation::ReinitializeMethodsCode()` for
the cases where we want to reset the entrypoint after the
method has already been initialized. Keep the old function
`Instrumentation::InitializeMethodsCode()` exclusively for
the initialization of a newly loaded method's entrypoint,
split out the work that can be done in suspended state and
remove any unnecessary work. For example, we do not use
the Nterp entrypoint until the class has been verified, so
all the Nterp checks can be removed.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 329196666
Change-Id: I1d0c195b0118fe50434d496f56346a9f744fbaf7
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r-- | runtime/class_linker.cc | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 078a5c8383..6418c1a885 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -96,6 +96,7 @@ #include "hidden_api.h" #include "imt_conflict_table.h" #include "imtable-inl.h" +#include "instrumentation-inl.h" #include "intern_table-inl.h" #include "interpreter/interpreter.h" #include "interpreter/mterp/nterp.h" @@ -228,7 +229,7 @@ static void UpdateClassAfterVerification(Handle<mirror::Class> klass, if (interpreter::CanRuntimeUseNterp()) { for (ArtMethod& m : klass->GetMethods(pointer_size)) { if (class_linker->IsQuickToInterpreterBridge(m.GetEntryPointFromQuickCompiledCode())) { - runtime->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/nullptr); + runtime->GetInstrumentation()->ReinitializeMethodsCode(&m); } } } @@ -3958,7 +3959,7 @@ class ClassLinker::LoadClassHelper { PointerSize pointer_size, LengthPrefixedArray<ArtField>* fields, LengthPrefixedArray<ArtMethod>* methods) - REQUIRES_SHARED(Locks::mutator_lock_); + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Roles::uninterruptible_); uint32_t NumFields() const { return dchecked_integral_cast<uint32_t>(fields_.size()); @@ -4003,7 +4004,7 @@ class ClassLinker::LoadClassHelper { template <PointerSize kPointerSize> ALWAYS_INLINE void FillMethods(ObjPtr<mirror::Class> klass, /*out*/ LengthPrefixedArray<ArtMethod>* methods) - REQUIRES_SHARED(Locks::mutator_lock_); + REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Roles::uninterruptible_); Runtime* const runtime_; const DexFile& dex_file_; @@ -4135,28 +4136,29 @@ inline void ClassLinker::LoadClassHelper::LinkCode(ArtMethodData* method, // Method shouldn't have already been linked. DCHECK_EQ(method->entrypoint, nullptr); - if (!ArtMethod::IsInvokable(method->access_flags)) { + uint32_t access_flags = method->access_flags; + if (!ArtMethod::IsInvokable(access_flags)) { method->entrypoint = GetQuickToInterpreterBridge(); occi->SkipAbstract(class_def_method_index); return; } const void* quick_code = occi->GetAndAdvance(class_def_method_index); - if (ArtMethod::IsNative(method->access_flags) && quick_code == nullptr) { + if (ArtMethod::IsNative(access_flags) && quick_code == nullptr) { std::string_view shorty = dex_file_.GetMethodShortyView(method->dex_method_index); - const void* boot_jni_stub = - runtime_->GetClassLinker()->FindBootJniStub(method->access_flags, shorty); + const void* boot_jni_stub = runtime_->GetClassLinker()->FindBootJniStub(access_flags, shorty); if (boot_jni_stub != nullptr) { // Use boot JNI stub if found. quick_code = boot_jni_stub; } } - method->entrypoint = quick_code; + method->entrypoint = + runtime_->GetInstrumentation()->GetInitialEntrypoint(access_flags, quick_code); - if (ArtMethod::IsNative(method->access_flags)) { + if (ArtMethod::IsNative(access_flags)) { // Set up the dlsym lookup stub. Do not go through `UnregisterNative()` // as the extra processing for @CriticalNative is not needed yet. - method->data = ArtMethod::IsCriticalNative(method->access_flags) + method->data = ArtMethod::IsCriticalNative(access_flags) ? GetJniDlsymLookupCriticalStub() : GetJniDlsymLookupStub(); } @@ -4278,8 +4280,12 @@ void ClassLinker::LoadClassHelper::FillMethods(ObjPtr<mirror::Class> klass, DCHECK_EQ(methods_.size(), (methods != nullptr) ? methods->size() : 0u); static constexpr size_t kMethodAlignment = ArtMethod::Alignment(kPointerSize); static constexpr size_t kMethodSize = ArtMethod::Size(kPointerSize); - instrumentation::Instrumentation* instr = - is_aot_compiler_ ? nullptr : runtime_->GetInstrumentation(); + instrumentation::Instrumentation* instr = nullptr; + bool use_stubs = false; + if (!is_aot_compiler_) { + instr = runtime_->GetInstrumentation(); + use_stubs = instr->InitialEntrypointNeedsInstrumentationStubs(); + } for (size_t i = 0, size = methods_.size(); i != size; ++i) { const ArtMethodData& src = methods_[i]; ArtMethod* dst = &methods->At(i, kMethodSize, kMethodAlignment); @@ -4305,12 +4311,12 @@ void ClassLinker::LoadClassHelper::FillMethods(ObjPtr<mirror::Class> klass, dst->SetDataPtrSize(src.data, kPointerSize); if (instr != nullptr) { DCHECK_IMPLIES(dst->IsNative(), dst->GetEntryPointFromJniPtrSize(kPointerSize) == src.data); - if (ArtMethod::IsInvokable(access_flags)) { - instr->InitializeMethodsCode(dst, src.entrypoint); - } else { - DCHECK_EQ(src.entrypoint, GetQuickToInterpreterBridge()); - dst->SetEntryPointFromQuickCompiledCodePtrSize(src.entrypoint, kPointerSize); + const void* entrypoint = src.entrypoint; + if (UNLIKELY(use_stubs)) { + bool is_native = ArtMethod::IsNative(access_flags); + entrypoint = is_native ? GetQuickGenericJniStub() : GetQuickToInterpreterBridge(); } + instr->InitializeMethodsCode(dst, entrypoint, kPointerSize); } } } |