mirror of
https://github.com/RGBCube/serenity
synced 2025-05-18 21:35:06 +00:00
LibJS: Keep return value in a call frame register
This commit is contained in:
parent
c833885fb5
commit
0c746366cc
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()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue