1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 21:37:34 +00:00

LibJS: Use static unwind mappings for unwind related functions

This commit is contained in:
Hendiadyoin1 2023-10-20 00:33:51 +02:00 committed by Andreas Kling
parent 73f347b75c
commit f5645e3c9c
3 changed files with 27 additions and 26 deletions

View file

@ -15,8 +15,6 @@ namespace JS::Bytecode {
struct UnwindInfo { struct UnwindInfo {
Executable const* executable; Executable const* executable;
BasicBlock const* handler;
BasicBlock const* finalizer;
JS::GCPtr<Environment> lexical_environment; JS::GCPtr<Environment> lexical_environment;

View file

@ -13,6 +13,7 @@
#include <LibJS/Bytecode/Generator.h> #include <LibJS/Bytecode/Generator.h>
#include <LibJS/Bytecode/Instruction.h> #include <LibJS/Bytecode/Instruction.h>
#include <LibJS/Bytecode/Interpreter.h> #include <LibJS/Bytecode/Interpreter.h>
#include <LibJS/Bytecode/Label.h>
#include <LibJS/Bytecode/Op.h> #include <LibJS/Bytecode/Op.h>
#include <LibJS/JIT/Compiler.h> #include <LibJS/JIT/Compiler.h>
#include <LibJS/Runtime/AbstractOperations.h> #include <LibJS/Runtime/AbstractOperations.h>
@ -242,9 +243,7 @@ void Interpreter::run_bytecode()
m_current_block = &static_cast<Op::Jump const&>(instruction).false_target()->block(); m_current_block = &static_cast<Op::Jump const&>(instruction).false_target()->block();
goto start; goto start;
case Instruction::Type::EnterUnwindContext: case Instruction::Type::EnterUnwindContext:
enter_unwind_context( enter_unwind_context();
static_cast<Op::EnterUnwindContext const&>(instruction).handler_target(),
static_cast<Op::EnterUnwindContext const&>(instruction).finalizer_target());
m_current_block = &static_cast<Op::EnterUnwindContext const&>(instruction).entry_point().block(); m_current_block = &static_cast<Op::EnterUnwindContext const&>(instruction).entry_point().block();
goto start; goto start;
case Instruction::Type::ContinuePendingUnwind: case Instruction::Type::ContinuePendingUnwind:
@ -264,10 +263,13 @@ void Interpreter::run_bytecode()
m_current_block = &static_cast<Op::ContinuePendingUnwind const&>(instruction).resume_target().block(); m_current_block = &static_cast<Op::ContinuePendingUnwind const&>(instruction).resume_target().block();
} }
goto start; goto start;
case Instruction::Type::ScheduleJump: case Instruction::Type::ScheduleJump: {
m_scheduled_jump = &static_cast<Op::ScheduleJump const&>(instruction).target().block(); m_scheduled_jump = &static_cast<Op::ScheduleJump const&>(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; goto start;
}
default: default:
result = instruction.execute(*this); result = instruction.execute(*this);
break; break;
@ -275,22 +277,26 @@ void Interpreter::run_bytecode()
if (result.is_error()) [[unlikely]] { if (result.is_error()) [[unlikely]] {
reg(Register::exception()) = *result.throw_completion().value(); 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; return;
auto& unwind_context = unwind_contexts().last(); auto& unwind_context = unwind_contexts().last();
if (unwind_context.executable != m_current_executable) VERIFY(unwind_context.executable == m_current_executable);
return;
if (unwind_context.handler && !unwind_context.handler_called) { if (handler) {
VERIFY(!unwind_context.handler_called);
vm().running_execution_context().lexical_environment = unwind_context.lexical_environment; 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; unwind_context.handler_called = true;
accumulator = reg(Register::exception()); accumulator = reg(Register::exception());
reg(Register::exception()) = {}; reg(Register::exception()) = {};
goto start; goto start;
} }
if (unwind_context.finalizer) { if (finalizer) {
m_current_block = unwind_context.finalizer; m_current_block = finalizer;
// If an exception was thrown inside the corresponding `catch` block, we need to rethrow it // 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 // from the `finally` block. But if the exception is from the `try` block, and has already been
// handled by `catch`, we swallow it. // handled by `catch`, we swallow it.
@ -316,15 +322,14 @@ void Interpreter::run_bytecode()
++pc; ++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(); auto& unwind_context = unwind_contexts().last();
if (unwind_context.executable == m_current_executable && unwind_context.finalizer) { VERIFY(unwind_context.executable == m_current_executable);
reg(Register::saved_return_value()) = reg(Register::return_value()); reg(Register::saved_return_value()) = reg(Register::return_value());
reg(Register::return_value()) = {}; reg(Register::return_value()) = {};
m_current_block = unwind_context.finalizer; m_current_block = finalizer;
// the unwind_context will be pop'ed when entering the finally block // the unwind_context will be pop'ed when entering the finally block
continue; continue;
}
} }
if (pc.at_end()) if (pc.at_end())
@ -407,12 +412,10 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable& executa
return { return_value, nullptr }; return { return_value, nullptr };
} }
void Interpreter::enter_unwind_context(Optional<Label> handler_target, Optional<Label> finalizer_target) void Interpreter::enter_unwind_context()
{ {
unwind_contexts().empend( unwind_contexts().empend(
m_current_executable, m_current_executable,
handler_target.has_value() ? &handler_target->block() : nullptr,
finalizer_target.has_value() ? &finalizer_target->block() : nullptr,
vm().running_execution_context().lexical_environment); vm().running_execution_context().lexical_environment);
} }

View file

@ -70,7 +70,7 @@ public:
reg(Register::exception()) = {}; reg(Register::exception()) = {};
} }
void enter_unwind_context(Optional<Label> handler_target, Optional<Label> finalizer_target); void enter_unwind_context();
void leave_unwind_context(); void leave_unwind_context();
Executable& current_executable() { return *m_current_executable; } Executable& current_executable() { return *m_current_executable; }