1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 12:55:09 +00:00

LibJS: Convert Instruction::execute in bytecode to ThrowCompletionOr

This allows us to use TRY in these functions :^).
This commit is contained in:
davidot 2022-02-07 14:36:45 +01:00 committed by Linus Groh
parent de90d54be0
commit 8108fc7f9c
6 changed files with 238 additions and 294 deletions

View file

@ -44,6 +44,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
dbgln_if(JS_BYTECODE_DEBUG, "Bytecode::Interpreter will run unit {:p}", &executable);
TemporaryChange restore_executable { m_current_executable, &executable };
VERIFY(m_saved_exception.is_null());
ExecutionContext execution_context(vm().heap());
if (vm().execution_context_stack().is_empty() || !vm().running_execution_context().lexical_environment) {
@ -76,9 +77,17 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
bool will_return = false;
while (!pc.at_end()) {
auto& instruction = *pc;
instruction.execute(*this);
auto ran_or_error = instruction.execute(*this);
if (vm().exception()) {
m_saved_exception = {};
if (!ran_or_error.is_error()) {
// FIXME: Until exception is removed use this to make sure we always get the error if there is one.
ran_or_error = throw_completion(vm().exception()->value());
}
vm().clear_exception();
}
if (ran_or_error.is_error()) {
auto exception_value = *ran_or_error.throw_completion().value();
m_saved_exception = make_handle(exception_value);
if (m_unwind_contexts.is_empty())
break;
auto& unwind_context = m_unwind_contexts.last();
@ -87,8 +96,8 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
if (unwind_context.handler) {
block = unwind_context.handler;
unwind_context.handler = nullptr;
accumulator() = vm().exception()->value();
vm().clear_exception();
accumulator() = exception_value;
m_saved_exception = {};
will_jump = true;
break;
}
@ -96,8 +105,6 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
block = unwind_context.finalizer;
m_unwind_contexts.take_last();
will_jump = true;
m_saved_exception = Handle<Exception>::create(vm().exception());
vm().clear_exception();
break;
}
}
@ -119,7 +126,7 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
if (pc.at_end() && !will_jump)
break;
if (vm().exception())
if (!m_saved_exception.is_null())
break;
}
@ -142,12 +149,6 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
m_manually_entered_frames.take_last();
}
Value exception_value;
if (vm().exception()) {
exception_value = vm().exception()->value();
vm().clear_exception();
}
auto return_value = m_return_value.value_or(js_undefined());
m_return_value = {};
@ -164,8 +165,11 @@ Interpreter::ValueAndFrame Interpreter::run_and_return_frame(Executable const& e
vm().finish_execution_generation();
if (!exception_value.is_empty())
return { throw_completion(exception_value), move(frame) };
if (!m_saved_exception.is_null()) {
Value thrown_value = m_saved_exception.value();
m_saved_exception = {};
return { throw_completion(thrown_value), move(frame) };
}
return { return_value, move(frame) };
}
@ -180,14 +184,16 @@ void Interpreter::leave_unwind_context()
m_unwind_contexts.take_last();
}
void Interpreter::continue_pending_unwind(Label const& resume_label)
ThrowCompletionOr<void> Interpreter::continue_pending_unwind(Label const& resume_label)
{
if (!m_saved_exception.is_null()) {
vm().set_exception(*m_saved_exception.cell());
auto result = throw_completion(m_saved_exception.value());
m_saved_exception = {};
} else {
jump(resume_label);
return result;
}
jump(resume_label);
return {};
}
AK::Array<OwnPtr<PassManager>, static_cast<UnderlyingType<Interpreter::OptimizationLevel>>(Interpreter::OptimizationLevel::__Count)> Interpreter::s_optimization_pipelines {};