From 5ec468bfdd234e5c0c5b8804fdfb76915c9c9ec8 Mon Sep 17 00:00:00 2001 From: Tim Ledbetter Date: Fri, 19 Jun 2026 15:07:27 +0100 Subject: [PATCH] LibJS: Store module indirect bindings in a HashMap Previously, these were stored in a vector that was linearly scanned. For large sites this vector could contain hundreds of entries, so a HashMap gives a significant speedup. --- Libraries/LibJS/Runtime/ModuleEnvironment.cpp | 18 +++++++----------- Libraries/LibJS/Runtime/ModuleEnvironment.h | 5 ++--- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/Libraries/LibJS/Runtime/ModuleEnvironment.cpp b/Libraries/LibJS/Runtime/ModuleEnvironment.cpp index 33b63eb2d2..37f21c0b1e 100644 --- a/Libraries/LibJS/Runtime/ModuleEnvironment.cpp +++ b/Libraries/LibJS/Runtime/ModuleEnvironment.cpp @@ -74,10 +74,8 @@ ThrowCompletionOr ModuleEnvironment::create_import_binding(Utf16FlyString // FIXME: I don't know what this means or how to check it. // 3. Create an immutable indirect binding in envRec for N that references M and N2 as its target binding and record that the binding is initialized. - // Note: We use the fact that the binding is in this list as it being initialized. - m_indirect_bindings.append({ move(name), - module, - move(binding_name) }); + // Note: We use the fact that the binding is in this map as it being initialized. + m_indirect_bindings.set(move(name), IndirectBinding { module, move(binding_name) }); // 4. Return unused. return {}; @@ -85,13 +83,11 @@ ThrowCompletionOr ModuleEnvironment::create_import_binding(Utf16FlyString ModuleEnvironment::IndirectBinding const* ModuleEnvironment::get_indirect_binding(Utf16FlyString const& name) const { - auto binding_or_end = m_indirect_bindings.find_if([&](IndirectBinding const& binding) { - return binding.name == name; - }); - if (binding_or_end.is_end()) + auto it = m_indirect_bindings.find(name); + if (it == m_indirect_bindings.end()) return nullptr; - return &(*binding_or_end); + return &it->value; } Optional ModuleEnvironment::find_binding_and_index(Utf16FlyString const& name) const @@ -131,14 +127,14 @@ Optional ModuleEnvironment::find_binding_and size_t ModuleEnvironment::external_memory_size() const { auto size = DeclarativeEnvironment::external_memory_size(); - size = saturating_add_external_memory_size(size, vector_external_memory_size(m_indirect_bindings)); + size = saturating_add_external_memory_size(size, hash_map_external_memory_size(m_indirect_bindings)); return size; } void ModuleEnvironment::visit_edges(Visitor& visitor) { Base::visit_edges(visitor); - for (auto& indirect_binding : m_indirect_bindings) + for (auto& [_, indirect_binding] : m_indirect_bindings) visitor.visit(indirect_binding.module); } diff --git a/Libraries/LibJS/Runtime/ModuleEnvironment.h b/Libraries/LibJS/Runtime/ModuleEnvironment.h index bdbc29c7ce..6102ac0e6e 100644 --- a/Libraries/LibJS/Runtime/ModuleEnvironment.h +++ b/Libraries/LibJS/Runtime/ModuleEnvironment.h @@ -6,6 +6,7 @@ #pragma once +#include #include #include #include @@ -35,7 +36,6 @@ private: virtual size_t external_memory_size() const override; struct IndirectBinding { - Utf16FlyString name; GC::Ptr module; Utf16FlyString binding_name; }; @@ -43,8 +43,7 @@ private: virtual Optional find_binding_and_index(Utf16FlyString const& name) const override; - // FIXME: Since we always access this via the name this could be a map. - Vector m_indirect_bindings; + HashMap m_indirect_bindings; }; }