diff options
author | Linus Groh <mail@linusgroh.de> | 2021-10-05 12:59:04 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-10-05 14:52:53 +0200 |
commit | 8074bdc04906ec019585f2a5e9208e86b88bf134 (patch) | |
tree | c53f93a9f1b91687b085743aa70422328259119d /Userland/Libraries/LibJS/AST.cpp | |
parent | d609dde7b00d1724035635114a09c6dd8fcb9cbd (diff) | |
download | serenity-8074bdc04906ec019585f2a5e9208e86b88bf134.zip |
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 :^)
Diffstat (limited to 'Userland/Libraries/LibJS/AST.cpp')
-rw-r--r-- | Userland/Libraries/LibJS/AST.cpp | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/Userland/Libraries/LibJS/AST.cpp b/Userland/Libraries/LibJS/AST.cpp index 5cd3a2d7c9..8b2bdfe7cb 100644 --- a/Userland/Libraries/LibJS/AST.cpp +++ b/Userland/Libraries/LibJS/AST.cpp @@ -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())) |