summaryrefslogtreecommitdiff
path: root/Userland/Libraries
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2021-08-09 17:09:48 -0400
committerAndreas Kling <kling@serenityos.org>2021-08-10 23:07:50 +0200
commit66264f7c2a823a9be09e91abe9b75041005d7045 (patch)
tree2753f75456538ab9f985a6de0d66cdcd60b335bb /Userland/Libraries
parent34bd25f6c280070581661bd7708830c772bfa604 (diff)
downloadserenity-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.cpp2
-rw-r--r--Userland/Libraries/LibJS/Interpreter.cpp2
-rw-r--r--Userland/Libraries/LibJS/Runtime/VM.cpp31
-rw-r--r--Userland/Libraries/LibJS/Runtime/VM.h7
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 };