From d11c004a5df78a67e6e9021492a8e096de336db3 Mon Sep 17 00:00:00 2001 From: Mythri Alle Date: Thu, 23 May 2024 07:38:46 +0000 Subject: Reland "Report method unwind events for native methods" This reverts commit db0551d164783866acf0cdcf9a7741ee6f21f0f2. Reason for revert: Updated test to a use method declared in the Test class instead of the hidden java.lang.classForName. Change-Id: Ifa725b5465163fa73e4808d87a2b205b92aa110f --- runtime/quick_exception_handler.cc | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'runtime/quick_exception_handler.cc') diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc index 2ebcbb0fd0..37734f7d74 100644 --- a/runtime/quick_exception_handler.cc +++ b/runtime/quick_exception_handler.cc @@ -439,19 +439,41 @@ class DeoptimizeStackVisitor final : public StackVisitor { ArtMethod* method = GetMethod(); VLOG(deopt) << "Deoptimizing stack: depth: " << GetFrameDepth() << " at method " << ArtMethod::PrettyMethod(method); + if (method == nullptr || single_frame_done_) { FinishStackWalk(); return false; // End stack walk. - } else if (method->IsRuntimeMethod()) { + } + + // Update if method exit event needs to be reported. We should report exit event only if we + // have reported an entry event. So tell interpreter if/ an entry event was reported. + bool supports_exit_events = Runtime::Current()->GetInstrumentation()->MethodSupportsExitEvents( + method, GetCurrentOatQuickMethodHeader()); + + if (method->IsRuntimeMethod()) { // Ignore callee save method. DCHECK(method->IsCalleeSaveMethod()); return true; } else if (method->IsNative()) { // If we return from JNI with a pending exception and want to deoptimize, we need to skip // the native method. The top method is a runtime method, the native method comes next. - // We also deoptimize due to method instrumentation reasons from method entry / exit - // callbacks. In these cases native method is at the top of stack. + // We also deoptimize due to method instrumentation reasons from method exit callbacks. + // In these cases native method is at the top of stack. CHECK((GetFrameDepth() == 1U) || (GetFrameDepth() == 0U)); + // We see a native frame when: + // 1. returning from JNI with a pending exception + // 2. deopting from method exit callbacks (with or without a pending exception). + // skip_method_exit_callbacks_ is set in this case + // 3. handling async exception on suspend points for fast native methods. + // We only need to call method unwind event in the first case. + if (supports_exit_events && + !skip_method_exit_callbacks_ && + GetThread()->IsExceptionPending()) { + // An exception has occurred in a native method and we are deoptimizing past the native + // method. So report method unwind event here. + Runtime::Current()->GetInstrumentation()->MethodUnwindEvent( + GetThread(), method, dex::kDexNoIndex); + } callee_method_ = method; return true; } else if (!single_frame_deopt_ && @@ -482,11 +504,6 @@ class DeoptimizeStackVisitor final : public StackVisitor { } else { HandleOptimizingDeoptimization(method, new_frame, updated_vregs); } - // Update if method exit event needs to be reported. We should report exit event only if we - // have reported an entry event. So tell interpreter if/ an entry event was reported. - bool supports_exit_events = - Runtime::Current()->GetInstrumentation()->MethodSupportsExitEvents( - method, GetCurrentOatQuickMethodHeader()); new_frame->SetSkipMethodExitEvents(!supports_exit_events); // If we are deoptimizing after method exit callback we shouldn't call the method exit // callbacks again for the top frame. We may have to deopt after the callback if the callback -- cgit v1.2.3-59-g8ed1b