Browse Source

LibJS: Ensure capacity for created lexical and variable environments

If the minimal amount of required bindings is known in advance, it could
be used to ensure capacity to avoid resizing the internal vector that
holds bindings.
Aliaksandr Kalenik 1 year ago
parent
commit
3d4b13a01c

+ 2 - 2
Userland/Libraries/LibJS/Bytecode/Generator.cpp

@@ -120,7 +120,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
             }
             }
         }
         }
     } else {
     } else {
-        emit<Op::CreateVariableEnvironment>();
+        emit<Op::CreateVariableEnvironment>(function.m_var_environment_bindings_count);
 
 
         if (scope_body) {
         if (scope_body) {
             for (auto const& variable_to_initialize : function.m_var_names_to_initialize_binding) {
             for (auto const& variable_to_initialize : function.m_var_names_to_initialize_binding) {
@@ -158,7 +158,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
     if (!function.m_strict) {
     if (!function.m_strict) {
         bool can_elide_declarative_environment = !function.m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_non_local_lexical_declarations());
         bool can_elide_declarative_environment = !function.m_contains_direct_call_to_eval && (!scope_body || !scope_body->has_non_local_lexical_declarations());
         if (!can_elide_declarative_environment) {
         if (!can_elide_declarative_environment) {
-            emit<Op::CreateLexicalEnvironment>();
+            emit<Op::CreateLexicalEnvironment>(function.m_lex_environment_bindings_count);
         }
         }
     }
     }
 
 

+ 4 - 1
Userland/Libraries/LibJS/Bytecode/Interpreter.cpp

@@ -1256,7 +1256,9 @@ ThrowCompletionOr<void> DeleteVariable::execute_impl(Bytecode::Interpreter& inte
 void CreateLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
 void CreateLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const
 {
 {
     auto make_and_swap_envs = [&](auto& old_environment) {
     auto make_and_swap_envs = [&](auto& old_environment) {
-        GCPtr<Environment> environment = new_declarative_environment(*old_environment).ptr();
+        auto declarative_environment = new_declarative_environment(*old_environment).ptr();
+        declarative_environment->ensure_capacity(m_capacity);
+        GCPtr<Environment> environment = declarative_environment;
         swap(old_environment, environment);
         swap(old_environment, environment);
         return environment;
         return environment;
     };
     };
@@ -1268,6 +1270,7 @@ ThrowCompletionOr<void> CreateVariableEnvironment::execute_impl(Bytecode::Interp
 {
 {
     auto& running_execution_context = interpreter.vm().running_execution_context();
     auto& running_execution_context = interpreter.vm().running_execution_context();
     auto var_environment = new_declarative_environment(*running_execution_context.lexical_environment);
     auto var_environment = new_declarative_environment(*running_execution_context.lexical_environment);
+    var_environment->ensure_capacity(m_capacity);
     running_execution_context.variable_environment = var_environment;
     running_execution_context.variable_environment = var_environment;
     running_execution_context.lexical_environment = var_environment;
     running_execution_context.lexical_environment = var_environment;
     return {};
     return {};

+ 10 - 2
Userland/Libraries/LibJS/Bytecode/Op.h

@@ -443,24 +443,32 @@ enum class EnvironmentMode {
 
 
 class CreateLexicalEnvironment final : public Instruction {
 class CreateLexicalEnvironment final : public Instruction {
 public:
 public:
-    explicit CreateLexicalEnvironment()
+    explicit CreateLexicalEnvironment(u32 capacity = 0)
         : Instruction(Type::CreateLexicalEnvironment)
         : Instruction(Type::CreateLexicalEnvironment)
+        , m_capacity(capacity)
     {
     {
     }
     }
 
 
     void execute_impl(Bytecode::Interpreter&) const;
     void execute_impl(Bytecode::Interpreter&) const;
     ByteString to_byte_string_impl(Bytecode::Executable const&) const;
     ByteString to_byte_string_impl(Bytecode::Executable const&) const;
+
+private:
+    u32 m_capacity { 0 };
 };
 };
 
 
 class CreateVariableEnvironment final : public Instruction {
 class CreateVariableEnvironment final : public Instruction {
 public:
 public:
-    explicit CreateVariableEnvironment()
+    explicit CreateVariableEnvironment(u32 capacity = 0)
         : Instruction(Type::CreateVariableEnvironment)
         : Instruction(Type::CreateVariableEnvironment)
+        , m_capacity(capacity)
     {
     {
     }
     }
 
 
     ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
     ThrowCompletionOr<void> execute_impl(Bytecode::Interpreter&) const;
     ByteString to_byte_string_impl(Bytecode::Executable const&) const;
     ByteString to_byte_string_impl(Bytecode::Executable const&) const;
+
+private:
+    u32 m_capacity { 0 };
 };
 };
 
 
 class EnterObjectEnvironment final : public Instruction {
 class EnterObjectEnvironment final : public Instruction {