mirror of
https://github.com/RGBCube/serenity
synced 2025-07-27 23:27: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:
parent
d609dde7b0
commit
8074bdc049
2 changed files with 16 additions and 5 deletions
|
@ -122,13 +122,21 @@ Value BlockStatement::execute(Interpreter& interpreter, GlobalObject& global_obj
|
||||||
InterpreterNodeScope node_scope { interpreter, *this };
|
InterpreterNodeScope node_scope { interpreter, *this };
|
||||||
|
|
||||||
auto& vm = interpreter.vm();
|
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;
|
vm.running_execution_context().lexical_environment = old_environment;
|
||||||
};
|
};
|
||||||
auto* block_environment = new_declarative_environment(*old_environment);
|
|
||||||
block_declaration_instantiation(global_object, block_environment);
|
// Optimization: We only need a new lexical environment if there are any lexical declarations. :^)
|
||||||
vm.running_execution_context().lexical_environment = block_environment;
|
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);
|
auto block_value = evaluate_statements(interpreter, global_object);
|
||||||
if (!labels().is_empty() && vm.should_unwind_until(ScopeType::Breakable, labels()))
|
if (!labels().is_empty() && vm.should_unwind_until(ScopeType::Breakable, labels()))
|
||||||
|
|
|
@ -183,6 +183,9 @@ public:
|
||||||
void add_lexical_declaration(NonnullRefPtr<Declaration> variables);
|
void add_lexical_declaration(NonnullRefPtr<Declaration> variables);
|
||||||
void add_hoisted_function(NonnullRefPtr<FunctionDeclaration> declaration);
|
void add_hoisted_function(NonnullRefPtr<FunctionDeclaration> declaration);
|
||||||
|
|
||||||
|
[[nodiscard]] bool has_lexical_declarations() const { return !m_lexical_declarations.is_empty(); }
|
||||||
|
[[nodiscard]] bool has_var_declarations() const { return !m_var_declarations.is_empty(); }
|
||||||
|
|
||||||
void for_each_lexically_scoped_declaration(IteratorOrVoidFunction<Declaration const&>&& callback) const;
|
void for_each_lexically_scoped_declaration(IteratorOrVoidFunction<Declaration const&>&& callback) const;
|
||||||
void for_each_lexically_declared_name(IteratorOrVoidFunction<FlyString const&>&& callback) const;
|
void for_each_lexically_declared_name(IteratorOrVoidFunction<FlyString const&>&& callback) const;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue