Revert "Use InitializeMethodsCode when we need to reinitialize a method entrypoint."
This reverts commit 82e525a4f5f08a72ea1b6907c0a10dacb77a8a87.
Reason for revert: Fails a test
Change-Id: Iab83b543b99fb6f6d5d9be22cd10d4eb88312d4b
diff --git a/compiler/common_compiler_test.cc b/compiler/common_compiler_test.cc
index bbb2016..1b69f2a 100644
--- a/compiler/common_compiler_test.cc
+++ b/compiler/common_compiler_test.cc
@@ -149,18 +149,20 @@
void CommonCompilerTestImpl::MakeExecutable(ArtMethod* method,
const CompiledMethod* compiled_method) {
CHECK(method != nullptr);
- const void* method_code = nullptr;
// If the code size is 0 it means the method was skipped due to profile guided compilation.
if (compiled_method != nullptr && compiled_method->GetQuickCode().size() != 0u) {
const void* code_ptr = MakeExecutable(compiled_method->GetQuickCode(),
compiled_method->GetVmapTable(),
compiled_method->GetInstructionSet());
- method_code =
+ const void* method_code =
CompiledMethod::CodePointer(code_ptr, compiled_method->GetInstructionSet());
LOG(INFO) << "MakeExecutable " << method->PrettyMethod() << " code=" << method_code;
+ method->SetEntryPointFromQuickCompiledCode(method_code);
+ } else {
+ // No code? You must mean to go into the interpreter.
+ // Or the generic JNI...
+ GetClassLinker()->SetEntryPointsToInterpreter(method);
}
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(
- method, /*aot_code=*/ method_code);
}
void CommonCompilerTestImpl::SetUp() {
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc
index a6425af..c69ee7b 100644
--- a/openjdkjvmti/events.cc
+++ b/openjdkjvmti/events.cc
@@ -1260,7 +1260,7 @@
continue;
} else if (!runtime_->GetClassLinker()->IsQuickToInterpreterBridge(code) &&
!runtime_->IsAsyncDeoptimizeable(reinterpret_cast<uintptr_t>(code))) {
- runtime_->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ runtime_->GetInstrumentation()->UpdateMethodsCodeToInterpreterEntryPoint(&m);
}
}
return true;
diff --git a/openjdkjvmti/ti_redefine.cc b/openjdkjvmti/ti_redefine.cc
index c234bd4..37a61d3 100644
--- a/openjdkjvmti/ti_redefine.cc
+++ b/openjdkjvmti/ti_redefine.cc
@@ -2116,7 +2116,7 @@
}
// Finish setting up methods.
linked_class->VisitMethods([&](art::ArtMethod* m) REQUIRES_SHARED(art::Locks::mutator_lock_) {
- driver_->runtime_->GetInstrumentation()->InitializeMethodsCode(m, /* aot_code= */ nullptr);
+ linker->SetEntryPointsToInterpreter(m);
m->SetNotIntrinsic();
DCHECK(m->IsCopied() || m->GetDeclaringClass() == linked_class.Get())
<< m->PrettyMethod()
@@ -2543,7 +2543,7 @@
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);
+ linker->SetEntryPointsToInterpreter(&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 62dd4d2..d2ab81e 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -201,6 +201,22 @@
self->AssertPendingException();
}
+static void ChangeInterpreterBridgeToNterp(ArtMethod* method, ClassLinker* class_linker)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ Runtime* runtime = Runtime::Current();
+ if (class_linker->IsQuickToInterpreterBridge(method->GetEntryPointFromQuickCompiledCode()) &&
+ CanMethodUseNterp(method)) {
+ if (method->GetDeclaringClass()->IsVisiblyInitialized() ||
+ !NeedsClinitCheckBeforeCall(method)) {
+ runtime->GetInstrumentation()->UpdateMethodsCode(method, interpreter::GetNterpEntryPoint());
+ } else {
+ // Put the resolution stub, which will initialize the class and then
+ // call the method with nterp.
+ runtime->GetInstrumentation()->UpdateMethodsCode(method, GetQuickResolutionStub());
+ }
+ }
+}
+
static void UpdateClassAfterVerification(Handle<mirror::Class> klass,
PointerSize pointer_size,
verifier::FailureKind failure_kind)
@@ -215,9 +231,7 @@
// to methods that currently use the switch interpreter.
if (interpreter::CanRuntimeUseNterp()) {
for (ArtMethod& m : klass->GetMethods(pointer_size)) {
- if (class_linker->IsQuickToInterpreterBridge(m.GetEntryPointFromQuickCompiledCode())) {
- runtime->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/nullptr);
- }
+ ChangeInterpreterBridgeToNterp(&m, class_linker);
}
}
}
@@ -1959,11 +1973,10 @@
// reset it with the runtime value.
method.ResetCounter(hotness_threshold);
}
+ // Set image methods' entry point that point to the interpreter bridge to the
+ // nterp entry point.
if (method.GetEntryPointFromQuickCompiledCode() == nterp_trampoline_) {
if (can_use_nterp) {
- // Set image methods' entry point that point to the nterp trampoline to the
- // nterp entry point. This allows taking the fast path when doing a
- // nterp->nterp call.
DCHECK(!NeedsClinitCheckBeforeCall(&method) ||
method.GetDeclaringClass()->IsVisiblyInitialized());
method.SetEntryPointFromQuickCompiledCode(interpreter::GetNterpEntryPoint());
@@ -3340,7 +3353,6 @@
return;
}
- instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
// Link the code of methods skipped by LinkCode.
for (size_t method_index = 0; method_index < num_direct_methods; ++method_index) {
ArtMethod* method = klass->GetDirectMethod(method_index, pointer_size);
@@ -3348,6 +3360,7 @@
// Only update static methods.
continue;
}
+ instrumentation::Instrumentation* instrumentation = runtime->GetInstrumentation();
instrumentation->UpdateMethodsCode(method, instrumentation->GetCodeForInvoke(method));
}
// Ignore virtual methods on the iterator.
@@ -9643,6 +9656,14 @@
return GetQuickGenericJniStub();
}
+void ClassLinker::SetEntryPointsToInterpreter(ArtMethod* method) const {
+ if (!method->IsNative()) {
+ method->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
+ } else {
+ method->SetEntryPointFromQuickCompiledCode(GetQuickGenericJniStub());
+ }
+}
+
void ClassLinker::SetEntryPointsForObsoleteMethod(ArtMethod* method) const {
DCHECK(method->IsObsolete());
// We cannot mess with the entrypoints of native methods because they are used to determine how
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 7ba62f4..b0c02e5 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -620,6 +620,10 @@
return intern_table_;
}
+ // Set the entrypoints up for method to the enter the interpreter.
+ void SetEntryPointsToInterpreter(ArtMethod* method) const
+ REQUIRES_SHARED(Locks::mutator_lock_);
+
// Set the entrypoints up for an obsolete method.
void SetEntryPointsForObsoleteMethod(ArtMethod* method) const
REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/common_runtime_test.cc b/runtime/common_runtime_test.cc
index 6ff4f1a..f949759 100644
--- a/runtime/common_runtime_test.cc
+++ b/runtime/common_runtime_test.cc
@@ -400,7 +400,7 @@
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);
+ class_linker_->SetEntryPointsToInterpreter(&method);
}
}
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 926d534..027bda5 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -1052,7 +1052,7 @@
!jit->GetCodeCache()->ContainsPc(result))
<< method->PrettyMethod() << " code will jump to possibly cleaned up jit code!";
- bool interpreter_entry = Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(result);
+ bool interpreter_entry = (result == GetQuickToInterpreterBridge());
bool is_static = method->IsStatic();
uint32_t shorty_len;
const char* shorty =
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 65123ff..71d48ee 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -375,7 +375,7 @@
}
// Special case if we need an initialization check.
- if (NeedsClinitCheckBeforeCall(method) && !method->GetDeclaringClass()->IsVisiblyInitialized()) {
+ if (NeedsClinitCheckBeforeCall(method)) {
// 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
@@ -397,17 +397,10 @@
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.
- if (interpreter::CanRuntimeUseNterp() &&
- CanMethodUseNterp(method) &&
- method->GetDeclaringClass()->IsVerified()) {
- UpdateEntryPoints(method, interpreter::GetNterpEntryPoint());
- return;
- }
-
// Use default entrypoints.
+ // Note we cannot use the nterp entrypoint because we do not know if the
+ // method will need the slow interpreter for lock verification. This will
+ // be updated in ClassLinker::UpdateClassAfterVerification.
UpdateEntryPoints(
method, method->IsNative() ? GetQuickGenericJniStub() : GetQuickToInterpreterBridge());
}
@@ -1107,6 +1100,19 @@
UpdateMethodsCodeImpl(method, new_code);
}
+void Instrumentation::UpdateMethodsCodeToInterpreterEntryPoint(ArtMethod* method) {
+ UpdateMethodsCodeImpl(method, GetQuickToInterpreterBridge());
+}
+
+void Instrumentation::UpdateMethodsCodeForJavaDebuggable(ArtMethod* method,
+ const void* new_code) {
+ // When the runtime is set to Java debuggable, we may update the entry points of
+ // all methods of a class to the interpreter bridge. A method's declaring class
+ // might not be in resolved state yet in that case, so we bypass the DCHECK in
+ // UpdateMethodsCode.
+ UpdateMethodsCodeImpl(method, new_code);
+}
+
bool Instrumentation::AddDeoptimizedMethod(ArtMethod* method) {
if (IsDeoptimizedMethod(method)) {
// Already in the map. Return.
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index d4cb85b..276d1ca 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -312,6 +312,14 @@
void UpdateNativeMethodsCodeToJitCode(ArtMethod* method, const void* new_code)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
+ // Update the code of a method to the interpreter respecting any installed stubs from debugger.
+ void UpdateMethodsCodeToInterpreterEntryPoint(ArtMethod* method)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
+
+ // Update the code of a method respecting any installed stubs from debugger.
+ void UpdateMethodsCodeForJavaDebuggable(ArtMethod* method, const void* new_code)
+ REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!GetDeoptimizedMethodsLock());
+
// Return the code that we can execute for an invoke including from the JIT.
const void* GetCodeForInvoke(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_);
diff --git a/runtime/jit/jit_code_cache.cc b/runtime/jit/jit_code_cache.cc
index 34ddfc4..8b91f9e 100644
--- a/runtime/jit/jit_code_cache.cc
+++ b/runtime/jit/jit_code_cache.cc
@@ -793,7 +793,8 @@
}
ClearMethodCounter(method, /* was_warm= */ false);
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
+ method, GetQuickToInterpreterBridge());
VLOG(jit)
<< "JIT removed (osr=" << std::boolalpha << osr << std::noboolalpha << ") "
<< ArtMethod::PrettyMethod(method) << "@" << method
@@ -1317,8 +1318,7 @@
OatQuickMethodHeader::FromEntryPoint(entry_point);
if (CodeInfo::IsBaseline(method_header->GetOptimizedCodeInfoPtr())) {
info->GetMethod()->ResetCounter(warmup_threshold);
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(
- info->GetMethod(), /*aot_code=*/ nullptr);
+ info->GetMethod()->SetEntryPointFromQuickCompiledCode(GetQuickToInterpreterBridge());
}
}
}
@@ -1744,7 +1744,7 @@
if (meth->IsObsolete()) {
linker->SetEntryPointsForObsoleteMethod(meth);
} else {
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(meth, /*aot_code=*/ nullptr);
+ linker->SetEntryPointsToInterpreter(meth);
}
}
saved_compiled_methods_map_.clear();
@@ -1761,7 +1761,8 @@
if (method_entrypoint == header->GetEntryPoint()) {
// The entrypoint is the one to invalidate, so we just update it to the interpreter entry point
// and clear the counter to get the method Jitted again.
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(method, /*aot_code=*/ nullptr);
+ Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
+ method, GetQuickToInterpreterBridge());
ClearMethodCounter(method, /*was_warm=*/ true);
} else {
MutexLock mu(Thread::Current(), *Locks::jit_lock_);
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index c372248..ac5065b 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -606,8 +606,9 @@
Runtime::Current()->GetJit()->GetCodeCache()->InvalidateCompiledCodeFor(
deopt_method, visitor.GetSingleFrameDeoptQuickMethodHeader());
} else {
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(
- deopt_method, /*aot_code=*/ nullptr);
+ // Transfer the code to interpreter.
+ Runtime::Current()->GetInstrumentation()->UpdateMethodsCode(
+ deopt_method, GetQuickToInterpreterBridge());
}
PrepareForLongJumpToInvokeStubOrInterpreterBridge();
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index afa8504..54e9d38 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -3095,21 +3095,21 @@
if (Runtime::Current()->GetHeap()->IsInBootImageOatFile(code) &&
!m.IsNative() &&
!m.IsProxyMethod()) {
- instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge());
}
if (Runtime::Current()->GetJit() != nullptr &&
Runtime::Current()->GetJit()->GetCodeCache()->IsInZygoteExecSpace(code) &&
!m.IsNative()) {
DCHECK(!m.IsProxyMethod());
- instrumentation_->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ instrumentation_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge());
}
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_->UpdateMethodsCodeForJavaDebuggable(&m, GetQuickToInterpreterBridge());
}
}
return true;
diff --git a/runtime/runtime_callbacks_test.cc b/runtime/runtime_callbacks_test.cc
index 7f64721..7619750 100644
--- a/runtime/runtime_callbacks_test.cc
+++ b/runtime/runtime_callbacks_test.cc
@@ -80,7 +80,7 @@
PointerSize pointer_size = class_linker_->GetImagePointerSize();
for (auto& m : klass->GetMethods(pointer_size)) {
if (!m.IsAbstract()) {
- Runtime::Current()->GetInstrumentation()->InitializeMethodsCode(&m, /*aot_code=*/ nullptr);
+ class_linker_->SetEntryPointsToInterpreter(&m);
}
}
}