diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index 14660e38a8a..e91ec30aef6 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -647,7 +647,7 @@ struct BindingPattern : RefCounted { bool contains_expression() const; - Bytecode::CodeGenerationErrorOr generate_bytecode(Bytecode::Generator&, Bytecode::Op::SetVariable::InitializationMode initialization_mode, Bytecode::ScopedOperand const& object, bool create_variables) const; + Bytecode::CodeGenerationErrorOr generate_bytecode(Bytecode::Generator&, Bytecode::Op::BindingInitializationMode initialization_mode, Bytecode::ScopedOperand const& object, bool create_variables) const; Vector entries; Kind kind { Kind::Object }; diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index f976b941183..09d2ee68761 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -585,7 +585,7 @@ Bytecode::CodeGenerationErrorOr> AssignmentExpression::g auto rval = TRY(m_rhs->generate_bytecode(generator)).value(); // 5. Perform ? DestructuringAssignmentEvaluation of assignmentPattern with argument rval. - TRY(pattern->generate_bytecode(generator, Bytecode::Op::SetVariable::InitializationMode::Set, rval, false)); + TRY(pattern->generate_bytecode(generator, Bytecode::Op::BindingInitializationMode::Set, rval, false)); // 6. Return rval. return rval; @@ -1151,7 +1151,7 @@ Bytecode::CodeGenerationErrorOr> FunctionDeclaration::ge auto index = generator.intern_identifier(name()); auto value = generator.allocate_register(); generator.emit(value, index); - generator.emit(index, value, Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode::Var); + generator.emit(index, value); } return Optional {}; } @@ -1173,7 +1173,7 @@ Bytecode::CodeGenerationErrorOr> FunctionExpression::gen generator.emit_new_function(new_function, *this, lhs_name); if (has_name) { - generator.emit(*name_identifier, new_function, Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical); + generator.emit(*name_identifier, new_function); generator.end_variable_scope(); } @@ -1186,7 +1186,7 @@ Bytecode::CodeGenerationErrorOr> FunctionExpression::gen return generate_bytecode_with_lhs_name(generator, {}, preferred_dst); } -static Bytecode::CodeGenerationErrorOr generate_object_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::SetVariable::InitializationMode initialization_mode, ScopedOperand const& object, bool create_variables) +static Bytecode::CodeGenerationErrorOr generate_object_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::BindingInitializationMode initialization_mode, ScopedOperand const& object, bool create_variables) { generator.emit(object); @@ -1300,7 +1300,7 @@ static Bytecode::CodeGenerationErrorOr generate_object_binding_pattern_byt return {}; } -static Bytecode::CodeGenerationErrorOr generate_array_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::SetVariable::InitializationMode initialization_mode, ScopedOperand const& input_array, bool create_variables, [[maybe_unused]] Optional preferred_dst = {}) +static Bytecode::CodeGenerationErrorOr generate_array_binding_pattern_bytecode(Bytecode::Generator& generator, BindingPattern const& pattern, Bytecode::Op::BindingInitializationMode initialization_mode, ScopedOperand const& input_array, bool create_variables, [[maybe_unused]] Optional preferred_dst = {}) { /* * Consider the following destructuring assignment: @@ -1476,7 +1476,7 @@ static Bytecode::CodeGenerationErrorOr generate_array_binding_pattern_byte return {}; } -Bytecode::CodeGenerationErrorOr BindingPattern::generate_bytecode(Bytecode::Generator& generator, Bytecode::Op::SetVariable::InitializationMode initialization_mode, ScopedOperand const& input_value, bool create_variables) const +Bytecode::CodeGenerationErrorOr BindingPattern::generate_bytecode(Bytecode::Generator& generator, Bytecode::Op::BindingInitializationMode initialization_mode, ScopedOperand const& input_value, bool create_variables) const { if (kind == Kind::Object) return generate_object_binding_pattern_bytecode(generator, *this, initialization_mode, input_value, create_variables); @@ -1486,7 +1486,7 @@ Bytecode::CodeGenerationErrorOr BindingPattern::generate_bytecode(Bytecode static Bytecode::CodeGenerationErrorOr assign_value_to_variable_declarator(Bytecode::Generator& generator, VariableDeclarator const& declarator, VariableDeclaration const& declaration, ScopedOperand value) { - auto initialization_mode = declaration.is_lexical_declaration() ? Bytecode::Op::SetVariable::InitializationMode::Initialize : Bytecode::Op::SetVariable::InitializationMode::Set; + auto initialization_mode = declaration.is_lexical_declaration() ? Bytecode::Op::BindingInitializationMode::Initialize : Bytecode::Op::BindingInitializationMode::Set; return declarator.target().visit( [&](NonnullRefPtr const& id) -> Bytecode::CodeGenerationErrorOr { @@ -2569,14 +2569,14 @@ Bytecode::CodeGenerationErrorOr> TryStatement::generate_ did_create_variable_scope_for_catch_clause = true; auto parameter_identifier = generator.intern_identifier(parameter); generator.emit(parameter_identifier, Bytecode::Op::EnvironmentMode::Lexical, false); - generator.emit(parameter_identifier, caught_value, Bytecode::Op::SetVariable::InitializationMode::Initialize); + generator.emit(parameter_identifier, caught_value); } return {}; }, [&](NonnullRefPtr const& binding_pattern) -> Bytecode::CodeGenerationErrorOr { generator.begin_variable_scope(); did_create_variable_scope_for_catch_clause = true; - TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::SetVariable::InitializationMode::Initialize, caught_value, true)); + TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::BindingInitializationMode::Initialize, caught_value, true)); return {}; })); @@ -2763,7 +2763,7 @@ Bytecode::CodeGenerationErrorOr> ClassDeclaration::gener { Bytecode::Generator::SourceLocationScope scope(generator, *this); auto value = TRY(m_class_expression->generate_bytecode(generator)).value(); - generator.emit_set_variable(*m_class_expression.ptr()->m_name, value, Bytecode::Op::SetVariable::InitializationMode::Initialize); + generator.emit_set_variable(*m_class_expression.ptr()->m_name, value, Bytecode::Op::BindingInitializationMode::Initialize); // NOTE: ClassDeclaration does not produce a value. return Optional {}; } @@ -3130,7 +3130,7 @@ static Bytecode::CodeGenerationErrorOr> for_in_of_body_e TRY(generator.emit_store_to_reference(**ptr, next_value)); } else { auto& binding_pattern = lhs.get>(); - TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::SetVariable::InitializationMode::Set, next_value, false)); + TRY(binding_pattern->generate_bytecode(generator, Bytecode::Op::BindingInitializationMode::Set, next_value, false)); } } } @@ -3186,7 +3186,7 @@ static Bytecode::CodeGenerationErrorOr> for_in_of_body_e // 3. Let lhsRef be ! ResolveBinding(lhsName). // NOTE: We're skipping all the completion stuff that the spec does, as the unwinding mechanism will take case of doing that. - generator.emit_set_variable(*lhs_name, next_value, Bytecode::Op::SetVariable::InitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical); + generator.emit_set_variable(*lhs_name, next_value, Bytecode::Op::BindingInitializationMode::Initialize, Bytecode::Op::EnvironmentMode::Lexical); } } // i. If destructuring is false, then @@ -3217,7 +3217,7 @@ static Bytecode::CodeGenerationErrorOr> for_in_of_body_e auto& binding_pattern = declaration.declarations().first()->target().get>(); (void)TRY(binding_pattern->generate_bytecode( generator, - head_result.lhs_kind == LHSKind::VarBinding ? Bytecode::Op::SetVariable::InitializationMode::Set : Bytecode::Op::SetVariable::InitializationMode::Initialize, + head_result.lhs_kind == LHSKind::VarBinding ? Bytecode::Op::BindingInitializationMode::Set : Bytecode::Op::BindingInitializationMode::Initialize, next_value, false)); } else { @@ -3466,10 +3466,9 @@ Bytecode::CodeGenerationErrorOr> ExportStatement::genera auto value = TRY(generator.emit_named_evaluation_if_anonymous_function(static_cast(*m_statement), generator.intern_identifier("default"sv))).value(); if (!static_cast(*m_statement).has_name()) { - generator.emit( + generator.emit( generator.intern_identifier(ExportStatement::local_name_for_default), - value, - Bytecode::Op::SetVariable::InitializationMode::Initialize); + value); } return value; @@ -3478,10 +3477,9 @@ Bytecode::CodeGenerationErrorOr> ExportStatement::genera // ExportDeclaration : export default AssignmentExpression ; VERIFY(is(*m_statement)); auto value = TRY(generator.emit_named_evaluation_if_anonymous_function(static_cast(*m_statement), generator.intern_identifier("default"sv))).value(); - generator.emit( + generator.emit( generator.intern_identifier(ExportStatement::local_name_for_default), - value, - Bytecode::Op::SetVariable::InitializationMode::Initialize); + value); return value; } diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index f502df24411..a6da4422872 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -399,29 +399,6 @@ inline ThrowCompletionOr typeof_variable(VM& vm, DeprecatedFlyString cons return PrimitiveString::create(vm, value.typeof()); } -inline ThrowCompletionOr set_variable( - VM& vm, - DeprecatedFlyString const& name, - Value value, - Op::EnvironmentMode mode, - Op::SetVariable::InitializationMode initialization_mode, - EnvironmentCoordinate& cache) -{ - auto environment = mode == Op::EnvironmentMode::Lexical ? vm.running_execution_context().lexical_environment : vm.running_execution_context().variable_environment; - auto reference = TRY(vm.resolve_binding(name, environment)); - if (reference.environment_coordinate().has_value()) - cache = reference.environment_coordinate().value(); - switch (initialization_mode) { - case Op::SetVariable::InitializationMode::Initialize: - TRY(reference.initialize_referenced_binding(vm, value)); - break; - case Op::SetVariable::InitializationMode::Set: - TRY(reference.put_value(vm, value)); - break; - } - return {}; -} - inline Value new_function(VM& vm, FunctionNode const& function_node, Optional const& lhs_name, Optional const& home_object) { Value value; diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 1e1ba31a9bb..5915404d4b3 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -39,7 +39,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E auto id = intern_identifier(parameter_name.key); emit(id, Op::EnvironmentMode::Lexical, false); if (function.m_has_duplicates) { - emit(id, add_constant(js_undefined()), Op::SetVariable::InitializationMode::Initialize, Op::EnvironmentMode::Lexical); + emit(id, add_constant(js_undefined())); } } } @@ -87,17 +87,18 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E set_local_initialized((*identifier)->local_variable_index()); } else { auto id = intern_identifier((*identifier)->string()); - auto init_mode = function.m_has_duplicates ? Op::SetVariable::InitializationMode::Set : Op::SetVariable::InitializationMode::Initialize; auto argument_reg = allocate_register(); emit(argument_reg.operand(), param_index); - emit(id, argument_reg.operand(), - init_mode, - Op::EnvironmentMode::Lexical); + if (function.m_has_duplicates) { + emit(id, argument_reg.operand()); + } else { + emit(id, argument_reg.operand()); + } } } else if (auto const* binding_pattern = parameter.binding.get_pointer>(); binding_pattern) { auto input_operand = allocate_register(); emit(input_operand.operand(), param_index); - auto init_mode = function.m_has_duplicates ? Op::SetVariable::InitializationMode::Set : Bytecode::Op::SetVariable::InitializationMode::Initialize; + auto init_mode = function.m_has_duplicates ? Op::BindingInitializationMode::Set : Bytecode::Op::BindingInitializationMode::Initialize; TRY((*binding_pattern)->generate_bytecode(*this, init_mode, input_operand, false)); } } @@ -115,7 +116,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E } else { auto intern_id = intern_identifier(id.string()); emit(intern_id, Op::EnvironmentMode::Var, false); - emit(intern_id, add_constant(js_undefined()), Bytecode::Op::SetVariable::InitializationMode::Initialize, Op::EnvironmentMode::Var); + emit(intern_id, add_constant(js_undefined())); } } } @@ -141,7 +142,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E } else { auto intern_id = intern_identifier(id.string()); emit(intern_id, Op::EnvironmentMode::Var, false); - emit(intern_id, initial_value, Op::SetVariable::InitializationMode::Initialize, Op::EnvironmentMode::Var); + emit(intern_id, initial_value); } } } @@ -151,7 +152,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E for (auto const& function_name : function.m_function_names_to_initialize_binding) { auto intern_id = intern_identifier(function_name); emit(intern_id, Op::EnvironmentMode::Var, false); - emit(intern_id, add_constant(js_undefined()), Bytecode::Op::SetVariable::InitializationMode::Initialize, Op::EnvironmentMode::Var); + emit(intern_id, add_constant(js_undefined())); } } @@ -184,7 +185,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E if (declaration.name_identifier()->is_local()) { emit(local(declaration.name_identifier()->local_variable_index()), function); } else { - emit(intern_identifier(declaration.name()), function, Op::SetVariable::InitializationMode::Set, Op::EnvironmentMode::Var); + emit(intern_identifier(declaration.name()), function); } } @@ -808,7 +809,7 @@ CodeGenerationErrorOr> Generator::emit_delete_reference( return add_constant(Value(true)); } -void Generator::emit_set_variable(JS::Identifier const& identifier, ScopedOperand value, Bytecode::Op::SetVariable::InitializationMode initialization_mode, Bytecode::Op::EnvironmentMode mode) +void Generator::emit_set_variable(JS::Identifier const& identifier, ScopedOperand value, Bytecode::Op::BindingInitializationMode initialization_mode, Bytecode::Op::EnvironmentMode environment_mode) { if (identifier.is_local()) { if (value.operand().is_local() && value.operand().index() == identifier.local_variable_index()) { @@ -817,7 +818,22 @@ void Generator::emit_set_variable(JS::Identifier const& identifier, ScopedOperan } emit(local(identifier.local_variable_index()), value); } else { - emit(intern_identifier(identifier.string()), value, initialization_mode, mode); + auto identifier_index = intern_identifier(identifier.string()); + if (environment_mode == Bytecode::Op::EnvironmentMode::Lexical) { + if (initialization_mode == Bytecode::Op::BindingInitializationMode::Initialize) { + emit(identifier_index, value); + } else if (initialization_mode == Bytecode::Op::BindingInitializationMode::Set) { + emit(identifier_index, value); + } + } else if (environment_mode == Bytecode::Op::EnvironmentMode::Var) { + if (initialization_mode == Bytecode::Op::BindingInitializationMode::Initialize) { + emit(identifier_index, value); + } else if (initialization_mode == Bytecode::Op::BindingInitializationMode::Set) { + emit(identifier_index, value); + } + } else { + VERIFY_NOT_REACHED(); + } } } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.h b/Userland/Libraries/LibJS/Bytecode/Generator.h index f28cb4ba7e6..88782c21ab2 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.h +++ b/Userland/Libraries/LibJS/Bytecode/Generator.h @@ -144,7 +144,7 @@ public: CodeGenerationErrorOr emit_super_reference(MemberExpression const&); - void emit_set_variable(JS::Identifier const& identifier, ScopedOperand value, Bytecode::Op::SetVariable::InitializationMode initialization_mode = Bytecode::Op::SetVariable::InitializationMode::Set, Bytecode::Op::EnvironmentMode mode = Bytecode::Op::EnvironmentMode::Lexical); + void emit_set_variable(JS::Identifier const& identifier, ScopedOperand value, Bytecode::Op::BindingInitializationMode initialization_mode = Bytecode::Op::BindingInitializationMode::Set, Bytecode::Op::EnvironmentMode mode = Bytecode::Op::EnvironmentMode::Lexical); void push_home_object(ScopedOperand); void pop_home_object(); diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index f8ec270eb8c..e9af855b2a9 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -70,6 +70,8 @@ O(ImportCall) \ O(In) \ O(Increment) \ + O(InitializeLexicalBinding) \ + O(InitializeVariableBinding) \ O(InstanceOf) \ O(IteratorClose) \ O(IteratorNext) \ @@ -122,7 +124,8 @@ O(RightShift) \ O(ScheduleJump) \ O(SetArgument) \ - O(SetVariable) \ + O(SetLexicalBinding) \ + O(SetVariableBinding) \ O(StrictlyEquals) \ O(StrictlyInequals) \ O(Sub) \ diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 2004d776d74..03008d7d160 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -584,6 +584,8 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point) HANDLE_INSTRUCTION(ImportCall); HANDLE_INSTRUCTION(In); HANDLE_INSTRUCTION(Increment); + HANDLE_INSTRUCTION(InitializeLexicalBinding); + HANDLE_INSTRUCTION(InitializeVariableBinding); HANDLE_INSTRUCTION(InstanceOf); HANDLE_INSTRUCTION(IteratorClose); HANDLE_INSTRUCTION(IteratorNext); @@ -618,7 +620,8 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point) HANDLE_INSTRUCTION(ResolveThisBinding); HANDLE_INSTRUCTION_WITHOUT_EXCEPTION_CHECK(RestoreScheduledJump); HANDLE_INSTRUCTION(RightShift); - HANDLE_INSTRUCTION(SetVariable); + HANDLE_INSTRUCTION(SetLexicalBinding); + HANDLE_INSTRUCTION(SetVariableBinding); HANDLE_INSTRUCTION(StrictlyEquals); HANDLE_INSTRUCTION(StrictlyInequals); HANDLE_INSTRUCTION(Sub); @@ -1376,38 +1379,60 @@ ThrowCompletionOr CreateArguments::execute_impl(Bytecode::Interpreter& int return {}; } -ThrowCompletionOr SetVariable::execute_impl(Bytecode::Interpreter& interpreter) const +template +static ThrowCompletionOr initialize_or_set_binding(Interpreter& interpreter, IdentifierTableIndex identifier_index, Value value, EnvironmentCoordinate& cache) { auto& vm = interpreter.vm(); - if (m_cache.is_valid()) { - auto* environment = m_mode == EnvironmentMode::Lexical - ? interpreter.running_execution_context().lexical_environment.ptr() - : interpreter.running_execution_context().variable_environment.ptr(); - for (size_t i = 0; i < m_cache.hops; ++i) + auto* environment = environment_mode == EnvironmentMode::Lexical + ? interpreter.running_execution_context().lexical_environment.ptr() + : interpreter.running_execution_context().variable_environment.ptr(); + + if (cache.is_valid()) { + for (size_t i = 0; i < cache.hops; ++i) environment = environment->outer_environment(); if (!environment->is_permanently_screwed_by_eval()) { - auto value = interpreter.get(src()); - if (m_initialization_mode == InitializationMode::Initialize) { - TRY(static_cast(*environment).initialize_binding_direct(vm, m_cache.index, value, Environment::InitializeBindingHint::Normal)); - return {}; + if constexpr (initialization_mode == BindingInitializationMode::Initialize) { + TRY(static_cast(*environment).initialize_binding_direct(vm, cache.index, value, Environment::InitializeBindingHint::Normal)); + } else { + TRY(static_cast(*environment).set_mutable_binding_direct(vm, cache.index, value, vm.in_strict_mode())); } - TRY(static_cast(*environment).set_mutable_binding_direct(vm, m_cache.index, value, vm.in_strict_mode())); return {}; } - m_cache = {}; + cache = {}; } - auto const& name = interpreter.current_executable().get_identifier(m_identifier); - TRY(set_variable(vm, - name, - interpreter.get(src()), - m_mode, - m_initialization_mode, - m_cache)); + auto reference = TRY(vm.resolve_binding(interpreter.current_executable().get_identifier(identifier_index), environment)); + if (reference.environment_coordinate().has_value()) + cache = reference.environment_coordinate().value(); + if constexpr (initialization_mode == BindingInitializationMode::Initialize) { + TRY(reference.initialize_referenced_binding(vm, value)); + } else if (initialization_mode == BindingInitializationMode::Set) { + TRY(reference.put_value(vm, value)); + } return {}; } +ThrowCompletionOr InitializeLexicalBinding::execute_impl(Bytecode::Interpreter& interpreter) const +{ + return initialize_or_set_binding(interpreter, m_identifier, interpreter.get(m_src), m_cache); +} + +ThrowCompletionOr InitializeVariableBinding::execute_impl(Bytecode::Interpreter& interpreter) const +{ + return initialize_or_set_binding(interpreter, m_identifier, interpreter.get(m_src), m_cache); +} + +ThrowCompletionOr SetLexicalBinding::execute_impl(Bytecode::Interpreter& interpreter) const +{ + return initialize_or_set_binding(interpreter, m_identifier, interpreter.get(m_src), m_cache); +} + +ThrowCompletionOr SetVariableBinding::execute_impl(Bytecode::Interpreter& interpreter) const +{ + return initialize_or_set_binding(interpreter, m_identifier, interpreter.get(m_src), m_cache); +} + ThrowCompletionOr SetArgument::execute_impl(Bytecode::Interpreter&) const { // Handled in the interpreter loop. @@ -2152,14 +2177,32 @@ ByteString EnterObjectEnvironment::to_byte_string_impl(Executable const& executa format_operand("object"sv, m_object, executable)); } -ByteString SetVariable::to_byte_string_impl(Bytecode::Executable const& executable) const +ByteString InitializeLexicalBinding::to_byte_string_impl(Bytecode::Executable const& executable) const { - auto initialization_mode_name = m_initialization_mode == InitializationMode::Initialize ? "Initialize" : "Set"; - auto mode_string = m_mode == EnvironmentMode::Lexical ? "Lexical" : "Variable"; - return ByteString::formatted("SetVariable {}, {}, env:{} init:{}", + return ByteString::formatted("InitializeLexicalBinding {}, {}", executable.identifier_table->get(m_identifier), - format_operand("src"sv, src(), executable), - mode_string, initialization_mode_name); + format_operand("src"sv, src(), executable)); +} + +ByteString InitializeVariableBinding::to_byte_string_impl(Bytecode::Executable const& executable) const +{ + return ByteString::formatted("InitializeVariableBinding {}, {}", + executable.identifier_table->get(m_identifier), + format_operand("src"sv, src(), executable)); +} + +ByteString SetLexicalBinding::to_byte_string_impl(Bytecode::Executable const& executable) const +{ + return ByteString::formatted("SetLexicalBinding {}, {}", + executable.identifier_table->get(m_identifier), + format_operand("src"sv, src(), executable)); +} + +ByteString SetVariableBinding::to_byte_string_impl(Bytecode::Executable const& executable) const +{ + return ByteString::formatted("SetVariableBinding {}, {}", + executable.identifier_table->get(m_identifier), + format_operand("src"sv, src(), executable)); } ByteString GetArgument::to_byte_string_impl(Bytecode::Executable const& executable) const diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index d3b941d1777..99e899beb8f 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -528,6 +528,11 @@ enum class EnvironmentMode { Var, }; +enum class BindingInitializationMode { + Initialize, + Set, +}; + class CreateLexicalEnvironment final : public Instruction { public: explicit CreateLexicalEnvironment(u32 capacity = 0) @@ -664,18 +669,87 @@ private: bool m_is_strict { false }; }; -class SetVariable final : public Instruction { +class InitializeLexicalBinding final : public Instruction { public: - enum class InitializationMode { - Initialize, - Set, - }; - explicit SetVariable(IdentifierTableIndex identifier, Operand src, InitializationMode initialization_mode = InitializationMode::Set, EnvironmentMode mode = EnvironmentMode::Lexical) - : Instruction(Type::SetVariable) + explicit InitializeLexicalBinding(IdentifierTableIndex identifier, Operand src) + : Instruction(Type::InitializeLexicalBinding) + , m_identifier(identifier) + , m_src(src) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + ByteString to_byte_string_impl(Bytecode::Executable const&) const; + void visit_operands_impl(Function visitor) + { + visitor(m_src); + } + + IdentifierTableIndex identifier() const { return m_identifier; } + Operand src() const { return m_src; } + +private: + IdentifierTableIndex m_identifier; + Operand m_src; + mutable EnvironmentCoordinate m_cache; +}; + +class InitializeVariableBinding final : public Instruction { +public: + explicit InitializeVariableBinding(IdentifierTableIndex identifier, Operand src) + : Instruction(Type::InitializeVariableBinding) + , m_identifier(identifier) + , m_src(src) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + ByteString to_byte_string_impl(Bytecode::Executable const&) const; + void visit_operands_impl(Function visitor) + { + visitor(m_src); + } + + IdentifierTableIndex identifier() const { return m_identifier; } + Operand src() const { return m_src; } + +private: + IdentifierTableIndex m_identifier; + Operand m_src; + mutable EnvironmentCoordinate m_cache; +}; + +class SetLexicalBinding final : public Instruction { +public: + explicit SetLexicalBinding(IdentifierTableIndex identifier, Operand src) + : Instruction(Type::SetLexicalBinding) + , m_identifier(identifier) + , m_src(src) + { + } + + ThrowCompletionOr execute_impl(Bytecode::Interpreter&) const; + ByteString to_byte_string_impl(Bytecode::Executable const&) const; + void visit_operands_impl(Function visitor) + { + visitor(m_src); + } + + IdentifierTableIndex identifier() const { return m_identifier; } + Operand src() const { return m_src; } + +private: + IdentifierTableIndex m_identifier; + Operand m_src; + mutable EnvironmentCoordinate m_cache; +}; + +class SetVariableBinding final : public Instruction { +public: + explicit SetVariableBinding(IdentifierTableIndex identifier, Operand src) + : Instruction(Type::SetVariableBinding) , m_identifier(identifier) , m_src(src) - , m_mode(mode) - , m_initialization_mode(initialization_mode) { } @@ -688,14 +762,10 @@ public: IdentifierTableIndex identifier() const { return m_identifier; } Operand src() const { return m_src; } - EnvironmentMode mode() const { return m_mode; } - InitializationMode initialization_mode() const { return m_initialization_mode; } private: IdentifierTableIndex m_identifier; Operand m_src; - EnvironmentMode m_mode; - InitializationMode m_initialization_mode { InitializationMode::Set }; mutable EnvironmentCoordinate m_cache; };