From 8074bdc04906ec019585f2a5e9208e86b88bf134 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Tue, 5 Oct 2021 12:59:04 +0100 Subject: 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 :^) --- Userland/Libraries/LibJS/AST.cpp | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'Userland/Libraries/LibJS/AST.cpp') 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())) -- cgit v1.2.3