Revert^4 "Remove Global deopt requirement for several jvmti events"
It was possible for the top frame of a thread to enter the
artQuickToInterpreterBridge during runtime shutdown. This could be
caused by the libjdwp agent. If this happens the caller of the frame
will be 'null', which could cause a segv if not detected correctly.
This reverts commit 939798e6a565a92e597136c589428e89c28bffd5.
Reason for revert: Fixed issue that could cause crash during process
shutdown.
Test: ./art/tools/run-libjdwp-tests.sh --mode=host
Test: ./test.py --host
Change-Id: I2aad1705c761edb4ed788cec4fc8a3068d67aee5
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 6deb509..00c0a52 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -799,9 +799,12 @@
ArtMethod* caller = QuickArgumentVisitor::GetCallingMethod(sp);
uintptr_t caller_pc = QuickArgumentVisitor::GetCallingPc(sp);
// If caller_pc is the instrumentation exit stub, the stub will check to see if deoptimization
- // should be done and it knows the real return pc.
- if (UNLIKELY(caller_pc != reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) &&
- Dbg::IsForcedInterpreterNeededForUpcall(self, caller))) {
+ // should be done and it knows the real return pc. NB If the upcall is null we don't need to do
+ // anything. This can happen during shutdown or early startup.
+ if (UNLIKELY(
+ caller != nullptr &&
+ caller_pc != reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc()) &&
+ (self->IsForceInterpreter() || Dbg::IsForcedInterpreterNeededForUpcall(self, caller)))) {
if (!Runtime::Current()->IsAsyncDeoptimizeable(caller_pc)) {
LOG(WARNING) << "Got a deoptimization request on un-deoptimizable method "
<< caller->PrettyMethod();
@@ -1453,8 +1456,10 @@
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> called_class(hs.NewHandle(called->GetDeclaringClass()));
linker->EnsureInitialized(soa.Self(), called_class, true, true);
+ bool force_interpreter = self->IsForceInterpreter() && !called->IsNative();
if (LIKELY(called_class->IsInitialized())) {
- if (UNLIKELY(Dbg::IsForcedInterpreterNeededForResolution(self, called))) {
+ if (UNLIKELY(force_interpreter ||
+ Dbg::IsForcedInterpreterNeededForResolution(self, called))) {
// If we are single-stepping or the called method is deoptimized (by a
// breakpoint, for example), then we have to execute the called method
// with the interpreter.
@@ -1473,7 +1478,8 @@
code = called->GetEntryPointFromQuickCompiledCode();
}
} else if (called_class->IsInitializing()) {
- if (UNLIKELY(Dbg::IsForcedInterpreterNeededForResolution(self, called))) {
+ if (UNLIKELY(force_interpreter ||
+ Dbg::IsForcedInterpreterNeededForResolution(self, called))) {
// If we are single-stepping or the called method is deoptimized (by a
// breakpoint, for example), then we have to execute the called method
// with the interpreter.