diff --git a/Userland/Libraries/LibJS/AST.h b/Userland/Libraries/LibJS/AST.h index a2efbcdea9..f35122cabb 100644 --- a/Userland/Libraries/LibJS/AST.h +++ b/Userland/Libraries/LibJS/AST.h @@ -37,7 +37,7 @@ class ASTNode : public RefCounted { public: virtual ~ASTNode() { } virtual Value execute(Interpreter&, GlobalObject&) const = 0; - virtual Optional generate_bytecode(Bytecode::Generator&) const; + virtual void generate_bytecode(Bytecode::Generator&) const; virtual void dump(int indent) const; const SourceRange& source_range() const { return m_source_range; } @@ -76,7 +76,7 @@ public: { } Value execute(Interpreter&, GlobalObject&) const override { return {}; } - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; }; class ErrorStatement final : public Statement { @@ -98,7 +98,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; const Expression& expression() const { return m_expression; }; @@ -123,7 +123,7 @@ public: const NonnullRefPtrVector& children() const { return m_children; } virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; void add_variables(NonnullRefPtrVector); void add_functions(NonnullRefPtrVector); @@ -273,7 +273,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; }; class FunctionExpression final @@ -330,7 +330,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: RefPtr m_argument; @@ -352,7 +352,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_predicate; @@ -374,7 +374,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; @@ -395,7 +395,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; @@ -440,7 +440,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: RefPtr m_init; @@ -532,7 +532,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: BinaryOp m_op; @@ -558,7 +558,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: LogicalOp m_op; @@ -587,7 +587,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: UnaryOp m_op; @@ -605,7 +605,7 @@ public: virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtrVector m_expressions; @@ -629,7 +629,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: bool m_value { false }; @@ -645,7 +645,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: Value m_value; @@ -661,7 +661,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: String m_value; @@ -678,7 +678,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; StringView value() const { return m_value; } bool is_use_strict_directive() const { return m_is_use_strict_directive; }; @@ -697,7 +697,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; }; class RegExpLiteral final : public Literal { @@ -733,7 +733,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual Reference to_reference(Interpreter&, GlobalObject&) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: FlyString m_string; @@ -860,7 +860,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: struct ThisAndCallee { @@ -912,7 +912,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: AssignmentOp m_op; @@ -1052,7 +1052,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtrVector m_properties; @@ -1092,7 +1092,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; const NonnullRefPtrVector& expressions() const { return m_expressions; } const NonnullRefPtrVector& raw_strings() const { return m_raw_strings; } @@ -1132,7 +1132,7 @@ public: virtual Value execute(Interpreter&, GlobalObject&) const override; virtual void dump(int indent) const override; virtual Reference to_reference(Interpreter&, GlobalObject&) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; bool is_computed() const { return m_computed; } const Expression& object() const { return *m_object; } @@ -1180,7 +1180,7 @@ public: virtual void dump(int indent) const override; virtual Value execute(Interpreter&, GlobalObject&) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; private: NonnullRefPtr m_test; @@ -1310,7 +1310,7 @@ public: } virtual Value execute(Interpreter&, GlobalObject&) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; const FlyString& target_label() const { return m_target_label; } @@ -1326,7 +1326,7 @@ public: } virtual Value execute(Interpreter&, GlobalObject&) const override; - virtual Optional generate_bytecode(Bytecode::Generator&) const override; + virtual void generate_bytecode(Bytecode::Generator&) const override; }; template diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 5a26fa6cdf..68d6d7d4d5 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -13,489 +13,422 @@ namespace JS { -Optional ASTNode::generate_bytecode(Bytecode::Generator&) const +void ASTNode::generate_bytecode(Bytecode::Generator&) const { dbgln("Missing generate_bytecode()"); TODO(); } -Optional ScopeNode::generate_bytecode(Bytecode::Generator& generator) const +void ScopeNode::generate_bytecode(Bytecode::Generator& generator) const { generator.emit(*this); - Optional last_value_reg; - for (auto& child : children()) { - last_value_reg = child.generate_bytecode(generator); - } - return last_value_reg; + for (auto& child : children()) + child.generate_bytecode(generator); } -Optional EmptyStatement::generate_bytecode(Bytecode::Generator&) const +void EmptyStatement::generate_bytecode(Bytecode::Generator&) const { - return {}; } -Optional ExpressionStatement::generate_bytecode(Bytecode::Generator& generator) const +void ExpressionStatement::generate_bytecode(Bytecode::Generator& generator) const { - return m_expression->generate_bytecode(generator); + m_expression->generate_bytecode(generator); } -Optional BinaryExpression::generate_bytecode(Bytecode::Generator& generator) const +void BinaryExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto lhs_reg = m_lhs->generate_bytecode(generator); - auto rhs_reg = m_rhs->generate_bytecode(generator); + m_lhs->generate_bytecode(generator); + auto lhs_reg = generator.allocate_register(); + generator.emit(lhs_reg); - VERIFY(lhs_reg.has_value()); - VERIFY(rhs_reg.has_value()); - - auto dst_reg = generator.allocate_register(); + m_rhs->generate_bytecode(generator); switch (m_op) { case BinaryOp::Addition: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::Subtraction: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::Multiplication: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::Division: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::Modulo: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::Exponentiation: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::GreaterThan: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::GreaterThanEquals: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::LessThan: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::LessThanEquals: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::AbstractInequals: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::AbstractEquals: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::TypedInequals: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::TypedEquals: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::BitwiseAnd: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::BitwiseOr: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::BitwiseXor: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::LeftShift: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::RightShift: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::UnsignedRightShift: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::In: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; case BinaryOp::InstanceOf: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); - return dst_reg; + generator.emit(lhs_reg); + break; default: VERIFY_NOT_REACHED(); } } -Optional LogicalExpression::generate_bytecode(Bytecode::Generator& generator) const +void LogicalExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto result_reg = generator.allocate_register(); - auto lhs_reg = m_lhs->generate_bytecode(generator); + m_lhs->generate_bytecode(generator); Bytecode::Op::Jump* test_instr; switch (m_op) { case LogicalOp::And: - test_instr = &generator.emit(*lhs_reg); + test_instr = &generator.emit(); break; case LogicalOp::Or: - test_instr = &generator.emit(*lhs_reg); + test_instr = &generator.emit(); break; case LogicalOp::NullishCoalescing: - test_instr = &generator.emit(*lhs_reg); + test_instr = &generator.emit(); break; default: VERIFY_NOT_REACHED(); } - generator.emit(result_reg, *lhs_reg); - auto& end_jump = generator.emit(); - - auto rhs_label = generator.make_label(); - test_instr->set_target(rhs_label); - - auto rhs_reg = m_rhs->generate_bytecode(generator); - generator.emit(result_reg, *rhs_reg); - - end_jump.set_target(generator.make_label()); - - return result_reg; + m_rhs->generate_bytecode(generator); + test_instr->set_target(generator.make_label()); } -Optional UnaryExpression::generate_bytecode(Bytecode::Generator& generator) const +void UnaryExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto lhs_reg = m_lhs->generate_bytecode(generator); - - VERIFY(lhs_reg.has_value()); - - auto dst_reg = generator.allocate_register(); + m_lhs->generate_bytecode(generator); switch (m_op) { case UnaryOp::BitwiseNot: - generator.emit(dst_reg, *lhs_reg); - return dst_reg; + generator.emit(); + break; case UnaryOp::Not: - generator.emit(dst_reg, *lhs_reg); - return dst_reg; + generator.emit(); + break; case UnaryOp::Plus: - generator.emit(dst_reg, *lhs_reg); - return dst_reg; + generator.emit(); + break; case UnaryOp::Minus: - generator.emit(dst_reg, *lhs_reg); - return dst_reg; + generator.emit(); + break; case UnaryOp::Typeof: - generator.emit(dst_reg, *lhs_reg); - return dst_reg; + generator.emit(); + break; case UnaryOp::Void: - generator.emit(dst_reg, js_undefined()); - return dst_reg; + generator.emit(js_undefined()); + break; default: TODO(); } } -Optional NumericLiteral::generate_bytecode(Bytecode::Generator& generator) const +void NumericLiteral::generate_bytecode(Bytecode::Generator& generator) const { - auto dst = generator.allocate_register(); - generator.emit(dst, m_value); - return dst; + generator.emit(m_value); } -Optional BooleanLiteral::generate_bytecode(Bytecode::Generator& generator) const +void BooleanLiteral::generate_bytecode(Bytecode::Generator& generator) const { - auto dst = generator.allocate_register(); - generator.emit(dst, Value(m_value)); - return dst; + generator.emit(Value(m_value)); } -Optional NullLiteral::generate_bytecode(Bytecode::Generator& generator) const +void NullLiteral::generate_bytecode(Bytecode::Generator& generator) const { - auto dst = generator.allocate_register(); - generator.emit(dst, js_null()); - return dst; + generator.emit(js_null()); } -Optional BigIntLiteral::generate_bytecode(Bytecode::Generator& generator) const +void BigIntLiteral::generate_bytecode(Bytecode::Generator& generator) const { - auto dst = generator.allocate_register(); - generator.emit(dst, Crypto::SignedBigInteger::from_base10(m_value.substring(0, m_value.length() - 1))); - return dst; + generator.emit(Crypto::SignedBigInteger::from_base10(m_value.substring(0, m_value.length() - 1))); } -Optional StringLiteral::generate_bytecode(Bytecode::Generator& generator) const +void StringLiteral::generate_bytecode(Bytecode::Generator& generator) const { - auto dst = generator.allocate_register(); - generator.emit(dst, m_value); - return dst; + generator.emit(m_value); } -Optional Identifier::generate_bytecode(Bytecode::Generator& generator) const +void Identifier::generate_bytecode(Bytecode::Generator& generator) const { - auto reg = generator.allocate_register(); - generator.emit(reg, m_string); - return reg; + generator.emit(m_string); } -Optional AssignmentExpression::generate_bytecode(Bytecode::Generator& generator) const +void AssignmentExpression::generate_bytecode(Bytecode::Generator& generator) const { if (is(*m_lhs)) { auto& identifier = static_cast(*m_lhs); - auto rhs_reg = m_rhs->generate_bytecode(generator); - VERIFY(rhs_reg.has_value()); if (m_op == AssignmentOp::Assignment) { - generator.emit(identifier.string(), *rhs_reg); - return rhs_reg; + m_rhs->generate_bytecode(generator); + generator.emit(identifier.string()); + return; } - auto lhs_reg = m_lhs->generate_bytecode(generator); - auto dst_reg = generator.allocate_register(); + m_lhs->generate_bytecode(generator); + auto lhs_reg = generator.allocate_register(); + generator.emit(lhs_reg); + m_rhs->generate_bytecode(generator); switch (m_op) { case AssignmentOp::AdditionAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::SubtractionAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::MultiplicationAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::DivisionAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::ModuloAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::ExponentiationAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::BitwiseAndAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::BitwiseOrAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::BitwiseXorAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::LeftShiftAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::RightShiftAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; case AssignmentOp::UnsignedRightShiftAssignment: - generator.emit(dst_reg, *lhs_reg, *rhs_reg); + generator.emit(lhs_reg); break; default: TODO(); } - generator.emit(identifier.string(), dst_reg); + generator.emit(identifier.string()); - return dst_reg; + return; } if (is(*m_lhs)) { auto& expression = static_cast(*m_lhs); - auto object_reg = expression.object().generate_bytecode(generator); + expression.object().generate_bytecode(generator); + auto object_reg = generator.allocate_register(); + generator.emit(object_reg); if (expression.is_computed()) { TODO(); } else { VERIFY(is(expression.property())); - auto rhs_reg = m_rhs->generate_bytecode(generator); - generator.emit(*object_reg, static_cast(expression.property()).string(), *rhs_reg); - return rhs_reg; + m_rhs->generate_bytecode(generator); + generator.emit(object_reg, static_cast(expression.property()).string()); + return; } } TODO(); } -Optional WhileStatement::generate_bytecode(Bytecode::Generator& generator) const +void WhileStatement::generate_bytecode(Bytecode::Generator& generator) const { generator.begin_continuable_scope(); auto test_label = generator.make_label(); - auto test_result_reg = m_test->generate_bytecode(generator); - VERIFY(test_result_reg.has_value()); - auto& test_jump = generator.emit(*test_result_reg); - auto body_result_reg = m_body->generate_bytecode(generator); + m_test->generate_bytecode(generator); + auto& test_jump = generator.emit(); + m_body->generate_bytecode(generator); generator.emit(test_label); test_jump.set_target(generator.make_label()); generator.end_continuable_scope(); - return body_result_reg; } -Optional DoWhileStatement::generate_bytecode(Bytecode::Generator& generator) const +void DoWhileStatement::generate_bytecode(Bytecode::Generator& generator) const { generator.begin_continuable_scope(); auto head_label = generator.make_label(); - auto body_result_reg = m_body->generate_bytecode(generator); + m_body->generate_bytecode(generator); generator.end_continuable_scope(); - auto test_result_reg = m_test->generate_bytecode(generator); - VERIFY(test_result_reg.has_value()); - generator.emit(*test_result_reg, head_label); - return body_result_reg; + m_test->generate_bytecode(generator); + generator.emit(head_label); } -Optional ForStatement::generate_bytecode(Bytecode::Generator& generator) const +void ForStatement::generate_bytecode(Bytecode::Generator& generator) const { Bytecode::Op::Jump* test_jump { nullptr }; - if (m_init) { - [[maybe_unused]] auto init_result_reg = m_init->generate_bytecode(generator); - } + if (m_init) + m_init->generate_bytecode(generator); + generator.begin_continuable_scope(); auto jump_label = generator.make_label(); if (m_test) { - auto test_result_reg = m_test->generate_bytecode(generator); - VERIFY(test_result_reg.has_value()); - test_jump = &generator.emit(*test_result_reg); - } - auto body_result_reg = m_body->generate_bytecode(generator); - if (m_update) { - [[maybe_unused]] auto update_result_reg = m_update->generate_bytecode(generator); + m_test->generate_bytecode(generator); + test_jump = &generator.emit(); } + + m_body->generate_bytecode(generator); + if (m_update) + m_update->generate_bytecode(generator); generator.emit(jump_label); if (m_test) test_jump->set_target(generator.make_label()); generator.end_continuable_scope(); - return body_result_reg; } -Optional ObjectExpression::generate_bytecode(Bytecode::Generator& generator) const +void ObjectExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto reg = generator.allocate_register(); - generator.emit(reg); + generator.emit(); - if (!m_properties.is_empty()) { + if (!m_properties.is_empty()) TODO(); - } - - return reg; } -Optional MemberExpression::generate_bytecode(Bytecode::Generator& generator) const +void MemberExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto object_reg = object().generate_bytecode(generator); + object().generate_bytecode(generator); if (is_computed()) { TODO(); } else { VERIFY(is(property())); - auto dst_reg = generator.allocate_register(); - generator.emit(dst_reg, *object_reg, static_cast(property()).string()); - return dst_reg; + generator.emit(static_cast(property()).string()); } } -Optional FunctionDeclaration::generate_bytecode(Bytecode::Generator&) const +void FunctionDeclaration::generate_bytecode(Bytecode::Generator&) const { - return {}; } -Optional CallExpression::generate_bytecode(Bytecode::Generator& generator) const +void CallExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto callee_reg = m_callee->generate_bytecode(generator); + m_callee->generate_bytecode(generator); + auto callee_reg = generator.allocate_register(); + generator.emit(callee_reg); // FIXME: Load the correct 'this' value into 'this_reg'. auto this_reg = generator.allocate_register(); - generator.emit(this_reg, js_undefined()); + generator.emit(js_undefined()); + generator.emit(this_reg); Vector argument_registers; - for (auto& arg : m_arguments) - argument_registers.append(*arg.value->generate_bytecode(generator)); - auto dst_reg = generator.allocate_register(); - generator.emit_with_extra_register_slots(argument_registers.size(), dst_reg, *callee_reg, this_reg, argument_registers); - return dst_reg; -} - -Optional ReturnStatement::generate_bytecode(Bytecode::Generator& generator) const -{ - Optional argument_reg; - if (m_argument) - argument_reg = m_argument->generate_bytecode(generator); - - generator.emit(argument_reg); - return argument_reg; -} - -Optional IfStatement::generate_bytecode(Bytecode::Generator& generator) const -{ - auto result_reg = generator.allocate_register(); - auto predicate_reg = m_predicate->generate_bytecode(generator); - auto& else_jump = generator.emit(*predicate_reg); - - auto consequent_reg = m_consequent->generate_bytecode(generator); - generator.emit(result_reg, *consequent_reg); - auto& end_jump = generator.emit(); - - else_jump.set_target(generator.make_label()); - if (m_alternate) { - auto alternative_reg = m_alternate->generate_bytecode(generator); - generator.emit(result_reg, *alternative_reg); - } else { - generator.emit(result_reg, js_undefined()); + for (auto& arg : m_arguments) { + arg.value->generate_bytecode(generator); + auto arg_reg = generator.allocate_register(); + generator.emit(arg_reg); + argument_registers.append(arg_reg); } - - end_jump.set_target(generator.make_label()); - - return result_reg; + generator.emit_with_extra_register_slots(argument_registers.size(), callee_reg, this_reg, argument_registers); } -Optional ContinueStatement::generate_bytecode(Bytecode::Generator& generator) const +void ReturnStatement::generate_bytecode(Bytecode::Generator& generator) const +{ + generator.emit(); +} + +void IfStatement::generate_bytecode(Bytecode::Generator& generator) const +{ + m_predicate->generate_bytecode(generator); + auto& else_jump = generator.emit(); + + m_consequent->generate_bytecode(generator); + if (m_alternate) { + auto& if_jump = generator.emit(); + else_jump.set_target(generator.make_label()); + m_alternate->generate_bytecode(generator); + if_jump.set_target(generator.make_label()); + } else { + else_jump.set_target(generator.make_label()); + } +} + +void ContinueStatement::generate_bytecode(Bytecode::Generator& generator) const { generator.emit(generator.nearest_continuable_scope()); - return {}; } -Optional DebuggerStatement::generate_bytecode(Bytecode::Generator&) const +void DebuggerStatement::generate_bytecode(Bytecode::Generator&) const { - return {}; } -Optional ConditionalExpression::generate_bytecode(Bytecode::Generator& generator) const +void ConditionalExpression::generate_bytecode(Bytecode::Generator& generator) const { - auto result_reg = generator.allocate_register(); - auto test_reg = m_test->generate_bytecode(generator); - auto& alternate_jump = generator.emit(*test_reg); + m_test->generate_bytecode(generator); + auto& alternate_jump = generator.emit(); - auto consequent_reg = m_consequent->generate_bytecode(generator); - generator.emit(result_reg, *consequent_reg); + m_consequent->generate_bytecode(generator); auto& end_jump = generator.emit(); alternate_jump.set_target(generator.make_label()); - auto alternative_reg = m_alternate->generate_bytecode(generator); - generator.emit(result_reg, *alternative_reg); + m_alternate->generate_bytecode(generator); end_jump.set_target(generator.make_label()); - - return result_reg; } -Optional SequenceExpression::generate_bytecode(Bytecode::Generator& generator) const +void SequenceExpression::generate_bytecode(Bytecode::Generator& generator) const { - Optional last_reg; - for (auto& expression : m_expressions) - last_reg = expression.generate_bytecode(generator); - - return last_reg; + expression.generate_bytecode(generator); } -Optional TemplateLiteral::generate_bytecode(Bytecode::Generator& generator) const +void TemplateLiteral::generate_bytecode(Bytecode::Generator& generator) const { - Optional result_reg; + auto string_reg = generator.allocate_register(); - for (auto& expression : m_expressions) { - auto expr_reg = expression.generate_bytecode(generator); - if (!result_reg.has_value()) - result_reg = expr_reg; - else - generator.emit(*result_reg, *result_reg, *expr_reg); + for (size_t i = 0; i < m_expressions.size(); i++) { + m_expressions[i].generate_bytecode(generator); + if (i == 0) { + generator.emit(string_reg); + } else { + generator.emit(string_reg); + } } - - if (!result_reg.has_value()) { - result_reg = generator.allocate_register(); - generator.emit(*result_reg, ""); - } - - return result_reg; } } diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 6b43bf3002..2d2ad73520 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -26,7 +26,7 @@ Generator::~Generator() OwnPtr Generator::generate(ASTNode const& node) { Generator generator; - [[maybe_unused]] auto dummy = node.generate_bytecode(generator); + node.generate_bytecode(generator); generator.m_block->set_register_count({}, generator.m_next_register); generator.m_block->seal(); return move(generator.m_block); diff --git a/Userland/Libraries/LibJS/Bytecode/Instruction.h b/Userland/Libraries/LibJS/Bytecode/Instruction.h index 6bea827a35..1b7286eea8 100644 --- a/Userland/Libraries/LibJS/Bytecode/Instruction.h +++ b/Userland/Libraries/LibJS/Bytecode/Instruction.h @@ -11,7 +11,8 @@ #define ENUMERATE_BYTECODE_OPS(O) \ O(Load) \ - O(LoadRegister) \ + O(LoadImmediate) \ + O(Store) \ O(Add) \ O(Sub) \ O(Mul) \ @@ -36,7 +37,7 @@ O(Jump) \ O(JumpIfFalse) \ O(JumpIfTrue) \ - O(JumpIfNullish) \ + O(JumpIfNotNullish) \ O(Call) \ O(EnterScope) \ O(Return) \ @@ -52,7 +53,8 @@ O(RightShift) \ O(UnsignedRightShift) \ O(In) \ - O(InstanceOf) + O(InstanceOf) \ + O(ConcatString) namespace JS::Bytecode { diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.h b/Userland/Libraries/LibJS/Bytecode/Interpreter.h index f48cce2231..4611bcf0af 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.h +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.h @@ -30,6 +30,7 @@ public: Value run(Bytecode::Block const&); + ALWAYS_INLINE Value& accumulator() { return reg(Register::accumulator()); } Value& reg(Register const& r) { return registers()[r.index()]; } void jump(Label const& label) { m_pending_jump = label.address(); } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index e2691681ed..ee21957f58 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -51,12 +51,17 @@ namespace JS::Bytecode::Op { void Load::execute(Bytecode::Interpreter& interpreter) const { - interpreter.reg(m_dst) = m_value; + interpreter.accumulator() = interpreter.reg(m_src); } -void LoadRegister::execute(Bytecode::Interpreter& interpreter) const +void LoadImmediate::execute(Bytecode::Interpreter& interpreter) const { - interpreter.reg(m_dst) = interpreter.reg(m_src); + interpreter.accumulator() = m_value; +} + +void Store::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_dst) = interpreter.accumulator(); } static Value abstract_inequals(GlobalObject& global_object, Value src1, Value src2) @@ -79,14 +84,16 @@ static Value typed_equals(GlobalObject&, Value src1, Value src2) return Value(strict_eq(src1, src2)); } -#define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \ - void OpTitleCase::execute(Bytecode::Interpreter& interpreter) const \ - { \ - interpreter.reg(m_dst) = op_snake_case(interpreter.global_object(), interpreter.reg(m_src1), interpreter.reg(m_src2)); \ - } \ - String OpTitleCase::to_string() const \ - { \ - return String::formatted(#OpTitleCase " dst:{}, src1:{}, src2:{}", m_dst, m_src1, m_src2); \ +#define JS_DEFINE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \ + void OpTitleCase::execute(Bytecode::Interpreter& interpreter) const \ + { \ + auto lhs = interpreter.reg(m_lhs_reg); \ + auto rhs = interpreter.accumulator(); \ + interpreter.accumulator() = op_snake_case(interpreter.global_object(), lhs, rhs); \ + } \ + String OpTitleCase::to_string() const \ + { \ + return String::formatted(#OpTitleCase " lhs:{}", m_lhs_reg); \ } JS_ENUMERATE_COMMON_BINARY_OPS(JS_DEFINE_COMMON_BINARY_OP) @@ -101,53 +108,58 @@ static Value typeof_(GlobalObject& global_object, Value value) return js_string(global_object.vm(), value.typeof()); } -#define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \ - void OpTitleCase::execute(Bytecode::Interpreter& interpreter) const \ - { \ - interpreter.reg(m_dst) = op_snake_case(interpreter.global_object(), interpreter.reg(m_src)); \ - } \ - String OpTitleCase::to_string() const \ - { \ - return String::formatted(#OpTitleCase " dst:{}, src:{}", m_dst, m_src); \ +#define JS_DEFINE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \ + void OpTitleCase::execute(Bytecode::Interpreter& interpreter) const \ + { \ + interpreter.accumulator() = op_snake_case(interpreter.global_object(), interpreter.accumulator()); \ + } \ + String OpTitleCase::to_string() const \ + { \ + return #OpTitleCase; \ } JS_ENUMERATE_COMMON_UNARY_OPS(JS_DEFINE_COMMON_UNARY_OP) void NewBigInt::execute(Bytecode::Interpreter& interpreter) const { - interpreter.reg(m_dst) = js_bigint(interpreter.vm().heap(), m_bigint); + interpreter.accumulator() = js_bigint(interpreter.vm().heap(), m_bigint); } void NewString::execute(Bytecode::Interpreter& interpreter) const { - interpreter.reg(m_dst) = js_string(interpreter.vm(), m_string); + interpreter.accumulator() = js_string(interpreter.vm(), m_string); } void NewObject::execute(Bytecode::Interpreter& interpreter) const { - interpreter.reg(m_dst) = Object::create_empty(interpreter.global_object()); + interpreter.accumulator() = Object::create_empty(interpreter.global_object()); +} + +void ConcatString::execute(Bytecode::Interpreter& interpreter) const +{ + interpreter.reg(m_lhs) = add(interpreter.global_object(), interpreter.reg(m_lhs), interpreter.accumulator()); } void GetVariable::execute(Bytecode::Interpreter& interpreter) const { - interpreter.reg(m_dst) = interpreter.vm().get_variable(m_identifier, interpreter.global_object()); + interpreter.accumulator() = interpreter.vm().get_variable(m_identifier, interpreter.global_object()); } void SetVariable::execute(Bytecode::Interpreter& interpreter) const { - interpreter.vm().set_variable(m_identifier, interpreter.reg(m_src), interpreter.global_object()); + interpreter.vm().set_variable(m_identifier, interpreter.accumulator(), interpreter.global_object()); } void GetById::execute(Bytecode::Interpreter& interpreter) const { - if (auto* object = interpreter.reg(m_base).to_object(interpreter.global_object())) - interpreter.reg(m_dst) = object->get(m_property); + if (auto* object = interpreter.accumulator().to_object(interpreter.global_object())) + interpreter.accumulator() = object->get(m_property); } void PutById::execute(Bytecode::Interpreter& interpreter) const { if (auto* object = interpreter.reg(m_base).to_object(interpreter.global_object())) - object->put(m_property, interpreter.reg(m_src)); + object->put(m_property, interpreter.accumulator()); } void Jump::execute(Bytecode::Interpreter& interpreter) const @@ -158,7 +170,7 @@ void Jump::execute(Bytecode::Interpreter& interpreter) const void JumpIfFalse::execute(Bytecode::Interpreter& interpreter) const { VERIFY(m_target.has_value()); - auto result = interpreter.reg(m_result); + auto result = interpreter.accumulator(); if (!result.to_boolean()) interpreter.jump(m_target.value()); } @@ -166,16 +178,16 @@ void JumpIfFalse::execute(Bytecode::Interpreter& interpreter) const void JumpIfTrue::execute(Bytecode::Interpreter& interpreter) const { VERIFY(m_target.has_value()); - auto result = interpreter.reg(m_result); + auto result = interpreter.accumulator(); if (result.to_boolean()) interpreter.jump(m_target.value()); } -void JumpIfNullish::execute(Bytecode::Interpreter& interpreter) const +void JumpIfNotNullish::execute(Bytecode::Interpreter& interpreter) const { VERIFY(m_target.has_value()); - auto result = interpreter.reg(m_result); - if (result.is_nullish()) + auto result = interpreter.accumulator(); + if (!result.is_nullish()) interpreter.jump(m_target.value()); } @@ -201,7 +213,7 @@ void Call::execute(Bytecode::Interpreter& interpreter) const return_value = interpreter.vm().call(function, this_value, move(argument_values)); } - interpreter.reg(m_dst) = return_value; + interpreter.accumulator() = return_value; } void EnterScope::execute(Bytecode::Interpreter& interpreter) const @@ -223,53 +235,62 @@ void EnterScope::execute(Bytecode::Interpreter& interpreter) const void Return::execute(Bytecode::Interpreter& interpreter) const { - auto return_value = m_argument.has_value() ? interpreter.reg(m_argument.value()) : js_undefined(); - interpreter.do_return(return_value); + interpreter.do_return(interpreter.accumulator().value_or(js_undefined())); } String Load::to_string() const { - return String::formatted("Load dst:{}, value:{}", m_dst, m_value.to_string_without_side_effects()); + return String::formatted("Load src:{}", m_src); } -String LoadRegister::to_string() const +String LoadImmediate::to_string() const { - return String::formatted("LoadRegister dst:{}, src:{}", m_dst, m_src); + return String::formatted("LoadImmediate value:{}", m_value); +} + +String Store::to_string() const +{ + return String::formatted("Store dst:{}", m_dst); } String NewBigInt::to_string() const { - return String::formatted("NewBigInt dst:{}, bigint:\"{}\"", m_dst, m_bigint.to_base10()); + return String::formatted("NewBigInt bigint:\"{}\"", m_bigint.to_base10()); } String NewString::to_string() const { - return String::formatted("NewString dst:{}, string:\"{}\"", m_dst, m_string); + return String::formatted("NewString string:\"{}\"", m_string); } String NewObject::to_string() const { - return String::formatted("NewObject dst:{}", m_dst); + return "NewObject"; +} + +String ConcatString::to_string() const +{ + return String::formatted("ConcatString lhs:{}", m_lhs); } String GetVariable::to_string() const { - return String::formatted("GetVariable dst:{}, identifier:{}", m_dst, m_identifier); + return String::formatted("GetVariable identifier:{}", m_identifier); } String SetVariable::to_string() const { - return String::formatted("SetVariable identifier:{}, src:{}", m_identifier, m_src); + return String::formatted("SetVariable identifier:{}", m_identifier); } String PutById::to_string() const { - return String::formatted("PutById base:{}, property:{}, src:{}", m_base, m_property, m_src); + return String::formatted("PutById base:{}, property:{}", m_base, m_property); } String GetById::to_string() const { - return String::formatted("GetById dst:{}, base:{}, property:{}", m_dst, m_base, m_property); + return String::formatted("GetById property:{}", m_property); } String Jump::to_string() const @@ -280,28 +301,28 @@ String Jump::to_string() const String JumpIfFalse::to_string() const { if (m_target.has_value()) - return String::formatted("JumpIfFalse result:{}, target:{}", m_result, m_target.value()); - return String::formatted("JumpIfFalse result:{}, target:", m_result); + return String::formatted("JumpIfFalse target:{}", m_target.value()); + return "JumpIfFalse target:"; } String JumpIfTrue::to_string() const { if (m_target.has_value()) - return String::formatted("JumpIfTrue result:{}, target:{}", m_result, m_target.value()); - return String::formatted("JumpIfTrue result:{}, target:", m_result); + return String::formatted("JumpIfTrue target:{}", m_target.value()); + return "JumpIfTrue result:{}, target:"; } -String JumpIfNullish::to_string() const +String JumpIfNotNullish::to_string() const { if (m_target.has_value()) - return String::formatted("JumpIfNullish result:{}, target:{}", m_result, m_target.value()); - return String::formatted("JumpIfNullish result:{}, target:", m_result); + return String::formatted("JumpIfNotNullish target:{}", m_target.value()); + return "JumpIfNotNullish target:"; } String Call::to_string() const { StringBuilder builder; - builder.appendff("Call dst:{}, callee:{}, this:{}", m_dst, m_callee, m_this_value); + builder.appendff("Call callee:{}, this:{}", m_callee, m_this_value); if (m_argument_count != 0) { builder.append(", arguments:["); for (size_t i = 0; i < m_argument_count; ++i) { @@ -321,8 +342,6 @@ String EnterScope::to_string() const String Return::to_string() const { - if (m_argument.has_value()) - return String::formatted("Return {}", m_argument.value()); return "Return"; } diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index fb286ef2fa..73d6f837ba 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -19,26 +19,8 @@ namespace JS::Bytecode::Op { class Load final : public Instruction { public: - Load(Register dst, Value value) + Load(Register src) : Instruction(Type::Load) - , m_dst(dst) - , m_value(value) - { - } - - void execute(Bytecode::Interpreter&) const; - String to_string() const; - -private: - Register m_dst; - Value m_value; -}; - -class LoadRegister final : public Instruction { -public: - LoadRegister(Register dst, Register src) - : Instruction(Type::LoadRegister) - , m_dst(dst) , m_src(src) { } @@ -47,10 +29,39 @@ public: String to_string() const; private: - Register m_dst; Register m_src; }; +class LoadImmediate final : public Instruction { +public: + LoadImmediate(Value value) + : Instruction(Type::LoadImmediate) + , m_value(value) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Value m_value; +}; + +class Store final : public Instruction { +public: + Store(Register dst) + : Instruction(Type::Store) + , m_dst(dst) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_dst; +}; + #define JS_ENUMERATE_COMMON_BINARY_OPS(O) \ O(Add, add) \ O(Sub, sub) \ @@ -78,11 +89,9 @@ private: #define JS_DECLARE_COMMON_BINARY_OP(OpTitleCase, op_snake_case) \ class OpTitleCase final : public Instruction { \ public: \ - OpTitleCase(Register dst, Register src1, Register src2) \ + OpTitleCase(Register lhs_reg) \ : Instruction(Type::OpTitleCase) \ - , m_dst(dst) \ - , m_src1(src1) \ - , m_src2(src2) \ + , m_lhs_reg(lhs_reg) \ { \ } \ \ @@ -90,9 +99,7 @@ private: String to_string() const; \ \ private: \ - Register m_dst; \ - Register m_src1; \ - Register m_src2; \ + Register m_lhs_reg; \ }; JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP) @@ -108,19 +115,13 @@ JS_ENUMERATE_COMMON_BINARY_OPS(JS_DECLARE_COMMON_BINARY_OP) #define JS_DECLARE_COMMON_UNARY_OP(OpTitleCase, op_snake_case) \ class OpTitleCase final : public Instruction { \ public: \ - OpTitleCase(Register dst, Register src) \ + OpTitleCase() \ : Instruction(Type::OpTitleCase) \ - , m_dst(dst) \ - , m_src(src) \ { \ } \ \ void execute(Bytecode::Interpreter&) const; \ String to_string() const; \ - \ - private: \ - Register m_dst; \ - Register m_src; \ }; JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP) @@ -128,9 +129,8 @@ JS_ENUMERATE_COMMON_UNARY_OPS(JS_DECLARE_COMMON_UNARY_OP) class NewString final : public Instruction { public: - NewString(Register dst, String string) + NewString(String string) : Instruction(Type::NewString) - , m_dst(dst) , m_string(move(string)) { } @@ -139,30 +139,24 @@ public: String to_string() const; private: - Register m_dst; String m_string; }; class NewObject final : public Instruction { public: - explicit NewObject(Register dst) + NewObject() : Instruction(Type::NewObject) - , m_dst(dst) { } void execute(Bytecode::Interpreter&) const; String to_string() const; - -private: - Register m_dst; }; class NewBigInt final : public Instruction { public: - explicit NewBigInt(Register dst, Crypto::SignedBigInteger bigint) + explicit NewBigInt(Crypto::SignedBigInteger bigint) : Instruction(Type::NewBigInt) - , m_dst(dst) , m_bigint(move(bigint)) { } @@ -171,16 +165,29 @@ public: String to_string() const; private: - Register m_dst; Crypto::SignedBigInteger m_bigint; }; +class ConcatString final : public Instruction { +public: + ConcatString(Register lhs) + : Instruction(Type::ConcatString) + , m_lhs(lhs) + { + } + + void execute(Bytecode::Interpreter&) const; + String to_string() const; + +private: + Register m_lhs; +}; + class SetVariable final : public Instruction { public: - SetVariable(FlyString identifier, Register src) + SetVariable(FlyString identifier) : Instruction(Type::SetVariable) , m_identifier(move(identifier)) - , m_src(src) { } @@ -189,14 +196,12 @@ public: private: FlyString m_identifier; - Register m_src; }; class GetVariable final : public Instruction { public: - GetVariable(Register dst, FlyString identifier) + GetVariable(FlyString identifier) : Instruction(Type::GetVariable) - , m_dst(dst) , m_identifier(move(identifier)) { } @@ -205,16 +210,13 @@ public: String to_string() const; private: - Register m_dst; FlyString m_identifier; }; class GetById final : public Instruction { public: - GetById(Register dst, Register base, FlyString property) + GetById(FlyString property) : Instruction(Type::GetById) - , m_dst(dst) - , m_base(base) , m_property(move(property)) { } @@ -223,18 +225,15 @@ public: String to_string() const; private: - Register m_dst; - Register m_base; FlyString m_property; }; class PutById final : public Instruction { public: - PutById(Register base, FlyString property, Register src) + PutById(Register base, FlyString property) : Instruction(Type::PutById) , m_base(base) , m_property(move(property)) - , m_src(src) { } @@ -244,7 +243,6 @@ public: private: Register m_base; FlyString m_property; - Register m_src; }; class Jump : public Instruction { @@ -272,55 +270,42 @@ protected: class JumpIfFalse final : public Jump { public: - explicit JumpIfFalse(Register result, Optional