summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp')
-rw-r--r--Userland/Libraries/LibJS/Runtime/ScriptFunction.cpp89
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()