diff options
author | Timothy Flynn <trflynn89@pm.me> | 2021-08-09 17:09:48 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-08-10 23:07:50 +0200 |
commit | 66264f7c2a823a9be09e91abe9b75041005d7045 (patch) | |
tree | 2753f75456538ab9f985a6de0d66cdcd60b335bb /Userland/Libraries | |
parent | 34bd25f6c280070581661bd7708830c772bfa604 (diff) | |
download | serenity-66264f7c2a823a9be09e91abe9b75041005d7045.zip |
LibJS: Change ExecutionContext's arguments list to a MarkedValueList
The test262 tests under RegExp/property-escapes/generated will invoke
Reflect.apply with up to 10,000 arguments at a time. In LibJS, when the
call stack reached VM::call_internal, we transfer those arguments from
a MarkedValueList to the execution context's arguments Vector.
Because these types differ (MarkedValueList is a Vector<Value, 32>), the
arguments are copied rather than moved. By changing the arguments vector
to a MarkedValueList, we can properly move the passed arguments over.
This shaves about 2 seconds off the following test262 test (from 15sec):
RegExp/property-escapes/generated/General_Category_-_Decimal_Number.js
Diffstat (limited to 'Userland/Libraries')
-rw-r--r-- | Userland/Libraries/LibJS/Bytecode/Interpreter.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Interpreter.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/VM.cpp | 31 | ||||
-rw-r--r-- | Userland/Libraries/LibJS/Runtime/VM.h | 7 |
4 files changed, 25 insertions, 17 deletions
diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 9e6f04b26f..50d9f2a49b 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -44,7 +44,7 @@ Value Interpreter::run(Executable const& executable, BasicBlock const* entry_poi vm().set_last_value(Badge<Interpreter> {}, {}); - ExecutionContext execution_context; + ExecutionContext execution_context(vm().heap()); if (vm().execution_context_stack().is_empty()) { execution_context.this_value = &global_object(); static FlyString global_execution_context_name = "(*BC* global execution context)"; diff --git a/Userland/Libraries/LibJS/Interpreter.cpp b/Userland/Libraries/LibJS/Interpreter.cpp index e5d800042f..41db16c75d 100644 --- a/Userland/Libraries/LibJS/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Interpreter.cpp @@ -45,7 +45,7 @@ void Interpreter::run(GlobalObject& global_object, const Program& program) vm.set_last_value(Badge<Interpreter> {}, {}); - ExecutionContext execution_context; + ExecutionContext execution_context(heap()); execution_context.current_node = &program; execution_context.this_value = &global_object; static FlyString global_execution_context_name = "(global execution context)"; diff --git a/Userland/Libraries/LibJS/Runtime/VM.cpp b/Userland/Libraries/LibJS/Runtime/VM.cpp index 8e993bcd7f..048004e61d 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.cpp +++ b/Userland/Libraries/LibJS/Runtime/VM.cpp @@ -442,6 +442,18 @@ Reference VM::resolve_binding(FlyString const& name, Environment* environment) return get_identifier_reference(environment, name, strict); } +static void append_bound_and_passed_arguments(MarkedValueList& arguments, Vector<Value> bound_arguments, Optional<MarkedValueList> passed_arguments) +{ + arguments.ensure_capacity(bound_arguments.size()); + arguments.extend(move(bound_arguments)); + + if (passed_arguments.has_value()) { + auto arguments_list = move(passed_arguments.release_value().values()); + arguments.grow_capacity(arguments_list.size()); + arguments.extend(move(arguments_list)); + } +} + Value VM::construct(FunctionObject& function, FunctionObject& new_target, Optional<MarkedValueList> arguments) { auto& global_object = function.global_object(); @@ -453,7 +465,7 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option return {}; } - ExecutionContext callee_context; + ExecutionContext callee_context(heap()); prepare_for_ordinary_call(function, callee_context, &new_target); if (exception()) return {}; @@ -465,9 +477,7 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option if (auto* interpreter = interpreter_if_exists()) callee_context.current_node = interpreter->current_node(); - callee_context.arguments = function.bound_arguments(); - if (arguments.has_value()) - callee_context.arguments.extend(arguments.value().values()); + append_bound_and_passed_arguments(callee_context.arguments, function.bound_arguments(), move(arguments)); if (auto* environment = callee_context.lexical_environment) { auto& function_environment = verify_cast<FunctionEnvironment>(*environment); @@ -631,19 +641,14 @@ Value VM::call_internal(FunctionObject& function, Value this_value, Optional<Mar if (is<BoundFunction>(function)) { auto& bound_function = static_cast<BoundFunction&>(function); - auto bound_arguments = bound_function.bound_arguments(); - if (arguments.has_value()) - bound_arguments.extend(*arguments); MarkedValueList with_bound_arguments { heap() }; - with_bound_arguments.extend(bound_function.bound_arguments()); - if (arguments.has_value()) - with_bound_arguments.extend(*arguments); + append_bound_and_passed_arguments(with_bound_arguments, bound_function.bound_arguments(), move(arguments)); return call_internal(bound_function.target_function(), bound_function.bound_this(), move(with_bound_arguments)); } - ExecutionContext callee_context; + ExecutionContext callee_context(heap()); prepare_for_ordinary_call(function, callee_context, js_undefined()); if (exception()) return {}; @@ -656,9 +661,7 @@ Value VM::call_internal(FunctionObject& function, Value this_value, Optional<Mar callee_context.current_node = interpreter->current_node(); callee_context.this_value = function.bound_this().value_or(this_value); - callee_context.arguments = function.bound_arguments(); - if (arguments.has_value()) - callee_context.arguments.extend(arguments.value().values()); + append_bound_and_passed_arguments(callee_context.arguments, function.bound_arguments(), move(arguments)); if (callee_context.lexical_environment) ordinary_call_bind_this(function, callee_context, this_value); diff --git a/Userland/Libraries/LibJS/Runtime/VM.h b/Userland/Libraries/LibJS/Runtime/VM.h index d06d8b5d7f..5e4fc8a563 100644 --- a/Userland/Libraries/LibJS/Runtime/VM.h +++ b/Userland/Libraries/LibJS/Runtime/VM.h @@ -43,11 +43,16 @@ struct ScopeFrame { }; struct ExecutionContext { + explicit ExecutionContext(Heap& heap) + : arguments(heap) + { + } + const ASTNode* current_node { nullptr }; FlyString function_name; FunctionObject* function { nullptr }; Value this_value; - Vector<Value> arguments; + MarkedValueList arguments; Object* arguments_object { nullptr }; Environment* lexical_environment { nullptr }; Environment* variable_environment { nullptr }; |