From 3d4b13a01c7e76cca30a543e2aabfeb9597dc4e9 Mon Sep 17 00:00:00 2001 From: Aliaksandr Kalenik Date: Thu, 9 May 2024 17:10:20 +0200 Subject: [PATCH] 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. --- Userland/Libraries/LibJS/Bytecode/Generator.cpp | 4 ++-- Userland/Libraries/LibJS/Bytecode/Interpreter.cpp | 5 ++++- Userland/Libraries/LibJS/Bytecode/Op.h | 12 ++++++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/Userland/Libraries/LibJS/Bytecode/Generator.cpp b/Userland/Libraries/LibJS/Bytecode/Generator.cpp index 290829b2b6..f7b6b5b4f2 100644 --- a/Userland/Libraries/LibJS/Bytecode/Generator.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Generator.cpp @@ -120,7 +120,7 @@ CodeGenerationErrorOr Generator::emit_function_declaration_instantiation(E } } } else { - emit(); + emit(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 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(); + emit(function.m_lex_environment_bindings_count); } } diff --git a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp index 22f2895c26..d39b0cbd15 100644 --- a/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp +++ b/Userland/Libraries/LibJS/Bytecode/Interpreter.cpp @@ -1256,7 +1256,9 @@ ThrowCompletionOr DeleteVariable::execute_impl(Bytecode::Interpreter& inte void CreateLexicalEnvironment::execute_impl(Bytecode::Interpreter& interpreter) const { auto make_and_swap_envs = [&](auto& old_environment) { - GCPtr environment = new_declarative_environment(*old_environment).ptr(); + auto declarative_environment = new_declarative_environment(*old_environment).ptr(); + declarative_environment->ensure_capacity(m_capacity); + GCPtr environment = declarative_environment; swap(old_environment, environment); return environment; }; @@ -1268,6 +1270,7 @@ ThrowCompletionOr 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 {}; diff --git a/Userland/Libraries/LibJS/Bytecode/Op.h b/Userland/Libraries/LibJS/Bytecode/Op.h index 661a7b25d9..970d2c2bd9 100644 --- a/Userland/Libraries/LibJS/Bytecode/Op.h +++ b/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 execute_impl(Bytecode::Interpreter&) const; ByteString to_byte_string_impl(Bytecode::Executable const&) const; + +private: + u32 m_capacity { 0 }; }; class EnterObjectEnvironment final : public Instruction {