From eb9298b54e7326cee5cf5b8ecc53971e75e90800 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 24 Jun 2023 06:44:01 +0200 Subject: [PATCH] LibJS/Bytecode: Support destructuring function parameters To reduce code duplication, I've added new VM::execute_ast_node() helper that handles bytecode compilation if needed. 918 new passes on test262. :^) --- Userland/Libraries/LibJS/Runtime/VM.cpp | 26 ++++++++++++++++--------- Userland/Libraries/LibJS/Runtime/VM.h | 4 ++++ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 8294953fad..427d86401a 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -295,12 +295,7 @@ ThrowCompletionOr VM::named_evaluation_if_anonymous_function(ASTNode cons } } - if (auto* bytecode_interpreter = bytecode_interpreter_if_exists()) { - auto executable = TRY(Bytecode::compile(*this, expression, FunctionKind::Normal, name)); - return TRY(bytecode_interpreter->run(*current_realm(), *executable)); - } - - return TRY(expression.execute(interpreter())).release_value(); + return execute_ast_node(expression); } // 13.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-destructuringassignmentevaluation @@ -361,6 +356,19 @@ ThrowCompletionOr VM::binding_initialization(NonnullRefPtr VM::execute_ast_node(ASTNode const& node) +{ + if (auto* bytecode_interpreter = bytecode_interpreter_if_exists()) { + auto executable = TRY(Bytecode::compile(*this, node, FunctionKind::Normal, ""sv)); + auto result_or_error = bytecode_interpreter->run_and_return_frame(*current_realm(), *executable, nullptr); + if (result_or_error.value.is_error()) + return result_or_error.value.release_error(); + return result_or_error.frame->registers[0]; + } + + return TRY(node.execute(interpreter())).value(); +} + // 13.15.5.3 Runtime Semantics: PropertyDestructuringAssignmentEvaluation, https://tc39.es/ecma262/#sec-runtime-semantics-propertydestructuringassignmentevaluation // 14.3.3.1 Runtime Semantics: PropertyBindingInitialization, https://tc39.es/ecma262/#sec-destructuring-binding-patterns-runtime-semantics-propertybindinginitialization ThrowCompletionOr VM::property_binding_initialization(BindingPattern const& binding, Value value, Environment* environment) @@ -401,7 +409,7 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const return identifier->string(); }, [&](NonnullRefPtr const& expression) -> ThrowCompletionOr { - auto result = TRY(expression->execute(interpreter())).release_value(); + auto result = TRY(execute_ast_node(*expression)); return result.to_property_key(vm); })); @@ -439,7 +447,7 @@ ThrowCompletionOr VM::property_binding_initialization(BindingPattern const if (auto* identifier_ptr = property.alias.get_pointer>()) value_to_assign = TRY(named_evaluation_if_anonymous_function(*property.initializer, (*identifier_ptr)->string())); else - value_to_assign = TRY(property.initializer->execute(interpreter())).release_value(); + value_to_assign = TRY(execute_ast_node(*property.initializer)); } if (auto* binding_ptr = property.alias.get_pointer>()) { @@ -576,7 +584,7 @@ ThrowCompletionOr VM::iterator_binding_initialization(BindingPattern const if (auto* identifier_ptr = entry.alias.get_pointer>()) value = TRY(named_evaluation_if_anonymous_function(*entry.initializer, (*identifier_ptr)->string())); else - value = TRY(entry.initializer->execute(interpreter())).release_value(); + value = TRY(execute_ast_node(*entry.initializer)); } if (auto* binding_ptr = entry.alias.get_pointer>()) { diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index adeb242b42..457315f3e3 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -272,6 +272,10 @@ public: Function(Realm&)> host_ensure_can_compile_strings; Function(Object&)> host_ensure_can_add_private_element; + // Execute a specific AST node either in AST or BC interpreter, depending on which one is enabled by default. + // NOTE: This is meant as a temporary stopgap until everything is bytecode. + ThrowCompletionOr execute_ast_node(ASTNode const&); + private: using ErrorMessages = AK::Array;