Skip to content

Commit 83a6be5

Browse files
committed
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.
1 parent e737044 commit 83a6be5

File tree

2 files changed

+40
-17
lines changed

2 files changed

+40
-17
lines changed

Userland/Libraries/LibWeb/Layout/FormattingState.cpp

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,32 +12,48 @@ namespace Web::Layout {
1212

1313
FormattingState::NodeState& FormattingState::get_mutable(NodeWithStyleAndBoxModelMetrics const& box)
1414
{
15-
if (auto it = nodes.find(&box); it != nodes.end())
16-
return *it->value;
17-
18-
for (auto* ancestor = m_parent; ancestor; ancestor = ancestor->m_parent) {
19-
if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end()) {
20-
auto cow_node_state = adopt_own(*new NodeState(*it->value));
21-
auto* cow_node_state_ptr = cow_node_state.ptr();
22-
nodes.set(&box, move(cow_node_state));
23-
return *cow_node_state_ptr;
15+
if (m_lookup_cache.box == &box && m_lookup_cache.is_mutable)
16+
return *m_lookup_cache.state;
17+
18+
auto& node_state = [&]() -> NodeState& {
19+
if (auto it = nodes.find(&box); it != nodes.end())
20+
return *it->value;
21+
22+
for (auto const* ancestor = m_parent; ancestor; ancestor = ancestor->m_parent) {
23+
if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end()) {
24+
auto cow_node_state = adopt_own(*new NodeState(*it->value));
25+
auto* cow_node_state_ptr = cow_node_state.ptr();
26+
nodes.set(&box, move(cow_node_state));
27+
return *cow_node_state_ptr;
28+
}
2429
}
25-
}
2630

27-
return *nodes.ensure(&box, [] { return adopt_own(*new NodeState); });
31+
return *nodes.ensure(&box, [] { return adopt_own(*new NodeState); });
32+
}();
33+
34+
m_lookup_cache = LookupCache { .box = &box, .state = &node_state, .is_mutable = true };
35+
36+
return node_state;
2837
}
2938

3039
FormattingState::NodeState const& FormattingState::get(NodeWithStyleAndBoxModelMetrics const& box) const
3140
{
32-
if (auto it = nodes.find(&box); it != nodes.end())
33-
return *it->value;
41+
if (m_lookup_cache.box == &box)
42+
return *m_lookup_cache.state;
3443

35-
for (auto* ancestor = m_parent; ancestor; ancestor = ancestor->m_parent) {
36-
if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end())
44+
auto& node_state = [&]() -> NodeState const& {
45+
if (auto it = nodes.find(&box); it != nodes.end())
3746
return *it->value;
38-
}
3947

40-
return *const_cast<FormattingState&>(*this).nodes.ensure(&box, [] { return adopt_own(*new NodeState); });
48+
for (auto* ancestor = m_parent; ancestor; ancestor = ancestor->m_parent) {
49+
if (auto it = ancestor->nodes.find(&box); it != ancestor->nodes.end())
50+
return *it->value;
51+
}
52+
return *const_cast<FormattingState&>(*this).nodes.ensure(&box, [] { return adopt_own(*new NodeState); });
53+
}();
54+
55+
const_cast<FormattingState*>(this)->m_lookup_cache = LookupCache { .box = &box, .state = const_cast<NodeState*>(&node_state), .is_mutable = false };
56+
return node_state;
4157
}
4258

4359
void FormattingState::commit()

Userland/Libraries/LibWeb/Layout/FormattingState.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,13 @@ struct FormattingState {
111111

112112
FormattingState const* m_parent { nullptr };
113113
FormattingState const& m_root;
114+
115+
struct LookupCache {
116+
NodeWithStyleAndBoxModelMetrics const* box { nullptr };
117+
NodeState* state { nullptr };
118+
bool is_mutable { false };
119+
};
120+
LookupCache m_lookup_cache;
114121
};
115122

116123
Gfx::FloatRect absolute_content_rect(Box const&, FormattingState const&);

0 commit comments

Comments
 (0)