On partial fragment deopts, update return PC only when necessary
JITed code in debuggable apps don't have instrumentation stubs
installed and hence don't have an entry in the instrumentation
stack. In the case of a deopt the last frame that is popped
from instrumentation stack could be different from that of the
actual stack. Hence we shouldn't update the return PC
unconditionally incase of a partial fragment deopt.
Test: art/test.py -t 989-method-trace-throw
Bug: 214001306
Change-Id: I10cf74b3a1481429502b46e9d69b5274cce0f000
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index c372248..2a6929a 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -616,11 +616,15 @@
void QuickExceptionHandler::DeoptimizePartialFragmentFixup(uintptr_t return_pc) {
// At this point, the instrumentation stack has been updated. We need to install
// the real return pc on stack, in case instrumentation stub is stored there,
- // so that the interpreter bridge code can return to the right place.
- if (return_pc != 0) {
- uintptr_t* pc_addr = reinterpret_cast<uintptr_t*>(handler_quick_frame_);
- CHECK(pc_addr != nullptr);
- pc_addr--;
+ // so that the interpreter bridge code can return to the right place. JITed
+ // frames in Java debuggable runtimes may not have an instrumentation stub, so
+ // update the PC only when required.
+ uintptr_t* pc_addr = reinterpret_cast<uintptr_t*>(handler_quick_frame_);
+ CHECK(pc_addr != nullptr);
+ pc_addr--;
+ if (return_pc != 0 &&
+ (*reinterpret_cast<uintptr_t*>(pc_addr)) ==
+ reinterpret_cast<uintptr_t>(GetQuickInstrumentationExitPc())) {
*reinterpret_cast<uintptr_t*>(pc_addr) = return_pc;
}