diff options
author | Andreas Kling <kling@serenityos.org> | 2021-06-10 23:01:49 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-06-10 23:01:49 +0200 |
commit | f5feb1d2cd1198eb681592361340c5b02779524f (patch) | |
tree | 118761ab11d8b45f97dd77b6be3ba8874d4443a6 /Userland/Libraries/LibJS | |
parent | c3c68399b5e7019c30e5ac6fb7cb38d586f2a7f3 (diff) | |
download | serenity-f5feb1d2cd1198eb681592361340c5b02779524f.zip |
LibJS: Very basic support for "new" construction in bytecode VM
This patch adds a CallType to the Bytecode::Op::Call instruction,
which can be either Call or Construct. We then generate Construct
calls for the NewExpression AST node.
When executed, these get fed into VM::construct().
Diffstat (limited to 'Userland/Libraries/LibJS')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/ASTCodegen.cpp | 12 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.cpp | 7 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Op.h | 9 |
3 files changed, 23 insertions, 5 deletions
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<Bytecode::Op::Store>(arg_reg); argument_registers.append(arg_reg); } - generator.emit_with_extra_register_slots<Bytecode::Op::Call>(argument_registers.size(), callee_reg, this_reg, argument_registers); + + Bytecode::Op::Call::CallType call_type; + if (is<NewExpression>(*this)) { + call_type = Bytecode::Op::Call::CallType::Construct; + } else { + call_type = Bytecode::Op::Call::CallType::Call; + } + + generator.emit_with_extra_register_slots<Bytecode::Op::Call>(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<Bytecode::Op::Store>(this_reg); - generator.emit_with_extra_register_slots<Bytecode::Op::Call>(argument_regs.size(), tag_reg, this_reg, move(argument_regs)); + generator.emit_with_extra_register_slots<Bytecode::Op::Call>(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<Register> const& arguments) + enum class CallType { + Call, + Construct, + }; + + Call(CallType type, Register callee, Register this_value, Vector<Register> 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[]; }; |