mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-05-02 09:18:52 +00:00
LibJS: Make return control flow more static
With this only `ContinuePendingUnwind` needs to dynamically check if a scheduled return needs to go through a `finally` block, making the interpreter loop a bit nicer
This commit is contained in:
parent
73fdd31124
commit
c8e4499b08
Notes:
sideshowbarker
2024-07-17 03:30:41 +09:00
Author: https://github.com/Hendiadyoin1
Commit: c8e4499b08
Pull-request: https://github.com/SerenityOS/serenity/pull/24295
4 changed files with 54 additions and 38 deletions
|
@ -356,8 +356,6 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
goto* bytecode_dispatch_table[static_cast<size_t>(next_instruction.type())]; \
|
||||
} while (0)
|
||||
|
||||
bool will_yield = false;
|
||||
|
||||
for (;;) {
|
||||
start:
|
||||
for (;;) {
|
||||
|
@ -486,7 +484,19 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
}
|
||||
if (!saved_return_value().is_empty()) {
|
||||
do_return(saved_return_value());
|
||||
goto run_finalizer_and_return;
|
||||
if (auto handlers = executable.exception_handlers_for_offset(program_counter); handlers.has_value()) {
|
||||
if (auto finalizer = handlers.value().finalizer_offset; finalizer.has_value()) {
|
||||
VERIFY(!running_execution_context.unwind_contexts.is_empty());
|
||||
auto& unwind_context = running_execution_context.unwind_contexts.last();
|
||||
VERIFY(unwind_context.executable == m_current_executable);
|
||||
reg(Register::saved_return_value()) = reg(Register::return_value());
|
||||
reg(Register::return_value()) = {};
|
||||
program_counter = finalizer.value();
|
||||
// the unwind_context will be pop'ed when entering the finally block
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
auto const old_scheduled_jump = running_execution_context.previously_scheduled_jumps.take_last();
|
||||
if (m_scheduled_jump.has_value()) {
|
||||
|
@ -639,14 +649,13 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
handle_Await: {
|
||||
auto& instruction = *reinterpret_cast<Op::Await const*>(&bytecode[program_counter]);
|
||||
instruction.execute_impl(*this);
|
||||
will_yield = true;
|
||||
goto run_finalizer_and_return;
|
||||
return;
|
||||
}
|
||||
|
||||
handle_Return: {
|
||||
auto& instruction = *reinterpret_cast<Op::Return const*>(&bytecode[program_counter]);
|
||||
instruction.execute_impl(*this);
|
||||
goto run_finalizer_and_return;
|
||||
return;
|
||||
}
|
||||
|
||||
handle_Yield: {
|
||||
|
@ -657,27 +666,10 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
// but we generate a Yield Operation in the case of returns in
|
||||
// generators as well, so we need to check if it will actually
|
||||
// continue or is a `return` in disguise
|
||||
will_yield = instruction.continuation().has_value();
|
||||
goto run_finalizer_and_return;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run_finalizer_and_return:
|
||||
if (!will_yield) {
|
||||
if (auto handlers = executable.exception_handlers_for_offset(program_counter); handlers.has_value()) {
|
||||
if (auto finalizer = handlers.value().finalizer_offset; finalizer.has_value()) {
|
||||
VERIFY(!running_execution_context.unwind_contexts.is_empty());
|
||||
auto& unwind_context = running_execution_context.unwind_contexts.last();
|
||||
VERIFY(unwind_context.executable == m_current_executable);
|
||||
reg(Register::saved_return_value()) = reg(Register::return_value());
|
||||
reg(Register::return_value()) = {};
|
||||
program_counter = finalizer.value();
|
||||
// the unwind_context will be pop'ed when entering the finally block
|
||||
goto start;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Interpreter::ResultAndReturnRegister Interpreter::run_executable(Executable& executable, Optional<size_t> entry_point, Value initial_accumulator_value)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue