diff options
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp')
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp | 89 |
1 files changed, 56 insertions, 33 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp b/Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp index e80954b4a0..4e4cf9698b 100644 --- a/Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp +++ b/Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp @@ -6,6 +6,9 @@ #include <AK/Function.h> #include <LibJS/AST.h> +#include <LibJS/Bytecode/Block.h> +#include <LibJS/Bytecode/Generator.h> +#include <LibJS/Bytecode/Interpreter.h> #include <LibJS/Interpreter.h> #include <LibJS/Runtime/Array.h> #include <LibJS/Runtime/Error.h> @@ -110,45 +113,65 @@ Value ScriptFunction::execute_function_body() { auto& vm = this->vm(); - OwnPtr<Interpreter> local_interpreter; - Interpreter* interpreter = vm.interpreter_if_exists(); + Interpreter* ast_interpreter = nullptr; + auto* bytecode_interpreter = Bytecode::Interpreter::current(); + + auto prepare_arguments = [&] { + auto& call_frame_args = vm.call_frame().arguments; + for (size_t i = 0; i < m_parameters.size(); ++i) { + auto& parameter = m_parameters[i]; + parameter.binding.visit( + [&](const auto& param) { + Value argument_value; + if (parameter.is_rest) { + auto* array = Array::create(global_object()); + for (size_t rest_index = i; rest_index < call_frame_args.size(); ++rest_index) + array->indexed_properties().append(call_frame_args[rest_index]); + argument_value = move(array); + } else if (i < call_frame_args.size() && !call_frame_args[i].is_undefined()) { + argument_value = call_frame_args[i]; + } else if (parameter.default_value) { + // FIXME: Support default arguments in the bytecode world! + if (!bytecode_interpreter) + argument_value = parameter.default_value->execute(*ast_interpreter, global_object()); + if (vm.exception()) + return; + } else { + argument_value = js_undefined(); + } + + vm.assign(param, argument_value, global_object(), true, vm.current_scope()); + }); - if (!interpreter) { - local_interpreter = Interpreter::create_with_existing_global_object(global_object()); - interpreter = local_interpreter.ptr(); - } + if (vm.exception()) + return; + } + }; + + if (bytecode_interpreter) { + prepare_arguments(); + auto block = Bytecode::Generator::generate(m_body); + VERIFY(block); + dbgln("Compiled Bytecode::Block for function '{}':", m_name); + block->dump(); + return bytecode_interpreter->run(*block); + } else { + OwnPtr<Interpreter> local_interpreter; + ast_interpreter = vm.interpreter_if_exists(); + + if (!ast_interpreter) { + local_interpreter = Interpreter::create_with_existing_global_object(global_object()); + ast_interpreter = local_interpreter.ptr(); + } - VM::InterpreterExecutionScope scope(*interpreter); - - auto& call_frame_args = vm.call_frame().arguments; - for (size_t i = 0; i < m_parameters.size(); ++i) { - auto& parameter = m_parameters[i]; - parameter.binding.visit( - [&](const auto& param) { - Value argument_value; - if (parameter.is_rest) { - auto* array = Array::create(global_object()); - for (size_t rest_index = i; rest_index < call_frame_args.size(); ++rest_index) - array->indexed_properties().append(call_frame_args[rest_index]); - argument_value = move(array); - } else if (i < call_frame_args.size() && !call_frame_args[i].is_undefined()) { - argument_value = call_frame_args[i]; - } else if (parameter.default_value) { - argument_value = parameter.default_value->execute(*interpreter, global_object()); - if (vm.exception()) - return; - } else { - argument_value = js_undefined(); - } - - vm.assign(param, argument_value, global_object(), true, vm.current_scope()); - }); + VM::InterpreterExecutionScope scope(*ast_interpreter); + prepare_arguments(); if (vm.exception()) return {}; - } - return interpreter->execute_statement(global_object(), m_body, ScopeType::Function); + return ast_interpreter->execute_statement(global_object(), m_body, ScopeType::Function); + } } Value ScriptFunction::call() |