summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/common_compiler_test.cc7
-rw-r--r--dex2oat/driver/compiler_driver_test.cc7
-rw-r--r--openjdkjvmti/events.cc2
-rw-r--r--openjdkjvmti/ti_redefine.cc4
-rw-r--r--runtime/class_linker.cc40
-rw-r--r--runtime/common_runtime_test.cc2
-rw-r--r--runtime/gc/heap.h3
-rw-r--r--runtime/instrumentation-inl.h129
-rw-r--r--runtime/instrumentation.cc39
-rw-r--r--runtime/instrumentation.h21
-rw-r--r--runtime/jit/jit_code_cache.cc10
-rw-r--r--runtime/quick_exception_handler.cc3
-rw-r--r--runtime/runtime.cc6
-rw-r--r--runtime/runtime_callbacks_test.cc2
-rw-r--r--test/common/runtime_state.cc2
15 files changed, 203 insertions, 74 deletions
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index f24406e599..26800637fa 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -32,6 +32,7 @@
#include "driver/compiled_code_storage.h"
#include "driver/compiler_options.h"
#include "jni/java_vm_ext.h"
+#include "instrumentation-inl.h"
#include "interpreter/interpreter.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
@@ -306,7 +307,11 @@ void CommonCompilerTestImpl::CompileMethod(ArtMethod* method) {
storage.GetStackMap(),
storage.GetInstructionSet());
LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
- GetRuntime()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ method_code);
+ instrumentation::Instrumentation* instr = GetRuntime()->GetInstrumentation();
+ const void* entrypoint = instr->GetInitialEntrypoint(method->GetAccessFlags(), method_code);
+ CHECK(!instr->IsForcedInterpretOnly());
+ CHECK(!instr->EntryExitStubsInstalled());
+ instr->UpdateMethodsCode(method, entrypoint);
}
}
diff --git a/dex2oat/driver/compiler_driver_test.cc b/dex2oat/driver/compiler_driver_test.cc
index 7d4c32b25c..5dc6589d53 100644
--- a/dex2oat/driver/compiler_driver_test.cc
+++ b/dex2oat/driver/compiler_driver_test.cc
@@ -31,6 +31,7 @@
#include "dex/dex_file_types.h"
#include "gc/heap.h"
#include "handle_scope-inl.h"
+#include "instrumentation-inl.h"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/dex_cache-inl.h"
@@ -93,7 +94,11 @@ class CompilerDriverTest : public CommonCompilerDriverTest {
LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
}
}
- runtime_->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ method_code);
+ instrumentation::Instrumentation* instr = runtime_->GetInstrumentation();
+ const void* entrypoint = instr->GetInitialEntrypoint(method->GetAccessFlags(), method_code);
+ CHECK(!instr->IsForcedInterpretOnly());
+ CHECK(!instr->EntryExitStubsInstalled());
+ instr->UpdateMethodsCode(method, entrypoint);
}
void MakeDexFileExecutable(jobject class_loader, const DexFile& dex_file) {
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index 31107d08a5..a1e9a3dcf4 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -1251,7 +1251,7 @@ void EventHandler::HandleLocalAccessCapabilityAdded() {
continue;
} else if (!runtime_->GetClassLinker()->IsQuickToInterpreterBridge(code) &&
!runtime_->IsAsyncDeoptimizeable(&m, reinterpret_cast<uintptr_t>(code))) {
- runtime_->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ runtime_->GetInstrumentation()->ReinitializeMethodsCode(&m);
}
}
return true;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index db9ad2417b..8e7885a726 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -2135,7 +2135,7 @@ art::ObjPtr<art::mirror::Class> Redefiner::ClassRedefinition::AllocateNewClassOb
}
// Finish setting up methods.
linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
- driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(m, /* aot_code= */ nullptr);
+ driver_->runtime_->GetInstrumentation()->ReinitializeMethodsCode(m);
m->SetNotIntrinsic();
DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get())
<< m->PrettyMethod()
@@ -2573,7 +2573,7 @@ void Redefiner::ClassRedefinition::UpdateMethods(art::ObjPtr<art::mirror::Class>
CHECK(method_id != nullptr);
uint32_t dex_method_idx = dex_file_->GetIndexForMethodId(*method_id);
method.SetDexMethodIndex(dex_method_idx);
- driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr);
+ driver_->runtime_->GetInstrumentation()->ReinitializeMethodsCode(&method);
if (method.HasCodeItem()) {
method.SetCodeItem(
dex_file_->GetCodeItem(dex_file_->FindCodeItemOffset(class_def, dex_method_idx)));
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);
}
}
}
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index ab7ddbcb25..fba0f1c758 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -412,7 +412,7 @@ void CommonRuntimeTestImpl::SetUpRuntimeOptionsForFillHeap(RuntimeOptions *optio
void CommonRuntimeTestImpl::MakeInterpreted(ObjPtr<mirror::Class> klass) {
PointerSize pointer_size = class_linker_->GetImagePointerSize();
for (ArtMethod& method : klass->GetMethods(pointer_size)) {
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&method, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->ReinitializeMethodsCode(&method);
}
}
diff --git a/runtime/gc/heap.h b/runtime/gc/heap.h
index 5d9fb1b647..7e30c3d14e 100644
--- a/runtime/gc/heap.h
+++ b/runtime/gc/heap.h
@@ -722,8 +722,7 @@ class Heap {
EXPORT bool ObjectIsInBootImageSpace(ObjPtr<mirror::Object> obj) const
REQUIRES_SHARED(Locks::mutator_lock_);
- bool IsInBootImageOatFile(const void* p) const
- REQUIRES_SHARED(Locks::mutator_lock_);
+ bool IsInBootImageOatFile(const void* p) const;
// Get the start address of the boot images if any; otherwise returns 0.
uint32_t GetBootImagesStartAddress() const {
diff --git a/runtime/instrumentation-inl.h b/runtime/instrumentation-inl.h
new file mode 100644
index 0000000000..3b035ea71b
--- /dev/null
+++ b/runtime/instrumentation-inl.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2025 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_INSTRUMENTATION_INL_H_
+#define ART_RUNTIME_INSTRUMENTATION_INL_H_
+
+#include "instrumentation.h"
+
+#include "art_method-inl.h"
+#include "entrypoints/runtime_asm_entrypoints.h"
+#include "gc/heap.h"
+#include "jit/jit.h"
+#include "runtime.h"
+
+namespace art HIDDEN {
+namespace instrumentation {
+
+inline bool Instrumentation::CanUseAotCode(const void* quick_code) {
+ if (quick_code == nullptr) {
+ return false;
+ }
+ Runtime* runtime = Runtime::Current();
+ // For simplicity, we never use AOT code for debuggable.
+ if (runtime->IsJavaDebuggable()) {
+ return false;
+ }
+
+ if (runtime->IsNativeDebuggable()) {
+ DCHECK(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse());
+ // If we are doing native debugging, ignore application's AOT code,
+ // since we want to JIT it (at first use) with extra stackmaps for native
+ // debugging. We keep however all AOT code from the boot image,
+ // since the JIT-at-first-use is blocking and would result in non-negligible
+ // startup performance impact.
+ return runtime->GetHeap()->IsInBootImageOatFile(quick_code);
+ }
+
+ return true;
+}
+
+inline const void* Instrumentation::GetInitialEntrypoint(uint32_t method_access_flags,
+ const void* aot_code) {
+ if (!ArtMethod::IsInvokable(method_access_flags)) {
+ return GetQuickToInterpreterBridge();
+ }
+
+ // Special case if we need an initialization check.
+ if (ArtMethod::NeedsClinitCheckBeforeCall(method_access_flags)) {
+ // If we have code but the method needs a class initialization check before calling that code,
+ // install the resolution stub that will perform the check. It will be replaced by the proper
+ // entry point by `ClassLinker::FixupStaticTrampolines()` after initializing class.
+ // Note: This mimics the logic in image_writer.cc that installs the resolution stub only
+ // if we have compiled code or we can execute nterp, and the method needs a class
+ // initialization check.
+ return (aot_code != nullptr || ArtMethod::IsNative(method_access_flags))
+ ? GetQuickResolutionStub()
+ : GetQuickToInterpreterBridge();
+ }
+
+ // Use the provided AOT code if possible.
+ if (CanUseAotCode(aot_code)) {
+ return aot_code;
+ }
+
+ // Use default entrypoints.
+ return ArtMethod::IsNative(method_access_flags) ? GetQuickGenericJniStub()
+ : GetQuickToInterpreterBridge();
+}
+
+
+inline bool Instrumentation::InitialEntrypointNeedsInstrumentationStubs() {
+ return IsForcedInterpretOnly() || EntryExitStubsInstalled();
+}
+
+inline void Instrumentation::InitializeMethodsCode(ArtMethod* method,
+ const void* entrypoint,
+ PointerSize pointer_size) {
+ if (kIsDebugBuild) {
+ // Entrypoint should be uninitialized.
+ CHECK(method->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size) == nullptr)
+ << method->PrettyMethod();
+ // We initialize the entrypoint while loading the class, well before the class
+ // is verified and Nterp entrypoint is allowed. We prefer to check for resolved
+ // because a verified class may lose its "verified" status (by becoming erroneous)
+ // but the resolved status is always kept (as "resolved erroneous" if needed).
+ CHECK(!method->GetDeclaringClass()->IsResolved());
+ CHECK_NE(entrypoint, interpreter::GetNterpEntryPoint()) << method->PrettyMethod();
+ if (InitialEntrypointNeedsInstrumentationStubs()) {
+ const void* expected =
+ method->IsNative() ? GetQuickGenericJniStub() : GetQuickToInterpreterBridge();
+ CHECK_EQ(entrypoint, expected) << method->PrettyMethod() << " " << method->IsNative();
+ } else if (method->NeedsClinitCheckBeforeCall()) {
+ if (method->IsNative()) {
+ CHECK_EQ(entrypoint, GetQuickResolutionStub());
+ } else {
+ // We do not have the original `aot_code` to determine which entrypoint to expect.
+ CHECK(entrypoint == GetQuickResolutionStub() ||
+ entrypoint == GetQuickToInterpreterBridge());
+ }
+ } else {
+ bool is_stub = (entrypoint == GetQuickToInterpreterBridge()) ||
+ (entrypoint == GetQuickGenericJniStub()) ||
+ (entrypoint == GetQuickResolutionStub());
+ const void* aot_code = is_stub ? nullptr : entrypoint;
+ const void* initial = GetInitialEntrypoint(method->GetAccessFlags(), aot_code);
+ CHECK_EQ(initial, entrypoint)
+ << method->PrettyMethod() << " 0x" << std::hex << method->GetAccessFlags();
+ }
+ }
+ method->SetEntryPointFromQuickCompiledCodePtrSize(entrypoint, pointer_size);
+}
+
+} // namespace instrumentation
+} // namespace art
+
+#endif // ART_RUNTIME_INSTRUMENTATION_INL_H_
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index ce740da1a8..28c4f35db3 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "instrumentation.h"
+#include "instrumentation-inl.h"
#include <functional>
#include <optional>
@@ -315,37 +315,13 @@ bool Instrumentation::InterpretOnly(ArtMethod* method) REQUIRES_SHARED(Locks::mu
return InterpretOnly() || IsDeoptimized(method);
}
-static bool CanUseAotCode(const void* quick_code)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (quick_code == nullptr) {
- return false;
- }
- Runtime* runtime = Runtime::Current();
- // For simplicity, we never use AOT code for debuggable.
- if (runtime->IsJavaDebuggable()) {
- return false;
- }
-
- if (runtime->IsNativeDebuggable()) {
- DCHECK(runtime->UseJitCompilation() && runtime->GetJit()->JitAtFirstUse());
- // If we are doing native debugging, ignore application's AOT code,
- // since we want to JIT it (at first use) with extra stackmaps for native
- // debugging. We keep however all AOT code from the boot image,
- // since the JIT-at-first-use is blocking and would result in non-negligible
- // startup performance impact.
- return runtime->GetHeap()->IsInBootImageOatFile(quick_code);
- }
-
- return true;
-}
-
static bool CanUseNterp(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
return interpreter::CanRuntimeUseNterp() &&
CanMethodUseNterp(method) &&
method->IsDeclaringClassVerifiedMayBeDead();
}
-static const void* GetOptimizedCodeFor(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
+const void* Instrumentation::GetOptimizedCodeFor(ArtMethod* method) {
DCHECK(!Runtime::Current()->GetInstrumentation()->InterpretOnly(method));
CHECK(method->IsInvokable()) << method->PrettyMethod();
if (method->IsProxyMethod()) {
@@ -378,8 +354,7 @@ static const void* GetOptimizedCodeFor(ArtMethod* method) REQUIRES_SHARED(Locks:
return method->IsNative() ? GetQuickGenericJniStub() : GetQuickToInterpreterBridge();
}
-void Instrumentation::InitializeMethodsCode(ArtMethod* method, const void* aot_code)
- REQUIRES_SHARED(Locks::mutator_lock_) {
+void Instrumentation::ReinitializeMethodsCode(ArtMethod* method) {
if (!method->IsInvokable()) {
DCHECK(method->GetEntryPointFromQuickCompiledCode() == nullptr ||
Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(
@@ -405,7 +380,7 @@ void Instrumentation::InitializeMethodsCode(ArtMethod* method, const void* aot_c
// Note: this mimics the logic in image_writer.cc that installs the resolution
// stub only if we have compiled code or we can execute nterp, and the method needs a class
// initialization check.
- if (aot_code != nullptr || method->IsNative() || CanUseNterp(method)) {
+ if (method->IsNative() || CanUseNterp(method)) {
if (kIsDebugBuild && CanUseNterp(method)) {
// Adds some test coverage for the nterp clinit entrypoint.
UpdateEntryPoints(method, interpreter::GetNterpWithClinitEntryPoint());
@@ -418,12 +393,6 @@ void Instrumentation::InitializeMethodsCode(ArtMethod* method, const void* aot_c
return;
}
- // Use the provided AOT code if possible.
- if (CanUseAotCode(aot_code)) {
- UpdateEntryPoints(method, aot_code);
- return;
- }
-
// We check if the class is verified as we need the slow interpreter for lock verification.
// If the class is not verified, This will be updated in
// ClassLinker::UpdateClassAfterVerification.
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 59e6b29b90..5112f0e789 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -322,8 +322,22 @@ class Instrumentation {
// Returns a string representation of the given entry point.
static std::string EntryPointString(const void* code);
- // Initialize the entrypoint of the method .`aot_code` is the AOT code.
- EXPORT void InitializeMethodsCode(ArtMethod* method, const void* aot_code)
+ // Return the best initial entrypoint of a method, assuming that stubs are not in use.
+ // This function can be called while the thread is suspended.
+ const void* GetInitialEntrypoint(uint32_t method_access_flags, const void* aot_code);
+
+ // Check if the best initial entrypoint needs to be overridden with stubs.
+ bool InitialEntrypointNeedsInstrumentationStubs()
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Roles::uninterruptible_);
+
+ // Initialize the method's entrypoint with aot code or runtime stub.
+ // The caller must check and apply `InitialEntrypointNeedsInstrumentationStubs()`
+ // in the same `Roles::uninterruptible_` section of code.
+ void InitializeMethodsCode(ArtMethod* method, const void* entrypoint, PointerSize pointer_size)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(Roles::uninterruptible_);
+
+ // Reinitialize the entrypoint of the method.
+ EXPORT void ReinitializeMethodsCode(ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_);
// Update the code of a method respecting any installed stubs.
@@ -601,6 +615,9 @@ class Instrumentation {
REQUIRES_SHARED(Locks::mutator_lock_);
private:
+ static bool CanUseAotCode(const void* quick_code);
+ static const void* GetOptimizedCodeFor(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
+
// Update the current instrumentation_level_.
void UpdateInstrumentationLevel(InstrumentationLevel level);
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index a8a03d4fdd..022532a54d 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -871,7 +871,7 @@ bool JitCodeCache::RemoveMethod(ArtMethod* method, bool release_memory) {
return false;
}
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->ReinitializeMethodsCode(method);
return true;
}
@@ -1779,7 +1779,7 @@ void JitCodeCache::InvalidateAllCompiledCode() {
OatQuickMethodHeader::FromCodePointer(data.GetCode());
for (ArtMethod* method : data.GetMethods()) {
if (method->GetEntryPointFromQuickCompiledCode() == method_header->GetEntryPoint()) {
- instr->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
+ instr->ReinitializeMethodsCode(method);
}
}
}
@@ -1789,7 +1789,7 @@ void JitCodeCache::InvalidateAllCompiledCode() {
if (UNLIKELY(meth->IsObsolete())) {
linker->SetEntryPointsForObsoleteMethod(meth);
} else {
- instr->InitializeMethodsCode(meth, /*aot_code=*/ nullptr);
+ instr->ReinitializeMethodsCode(meth);
}
}
osr_code_map_.clear();
@@ -1803,7 +1803,7 @@ void JitCodeCache::InvalidateAllCompiledCode() {
if (entry.method->IsPreCompiled()) {
entry.method->ClearPreCompiled();
}
- instr->InitializeMethodsCode(entry.method, /*aot_code=*/nullptr);
+ instr->ReinitializeMethodsCode(entry.method);
}
}
@@ -1816,7 +1816,7 @@ void JitCodeCache::InvalidateCompiledCodeFor(ArtMethod* method,
// the future.
if (method_entrypoint == header->GetEntryPoint()) {
// The entrypoint is the one to invalidate, so we just update it to the interpreter entry point.
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->ReinitializeMethodsCode(method);
} else {
Thread* self = Thread::Current();
ScopedDebugDisallowReadBarriers sddrb(self);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 09bbb2ab9e..365a63459d 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -745,8 +745,7 @@ void QuickExceptionHandler::DeoptimizeSingleFrame(DeoptimizationKind kind) {
runtime->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
deopt_method, visitor.GetSingleFrameDeoptQuickMethodHeader());
} else {
- runtime->GetInstrumentation()->InitializeMethodsCode(
- deopt_method, /*aot_code=*/ nullptr);
+ runtime->GetInstrumentation()->ReinitializeMethodsCode(deopt_method);
}
// If the deoptimization is due to an inline cache, update it with the type
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index e2c30d619c..d4677d5b86 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -3213,21 +3213,21 @@ class DeoptimizeBootImageClassVisitor : public ClassVisitor {
if (Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) &&
(!m.IsNative() || deoptimize_native_methods) &&
!m.IsProxyMethod()) {
- instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ instrumentation_->ReinitializeMethodsCode(&m);
}
if (Runtime::Current()->GetJit() != nullptr &&
Runtime::Current()->GetJit()->GetCodeCache()->IsInZygoteExecSpace(code) &&
(!m.IsNative() || deoptimize_native_methods)) {
DCHECK(!m.IsProxyMethod());
- instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ instrumentation_->ReinitializeMethodsCode(&m);
}
if (m.IsPreCompiled()) {
// Precompilation is incompatible with debuggable, so clear the flag
// and update the entrypoint in case it has been compiled.
m.ClearPreCompiled();
- instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ instrumentation_->ReinitializeMethodsCode(&m);
}
// Clear MemorySharedAccessFlags so the boot class methods can be JITed better.
diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc
index 053d4eaaf5..f63b2f4096 100644
--- a/runtime/runtime_callbacks_test.cc
+++ b/runtime/runtime_callbacks_test.cc
@@ -80,7 +80,7 @@ class RuntimeCallbacksTest : public CommonRuntimeTest {
PointerSize pointer_size = class_linker_->GetImagePointerSize();
for (auto& m : klass->GetMethods(pointer_size)) {
if (!m.IsAbstract()) {
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->ReinitializeMethodsCode(&m);
}
}
}
diff --git a/test/common/runtime_state.cc b/test/common/runtime_state.cc
index 6ff27f98f4..465e2f6850 100644
--- a/test/common/runtime_state.cc
+++ b/test/common/runtime_state.cc
@@ -457,7 +457,7 @@ extern "C" JNIEXPORT void JNICALL Java_Main_deoptimizeNativeMethod(JNIEnv* env,
ScopedUtfChars chars(env, method_name);
ArtMethod* method = GetMethod(soa, cls, chars);
CHECK(method->IsNative());
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->ReinitializeMethodsCode(method);
}
extern "C" JNIEXPORT jboolean JNICALL Java_Main_isDebuggable(JNIEnv*, jclass) {