Don't call MethodExitEvent if we require a deopt in MethodExitHook
With the change to method entry / exit hooks to be directly called
from JITed code we deoptimize from artMethodExitHook. Since we are
still in the Jited code, interpreter re-executes the return
instruction and calls any method exit events required. Hence, we
shouldn't call MethodExitEvent if we require a deoptimization.
Test: art/test.py
Bug: 208587492
Change-Id: Iefe29cb3b7cb8db394b3eb9ca100af1462687089
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index ab9825b..0d9c9bb 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -2629,10 +2629,6 @@
res.Assign(return_value.GetL());
}
DCHECK(!method->IsRuntimeMethod());
- instr->MethodExitEvent(self,
- method,
- /* frame= */ {},
- return_value);
// Deoptimize if the caller needs to continue execution in the interpreter. Do nothing if we get
// back to an upcall.
@@ -2640,6 +2636,15 @@
visitor.WalkStack(true);
deoptimize = instr->ShouldDeoptimizeMethod(self, visitor);
+ // If we need a deoptimization MethodExitEvent will be called by the interpreter when it
+ // re-executes the return instruction.
+ if (!deoptimize) {
+ instr->MethodExitEvent(self,
+ method,
+ /* frame= */ {},
+ return_value);
+ }
+
if (is_ref) {
// Restore the return value if it's a reference since it might have moved.
*reinterpret_cast<mirror::Object**>(gpr_result) = res.Get();