ladybird/Libraries/LibJS/Runtime/EnvironmentShape.cpp
Andreas Kling 5dfe145c03 LibJS: Share function environment binding shapes
Cache EnvironmentShape on SharedFunctionInstanceData after the first
function environment creates its statically known bindings. Install the
cached shape before later calls create bindings so those environments
avoid building their own name vector and lookup map.

Let DeclarativeEnvironment keep a local overlay for eval-created
bindings, and keep the packed flag mirror per environment while the asm
interpreter still reads flags directly from the environment. Add runtime
coverage for repeated calls with an eval-created binding.
2026-05-15 14:04:47 +02:00

56 lines
1.5 KiB
C++

/*
* Copyright (c) 2026-present, the Ladybird developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/EnvironmentShape.h>
#include <LibJS/Runtime/ExternalMemory.h>
#include <LibJS/Runtime/VM.h>
namespace JS {
GC_DEFINE_ALLOCATOR(EnvironmentShape);
EnvironmentShape::EnvironmentShape(Vector<BindingDescriptor> bindings, HashMap<Utf16FlyString, size_t> binding_indices)
: m_bindings(move(bindings))
, m_binding_indices(move(binding_indices))
{
}
GC::Ref<EnvironmentShape> EnvironmentShape::create(VM& vm, ReadonlySpan<Utf16FlyString> names, ReadonlySpan<u8> flags)
{
VERIFY(names.size() == flags.size());
Vector<BindingDescriptor> bindings;
bindings.ensure_capacity(names.size());
HashMap<Utf16FlyString, size_t> binding_indices;
binding_indices.ensure_capacity(names.size());
for (size_t i = 0; i < names.size(); ++i) {
bindings.unchecked_append({ names[i], flags[i] });
if (!names[i].is_empty())
binding_indices.set(names[i], i);
}
return vm.heap().allocate<EnvironmentShape>(move(bindings), move(binding_indices));
}
Optional<size_t> EnvironmentShape::find_binding(Utf16FlyString const& name) const
{
auto it = m_binding_indices.find(name);
if (it == m_binding_indices.end())
return {};
return it->value;
}
size_t EnvironmentShape::external_memory_size() const
{
auto size = vector_external_memory_size(m_bindings);
size = saturating_add_external_memory_size(size, hash_map_external_memory_size(m_binding_indices));
return size;
}
}