diff --git a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp index 028683b934..2264dc85a0 100644 --- a/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp +++ b/Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp @@ -632,7 +632,15 @@ void CallExpression::generate_bytecode(Bytecode::Generator& generator) const generator.emit(arg_reg); argument_registers.append(arg_reg); } - generator.emit_with_extra_register_slots(argument_registers.size(), callee_reg, this_reg, argument_registers); + + Bytecode::Op::Call::CallType call_type; + if (is(*this)) { + call_type = Bytecode::Op::Call::CallType::Construct; + } else { + call_type = Bytecode::Op::Call::CallType::Call; + } + + generator.emit_with_extra_register_slots(argument_registers.size(), call_type, callee_reg, this_reg, argument_registers); } void ReturnStatement::generate_bytecode(Bytecode::Generator& generator) const @@ -813,7 +821,7 @@ void TaggedTemplateLiteral::generate_bytecode(Bytecode::Generator& generator) co auto this_reg = generator.allocate_register(); generator.emit(this_reg); - generator.emit_with_extra_register_slots(argument_regs.size(), tag_reg, this_reg, move(argument_regs)); + generator.emit_with_extra_register_slots(argument_regs.size(), Bytecode::Op::Call::CallType::Call, tag_reg, this_reg, move(argument_regs)); } void UpdateExpression::generate_bytecode(Bytecode::Generator& generator) const diff --git a/Userland/Libraries/LibJS/Bytecode/Op.cpp b/Userland/Libraries/LibJS/Bytecode/Op.cpp index 27f51e8a77..8824dbb8f1 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Op.cpp @@ -199,14 +199,17 @@ void Call::execute(Bytecode::Interpreter& interpreter) const Value return_value; - if (m_argument_count == 0) { + if (m_argument_count == 0 && m_type == CallType::Call) { return_value = interpreter.vm().call(function, this_value); } else { MarkedValueList argument_values { interpreter.vm().heap() }; for (size_t i = 0; i < m_argument_count; ++i) { argument_values.append(interpreter.reg(m_arguments[i])); } - return_value = interpreter.vm().call(function, this_value, move(argument_values)); + if (m_type == CallType::Call) + return_value = interpreter.vm().call(function, this_value, move(argument_values)); + else + return_value = interpreter.vm().construct(function, function, move(argument_values), interpreter.global_object()); } interpreter.accumulator() = return_value; diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index e270003ee9..ca0497807e 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/Userland/Libraries/LibJS/Bytecode/Op.h @@ -325,10 +325,16 @@ public: // NOTE: This instruction is variable-width depending on the number of arguments! class Call final : public Instruction { public: - Call(Register callee, Register this_value, Vector const& arguments) + enum class CallType { + Call, + Construct, + }; + + Call(CallType type, Register callee, Register this_value, Vector const& arguments) : Instruction(Type::Call) , m_callee(callee) , m_this_value(this_value) + , m_type(type) , m_argument_count(arguments.size()) { for (size_t i = 0; i < m_argument_count; ++i) @@ -343,6 +349,7 @@ public: private: Register m_callee; Register m_this_value; + CallType m_type; size_t m_argument_count { 0 }; Register m_arguments[]; };