summaryrefslogtreecommitdiff
path: root/runtime/quick_exception_handler.cc
diff options
context:
space:
mode:
author Chris Jones <christopher.jones@arm.com> 2024-01-05 16:30:56 +0000
committer VladimĂ­r Marko <vmarko@google.com> 2024-08-01 14:13:33 +0000
commit3ea38e1d3e11417bb7f86a5dcd24187c299dcd73 (patch)
tree8cc043db0fde48cb70f19b065a2fbb0edb46606f /runtime/quick_exception_handler.cc
parent0a8d0cd9a4648619fd910964cfe1d6101d881968 (diff)
Rework exception delivery and deoptimization
Both exception delivery (various methods calling Thread::QuickDeliverException()) and deoptimization (via artDeoptimizeImpl) use QuickExceptionHandler to find the target context and do a long jump to it via QuickExceptionHandler::DoLongJump. The long jump is done directly from the C++ code, so the frames of the related C++ method are still on the stack before the change of the pc. Note that all those methods are marked as NO_RETURN to reflect that. This patch changes the approach; instead of having the long jump directly from the C++ methods related to exceptions and deoptimization, those methods now only prepare the long jump context and return. So their callers (mainly .S quick entry points and stubs) now need to do a long jump explicitly; thus there will be no C++ frames on the stack before the jump. This approach makes it possible to support exceptions and deoptimization in simulator mode; so we don't need to unwind native (C++ methods' frames) and simulated stacks at the same. Authors: Artem Serov <artem.serov@linaro.org>, Chris Jones <christopher.jones@arm.com> Test: test.py --host --target Change-Id: I5f90e6b5ba152fc2205728f1e814bbe3d609af9d
Diffstat (limited to 'runtime/quick_exception_handler.cc')
-rw-r--r--runtime/quick_exception_handler.cc16
1 files changed, 7 insertions, 9 deletions
diff --git a/runtime/quick_exception_handler.cc b/runtime/quick_exception_handler.cc
index 37734f7d74..8924108f74 100644
--- a/runtime/quick_exception_handler.cc
+++ b/runtime/quick_exception_handler.cc
@@ -52,7 +52,7 @@ static constexpr size_t kInvalidFrameDepth = 0xffffffff;
QuickExceptionHandler::QuickExceptionHandler(Thread* self, bool is_deoptimization)
: self_(self),
- context_(self->GetLongJumpContext()),
+ context_(Context::Create()),
is_deoptimization_(is_deoptimization),
handler_quick_frame_(nullptr),
handler_quick_frame_pc_(0),
@@ -200,7 +200,7 @@ void QuickExceptionHandler::FindCatch(ObjPtr<mirror::Throwable> exception,
// Walk the stack to find catch handler.
CatchBlockStackVisitor visitor(self_,
- context_,
+ context_.get(),
&exception_ref,
this,
/*skip_frames=*/already_popped,
@@ -709,7 +709,7 @@ void QuickExceptionHandler::DeoptimizeStack(bool skip_method_exit_callbacks) {
self_->DumpStack(LOG_STREAM(INFO) << "Deoptimizing: ");
}
- DeoptimizeStackVisitor visitor(self_, context_, this, false, skip_method_exit_callbacks);
+ DeoptimizeStackVisitor visitor(self_, context_.get(), this, false, skip_method_exit_callbacks);
visitor.WalkStack(true);
PrepareForLongJumpToInvokeStubOrInterpreterBridge();
}
@@ -720,7 +720,7 @@ void QuickExceptionHandler::DeoptimizeSingleFrame(DeoptimizationKind kind) {
// This deopt is requested while still executing the method. We haven't run method exit callbacks
// yet, so don't skip them.
DeoptimizeStackVisitor visitor(
- self_, context_, this, true, /* skip_method_exit_callbacks= */ false);
+ self_, context_.get(), this, true, /* skip_method_exit_callbacks= */ false);
visitor.WalkStack(true);
// Compiled code made an explicit deoptimization.
@@ -806,9 +806,8 @@ void QuickExceptionHandler::DeoptimizePartialFragmentFixup() {
}
}
-void QuickExceptionHandler::DoLongJump(bool smash_caller_saves) {
- // Place context back on thread so it will be available when we continue.
- self_->ReleaseLongJumpContext(context_);
+Context* QuickExceptionHandler::PrepareLongJump(bool smash_caller_saves) {
+ // Prepare and return the context.
context_->SetSP(reinterpret_cast<uintptr_t>(handler_quick_frame_));
CHECK_NE(handler_quick_frame_pc_, 0u);
context_->SetPC(handler_quick_frame_pc_);
@@ -827,8 +826,7 @@ void QuickExceptionHandler::DoLongJump(bool smash_caller_saves) {
}
// Clear the dex_pc list so as not to leak memory.
handler_dex_pc_list_.reset();
- context_->DoLongJump();
- UNREACHABLE();
+ return context_.release();
}
void QuickExceptionHandler::DumpFramesWithType(Thread* self, bool details) {