diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp index 00359a01b3..446c179cf8 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.cpp @@ -184,4 +184,27 @@ ThrowCompletionOr put_by_property_key(VM& vm, Value base, Value this_value return {}; } +template +ThrowCompletionOr perform_call(Interpreter& interpreter, InstructionType const& call, Value callee, MarkedVector argument_values) +{ + auto& vm = interpreter.vm(); + auto this_value = interpreter.reg(call.this_value()); + auto& function = callee.as_function(); + Value return_value; + if (call.call_type() == Op::CallType::DirectEval) { + if (callee == interpreter.realm().intrinsics().eval_function()) + return_value = TRY(perform_eval(vm, !argument_values.is_empty() ? argument_values[0].value_or(JS::js_undefined()) : js_undefined(), vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct)); + else + return_value = TRY(JS::call(vm, function, this_value, move(argument_values))); + } else if (call.call_type() == Op::CallType::Call) + return_value = TRY(JS::call(vm, function, this_value, move(argument_values))); + else + return_value = TRY(construct(vm, function, move(argument_values))); + + return return_value; +} + +template ThrowCompletionOr perform_call(Interpreter&, Op::Call const&, Value, MarkedVector); +template ThrowCompletionOr perform_call(Interpreter&, Op::CallWithArgumentArray const&, Value, MarkedVector); + } diff --git a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h index 81edbbb8c7..cf3a2debbe 100644 --- a/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h +++ b/Userland/Libraries/LibJS/Bytecode/CommonImplementations.h @@ -17,5 +17,7 @@ ThrowCompletionOr get_by_id(Bytecode::Interpreter&, IdentifierTableIndex, ThrowCompletionOr get_by_value(Bytecode::Interpreter&, Value base_value, Value property_key_value); ThrowCompletionOr get_global(Bytecode::Interpreter&, IdentifierTableIndex, u32 cache_index); ThrowCompletionOr put_by_property_key(VM&, Value base, Value this_value, Value value, PropertyKey name, Op::PropertyKind kind); +template +ThrowCompletionOr perform_call(Interpreter&, InstructionType const&, Value callee, MarkedVector argument_values); } diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 5a0417160a..f0e1e7a815 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1155,26 +1155,6 @@ static ThrowCompletionOr throw_if_needed_for_call(Interpreter& interpreter return {}; } -static ThrowCompletionOr perform_call(Interpreter& interpreter, auto& call, Value callee, MarkedVector argument_values) -{ - auto& vm = interpreter.vm(); - auto this_value = interpreter.reg(call.this_value()); - auto& function = callee.as_function(); - Value return_value; - if (call.call_type() == CallType::DirectEval) { - if (callee == interpreter.realm().intrinsics().eval_function()) - return_value = TRY(perform_eval(vm, !argument_values.is_empty() ? argument_values[0].value_or(JS::js_undefined()) : js_undefined(), vm.in_strict_mode() ? CallerMode::Strict : CallerMode::NonStrict, EvalMode::Direct)); - else - return_value = TRY(JS::call(vm, function, this_value, move(argument_values))); - } else if (call.call_type() == CallType::Call) - return_value = TRY(JS::call(vm, function, this_value, move(argument_values))); - else - return_value = TRY(construct(vm, function, move(argument_values))); - - interpreter.accumulator() = return_value; - return {}; -} - ThrowCompletionOr Call::execute_impl(Bytecode::Interpreter& interpreter) const { auto& vm = interpreter.vm(); @@ -1187,7 +1167,8 @@ ThrowCompletionOr Call::execute_impl(Bytecode::Interpreter& interpreter) c for (u32 i = 0; i < m_argument_count; ++i) { argument_values.unchecked_append(interpreter.reg(Register { m_first_argument.index() + i })); } - return perform_call(interpreter, *this, callee, move(argument_values)); + interpreter.accumulator() = TRY(perform_call(interpreter, *this, callee, move(argument_values))); + return {}; } ThrowCompletionOr CallWithArgumentArray::execute_impl(Bytecode::Interpreter& interpreter) const @@ -1195,7 +1176,8 @@ ThrowCompletionOr CallWithArgumentArray::execute_impl(Bytecode::Interprete auto callee = interpreter.reg(m_callee); TRY(throw_if_needed_for_call(interpreter, *this, callee)); auto argument_values = argument_list_evaluation(interpreter); - return perform_call(interpreter, *this, callee, move(argument_values)); + interpreter.accumulator() = TRY(perform_call(interpreter, *this, callee, move(argument_values))); + return {}; } // 13.3.7.1 Runtime Semantics: Evaluation, https://tc39.es/ecma262/#sec-super-keyword-runtime-semantics-evaluation