Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Side by Side Diff: Source/core/css/invalidation/StyleInvalidator.cpp

Issue 1317533002: Sibling invalidation sets (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: sibling-inserted Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 1
2 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Copyright 2014 The Chromium Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be 3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file. 4 // found in the LICENSE file.
5 5
6 #include "config.h" 6 #include "config.h"
7 7
8 #include "core/css/invalidation/StyleInvalidator.h" 8 #include "core/css/invalidation/StyleInvalidator.h"
9 9
10 #include "core/css/invalidation/DescendantInvalidationSet.h" 10 #include "core/css/invalidation/DescendantInvalidationSet.h"
(...skipping 15 matching lines...) Expand all
26 // with DescendantInvalidationSet to avoid additional GOT lookup cost. 26 // with DescendantInvalidationSet to avoid additional GOT lookup cost.
27 static const unsigned char* s_tracingEnabled = nullptr; 27 static const unsigned char* s_tracingEnabled = nullptr;
28 28
29 #define TRACE_STYLE_INVALIDATOR_INVALIDATION_IF_ENABLED(element, reason) \ 29 #define TRACE_STYLE_INVALIDATOR_INVALIDATION_IF_ENABLED(element, reason) \
30 if (UNLIKELY(*s_tracingEnabled)) \ 30 if (UNLIKELY(*s_tracingEnabled)) \
31 TRACE_STYLE_INVALIDATOR_INVALIDATION(element, reason); 31 TRACE_STYLE_INVALIDATOR_INVALIDATION(element, reason);
32 32
33 void StyleInvalidator::invalidate(Document& document) 33 void StyleInvalidator::invalidate(Document& document)
34 { 34 {
35 RecursionData recursionData; 35 RecursionData recursionData;
36 SiblingData siblingData;
36 if (Element* documentElement = document.documentElement()) 37 if (Element* documentElement = document.documentElement())
37 invalidate(*documentElement, recursionData); 38 invalidate(*documentElement, recursionData, siblingData);
38 document.clearChildNeedsStyleInvalidation(); 39 document.clearChildNeedsStyleInvalidation();
39 document.clearNeedsStyleInvalidation(); 40 document.clearNeedsStyleInvalidation();
40 clearPendingInvalidations(); 41 clearPendingInvalidations();
41 } 42 }
42 43
43 void StyleInvalidator::scheduleInvalidation(PassRefPtrWillBeRawPtr<DescendantInv alidationSet> invalidationSet, Element& element) 44 void StyleInvalidator::scheduleInvalidationSetsForElement(const InvalidationSetV ector& descendant, const InvalidationSetVector& sibling, Element& element)
44 { 45 {
45 ASSERT(element.inActiveDocument()); 46 ASSERT(element.inActiveDocument());
46 if (element.styleChangeType() >= SubtreeStyleChange) 47
47 return; 48 bool requiresDescendantInvalidation = false;
48 if (invalidationSet->wholeSubtreeInvalid()) { 49 if (element.styleChangeType() < SubtreeStyleChange) {
49 element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTrac ing::create(StyleChangeReason::StyleInvalidator)); 50 for (auto& invalidationSet : descendant) {
50 clearInvalidation(element); 51 if (invalidationSet->wholeSubtreeInvalid()) {
51 return; 52 element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReaso nForTracing::create(StyleChangeReason::StyleInvalidator));
52 } 53 requiresDescendantInvalidation = false;
53 if (invalidationSet->isEmpty()) { 54 break;
54 element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracin g::create(StyleChangeReason::StyleInvalidator)); 55 }
55 return; 56 if (invalidationSet->isEmpty()) {
57 element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonF orTracing::create(StyleChangeReason::StyleInvalidator));
58 } else {
59 requiresDescendantInvalidation = true;
60 }
61 }
56 } 62 }
57 63
58 InvalidationList& list = ensurePendingInvalidationList(element); 64 if (sibling.isEmpty() && !requiresDescendantInvalidation)
59 list.append(invalidationSet); 65 return;
66
60 element.setNeedsStyleInvalidation(); 67 element.setNeedsStyleInvalidation();
61 } 68 InvalidationListData& listData = ensurePendingInvalidationListData(element);
62 69
63 StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationL ist(Element& element) 70 for (auto& invalidationSet : sibling)
64 { 71 listData.siblings().append(invalidationSet);
65 PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(& element, nullptr); 72
66 if (addResult.isNewEntry) 73 if (!requiresDescendantInvalidation)
67 addResult.storedValue->value = adoptPtrWillBeNoop(new InvalidationList); 74 return;
68 return *addResult.storedValue->value; 75
76 for (auto& invalidationSet : descendant) {
77 ASSERT(!invalidationSet->wholeSubtreeInvalid());
78 if (!invalidationSet->isEmpty())
79 listData.descendants().append(invalidationSet);
80 }
69 } 81 }
70 82
71 void StyleInvalidator::clearInvalidation(Element& element) 83 void StyleInvalidator::clearInvalidation(Element& element)
72 { 84 {
73 if (!element.needsStyleInvalidation()) 85 if (!element.needsStyleInvalidation())
74 return; 86 return;
75 m_pendingInvalidationMap.remove(&element); 87 m_pendingInvalidationMap.remove(&element);
76 element.clearNeedsStyleInvalidation(); 88 }
89
90 InvalidationListData& StyleInvalidator::ensurePendingInvalidationListData(Elemen t& element)
91 {
92 PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(& element, nullptr);
93 if (addResult.isNewEntry)
94 addResult.storedValue->value = InvalidationListData::create();
95 return *addResult.storedValue->value;
77 } 96 }
78 97
79 void StyleInvalidator::clearPendingInvalidations() 98 void StyleInvalidator::clearPendingInvalidations()
80 { 99 {
81 m_pendingInvalidationMap.clear(); 100 m_pendingInvalidationMap.clear();
82 } 101 }
83 102
84 StyleInvalidator::StyleInvalidator() 103 StyleInvalidator::StyleInvalidator()
85 { 104 {
86 s_tracingEnabled = TRACE_EVENT_API_GET_CATEGORY_ENABLED(TRACE_DISABLED_BY_DE FAULT("devtools.timeline.invalidationTracking")); 105 s_tracingEnabled = TRACE_EVENT_API_GET_CATEGORY_ENABLED(TRACE_DISABLED_BY_DE FAULT("devtools.timeline.invalidationTracking"));
(...skipping 10 matching lines...) Expand all
97 ASSERT(!invalidationSet.wholeSubtreeInvalid()); 116 ASSERT(!invalidationSet.wholeSubtreeInvalid());
98 ASSERT(!invalidationSet.isEmpty()); 117 ASSERT(!invalidationSet.isEmpty());
99 if (invalidationSet.treeBoundaryCrossing()) 118 if (invalidationSet.treeBoundaryCrossing())
100 m_treeBoundaryCrossing = true; 119 m_treeBoundaryCrossing = true;
101 if (invalidationSet.insertionPointCrossing()) 120 if (invalidationSet.insertionPointCrossing())
102 m_insertionPointCrossing = true; 121 m_insertionPointCrossing = true;
103 m_invalidationSets.append(&invalidationSet); 122 m_invalidationSets.append(&invalidationSet);
104 m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid(); 123 m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid();
105 } 124 }
106 125
107 ALWAYS_INLINE bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSe ts(Element& element) 126 ALWAYS_INLINE bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSe ts(Element& element) const
108 { 127 {
109 if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom) { 128 if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom) {
110 TRACE_STYLE_INVALIDATOR_INVALIDATION_IF_ENABLED(element, InvalidateCusto mPseudo); 129 TRACE_STYLE_INVALIDATOR_INVALIDATION_IF_ENABLED(element, InvalidateCusto mPseudo);
111 return true; 130 return true;
112 } 131 }
113 132
114 if (m_insertionPointCrossing && element.isInsertionPoint()) 133 if (m_insertionPointCrossing && element.isInsertionPoint())
115 return true; 134 return true;
116 135
117 for (const auto& invalidationSet : m_invalidationSets) { 136 for (const auto& invalidationSet : m_invalidationSets) {
118 if (invalidationSet->invalidatesElement(element)) 137 if (invalidationSet->invalidatesElement(element))
119 return true; 138 return true;
120 } 139 }
121 140
122 return false; 141 return false;
123 } 142 }
124 143
125 ALWAYS_INLINE bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element & element, StyleInvalidator::RecursionData& recursionData) 144 void StyleInvalidator::SiblingData::pushInvalidationSet(const DescendantInvalida tionSet& invalidationSet)
145 {
146 unsigned invalidationLimit;
147 if (invalidationSet.maxDirectAdjacentSelectors() == std::numeric_limits<unsi gned>::max())
148 invalidationLimit = std::numeric_limits<unsigned>::max();
149 else
150 invalidationLimit = m_elementIndex + invalidationSet.maxDirectAdjacentSe lectors();
151 m_invalidationEntries.append(Entry { &invalidationSet, invalidationLimit });
152 }
153
154 ALWAYS_INLINE bool StyleInvalidator::SiblingData::matchCurrentInvalidationSets(E lement& element, RecursionData& recursionData, bool thisElementNeedsStyleRecalc)
155 {
156 ASSERT(!recursionData.wholeSubtreeInvalid());
157
158 unsigned index = 0;
159 while (index < m_invalidationEntries.size()) {
160 if (m_elementIndex > m_invalidationEntries[index].invalidationLimit) {
161 m_invalidationEntries[index] = m_invalidationEntries[m_invalidationE ntries.size() - 1];
162 m_invalidationEntries.removeLast();
163 continue;
164 }
165
166 const DescendantInvalidationSet* invalidationSet = m_invalidationEntries [index].invalidationSet.get();
167
168 if (invalidationSet->wholeSubtreeInvalid()) {
169 element.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonFor Tracing::create(StyleChangeReason::StyleInvalidator));
170 recursionData.setWholeSubtreeInvalid();
171 return false;
172 }
173
174 if (invalidationSet->invalidatesElement(element)) {
175 ASSERT(invalidationSet->siblingInvalid() || invalidationSet->descend ants());
176 if (invalidationSet->siblingInvalid())
177 thisElementNeedsStyleRecalc = true;
178 if (invalidationSet->descendants())
179 recursionData.pushInvalidationSet(*invalidationSet->descendants( ));
180 }
181
182 ++index;
183 }
184 return thisElementNeedsStyleRecalc;
185 }
186
187 ALWAYS_INLINE bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element & element, RecursionData& recursionData, SiblingData& siblingData)
126 { 188 {
127 if (element.styleChangeType() >= SubtreeStyleChange || recursionData.wholeSu btreeInvalid()) { 189 if (element.styleChangeType() >= SubtreeStyleChange || recursionData.wholeSu btreeInvalid()) {
128 recursionData.setWholeSubtreeInvalid(); 190 recursionData.setWholeSubtreeInvalid();
129 return false; 191 return false;
130 } 192 }
131 if (element.needsStyleInvalidation()) { 193
132 if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&e lement)) { 194 bool thisElementNeedsStyleRecalc = false;
133 for (const auto& invalidationSet : *invalidationList) 195 if (UNLIKELY(element.needsStyleInvalidation())) {
196 RefPtrWillBeRawPtr<InvalidationListData> listData = m_pendingInvalidatio nMap.get(&element);
197 ASSERT(listData);
198
199 if (listData->descendants().isEmpty()) {
200 thisElementNeedsStyleRecalc = recursionData.matchesCurrentInvalidati onSets(element);
201 } else {
202 for (const auto& invalidationSet : listData->descendants())
134 recursionData.pushInvalidationSet(*invalidationSet); 203 recursionData.pushInvalidationSet(*invalidationSet);
135 if (UNLIKELY(*s_tracingEnabled)) { 204 if (UNLIKELY(*s_tracingEnabled)) {
136 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timelin e.invalidationTracking"), 205 TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timelin e.invalidationTracking"),
137 "StyleInvalidatorInvalidationTracking", 206 "StyleInvalidatorInvalidationTracking",
138 TRACE_EVENT_SCOPE_THREAD, 207 TRACE_EVENT_SCOPE_THREAD,
139 "data", InspectorStyleInvalidatorInvalidateEvent::invalidati onList(element, *invalidationList)); 208 "data", InspectorStyleInvalidatorInvalidateEvent::invalidati onList(element, listData->descendants()));
140 } 209 }
141 return true; 210 thisElementNeedsStyleRecalc = true;
142 } 211 }
212 thisElementNeedsStyleRecalc = siblingData.matchCurrentInvalidationSets(e lement, recursionData, thisElementNeedsStyleRecalc);
213
214 // Only match listData->siblings() against future siblings, not against ourselves.
215 for (const auto& invalidationSet : listData->siblings())
216 siblingData.pushInvalidationSet(*invalidationSet);
217 } else {
218 thisElementNeedsStyleRecalc = recursionData.matchesCurrentInvalidationSe ts(element);
219 thisElementNeedsStyleRecalc = siblingData.matchCurrentInvalidationSets(e lement, recursionData, thisElementNeedsStyleRecalc);
143 } 220 }
144 221
145 return recursionData.matchesCurrentInvalidationSets(element); 222 return thisElementNeedsStyleRecalc;
146 } 223 }
147 224
148 bool StyleInvalidator::invalidateChildren(Element& element, StyleInvalidator::Re cursionData& recursionData) 225 bool StyleInvalidator::invalidateChildren(Element& element, RecursionData& recur sionData)
149 { 226 {
227 SiblingData siblingData;
228
150 bool someChildrenNeedStyleRecalc = false; 229 bool someChildrenNeedStyleRecalc = false;
151 for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->old erShadowRoot()) { 230 for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->old erShadowRoot()) {
152 if (!recursionData.treeBoundaryCrossing() && !root->childNeedsStyleInval idation() && !root->needsStyleInvalidation()) 231 if (!recursionData.treeBoundaryCrossing() && !root->childNeedsStyleInval idation() && !root->needsStyleInvalidation())
153 continue; 232 continue;
154 for (Element* child = ElementTraversal::firstChild(*root); child; child = ElementTraversal::nextSibling(*child)) { 233 for (Element* child = ElementTraversal::firstChild(*root); child; child = ElementTraversal::nextSibling(*child)) {
155 bool childRecalced = invalidate(*child, recursionData); 234 bool childRecalced = invalidate(*child, recursionData, siblingData);
156 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe calced; 235 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe calced;
157 } 236 }
158 root->clearChildNeedsStyleInvalidation(); 237 root->clearChildNeedsStyleInvalidation();
159 root->clearNeedsStyleInvalidation(); 238 root->clearNeedsStyleInvalidation();
160 } 239 }
161 for (Element* child = ElementTraversal::firstChild(element); child; child = ElementTraversal::nextSibling(*child)) { 240 for (Element* child = ElementTraversal::firstChild(element); child; child = ElementTraversal::nextSibling(*child)) {
162 bool childRecalced = invalidate(*child, recursionData); 241 bool childRecalced = invalidate(*child, recursionData, siblingData);
163 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc ed; 242 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc ed;
164 } 243 }
165 return someChildrenNeedStyleRecalc; 244 return someChildrenNeedStyleRecalc;
166 } 245 }
167 246
168 bool StyleInvalidator::invalidate(Element& element, StyleInvalidator::RecursionD ata& recursionData) 247 bool StyleInvalidator::invalidate(Element& element, RecursionData& recursionData , SiblingData& siblingData)
169 { 248 {
170 RecursionCheckpoint checkpoint(&recursionData); 249 RecursionCheckpoint checkpoint(&recursionData);
250 siblingData.advance();
171 251
172 bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(eleme nt, recursionData); 252 bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(eleme nt, recursionData, siblingData);
173 253
174 bool someChildrenNeedStyleRecalc = false; 254 bool someChildrenNeedStyleRecalc = false;
175 if (recursionData.hasInvalidationSets() || element.childNeedsStyleInvalidati on()) 255 if (recursionData.hasInvalidationSets() || element.childNeedsStyleInvalidati on())
176 someChildrenNeedStyleRecalc = invalidateChildren(element, recursionData) ; 256 someChildrenNeedStyleRecalc = invalidateChildren(element, recursionData) ;
177 257
178 if (thisElementNeedsStyleRecalc) { 258 if (thisElementNeedsStyleRecalc) {
179 ASSERT(!recursionData.wholeSubtreeInvalid()); 259 ASSERT(!recursionData.wholeSubtreeInvalid());
180 element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracin g::create(StyleChangeReason::StyleInvalidator)); 260 element.setNeedsStyleRecalc(LocalStyleChange, StyleChangeReasonForTracin g::create(StyleChangeReason::StyleInvalidator));
181 } else if (recursionData.hasInvalidationSets() && someChildrenNeedStyleRecal c) { 261 } else if (recursionData.hasInvalidationSets() && someChildrenNeedStyleRecal c) {
182 // Clone the ComputedStyle in order to preserve correct style sharing, i f possible. Otherwise recalc style. 262 // Clone the ComputedStyle in order to preserve correct style sharing, i f possible. Otherwise recalc style.
(...skipping 15 matching lines...) Expand all
198 } 278 }
199 279
200 DEFINE_TRACE(StyleInvalidator) 280 DEFINE_TRACE(StyleInvalidator)
201 { 281 {
202 #if ENABLE(OILPAN) 282 #if ENABLE(OILPAN)
203 visitor->trace(m_pendingInvalidationMap); 283 visitor->trace(m_pendingInvalidationMap);
204 #endif 284 #endif
205 } 285 }
206 286
207 } // namespace blink 287 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698