1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:07:35 +00:00

LibJS: Skip declarative env in block statement without lexical decls

The idea here is simple: If the block statement doesn't contain any
lexical declarations, we don't need to allocate, initialize and
eventually garbage collect a new declarative environment.
This even makes lookups across nested blocks slightly faster as we don't
have to traverse a chain of empty environments anymore - instead, the
execution context just stores the outermost non-empty one.

This doesn't speed up test-js considerably, but has a noticeable effect
on test262 and real-world web content :^)
This commit is contained in:
Linus Groh 2021-10-05 12:59:04 +01:00 committed by Andreas Kling
parent d609dde7b0
commit 8074bdc049
2 changed files with 16 additions and 5 deletions

View file

@ -122,13 +122,21 @@ Value BlockStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
InterpreterNodeScope node_scope { interpreter, *this };
auto& vm = interpreter.vm();
Environment* old_environment = vm.running_execution_context().lexical_environment;
ScopeGuard restore_environment = [&] {
Environment* old_environment { nullptr };
ArmedScopeGuard restore_environment = [&] {
vm.running_execution_context().lexical_environment = old_environment;
};
auto* block_environment = new_declarative_environment(*old_environment);
block_declaration_instantiation(global_object, block_environment);
vm.running_execution_context().lexical_environment = block_environment;
// Optimization: We only need a new lexical environment if there are any lexical declarations. :^)
if (has_lexical_declarations()) {
old_environment = vm.running_execution_context().lexical_environment;
auto* block_environment = new_declarative_environment(*old_environment);
block_declaration_instantiation(global_object, block_environment);
vm.running_execution_context().lexical_environment = block_environment;
} else {
restore_environment.disarm();
}
auto block_value = evaluate_statements(interpreter, global_object);
if (!labels().is_empty() && vm.should_unwind_until(ScopeType::Breakable, labels()))