LibJS: Key shape transitions on both property name and attributes

This allows us to cache forward transitions that reconfigure existing
properties as well, leading to better shape reuse.
This commit is contained in:
Andreas Kling 2020-04-10 16:33:44 +02:00
parent 8cbb8491cb
commit 0fea525373
Notes: sideshowbarker 2024-07-19 07:44:29 +09:00
2 changed files with 30 additions and 11 deletions

View file

@ -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<Shape>(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<Shape>(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<Shape>(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<Shape>(this, property_name, attributes, TransitionType::Configure);
m_forward_transitions.set(key, new_shape);
return new_shape;
}

View file

@ -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<HashMap<FlyString, PropertyMetadata>> m_property_table;
HashMap<FlyString, Shape*> m_forward_transitions;
HashMap<TransitionKey, Shape*> m_forward_transitions;
Shape* m_previous { nullptr };
FlyString m_property_name;
u8 m_attributes { 0 };
@ -93,3 +104,11 @@ private:
};
}
template<>
struct AK::Traits<JS::TransitionKey> : public GenericTraits<JS::TransitionKey> {
static unsigned hash(const JS::TransitionKey& key)
{
return pair_int_hash(int_hash(key.attributes), key.property_name.hash());
}
};