Replace the lazy per-shape OrderedHashMap cache for non-dictionary shapes with a GC-allocated descriptor array. Store descriptors in hash order for lookup while keeping an enum index so callers can still walk properties in insertion order. Keep dictionary shapes on the mutable OrderedHashMap path, and migrate callers that enumerated Shape::property_table() to the new insertion order iterator. Cap descriptor arrays to their compact u16 index range and keep larger dictionary shapes on the mutable table path across prototype transitions and prototype clones. Add coverage for setting the prototype of a dictionary object with more than 65536 named properties.
68 lines
1.9 KiB
C++
68 lines
1.9 KiB
C++
/*
|
|
* Copyright (c) 2026-present, the Ladybird developers.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <AK/Function.h>
|
|
#include <AK/NumericLimits.h>
|
|
#include <AK/Vector.h>
|
|
#include <LibJS/Export.h>
|
|
#include <LibJS/Heap/Cell.h>
|
|
#include <LibJS/Runtime/PropertyAttributes.h>
|
|
#include <LibJS/Runtime/PropertyKey.h>
|
|
|
|
namespace JS {
|
|
|
|
struct PropertyMetadata {
|
|
u32 offset { 0 };
|
|
PropertyAttributes attributes { 0 };
|
|
};
|
|
|
|
class JS_API DescriptorArray final : public Cell {
|
|
GC_CELL(DescriptorArray, Cell);
|
|
GC_DECLARE_ALLOCATOR(DescriptorArray);
|
|
|
|
public:
|
|
struct Entry {
|
|
PropertyKey property_key;
|
|
u32 offset { 0 };
|
|
u16 attributes { 0 };
|
|
u16 enum_index { 0 };
|
|
|
|
PropertyMetadata metadata() const
|
|
{
|
|
return { offset, static_cast<u8>(attributes) };
|
|
}
|
|
};
|
|
|
|
static constexpr u32 max_descriptor_count = NumericLimits<u16>::max() + 1;
|
|
|
|
DescriptorArray() = default;
|
|
explicit DescriptorArray(DescriptorArray const&, u32 descriptor_count);
|
|
virtual ~DescriptorArray() override = default;
|
|
|
|
[[nodiscard]] u32 size() const { return m_entries.size(); }
|
|
[[nodiscard]] Optional<PropertyMetadata> lookup(PropertyKey const&, u32 descriptor_count) const;
|
|
|
|
void set(PropertyKey const&, PropertyMetadata, u32 enum_index);
|
|
void set_attributes(PropertyKey const&, PropertyAttributes, u32 descriptor_count);
|
|
void remove(PropertyKey const&, u32 descriptor_count);
|
|
|
|
void for_each_in_insertion_order(Function<void(PropertyKey const&, PropertyMetadata const&)> const&, u32 descriptor_count) const;
|
|
|
|
private:
|
|
virtual void visit_edges(Visitor&) override;
|
|
virtual size_t external_memory_size() const override;
|
|
|
|
[[nodiscard]] Optional<size_t> find(PropertyKey const&, u32 descriptor_count) const;
|
|
[[nodiscard]] size_t find_insertion_index(PropertyKey const&) const;
|
|
|
|
Vector<Entry> m_entries;
|
|
};
|
|
|
|
static_assert(sizeof(DescriptorArray::Entry) == 16);
|
|
|
|
}
|