1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 15:37:46 +00:00

LibWeb: Use copy-on-write to make cloning a FormattingState much cheaper

Instead of making a full copy of every NodeState when cloning a
FormattingState, we make NodeState ref-counted and implement a basic
copy-on-write mechanism.

FormattingState::get_mutable() now makes a deep copy of the NodeState
when first accessed *if* it is shared with other FormattingStates.
This commit is contained in:
Andreas Kling 2022-02-28 12:32:23 +01:00
parent 0a533da22f
commit aa72ebf7aa
2 changed files with 36 additions and 18 deletions

View file

@ -62,30 +62,31 @@ struct FormattingState {
overflow_data = Layout::Box::OverflowData {};
return *overflow_data;
}
// NOTE: NodeState is ref-counted and accessed via copy-on-write helpers below.
size_t ref_count { 1 };
void ref()
{
VERIFY(ref_count);
++ref_count;
}
void unref()
{
VERIFY(ref_count);
if (!--ref_count)
delete this;
}
};
void commit();
FormattingState clone() const
{
FormattingState new_state;
for (auto& it : nodes) {
new_state.nodes.set(it.key, make<NodeState>(*it.value));
}
return new_state;
}
// NOTE: get_mutable() will CoW the NodeState if it's shared with another FormattingContext.
NodeState& get_mutable(NodeWithStyleAndBoxModelMetrics const&);
NodeState& get_mutable(NodeWithStyleAndBoxModelMetrics const& box)
{
return *nodes.ensure(&box, [] { return make<NodeState>(); });
}
// NOTE: get() will not CoW the NodeState.
NodeState const& get(NodeWithStyleAndBoxModelMetrics const&) const;
NodeState const& get(NodeWithStyleAndBoxModelMetrics const& box) const
{
return const_cast<FormattingState&>(*this).get_mutable(box);
}
HashMap<NodeWithStyleAndBoxModelMetrics const*, NonnullOwnPtr<NodeState>> nodes;
HashMap<NodeWithStyleAndBoxModelMetrics const*, NonnullRefPtr<NodeState>> nodes;
};
Gfx::FloatRect absolute_content_rect(Box const&, FormattingState const&);