mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-01-22 17:24:48 -05:00
LibJS: Keep return value in a call frame register
This commit is contained in:
parent
c833885fb5
commit
0c746366cc
Notes:
sideshowbarker
2024-07-17 10:05:47 +09:00
Author: https://github.com/awesomekling Commit: https://github.com/SerenityOS/serenity/commit/0c746366cc Pull-request: https://github.com/SerenityOS/serenity/pull/21241
3 changed files with 18 additions and 16 deletions
|
@ -31,8 +31,6 @@ Interpreter::~Interpreter()
|
|||
|
||||
void Interpreter::visit_edges(Cell::Visitor& visitor)
|
||||
{
|
||||
if (m_return_value.has_value())
|
||||
visitor.visit(*m_return_value);
|
||||
for (auto& frame : m_call_frames) {
|
||||
frame.visit([&](auto& value) { value->visit_edges(visitor); });
|
||||
}
|
||||
|
@ -226,7 +224,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable& executa
|
|||
will_jump = true;
|
||||
break;
|
||||
}
|
||||
if (m_return_value.has_value()) {
|
||||
if (!reg(Register::return_value()).is_empty()) {
|
||||
will_return = true;
|
||||
// Note: A `yield` statement will not go through a finally statement,
|
||||
// hence we need to set a flag to not do so,
|
||||
|
@ -245,7 +243,8 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable& executa
|
|||
if (!unwind_contexts().is_empty() && !will_yield) {
|
||||
auto& unwind_context = unwind_contexts().last();
|
||||
if (unwind_context.executable == m_current_executable && unwind_context.finalizer) {
|
||||
reg(Register::saved_return_value()) = m_return_value.release_value();
|
||||
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;
|
||||
|
@ -275,18 +274,15 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable& executa
|
|||
}
|
||||
}
|
||||
|
||||
auto saved_return_value = reg(Register::saved_return_value());
|
||||
auto return_value = js_undefined();
|
||||
if (!reg(Register::return_value()).is_empty())
|
||||
return_value = reg(Register::return_value());
|
||||
else if (!reg(Register::saved_return_value()).is_empty())
|
||||
return_value = reg(Register::saved_return_value());
|
||||
auto exception = reg(Register::exception());
|
||||
|
||||
auto frame = pop_call_frame();
|
||||
|
||||
Value return_value = js_undefined();
|
||||
if (m_return_value.has_value()) {
|
||||
return_value = m_return_value.release_value();
|
||||
} else if (!saved_return_value.is_empty()) {
|
||||
return_value = saved_return_value;
|
||||
}
|
||||
|
||||
// NOTE: The return value from a called function is put into $0 in the caller context.
|
||||
if (!m_call_frames.is_empty())
|
||||
call_frame().registers[0] = return_value;
|
||||
|
@ -374,6 +370,7 @@ void Interpreter::push_call_frame(Variant<NonnullOwnPtr<CallFrame>, CallFrame*>
|
|||
m_call_frames.append(move(frame));
|
||||
this->call_frame().registers.resize(register_count);
|
||||
m_current_call_frame = this->call_frame().registers;
|
||||
reg(Register::return_value()) = {};
|
||||
}
|
||||
|
||||
Variant<NonnullOwnPtr<CallFrame>, CallFrame*> Interpreter::pop_call_frame()
|
||||
|
|
|
@ -74,9 +74,9 @@ public:
|
|||
VERIFY(unwind_contexts().last().finalizer);
|
||||
jump(Label { *unwind_contexts().last().finalizer });
|
||||
}
|
||||
void do_return(Value return_value)
|
||||
void do_return(Value value)
|
||||
{
|
||||
m_return_value = return_value;
|
||||
reg(Register::return_value()) = value;
|
||||
reg(Register::exception()) = {};
|
||||
}
|
||||
|
||||
|
@ -114,7 +114,6 @@ private:
|
|||
Span<Value> m_current_call_frame;
|
||||
Optional<BasicBlock const*> m_pending_jump;
|
||||
BasicBlock const* m_scheduled_jump { nullptr };
|
||||
Optional<Value> m_return_value;
|
||||
Executable* m_current_executable { nullptr };
|
||||
BasicBlock const* m_current_block { nullptr };
|
||||
Optional<InstructionStreamIterator&> m_pc {};
|
||||
|
|
|
@ -39,7 +39,13 @@ public:
|
|||
return Register(this_value_index);
|
||||
}
|
||||
|
||||
static constexpr u32 reserved_register_count = 4;
|
||||
static constexpr Register return_value()
|
||||
{
|
||||
constexpr u32 return_value_index = 4;
|
||||
return Register(return_value_index);
|
||||
}
|
||||
|
||||
static constexpr u32 reserved_register_count = 5;
|
||||
|
||||
constexpr explicit Register(u32 index)
|
||||
: m_index(index)
|
||||
|
|
Loading…
Reference in a new issue