Reland "Limited deopt request from jvmti should enable entry / exit hooks""
This reverts commit b69a3ebf5a4a4ef8ae25db170fce9e25844a2f1b.
Reason for revert: Re-landing with a fix.
It is OK to use resolution stubs when entry / exit stubs are required.
Resolution stubs fetch code that supports entry / exit hooks when required.
Change-Id: I0e7d807df2c92249cd17e2a5df324ac47e248874
diff --git a/openjdkjvmti/deopt_manager.cc b/openjdkjvmti/deopt_manager.cc
index 129aa0f..99acb87 100644
--- a/openjdkjvmti/deopt_manager.cc
+++ b/openjdkjvmti/deopt_manager.cc
@@ -496,6 +496,15 @@
art::ScopedThreadStateChange stsc(self, art::ThreadState::kSuspended);
deoptimization_status_lock_.ExclusiveLock(self);
deopter_count_++;
+ if (deopter_count_ == 1) {
+ // When we add a deoptimization requester, we should enable entry / exit hooks. We only call
+ // this in debuggable runtimes and hence it won't be necessary to update entrypoints but we
+ // still need to inform instrumentation that we need to actually run entry / exit hooks. Though
+ // entrypoints are capable of running entry / exit hooks they won't run them unless enabled.
+ ScopedDeoptimizationContext sdc(self, this);
+ art::Runtime::Current()->GetInstrumentation()->EnableEntryExitHooks(kInstrumentationKey);
+ return;
+ }
deoptimization_status_lock_.ExclusiveUnlock(self);
}
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 60511b5..62a2d8f 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -223,8 +223,11 @@
return false;
}
- // Code running in the interpreter doesn't need entry/exit stubs.
- if (Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(entry_point)) {
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ // Interpreter supports entry / exit hooks. Resolution stubs fetch code that supports entry / exit
+ // hooks when required. So return true for both cases.
+ if (linker->IsQuickToInterpreterBridge(entry_point) ||
+ linker->IsQuickResolutionStub(entry_point)) {
return true;
}
@@ -238,7 +241,7 @@
}
// GenericJni trampoline can handle entry / exit hooks.
- if (Runtime::Current()->GetClassLinker()->IsQuickGenericJniStub(entry_point)) {
+ if (linker->IsQuickGenericJniStub(entry_point)) {
return true;
}
@@ -881,6 +884,11 @@
instrumentation_level_ = requested_level;
}
+void Instrumentation::EnableEntryExitHooks(const char* key) {
+ DCHECK(Runtime::Current()->IsJavaDebuggable());
+ ConfigureStubs(key, InstrumentationLevel::kInstrumentWithInstrumentationStubs);
+}
+
void Instrumentation::MaybeRestoreInstrumentationStack() {
// Restore stack only if there is no method currently deoptimized.
if (!IsDeoptimizedMethodsEmpty()) {
diff --git a/runtime/instrumentation.h b/runtime/instrumentation.h
index 3d868eb..626ff8e 100644
--- a/runtime/instrumentation.h
+++ b/runtime/instrumentation.h
@@ -243,6 +243,11 @@
void DisableDeoptimization(const char* key)
REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_);
+ // Enables entry exit hooks support. This is called in preparation for debug requests that require
+ // calling method entry / exit hooks.
+ void EnableEntryExitHooks(const char* key)
+ REQUIRES(Locks::mutator_lock_, Roles::uninterruptible_);
+
bool AreAllMethodsDeoptimized() const {
return InterpreterStubsInstalled();
}