mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:57:36 +00:00
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
This commit is contained in:
parent
34bd25f6c2
commit
66264f7c2a
4 changed files with 25 additions and 17 deletions
|
@ -44,7 +44,7 @@ Value Interpreter::run(Executable const& executable, BasicBlock const* entry_poi
|
||||||
|
|
||||||
vm().set_last_value(Badge<Interpreter> {}, {});
|
vm().set_last_value(Badge<Interpreter> {}, {});
|
||||||
|
|
||||||
ExecutionContext execution_context;
|
ExecutionContext execution_context(vm().heap());
|
||||||
if (vm().execution_context_stack().is_empty()) {
|
if (vm().execution_context_stack().is_empty()) {
|
||||||
execution_context.this_value = &global_object();
|
execution_context.this_value = &global_object();
|
||||||
static FlyString global_execution_context_name = "(*BC* global execution context)";
|
static FlyString global_execution_context_name = "(*BC* global execution context)";
|
||||||
|
|
|
@ -45,7 +45,7 @@ void Interpreter::run(GlobalObject& global_object, const Program& program)
|
||||||
|
|
||||||
vm.set_last_value(Badge<Interpreter> {}, {});
|
vm.set_last_value(Badge<Interpreter> {}, {});
|
||||||
|
|
||||||
ExecutionContext execution_context;
|
ExecutionContext execution_context(heap());
|
||||||
execution_context.current_node = &program;
|
execution_context.current_node = &program;
|
||||||
execution_context.this_value = &global_object;
|
execution_context.this_value = &global_object;
|
||||||
static FlyString global_execution_context_name = "(global execution context)";
|
static FlyString global_execution_context_name = "(global execution context)";
|
||||||
|
|
|
@ -442,6 +442,18 @@ Reference VM::resolve_binding(FlyString const& name, Environment* environment)
|
||||||
return get_identifier_reference(environment, name, strict);
|
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)
|
Value VM::construct(FunctionObject& function, FunctionObject& new_target, Optional<MarkedValueList> arguments)
|
||||||
{
|
{
|
||||||
auto& global_object = function.global_object();
|
auto& global_object = function.global_object();
|
||||||
|
@ -453,7 +465,7 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutionContext callee_context;
|
ExecutionContext callee_context(heap());
|
||||||
prepare_for_ordinary_call(function, callee_context, &new_target);
|
prepare_for_ordinary_call(function, callee_context, &new_target);
|
||||||
if (exception())
|
if (exception())
|
||||||
return {};
|
return {};
|
||||||
|
@ -465,9 +477,7 @@ Value VM::construct(FunctionObject& function, FunctionObject& new_target, Option
|
||||||
if (auto* interpreter = interpreter_if_exists())
|
if (auto* interpreter = interpreter_if_exists())
|
||||||
callee_context.current_node = interpreter->current_node();
|
callee_context.current_node = interpreter->current_node();
|
||||||
|
|
||||||
callee_context.arguments = function.bound_arguments();
|
append_bound_and_passed_arguments(callee_context.arguments, function.bound_arguments(), move(arguments));
|
||||||
if (arguments.has_value())
|
|
||||||
callee_context.arguments.extend(arguments.value().values());
|
|
||||||
|
|
||||||
if (auto* environment = callee_context.lexical_environment) {
|
if (auto* environment = callee_context.lexical_environment) {
|
||||||
auto& function_environment = verify_cast<FunctionEnvironment>(*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)) {
|
if (is<BoundFunction>(function)) {
|
||||||
auto& bound_function = static_cast<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() };
|
MarkedValueList with_bound_arguments { heap() };
|
||||||
with_bound_arguments.extend(bound_function.bound_arguments());
|
append_bound_and_passed_arguments(with_bound_arguments, bound_function.bound_arguments(), move(arguments));
|
||||||
if (arguments.has_value())
|
|
||||||
with_bound_arguments.extend(*arguments);
|
|
||||||
|
|
||||||
return call_internal(bound_function.target_function(), bound_function.bound_this(), move(with_bound_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());
|
prepare_for_ordinary_call(function, callee_context, js_undefined());
|
||||||
if (exception())
|
if (exception())
|
||||||
return {};
|
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.current_node = interpreter->current_node();
|
||||||
|
|
||||||
callee_context.this_value = function.bound_this().value_or(this_value);
|
callee_context.this_value = function.bound_this().value_or(this_value);
|
||||||
callee_context.arguments = function.bound_arguments();
|
append_bound_and_passed_arguments(callee_context.arguments, function.bound_arguments(), move(arguments));
|
||||||
if (arguments.has_value())
|
|
||||||
callee_context.arguments.extend(arguments.value().values());
|
|
||||||
|
|
||||||
if (callee_context.lexical_environment)
|
if (callee_context.lexical_environment)
|
||||||
ordinary_call_bind_this(function, callee_context, this_value);
|
ordinary_call_bind_this(function, callee_context, this_value);
|
||||||
|
|
|
@ -43,11 +43,16 @@ struct ScopeFrame {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ExecutionContext {
|
struct ExecutionContext {
|
||||||
|
explicit ExecutionContext(Heap& heap)
|
||||||
|
: arguments(heap)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
const ASTNode* current_node { nullptr };
|
const ASTNode* current_node { nullptr };
|
||||||
FlyString function_name;
|
FlyString function_name;
|
||||||
FunctionObject* function { nullptr };
|
FunctionObject* function { nullptr };
|
||||||
Value this_value;
|
Value this_value;
|
||||||
Vector<Value> arguments;
|
MarkedValueList arguments;
|
||||||
Object* arguments_object { nullptr };
|
Object* arguments_object { nullptr };
|
||||||
Environment* lexical_environment { nullptr };
|
Environment* lexical_environment { nullptr };
|
||||||
Environment* variable_environment { nullptr };
|
Environment* variable_environment { nullptr };
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue