LibJS: Update AST to use completions :^)

This is another major milestone on our journey towards removing global
VM exception state :^)
Does pretty much exactly what it says on the tin: updating
ASTNode::execute() to return a Completion instead of a plain value. This
will *also* allow us to eventually remove the non-standard unwinding
mechanism and purely rely on the various completion types.
This commit is contained in:
Linus Groh 2022-01-02 21:37:50 +01:00
parent 95acb1ce88
commit da856d7742
Notes: sideshowbarker 2024-07-17 21:44:39 +09:00
11 changed files with 507 additions and 692 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -17,6 +17,7 @@
#include <AK/Variant.h>
#include <AK/Vector.h>
#include <LibJS/Forward.h>
#include <LibJS/Runtime/Completion.h>
#include <LibJS/Runtime/EnvironmentCoordinate.h>
#include <LibJS/Runtime/FunctionKind.h>
#include <LibJS/Runtime/PropertyKey.h>
@ -44,7 +45,7 @@ create_ast_node(SourceRange range, Args&&... args)
class ASTNode : public RefCounted<ASTNode> {
public:
virtual ~ASTNode() { }
virtual Value execute(Interpreter&, GlobalObject&) const = 0;
virtual Completion execute(Interpreter&, GlobalObject&) const = 0;
virtual void generate_bytecode(Bytecode::Generator&) const;
virtual void dump(int indent) const;
@ -107,7 +108,7 @@ public:
: Statement(source_range)
{
}
Value execute(Interpreter&, GlobalObject&) const override { return {}; }
Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
};
@ -117,7 +118,7 @@ public:
: Statement(source_range)
{
}
Value execute(Interpreter&, GlobalObject&) const override { return {}; }
Completion execute(Interpreter&, GlobalObject&) const override { return {}; }
};
class ExpressionStatement final : public Statement {
@ -128,7 +129,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -177,7 +178,7 @@ public:
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
Value evaluate_statements(Interpreter& interpreter, GlobalObject& global_object) const;
Completion evaluate_statements(Interpreter& interpreter, GlobalObject& global_object) const;
void add_var_scoped_declaration(NonnullRefPtr<Declaration> variables);
void add_lexical_declaration(NonnullRefPtr<Declaration> variables);
@ -254,7 +255,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
@ -296,7 +297,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
@ -323,7 +324,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
bool is_strict_mode() const { return m_is_strict_mode; }
void set_strict_mode() { m_is_strict_mode = true; }
@ -363,7 +364,7 @@ public:
: ScopeNode(source_range)
{
}
Value execute(Interpreter& interpreter, GlobalObject& object) const override;
Completion execute(Interpreter& interpreter, GlobalObject& object) const override;
};
class FunctionBody final : public ScopeNode {
@ -377,7 +378,7 @@ public:
bool in_strict_mode() const { return m_in_strict_mode; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
private:
bool m_in_strict_mode { false };
@ -413,7 +414,7 @@ public:
: Declaration(source_range)
{
}
Value execute(Interpreter&, GlobalObject&) const override { return {}; }
Completion execute(Interpreter&, GlobalObject&) const override { return {}; }
void for_each_bound_name(IteratorOrVoidFunction<FlyString const&>) const override
{
@ -516,7 +517,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -542,7 +543,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -562,7 +563,7 @@ public:
{
}
Value execute(Interpreter&, GlobalObject&) const override { return {}; }
Completion execute(Interpreter&, GlobalObject&) const override { return {}; }
};
class YieldExpression final : public Expression {
@ -577,7 +578,7 @@ public:
Expression const* argument() const { return m_argument; }
bool is_yield_from() const { return m_is_yield_from; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -594,7 +595,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -612,7 +613,7 @@ public:
Expression const* argument() const { return m_argument; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -634,7 +635,7 @@ public:
Statement const& consequent() const { return *m_consequent; }
Statement const* alternate() const { return m_alternate; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -656,7 +657,7 @@ public:
Expression const& test() const { return *m_test; }
Statement const& body() const { return *m_body; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -677,7 +678,7 @@ public:
Expression const& test() const { return *m_test; }
Statement const& body() const { return *m_body; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -698,7 +699,7 @@ public:
Expression const& object() const { return *m_object; }
Statement const& body() const { return *m_body; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -722,7 +723,7 @@ public:
Expression const* update() const { return m_update; }
Statement const& body() const { return *m_body; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -747,7 +748,7 @@ public:
Expression const& rhs() const { return *m_rhs; }
Statement const& body() const { return *m_body; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -770,7 +771,7 @@ public:
Expression const& rhs() const { return *m_rhs; }
Statement const& body() const { return *m_body; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -789,7 +790,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -833,7 +834,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -859,7 +860,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -888,7 +889,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -907,7 +908,7 @@ public:
}
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
private:
@ -930,7 +931,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -946,7 +947,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -962,7 +963,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -979,7 +980,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -998,7 +999,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
};
@ -1015,7 +1016,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1044,7 +1045,7 @@ public:
FlyString const& string() const { return m_string; }
void set_lexically_bound_function_argument_index(size_t index) { m_lexically_bound_function_argument = index; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1067,7 +1068,7 @@ public:
FlyString const& string() const { return m_string; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -1082,7 +1083,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
enum class ElementKind {
Method,
@ -1192,7 +1193,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual bool is_super_expression() const override { return true; }
@ -1212,7 +1213,7 @@ public:
StringView name() const { return m_name; }
RefPtr<FunctionExpression> constructor() const { return m_constructor; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
bool has_name() const { return !m_name.is_empty(); }
@ -1236,7 +1237,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1246,6 +1247,8 @@ public:
StringView name() const { return m_class_expression->name(); }
ThrowCompletionOr<Value> binding_class_declaration_evaluation(Interpreter& interpreter, GlobalObject& global_object) const;
private:
NonnullRefPtr<ClassExpression> m_class_expression;
};
@ -1258,7 +1261,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -1271,7 +1274,7 @@ public:
: Expression(source_range)
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
};
@ -1290,14 +1293,14 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
Expression const& callee() const { return m_callee; }
protected:
void throw_type_error_for_callee(Interpreter&, GlobalObject&, Value callee_value, StringView call_type) const;
Completion throw_type_error_for_callee(Interpreter&, GlobalObject&, Value callee_value, StringView call_type) const;
NonnullRefPtr<Expression> m_callee;
Vector<Argument> const m_arguments;
@ -1307,8 +1310,7 @@ private:
Value this_value;
Value callee;
};
ThisAndCallee compute_this_and_callee(Interpreter&, GlobalObject&, Reference const&) const;
ThrowCompletionOr<ThisAndCallee> compute_this_and_callee(Interpreter&, GlobalObject&, Reference const&) const;
};
class NewExpression final : public CallExpression {
@ -1318,7 +1320,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual bool is_new_expression() const override { return true; }
};
@ -1331,7 +1333,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -1375,7 +1377,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1400,7 +1402,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1441,7 +1443,7 @@ public:
auto& target() const { return m_target; }
Expression const* init() const { return m_init; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -1460,7 +1462,7 @@ public:
DeclarationKind declaration_kind() const { return m_declaration_kind; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1506,7 +1508,7 @@ public:
bool is_method() const { return m_is_method; }
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
private:
NonnullRefPtr<Expression> m_key;
@ -1524,7 +1526,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1545,7 +1547,7 @@ public:
Vector<RefPtr<Expression>> const& elements() const { return m_elements; }
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1568,7 +1570,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1589,7 +1591,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1608,7 +1610,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1662,7 +1664,7 @@ public:
{
}
virtual Value execute(Interpreter& interpreter, GlobalObject& global_object) const override;
virtual Completion execute(Interpreter& interpreter, GlobalObject& global_object) const override;
virtual ThrowCompletionOr<JS::Reference> to_reference(Interpreter& interpreter, GlobalObject& global_object) const override;
virtual void dump(int indent) const override;
@ -1671,7 +1673,7 @@ private:
JS::Reference reference;
Value value;
};
Optional<ReferenceAndValue> to_reference_and_value(Interpreter&, GlobalObject&) const;
ThrowCompletionOr<ReferenceAndValue> to_reference_and_value(Interpreter&, GlobalObject&) const;
NonnullRefPtr<Expression> m_base;
Vector<Reference> m_references;
@ -1690,7 +1692,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void dump(int indent) const override;
private:
@ -1707,7 +1709,7 @@ public:
}
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
private:
NonnullRefPtr<Expression> m_specifier;
@ -1725,7 +1727,7 @@ public:
}
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
private:
@ -1754,7 +1756,7 @@ public:
BlockStatement const& body() const { return m_body; }
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
private:
Variant<FlyString, NonnullRefPtr<BindingPattern>> m_parameter;
@ -1776,7 +1778,7 @@ public:
BlockStatement const* finalizer() const { return m_finalizer; }
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
void add_label(FlyString string) override;
@ -1797,7 +1799,7 @@ public:
Expression const& argument() const { return m_argument; }
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
private:
@ -1815,7 +1817,7 @@ public:
Expression const* test() const { return m_test; }
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
private:
RefPtr<Expression> m_test;
@ -1830,7 +1832,7 @@ public:
}
virtual void dump(int indent) const override;
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
void add_case(NonnullRefPtr<SwitchCase> switch_case) { m_cases.append(move(switch_case)); }
@ -1848,7 +1850,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
FlyString const& target_label() const { return m_target_label; }
virtual void generate_bytecode(Bytecode::Generator&) const override;
@ -1865,7 +1867,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
FlyString const& target_label() const { return m_target_label; }
@ -1881,7 +1883,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override;
virtual Completion execute(Interpreter&, GlobalObject&) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
};
@ -1894,7 +1896,7 @@ public:
{
}
virtual Value execute(Interpreter&, GlobalObject&) const override { return m_value; }
virtual Completion execute(Interpreter&, GlobalObject&) const override { return m_value; }
virtual ThrowCompletionOr<Reference> to_reference(Interpreter&, GlobalObject&) const override { return m_reference; }
private:

View file

@ -315,13 +315,10 @@ void Jump::execute_impl(Bytecode::Interpreter& interpreter) const
void ResolveThisBinding::execute_impl(Bytecode::Interpreter& interpreter) const
{
auto this_binding_or_error = interpreter.vm().resolve_this_binding(interpreter.global_object());
if (this_binding_or_error.is_throw_completion()) {
interpreter.vm().throw_exception(interpreter.global_object(), this_binding_or_error.release_error().value());
auto value_or_error = interpreter.vm().resolve_this_binding(interpreter.global_object());
if (value_or_error.is_error())
return;
}
interpreter.accumulator() = this_binding_or_error.release_value();
interpreter.accumulator() = value_or_error.release_value();
}
void Jump::replace_references_impl(BasicBlock const& from, BasicBlock const& to)

View file

@ -59,8 +59,8 @@ void Interpreter::run(GlobalObject& global_object, const Program& program)
execution_context.realm = &realm();
execution_context.is_strict_mode = program.is_strict_mode();
MUST(vm.push_execution_context(execution_context, global_object));
auto value = program.execute(*this, global_object);
vm.set_last_value(Badge<Interpreter> {}, value.value_or(js_undefined()));
auto completion = program.execute(*this, global_object);
vm.set_last_value(Badge<Interpreter> {}, completion.value().value_or(js_undefined()));
// FIXME: We unconditionally stop the unwind here this should be done using completions leaving
// the VM in a cleaner state after executing. For example it does still store the exception.

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -564,7 +564,7 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
TemporaryChange scope_change_strict(vm.running_execution_context().is_strict_mode, strict_eval);
Value eval_result;
Optional<Value> eval_result;
if (auto* bytecode_interpreter = Bytecode::Interpreter::current()) {
auto executable = JS::Bytecode::Generator::generate(program);
@ -572,16 +572,16 @@ ThrowCompletionOr<Value> perform_eval(Value x, GlobalObject& caller_realm, Calle
if (JS::Bytecode::g_dump_bytecode)
executable.dump();
eval_result = TRY(bytecode_interpreter->run(executable));
// Turn potentially empty JS::Value from the bytecode interpreter into an empty Optional
if (eval_result.has_value() && eval_result->is_empty())
eval_result = {};
} else {
auto& ast_interpreter = vm.interpreter();
// FIXME: We need to use evaluate_statements() here because Program::execute() calls global_declaration_instantiation() when it shouldn't
eval_result = program->evaluate_statements(ast_interpreter, caller_realm);
eval_result = TRY(program->evaluate_statements(ast_interpreter, caller_realm));
}
if (auto* exception = vm.exception())
return throw_completion(exception->value());
else
return eval_result.value_or(js_undefined());
return eval_result.value_or(js_undefined());
}
// 19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict ), https://tc39.es/ecma262/#sec-evaldeclarationinstantiation

View file

@ -50,9 +50,7 @@ ThrowCompletionOr<Object*> AsyncFunctionConstructor::construct(FunctionObject& n
}
VM::InterpreterExecutionScope scope(*interpreter);
auto result = function->execute(*interpreter, global_object());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto result = TRY(function->execute(*interpreter, global_object())).release_value();
VERIFY(result.is_object() && is<ECMAScriptFunctionObject>(result.as_object()));
return &result.as_object();
}

View file

@ -54,9 +54,7 @@ ThrowCompletionOr<Object*> AsyncGeneratorFunctionConstructor::construct(Function
}
VM::InterpreterExecutionScope scope(*interpreter);
auto result = function->execute(*interpreter, global_object());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto result = TRY(function->execute(*interpreter, global_object())).release_value();
VERIFY(result.is_object() && is<ECMAScriptFunctionObject>(result.as_object()));
return &result.as_object();
}

View file

@ -431,9 +431,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
} else if (parameter.default_value) {
// FIXME: Support default arguments in the bytecode world!
if (interpreter)
argument_value = parameter.default_value->execute(*interpreter, global_object());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
argument_value = TRY(parameter.default_value->execute(*interpreter, global_object())).release_value();
} else {
argument_value = js_undefined();
}
@ -715,27 +713,26 @@ void ECMAScriptFunctionObject::async_block_start(PromiseCapability const& promis
// c. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
vm.pop_execution_context();
// NOTE: Running the AST node should eventually return a completion.
// Until it does, we assume "return" and include the undefined fallback from the call site.
// NOTE: Eventually we'll distinguish between normal and return completion.
// For now, we assume "return" and include the undefined fallback from the call site.
// d. If result.[[Type]] is normal, then
if (false) {
// i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
MUST(call(global_object, promise_capability.resolve, js_undefined(), js_undefined()));
}
// e. Else if result.[[Type]] is return, then
else if (!vm.exception()) {
else if (result.type() == Completion::Type::Return || result.type() == Completion::Type::Normal) {
// i. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
MUST(call(global_object, promise_capability.resolve, js_undefined(), result.value_or(js_undefined())));
MUST(call(global_object, promise_capability.resolve, js_undefined(), result.value().value_or(js_undefined())));
}
// f. Else,
else {
// i. Assert: result.[[Type]] is throw.
// ii. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
auto reason = vm.exception()->value();
vm.clear_exception();
vm.stop_unwind();
MUST(call(global_object, promise_capability.reject, js_undefined(), reason));
MUST(call(global_object, promise_capability.reject, js_undefined(), *result.value()));
}
// g. Return.
return js_undefined();
@ -823,11 +820,9 @@ Completion ECMAScriptFunctionObject::ordinary_call_evaluate_body()
if (m_kind == FunctionKind::Regular) {
TRY(function_declaration_instantiation(ast_interpreter));
auto result = m_ecmascript_code->execute(*ast_interpreter, global_object());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
// NOTE: Running the AST node should eventually return a completion.
// Until it does, we assume "return" and include the undefined fallback from the call site.
auto result = TRY(m_ecmascript_code->execute(*ast_interpreter, global_object()));
// NOTE: Once 'return' completions are being used, we can just return the completion from execute() directly.
// For now, we assume "return" and include the undefined fallback from the call site.
return { Completion::Type::Return, result.value_or(js_undefined()), {} };
} else if (m_kind == FunctionKind::Async) {
// 1. Let promiseCapability be ! NewPromiseCapability(%Promise%).

View file

@ -87,9 +87,7 @@ ThrowCompletionOr<Object*> FunctionConstructor::construct(FunctionObject& new_ta
}
VM::InterpreterExecutionScope scope(*interpreter);
auto result = function->execute(*interpreter, global_object());
if (auto* exception = vm.exception())
return throw_completion(exception->value());
auto result = TRY(function->execute(*interpreter, global_object())).release_value();
VERIFY(result.is_object() && is<ECMAScriptFunctionObject>(result.as_object()));
return &result.as_object();
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021-2022, Linus Groh <linusg@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@ -117,13 +117,7 @@ ThrowCompletionOr<Value> perform_shadow_realm_eval(GlobalObject& global_object,
// TODO: Optionally use bytecode interpreter?
// FIXME: We need to use evaluate_statements() here because Program::execute() calls global_declaration_instantiation() when it shouldn't
// a. Set result to the result of evaluating body.
auto result_value = program->evaluate_statements(vm.interpreter(), eval_realm.global_object());
if (auto* exception = vm.exception())
result = throw_completion(exception->value());
else if (!result_value.is_empty())
result = normal_completion(result_value);
else
result = Completion {}; // Normal completion with no value
result = program->evaluate_statements(vm.interpreter(), eval_realm.global_object());
}
// 21. If result.[[Type]] is normal and result.[[Value]] is empty, then

View file

@ -1,6 +1,6 @@
/*
* Copyright (c) 2020-2021, Andreas Kling <kling@serenityos.org>
* Copyright (c) 2020-2021, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2020-2022, Linus Groh <linusg@serenityos.org>
* Copyright (c) 2021, David Tuin <davidot@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -160,10 +160,7 @@ ThrowCompletionOr<Value> VM::named_evaluation_if_anonymous_function(GlobalObject
}
}
auto value = expression.execute(interpreter(), global_object);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
return value;
return TRY(expression.execute(interpreter(), global_object)).release_value();
}
// 13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-destructuringassignmentevaluation
@ -244,9 +241,6 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
VERIFY_NOT_REACHED();
}
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto* rest_object = Object::create(global_object, global_object.object_prototype());
VERIFY(rest_object);
@ -257,25 +251,15 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
return assignment_target.initialize_referenced_binding(global_object, rest_object);
}
PropertyKey name;
property.name.visit(
[&](Empty) { VERIFY_NOT_REACHED(); },
[&](NonnullRefPtr<Identifier> const& identifier) {
name = identifier->string();
auto name = TRY(property.name.visit(
[&](Empty) -> ThrowCompletionOr<PropertyKey> { VERIFY_NOT_REACHED(); },
[&](NonnullRefPtr<Identifier> const& identifier) -> ThrowCompletionOr<PropertyKey> {
return identifier->string();
},
[&](NonnullRefPtr<Expression> const& expression) {
auto result = expression->execute(interpreter(), global_object);
if (exception())
return;
auto name_or_error = result.to_property_key(global_object);
if (name_or_error.is_error())
return;
name = name_or_error.release_value();
});
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
[&](NonnullRefPtr<Expression> const& expression) -> ThrowCompletionOr<PropertyKey> {
auto result = TRY(expression->execute(interpreter(), global_object)).release_value();
return result.to_property_key(global_object);
}));
seen_names.set(name);
@ -306,18 +290,12 @@ ThrowCompletionOr<void> VM::property_binding_initialization(BindingPattern const
return TRY(member_expression->to_reference(interpreter(), global_object));
}));
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
auto value_to_assign = TRY(object->get(name));
if (property.initializer && value_to_assign.is_undefined()) {
if (auto* identifier_ptr = property.alias.get_pointer<NonnullRefPtr<Identifier>>())
value_to_assign = TRY(named_evaluation_if_anonymous_function(global_object, *property.initializer, (*identifier_ptr)->string()));
else
value_to_assign = property.initializer->execute(interpreter(), global_object);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
value_to_assign = TRY(property.initializer->execute(interpreter(), global_object)).release_value();
}
if (auto* binding_ptr = property.alias.get_pointer<NonnullRefPtr<BindingPattern>>()) {
@ -405,10 +383,7 @@ ThrowCompletionOr<void> VM::iterator_binding_initialization(BindingPattern const
if (auto* identifier_ptr = entry.alias.get_pointer<NonnullRefPtr<Identifier>>())
value = TRY(named_evaluation_if_anonymous_function(global_object, *entry.initializer, (*identifier_ptr)->string()));
else
value = entry.initializer->execute(interpreter(), global_object);
if (auto* thrown_exception = exception())
return JS::throw_completion(thrown_exception->value());
value = TRY(entry.initializer->execute(interpreter(), global_object)).release_value();
}
if (auto* binding_ptr = entry.alias.get_pointer<NonnullRefPtr<BindingPattern>>()) {