Procházet zdrojové kódy

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 před 1 rokem
rodič
revize
3d4b13a01c

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

@@ -120,7 +120,7 @@ CodeGenerationErrorOr<void> Generator::emit_function_declaration_instantiation(E
             }
         }
     } else {
-        emit<Op::CreateVariableEnvironment>();
+        emit<Op::CreateVariableEnvironment>(function.m_var_environment_bindings_count);
 
         if (scope_body) {
             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) {
         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) {
-            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
 {
     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);
         return environment;
     };
@@ -1268,6 +1270,7 @@ ThrowCompletionOr<void> CreateVariableEnvironment::execute_impl(Bytecode::Interp
 {
     auto& running_execution_context = interpreter.vm().running_execution_context();
     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.lexical_environment = var_environment;
     return {};

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

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