Преглед на файлове

LibJS: Skip some declarative env allocations in function instantiation

If all lexical declaration use local variables then there is no need
to allocate declarative environment.

With this change we skip ~3x more environment allocations on Github.
Aliaksandr Kalenik преди 1 година
родител
ревизия
f21c0f9dcd
променени са 3 файла, в които са добавени 13 реда и са изтрити 2 реда
  1. 10 0
      Userland/Libraries/LibJS/AST.cpp
  2. 1 0
      Userland/Libraries/LibJS/AST.h
  3. 2 2
      Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

+ 10 - 0
Userland/Libraries/LibJS/AST.cpp

@@ -1440,6 +1440,16 @@ void SequenceExpression::dump(int indent) const
         expression->dump(indent + 1);
 }
 
+bool ScopeNode::has_non_local_lexical_declarations() const
+{
+    bool result = false;
+    MUST(for_each_lexically_declared_identifier([&](Identifier const& identifier) {
+        if (!identifier.is_local())
+            result = true;
+    }));
+    return result;
+}
+
 ThrowCompletionOr<void> ScopeNode::for_each_lexically_scoped_declaration(ThrowCompletionOrVoidCallback<Declaration const&>&& callback) const
 {
     for (auto& declaration : m_lexical_declarations)

+ 1 - 0
Userland/Libraries/LibJS/AST.h

@@ -306,6 +306,7 @@ public:
     void add_hoisted_function(NonnullRefPtr<FunctionDeclaration const> declaration);
 
     [[nodiscard]] bool has_lexical_declarations() const { return !m_lexical_declarations.is_empty(); }
+    [[nodiscard]] bool has_non_local_lexical_declarations() const;
     [[nodiscard]] bool has_var_declarations() const { return !m_var_declarations.is_empty(); }
 
     [[nodiscard]] size_t var_declaration_count() const { return m_var_declarations.size(); }

+ 2 - 2
Userland/Libraries/LibJS/Runtime/ECMAScriptFunctionObject.cpp

@@ -308,7 +308,7 @@ ECMAScriptFunctionObject::ECMAScriptFunctionObject(DeprecatedFlyString name, Byt
 
     // 30. If strict is false, then
     if (!m_strict) {
-        bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_lexical_declarations());
+        bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_non_local_lexical_declarations());
         if (can_elide_declarative_environment) {
             lex_environment_size = var_environment_size;
         } else {
@@ -870,7 +870,7 @@ ThrowCompletionOr<void> ECMAScriptFunctionObject::function_declaration_instantia
         // Optimization: We avoid creating empty top-level declarative environments in non-strict mode, if both of these conditions are true:
         //               1. there is no direct call to eval() within this function
         //               2. there are no lexical declarations that would go into the environment
-        bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_lexical_declarations());
+        bool can_elide_declarative_environment = !m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_non_local_lexical_declarations());
         if (can_elide_declarative_environment) {
             lex_environment = var_environment;
         } else {