summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mythri Alle <mythria@google.com> 2022-05-11 11:50:26 +0000
committer Mythri Alle <mythria@google.com> 2022-05-12 14:53:31 +0000
commit6898d018f6a48bbc2a8e471850e84e4611c7815c (patch)
tree8b73a5ce6ae7db737684bccf99e715e4d82263ac
parent59831b5fe40249aab697915980caf2347be1199e (diff)
Use instrumentation stub if required when undeoptimizing a method
When undeoptimizing a method we have to check if we need entry / exit stubs for any other reason before installing a resolution trampoline. Also add a DCHECK that we always update entrypoints that can handle method entry / exit hooks when instrumentation is enabled. Bug: 231923130 Test: art/test.py Change-Id: I8d5e22d85bbd47ebedebe766caa7026b2b82cffb
-rw-r--r--runtime/instrumentation.cc65
-rw-r--r--runtime/instrumentation.h5
2 files changed, 38 insertions, 32 deletions
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 80e35ac0ae..b4dc9f6872 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -230,32 +230,9 @@ static bool IsProxyInit(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_)
method->GetDeclaringClass()->DescriptorEquals("Ljava/lang/reflect/Proxy;");
}
-static void UpdateEntryPoints(ArtMethod* method, const void* quick_code)
- REQUIRES_SHARED(Locks::mutator_lock_) {
- if (kIsDebugBuild) {
- if (NeedsClinitCheckBeforeCall(method) &&
- !method->GetDeclaringClass()->IsVisiblyInitialized()) {
- CHECK(CanHandleInitializationCheck(quick_code));
- }
- jit::Jit* jit = Runtime::Current()->GetJit();
- if (jit != nullptr && jit->GetCodeCache()->ContainsPc(quick_code)) {
- // Ensure we always have the thumb entrypoint for JIT on arm32.
- if (kRuntimeISA == InstructionSet::kArm) {
- CHECK_EQ(reinterpret_cast<uintptr_t>(quick_code) & 1, 1u);
- }
- }
- if (IsProxyInit(method)) {
- CHECK_NE(quick_code, GetQuickInstrumentationEntryPoint());
- }
- }
- // If the method is from a boot image, don't dirty it if the entrypoint
- // doesn't change.
- if (method->GetEntryPointFromQuickCompiledCode() != quick_code) {
- method->SetEntryPointFromQuickCompiledCode(quick_code);
- }
-}
-
-bool Instrumentation::CodeNeedsEntryExitStub(const void* code, ArtMethod* method)
+// Returns true if we need entry exit stub to call entry hooks. JITed code
+// directly call entry / exit hooks and don't need the stub.
+static bool CodeNeedsEntryExitStub(const void* code, ArtMethod* method)
REQUIRES_SHARED(Locks::mutator_lock_) {
// Proxy.init should never have entry/exit stubs.
if (IsProxyInit(method)) {
@@ -294,6 +271,36 @@ bool Instrumentation::CodeNeedsEntryExitStub(const void* code, ArtMethod* method
return true;
}
+static void UpdateEntryPoints(ArtMethod* method, const void* quick_code)
+ REQUIRES_SHARED(Locks::mutator_lock_) {
+ if (kIsDebugBuild) {
+ if (NeedsClinitCheckBeforeCall(method) &&
+ !method->GetDeclaringClass()->IsVisiblyInitialized()) {
+ CHECK(CanHandleInitializationCheck(quick_code));
+ }
+ jit::Jit* jit = Runtime::Current()->GetJit();
+ if (jit != nullptr && jit->GetCodeCache()->ContainsPc(quick_code)) {
+ // Ensure we always have the thumb entrypoint for JIT on arm32.
+ if (kRuntimeISA == InstructionSet::kArm) {
+ CHECK_EQ(reinterpret_cast<uintptr_t>(quick_code) & 1, 1u);
+ }
+ }
+ if (IsProxyInit(method)) {
+ CHECK_NE(quick_code, GetQuickInstrumentationEntryPoint());
+ }
+ const Instrumentation* instr = Runtime::Current()->GetInstrumentation();
+ if (instr->EntryExitStubsInstalled()) {
+ DCHECK(quick_code == GetQuickInstrumentationEntryPoint() ||
+ !CodeNeedsEntryExitStub(quick_code, method));
+ }
+ }
+ // If the method is from a boot image, don't dirty it if the entrypoint
+ // doesn't change.
+ if (method->GetEntryPointFromQuickCompiledCode() != quick_code) {
+ method->SetEntryPointFromQuickCompiledCode(quick_code);
+ }
+}
+
bool Instrumentation::InterpretOnly(ArtMethod* method) REQUIRES_SHARED(Locks::mutator_lock_) {
if (method->IsNative()) {
return false;
@@ -1199,7 +1206,11 @@ void Instrumentation::Undeoptimize(ArtMethod* method) {
UpdateEntryPoints(method, GetQuickToInterpreterBridge());
} else if (NeedsClinitCheckBeforeCall(method) &&
!method->GetDeclaringClass()->IsVisiblyInitialized()) {
- UpdateEntryPoints(method, GetQuickResolutionStub());
+ if (EntryExitStubsInstalled()) {
+ UpdateEntryPoints(method, GetQuickInstrumentationEntryPoint());
+ } else {
+ UpdateEntryPoints(method, GetQuickResolutionStub());
+ }
} else {
UpdateEntryPoints(method, GetMaybeInstrumentedCodeForInvoke(method));
}
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index c63e73eeea..33ff8ffa9e 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -580,11 +580,6 @@ class Instrumentation {
// False otherwise.
bool RequiresInstrumentationInstallation(InstrumentationLevel new_level) const;
- // Returns true if we need entry exit stub to call entry hooks. JITed code
- // directly call entry / exit hooks and don't need the stub.
- static bool CodeNeedsEntryExitStub(const void* code, ArtMethod* method)
- REQUIRES_SHARED(Locks::mutator_lock_);
-
// Update the current instrumentation_level_.
void UpdateInstrumentationLevel(InstrumentationLevel level);