diff options
author | 2024-01-05 16:30:56 +0000 | |
---|---|---|
committer | 2024-08-01 14:13:33 +0000 | |
commit | 3ea38e1d3e11417bb7f86a5dcd24187c299dcd73 (patch) | |
tree | 8cc043db0fde48cb70f19b065a2fbb0edb46606f /runtime/quick_exception_handler.cc | |
parent | 0a8d0cd9a4648619fd910964cfe1d6101d881968 (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.cc | 16 |
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) { |