1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 09:07:35 +00:00

LibWeb: Add a 1-entry lookup cache to FormattingState

This makes repeated lookups of the state for the same box much faster
by bypassing the HashMap.
This commit is contained in:
Andreas Kling 2022-07-06 14:56:10 +02:00
parent e7370443f2
commit 83a6be593c
2 changed files with 39 additions and 16 deletions

View file

@ -12,10 +12,14 @@ namespace Web::Layout {
FormattingState::NodeState& FormattingState::get_mutable(NodeWithStyleAndBoxModelMetrics const& box) FormattingState::NodeState& FormattingState::get_mutable(NodeWithStyleAndBoxModelMetrics const& box)
{ {
if (m_lookup_cache.box == &box && m_lookup_cache.is_mutable)
return *m_lookup_cache.state;
auto& node_state = [&]() -> NodeState& {
if (auto it = nodes.find(&box); it != nodes.end()) if (auto it = nodes.find(&box); it != nodes.end())
return *it->value; return *it->value;
for (auto* ancestor = m_parent; ancestor; ancestor = ancestor->m_parent) { for (auto const* ancestor = m_parent; ancestor; ancestor = ancestor->m_parent) {
if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end()) { if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end()) {
auto cow_node_state = adopt_own(*new NodeState(*it->value)); auto cow_node_state = adopt_own(*new NodeState(*it->value));
auto* cow_node_state_ptr = cow_node_state.ptr(); auto* cow_node_state_ptr = cow_node_state.ptr();
@ -25,10 +29,19 @@ FormattingState::NodeState& FormattingState::get_mutable(NodeWithStyleAndBoxMode
} }
return *nodes.ensure(&box, [] { return adopt_own(*new NodeState); }); return *nodes.ensure(&box, [] { return adopt_own(*new NodeState); });
}();
m_lookup_cache = LookupCache { .box = &box, .state = &node_state, .is_mutable = true };
return node_state;
} }
FormattingState::NodeState const& FormattingState::get(NodeWithStyleAndBoxModelMetrics const& box) const FormattingState::NodeState const& FormattingState::get(NodeWithStyleAndBoxModelMetrics const& box) const
{ {
if (m_lookup_cache.box == &box)
return *m_lookup_cache.state;
auto& node_state = [&]() -> NodeState const& {
if (auto it = nodes.find(&box); it != nodes.end()) if (auto it = nodes.find(&box); it != nodes.end())
return *it->value; return *it->value;
@ -36,8 +49,11 @@ FormattingState::NodeState const& FormattingState::get(NodeWithStyleAndBoxModelM
if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end()) if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end())
return *it->value; return *it->value;
} }
return *const_cast<FormattingState&>(*this).nodes.ensure(&box, [] { return adopt_own(*new NodeState); }); return *const_cast<FormattingState&>(*this).nodes.ensure(&box, [] { return adopt_own(*new NodeState); });
}();
const_cast<FormattingState*>(this)->m_lookup_cache = LookupCache { .box = &box, .state = const_cast<NodeState*>(&node_state), .is_mutable = false };
return node_state;
} }
void FormattingState::commit() void FormattingState::commit()

View file

@ -111,6 +111,13 @@ struct FormattingState {
FormattingState const* m_parent { nullptr }; FormattingState const* m_parent { nullptr };
FormattingState const& m_root; FormattingState const& m_root;
struct LookupCache {
NodeWithStyleAndBoxModelMetrics const* box { nullptr };
NodeState* state { nullptr };
bool is_mutable { false };
};
LookupCache m_lookup_cache;
}; };
Gfx::FloatRect absolute_content_rect(Box const&, FormattingState const&); Gfx::FloatRect absolute_content_rect(Box const&, FormattingState const&);