From f5645e3c9cc6ab63bd4a71cf91502b3d339f52b9 Mon Sep 17 00:00:00 2001 From: Hendiadyoin1 Date: Fri, 20 Oct 2023 00:33:51 +0200 Subject: [PATCH] LibJS: Use static unwind mappings for unwind related functions --- .../Libraries/LibJS/Bytecode/BasicBlock.h | 2 - .../Libraries/LibJS/Bytecode/Interpreter.cpp | 49 ++++++++++--------- .../Libraries/LibJS/Bytecode/Interpreter.h | 2 +- 3 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h index f3b5b65520..b0fbfc63ff 100644 --- a/Userland/Libraries/LibJS/Bytecode/BasicBlock.h +++ b/Userland/Libraries/LibJS/Bytecode/BasicBlock.h @@ -15,8 +15,6 @@ namespace JS::Bytecode { struct UnwindInfo { Executable const* executable; - BasicBlock const* handler; - BasicBlock const* finalizer; JS::GCPtr lexical_environment; diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index f1ae098d1d..81aa6bd59a 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -242,9 +243,7 @@ void Interpreter::run_bytecode() m_current_block = &static_cast(instruction).false_target()->block(); goto start; case Instruction::Type::EnterUnwindContext: - enter_unwind_context( - static_cast(instruction).handler_target(), - static_cast(instruction).finalizer_target()); + enter_unwind_context(); m_current_block = &static_cast(instruction).entry_point().block(); goto start; case Instruction::Type::ContinuePendingUnwind: @@ -264,10 +263,13 @@ void Interpreter::run_bytecode() m_current_block = &static_cast(instruction).resume_target().block(); } goto start; - case Instruction::Type::ScheduleJump: + case Instruction::Type::ScheduleJump: { m_scheduled_jump = &static_cast(instruction).target().block(); - m_current_block = unwind_contexts().last().finalizer; + auto const* finalizer = m_current_block->finalizer(); + VERIFY(finalizer); + m_current_block = finalizer; goto start; + } default: result = instruction.execute(*this); break; @@ -275,22 +277,26 @@ void Interpreter::run_bytecode() if (result.is_error()) [[unlikely]] { reg(Register::exception()) = *result.throw_completion().value(); - if (unwind_contexts().is_empty()) + auto const* handler = m_current_block->handler(); + auto const* finalizer = m_current_block->finalizer(); + if (!handler && !finalizer) return; + auto& unwind_context = unwind_contexts().last(); - if (unwind_context.executable != m_current_executable) - return; - if (unwind_context.handler && !unwind_context.handler_called) { + VERIFY(unwind_context.executable == m_current_executable); + + if (handler) { + VERIFY(!unwind_context.handler_called); vm().running_execution_context().lexical_environment = unwind_context.lexical_environment; - m_current_block = unwind_context.handler; + m_current_block = handler; unwind_context.handler_called = true; accumulator = reg(Register::exception()); reg(Register::exception()) = {}; goto start; } - if (unwind_context.finalizer) { - m_current_block = unwind_context.finalizer; + if (finalizer) { + m_current_block = finalizer; // If an exception was thrown inside the corresponding `catch` block, we need to rethrow it // from the `finally` block. But if the exception is from the `try` block, and has already been // handled by `catch`, we swallow it. @@ -316,15 +322,14 @@ void Interpreter::run_bytecode() ++pc; } - if (!unwind_contexts().is_empty() && !will_yield) { + if (auto const* finalizer = m_current_block->finalizer(); finalizer && !will_yield) { auto& unwind_context = unwind_contexts().last(); - if (unwind_context.executable == m_current_executable && unwind_context.finalizer) { - reg(Register::saved_return_value()) = reg(Register::return_value()); - reg(Register::return_value()) = {}; - m_current_block = unwind_context.finalizer; - // the unwind_context will be pop'ed when entering the finally block - continue; - } + VERIFY(unwind_context.executable == m_current_executable); + reg(Register::saved_return_value()) = reg(Register::return_value()); + reg(Register::return_value()) = {}; + m_current_block = finalizer; + // the unwind_context will be pop'ed when entering the finally block + continue; } if (pc.at_end()) @@ -407,12 +412,10 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable& executa return { return_value, nullptr }; } -void Interpreter::enter_unwind_context(Optional