mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 16:38:10 +00:00
LibJS: Use known binding indices when creating new for-loop environments
When the initialization statement of a for-loop uses 'let', we must create a new environment for each iteration of the for loop. The bindings of the initialization statement are copied over to the new environment. Since the bindings are created in the same order each time, we can use that order to directly initialize the bindings and avoid any O(n) lookups in this hot loop.
This commit is contained in:
parent
f56bf610c4
commit
f235f08e6d
1 changed files with 10 additions and 4 deletions
|
@ -736,13 +736,16 @@ Completion ForStatement::loop_evaluation(Interpreter& interpreter, GlobalObject&
|
|||
}
|
||||
|
||||
// 14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings ), https://tc39.es/ecma262/#sec-createperiterationenvironment
|
||||
// NOTE: Our implementation of this AO is heavily dependent on DeclarativeEnvironment using a Vector with constant indices.
|
||||
// For performance, we can take advantage of the fact that the declarations of the initialization statement are created
|
||||
// in the same order each time CreatePerIterationEnvironment is invoked.
|
||||
auto create_per_iteration_environment = [&]() -> ThrowCompletionOr<void> {
|
||||
// 1. If perIterationBindings has any elements, then
|
||||
if (let_declarations.is_empty())
|
||||
return {};
|
||||
|
||||
// a. Let lastIterationEnv be the running execution context's LexicalEnvironment.
|
||||
auto* last_iteration_env = interpreter.lexical_environment();
|
||||
auto* last_iteration_env = verify_cast<DeclarativeEnvironment>(interpreter.lexical_environment());
|
||||
|
||||
// b. Let outer be lastIterationEnv.[[OuterEnv]].
|
||||
auto* outer = last_iteration_env->outer_environment();
|
||||
|
@ -752,18 +755,21 @@ Completion ForStatement::loop_evaluation(Interpreter& interpreter, GlobalObject&
|
|||
|
||||
// d. Let thisIterationEnv be NewDeclarativeEnvironment(outer).
|
||||
auto* this_iteration_env = new_declarative_environment(*outer);
|
||||
this_iteration_env->ensure_capacity(let_declarations.size());
|
||||
|
||||
// e. For each element bn of perIterationBindings, do
|
||||
for (auto& name : let_declarations) {
|
||||
for (size_t declaration_index = 0; declaration_index < let_declarations.size(); ++declaration_index) {
|
||||
auto const& name = let_declarations[declaration_index];
|
||||
|
||||
// i. Perform ! thisIterationEnv.CreateMutableBinding(bn, false).
|
||||
MUST(this_iteration_env->create_mutable_binding(global_object, name, false));
|
||||
|
||||
// ii. Let lastValue be ? lastIterationEnv.GetBindingValue(bn, true).
|
||||
auto last_value = TRY(last_iteration_env->get_binding_value(global_object, name, true));
|
||||
auto last_value = TRY(last_iteration_env->get_binding_value_direct(global_object, declaration_index, true));
|
||||
VERIFY(!last_value.is_empty());
|
||||
|
||||
// iii. Perform thisIterationEnv.InitializeBinding(bn, lastValue).
|
||||
MUST(this_iteration_env->initialize_binding(global_object, name, last_value));
|
||||
MUST(this_iteration_env->initialize_binding_direct(global_object, declaration_index, last_value));
|
||||
}
|
||||
|
||||
// f. Set the running execution context's LexicalEnvironment to thisIterationEnv.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue