diff --git a/Libraries/LibJS/Runtime/Shape.cpp b/Libraries/LibJS/Runtime/Shape.cpp index a5490a6a30..28e10c5cc9 100644 --- a/Libraries/LibJS/Runtime/Shape.cpp +++ b/Libraries/LibJS/Runtime/Shape.cpp @@ -31,21 +31,21 @@ namespace JS { Shape* Shape::create_put_transition(const FlyString& property_name, u8 attributes) { - auto* new_shape = m_forward_transitions.get(property_name).value_or(nullptr); - if (new_shape && new_shape->m_attributes == attributes) - return new_shape; - new_shape = heap().allocate(this, property_name, attributes, TransitionType::Put); - m_forward_transitions.set(property_name, new_shape); + TransitionKey key { property_name, attributes }; + if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr)) + return existing_shape; + auto* new_shape = heap().allocate(this, property_name, attributes, TransitionType::Put); + m_forward_transitions.set(key, new_shape); return new_shape; } Shape* Shape::create_configure_transition(const FlyString& property_name, u8 attributes) { - auto* new_shape = m_forward_transitions.get(property_name).value_or(nullptr); - if (new_shape && new_shape->m_attributes == attributes) - return new_shape; - new_shape = heap().allocate(this, property_name, attributes, TransitionType::Configure); - m_forward_transitions.set(property_name, new_shape); + TransitionKey key { property_name, attributes }; + if (auto* existing_shape = m_forward_transitions.get(key).value_or(nullptr)) + return existing_shape; + auto* new_shape = heap().allocate(this, property_name, attributes, TransitionType::Configure); + m_forward_transitions.set(key, new_shape); return new_shape; } diff --git a/Libraries/LibJS/Runtime/Shape.h b/Libraries/LibJS/Runtime/Shape.h index ff7999db54..70c75fef78 100644 --- a/Libraries/LibJS/Runtime/Shape.h +++ b/Libraries/LibJS/Runtime/Shape.h @@ -48,6 +48,17 @@ struct PropertyMetadata { u8 attributes { 0 }; }; +struct TransitionKey { + FlyString property_name; + u8 attributes { 0 }; + + bool operator==(const TransitionKey& other) const + { + return property_name == other.property_name + && attributes == other.attributes; + } +}; + class Shape final : public Cell { public: virtual ~Shape() override; @@ -84,7 +95,7 @@ private: mutable OwnPtr> m_property_table; - HashMap m_forward_transitions; + HashMap m_forward_transitions; Shape* m_previous { nullptr }; FlyString m_property_name; u8 m_attributes { 0 }; @@ -93,3 +104,11 @@ private: }; } + +template<> +struct AK::Traits : public GenericTraits { + static unsigned hash(const JS::TransitionKey& key) + { + return pair_int_hash(int_hash(key.attributes), key.property_name.hash()); + } +};