mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-04-25 05:55:13 +00:00
LibJS: Cache arguments span in ExecutionContext
Allows us to avoid doing math in ExecutionContext::argument()
This commit is contained in:
parent
ff751173ac
commit
e48645c83f
Notes:
github-actions[bot]
2025-04-24 08:31:57 +00:00
Author: https://github.com/kalenikaliaksandr Commit: https://github.com/LadybirdBrowser/ladybird/commit/e48645c83f4 Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/4434 Reviewed-by: https://github.com/alimpfard
13 changed files with 24 additions and 31 deletions
|
@ -374,7 +374,7 @@ FLATTEN_ON_CLANG void Interpreter::run_bytecode(size_t entry_point)
|
|||
}
|
||||
|
||||
auto& running_execution_context = this->running_execution_context();
|
||||
auto* arguments = running_execution_context.arguments().data();
|
||||
auto* arguments = running_execution_context.arguments.data();
|
||||
auto& accumulator = this->accumulator();
|
||||
auto& executable = current_executable();
|
||||
auto const* bytecode = executable.bytecode.data();
|
||||
|
@ -2331,7 +2331,7 @@ ThrowCompletionOr<void> CreateVariable::execute_impl(Bytecode::Interpreter& inte
|
|||
|
||||
void CreateRestParams::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto const arguments = interpreter.running_execution_context().arguments();
|
||||
auto const arguments = interpreter.running_execution_context().arguments;
|
||||
auto arguments_count = interpreter.running_execution_context().passed_argument_count;
|
||||
auto array = MUST(Array::create(interpreter.realm(), 0));
|
||||
for (size_t rest_index = m_rest_index; rest_index < arguments_count; ++rest_index)
|
||||
|
@ -2342,7 +2342,7 @@ void CreateRestParams::execute_impl(Bytecode::Interpreter& interpreter) const
|
|||
void CreateArguments::execute_impl(Bytecode::Interpreter& interpreter) const
|
||||
{
|
||||
auto const& function = interpreter.running_execution_context().function;
|
||||
auto const arguments = interpreter.running_execution_context().arguments();
|
||||
auto const arguments = interpreter.running_execution_context().arguments;
|
||||
auto const& environment = interpreter.running_execution_context().lexical_environment;
|
||||
|
||||
auto passed_arguments = ReadonlySpan<Value> { arguments.data(), interpreter.running_execution_context().passed_argument_count };
|
||||
|
|
|
@ -46,7 +46,7 @@ ThrowCompletionOr<GC::Ref<Object>> AsyncFunctionConstructor::construct(FunctionO
|
|||
|
||||
// 2. If bodyArg is not present, set bodyArg to the empty String.
|
||||
// NOTE: This does that, as well as the string extraction done inside of CreateDynamicFunction
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments()));
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments));
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, async, parameterArgs, bodyArg).
|
||||
return TRY(FunctionConstructor::create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Async, extracted.parameters, extracted.body));
|
||||
|
|
|
@ -47,7 +47,7 @@ ThrowCompletionOr<GC::Ref<Object>> AsyncGeneratorFunctionConstructor::construct(
|
|||
|
||||
// 2. If bodyArg is not present, set bodyArg to the empty String.
|
||||
// NOTE: This does that, as well as the string extraction done inside of CreateDynamicFunction
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments()));
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments));
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, async-generator, parameterArgs, bodyArg).
|
||||
return TRY(FunctionConstructor::create_dynamic_function(vm, *constructor, &new_target, FunctionKind::AsyncGenerator, extracted.parameters, extracted.body));
|
||||
|
|
|
@ -506,7 +506,7 @@ ThrowCompletionOr<Value> ECMAScriptFunctionObject::internal_call(Value this_argu
|
|||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_constants_and_locals_count, arguments_count);
|
||||
|
||||
// Non-standard
|
||||
auto arguments = callee_context->arguments();
|
||||
auto arguments = callee_context->arguments;
|
||||
if (!arguments_list.is_empty())
|
||||
arguments.overwrite(0, arguments_list.data(), arguments_list.size() * sizeof(Value));
|
||||
callee_context->passed_argument_count = arguments_list.size();
|
||||
|
@ -578,7 +578,7 @@ ThrowCompletionOr<GC::Ref<Object>> ECMAScriptFunctionObject::internal_construct(
|
|||
ALLOCATE_EXECUTION_CONTEXT_ON_NATIVE_STACK(callee_context, registers_and_constants_and_locals_count, arguments_count);
|
||||
|
||||
// Non-standard
|
||||
auto arguments = callee_context->arguments();
|
||||
auto arguments = callee_context->arguments;
|
||||
if (!arguments_list.is_empty())
|
||||
arguments.overwrite(0, arguments_list.data(), arguments_list.size() * sizeof(Value));
|
||||
callee_context->passed_argument_count = arguments_list.size();
|
||||
|
|
|
@ -106,6 +106,7 @@ ExecutionContext::ExecutionContext(u32 registers_and_constants_and_locals_count,
|
|||
auto* registers_and_constants_and_locals_and_arguments = this->registers_and_constants_and_locals_and_arguments();
|
||||
for (size_t i = 0; i < registers_and_constants_and_locals_count; ++i)
|
||||
registers_and_constants_and_locals_and_arguments[i] = js_special_empty_value();
|
||||
arguments = { registers_and_constants_and_locals_and_arguments + arguments_offset, registers_and_constants_and_locals_and_arguments_count - arguments_offset };
|
||||
}
|
||||
|
||||
ExecutionContext::~ExecutionContext()
|
||||
|
@ -114,7 +115,7 @@ ExecutionContext::~ExecutionContext()
|
|||
|
||||
NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const
|
||||
{
|
||||
auto copy = create(registers_and_constants_and_locals_and_arguments_count, arguments().size());
|
||||
auto copy = create(registers_and_constants_and_locals_and_arguments_count, arguments.size());
|
||||
copy->function = function;
|
||||
copy->realm = realm;
|
||||
copy->script_or_module = script_or_module;
|
||||
|
@ -134,6 +135,7 @@ NonnullOwnPtr<ExecutionContext> ExecutionContext::copy() const
|
|||
copy->registers_and_constants_and_locals_and_arguments_count = registers_and_constants_and_locals_and_arguments_count;
|
||||
for (size_t i = 0; i < registers_and_constants_and_locals_and_arguments_count; ++i)
|
||||
copy->registers_and_constants_and_locals_and_arguments()[i] = registers_and_constants_and_locals_and_arguments()[i];
|
||||
copy->arguments = { copy->registers_and_constants_and_locals_and_arguments() + copy->arguments_offset, arguments.size() };
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
|
|
@ -83,10 +83,9 @@ public:
|
|||
|
||||
Value argument(size_t index) const
|
||||
{
|
||||
auto arguments_size = registers_and_constants_and_locals_and_arguments_count - arguments_offset;
|
||||
if (index >= arguments_size) [[unlikely]]
|
||||
if (index >= arguments.size()) [[unlikely]]
|
||||
return js_undefined();
|
||||
return registers_and_constants_and_locals_and_arguments()[arguments_offset + index];
|
||||
return arguments[index];
|
||||
}
|
||||
|
||||
Value& local(size_t index)
|
||||
|
@ -98,15 +97,7 @@ public:
|
|||
u32 passed_argument_count { 0 };
|
||||
bool is_strict_mode { false };
|
||||
|
||||
Span<Value> arguments()
|
||||
{
|
||||
return { registers_and_constants_and_locals_and_arguments() + arguments_offset, registers_and_constants_and_locals_and_arguments_count - arguments_offset };
|
||||
}
|
||||
|
||||
ReadonlySpan<Value> arguments() const
|
||||
{
|
||||
return { registers_and_constants_and_locals_and_arguments() + arguments_offset, registers_and_constants_and_locals_and_arguments_count - arguments_offset };
|
||||
}
|
||||
Span<Value> arguments;
|
||||
|
||||
Vector<Bytecode::UnwindInfo> unwind_contexts;
|
||||
Vector<Optional<size_t>> previously_scheduled_jumps;
|
||||
|
|
|
@ -269,7 +269,7 @@ ThrowCompletionOr<GC::Ref<Object>> FunctionConstructor::construct(FunctionObject
|
|||
|
||||
// 2. If bodyArg is not present, set bodyArg to the empty String.
|
||||
// NOTE: This does that, as well as the string extraction done inside of CreateDynamicFunction
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments()));
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments));
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, normal, parameterArgs, bodyArg).
|
||||
return TRY(create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Normal, extracted.parameters, extracted.body));
|
||||
|
|
|
@ -98,7 +98,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::bind)
|
|||
|
||||
Vector<Value> arguments;
|
||||
if (vm.argument_count() > 1) {
|
||||
arguments.append(vm.running_execution_context().arguments().slice(1).data(), vm.argument_count() - 1);
|
||||
arguments.append(vm.running_execution_context().arguments.slice(1).data(), vm.argument_count() - 1);
|
||||
}
|
||||
|
||||
// 3. Let F be ? BoundFunctionCreate(Target, thisArg, args).
|
||||
|
@ -129,7 +129,7 @@ JS_DEFINE_NATIVE_FUNCTION(FunctionPrototype::call)
|
|||
// FIXME: 3. Perform PrepareForTailCall().
|
||||
|
||||
auto this_arg = vm.argument(0);
|
||||
auto args = vm.argument_count() > 1 ? vm.running_execution_context().arguments().slice(1) : ReadonlySpan<Value> {};
|
||||
auto args = vm.argument_count() > 1 ? vm.running_execution_context().arguments.slice(1) : ReadonlySpan<Value> {};
|
||||
|
||||
// 4. Return ? Call(func, thisArg, args).
|
||||
return TRY(JS::call(vm, function, this_arg, args));
|
||||
|
|
|
@ -45,7 +45,7 @@ ThrowCompletionOr<GC::Ref<Object>> GeneratorFunctionConstructor::construct(Funct
|
|||
|
||||
// 2. If bodyArg is not present, set bodyArg to the empty String.
|
||||
// NOTE: This does that, as well as the string extraction done inside of CreateDynamicFunction
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments()));
|
||||
auto extracted = TRY(extract_parameter_arguments_and_body(vm, vm.running_execution_context().arguments));
|
||||
|
||||
// 3. Return ? CreateDynamicFunction(C, NewTarget, generator, parameterArgs, bodyArg).
|
||||
return TRY(FunctionConstructor::create_dynamic_function(vm, *constructor, &new_target, FunctionKind::Generator, extracted.parameters, extracted.body));
|
||||
|
|
|
@ -146,7 +146,7 @@ ThrowCompletionOr<Value> NativeFunction::internal_call(Value this_argument, Read
|
|||
// 8. Perform any necessary implementation-defined initialization of calleeContext.
|
||||
callee_context->this_value = this_argument;
|
||||
if (!arguments_list.is_empty())
|
||||
callee_context->arguments().overwrite(0, arguments_list.data(), arguments_list.size() * sizeof(Value));
|
||||
callee_context->arguments.overwrite(0, arguments_list.data(), arguments_list.size() * sizeof(Value));
|
||||
|
||||
callee_context->lexical_environment = caller_context.lexical_environment;
|
||||
callee_context->variable_environment = caller_context.variable_environment;
|
||||
|
@ -208,7 +208,7 @@ ThrowCompletionOr<GC::Ref<Object>> NativeFunction::internal_construct(ReadonlySp
|
|||
|
||||
// 8. Perform any necessary implementation-defined initialization of calleeContext.
|
||||
if (!arguments_list.is_empty())
|
||||
callee_context->arguments().overwrite(0, arguments_list.data(), arguments_list.size() * sizeof(Value));
|
||||
callee_context->arguments.overwrite(0, arguments_list.data(), arguments_list.size() * sizeof(Value));
|
||||
|
||||
callee_context->lexical_environment = caller_context.lexical_environment;
|
||||
callee_context->variable_environment = caller_context.variable_environment;
|
||||
|
|
|
@ -465,7 +465,7 @@ JS_DEFINE_NATIVE_FUNCTION(PromiseConstructor::try_)
|
|||
auto callback = vm.argument(0);
|
||||
Span<Value> args;
|
||||
if (vm.argument_count() > 1) {
|
||||
args = vm.running_execution_context().arguments().slice(1, vm.argument_count() - 1);
|
||||
args = vm.running_execution_context().arguments.slice(1, vm.argument_count() - 1);
|
||||
}
|
||||
|
||||
// 1. Let C be the this value.
|
||||
|
|
|
@ -160,7 +160,7 @@ public:
|
|||
|
||||
size_t argument_count() const
|
||||
{
|
||||
return running_execution_context().arguments().size();
|
||||
return running_execution_context().arguments.size();
|
||||
}
|
||||
|
||||
Value argument(size_t index) const
|
||||
|
|
|
@ -137,7 +137,7 @@ Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<HT
|
|||
if (value->is_function()) {
|
||||
value = JS::NativeFunction::create(
|
||||
realm, [function = GC::make_root(*value)](auto& vm) {
|
||||
return JS::call(vm, function.value(), JS::js_undefined(), vm.running_execution_context().arguments());
|
||||
return JS::call(vm, function.value(), JS::js_undefined(), vm.running_execution_context().arguments);
|
||||
},
|
||||
0);
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<HT
|
|||
if (*entry.needs_get) {
|
||||
cross_origin_get = JS::NativeFunction::create(
|
||||
realm, [object_ptr, getter = GC::make_root(*original_descriptor->get)](auto& vm) {
|
||||
return JS::call(vm, getter.cell(), object_ptr, vm.running_execution_context().arguments());
|
||||
return JS::call(vm, getter.cell(), object_ptr, vm.running_execution_context().arguments);
|
||||
},
|
||||
0);
|
||||
}
|
||||
|
@ -166,7 +166,7 @@ Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<HT
|
|||
if (*entry.needs_set) {
|
||||
cross_origin_set = JS::NativeFunction::create(
|
||||
realm, [object_ptr, setter = GC::make_root(*original_descriptor->set)](auto& vm) {
|
||||
return JS::call(vm, setter.cell(), object_ptr, vm.running_execution_context().arguments());
|
||||
return JS::call(vm, setter.cell(), object_ptr, vm.running_execution_context().arguments);
|
||||
},
|
||||
0);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue