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

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

Issue 233243003: Avoid looking at invalidation sets in a SubtreeStyleChange subtree (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Add ASSERT Created 6 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « Source/core/css/invalidation/StyleInvalidator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 10 matching lines...) Expand all
21 { 21 {
22 if (Element* documentElement = document.documentElement()) 22 if (Element* documentElement = document.documentElement())
23 invalidate(*documentElement); 23 invalidate(*documentElement);
24 document.clearChildNeedsStyleInvalidation(); 24 document.clearChildNeedsStyleInvalidation();
25 document.clearNeedsStyleInvalidation(); 25 document.clearNeedsStyleInvalidation();
26 clearPendingInvalidations(); 26 clearPendingInvalidations();
27 } 27 }
28 28
29 void StyleInvalidator::scheduleInvalidation(PassRefPtr<DescendantInvalidationSet > invalidationSet, Element& element) 29 void StyleInvalidator::scheduleInvalidation(PassRefPtr<DescendantInvalidationSet > invalidationSet, Element& element)
30 { 30 {
31 ensurePendingInvalidationList(element).append(invalidationSet); 31 InvalidationList& list = ensurePendingInvalidationList(element);
32 // If we're already going to invalidate the whole subtree we don't need to s tore any new sets.
33 if (!list.isEmpty() && list.last()->wholeSubtreeInvalid())
34 return;
35 // If this set would invalidate the whole subtree we can discard all existin g sets.
36 if (invalidationSet->wholeSubtreeInvalid())
37 list.clear();
38 list.append(invalidationSet);
32 element.setNeedsStyleInvalidation(); 39 element.setNeedsStyleInvalidation();
33 } 40 }
34 41
35 StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationL ist(Element& element) 42 StyleInvalidator::InvalidationList& StyleInvalidator::ensurePendingInvalidationL ist(Element& element)
36 { 43 {
37 PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(& element, nullptr); 44 PendingInvalidationMap::AddResult addResult = m_pendingInvalidationMap.add(& element, nullptr);
38 if (addResult.isNewEntry) 45 if (addResult.isNewEntry)
39 addResult.storedValue->value = adoptPtr(new InvalidationList); 46 addResult.storedValue->value = adoptPtr(new InvalidationList);
40 return *addResult.storedValue->value; 47 return *addResult.storedValue->value;
41 } 48 }
(...skipping 14 matching lines...) Expand all
56 StyleInvalidator::StyleInvalidator() 63 StyleInvalidator::StyleInvalidator()
57 { 64 {
58 } 65 }
59 66
60 StyleInvalidator::~StyleInvalidator() 67 StyleInvalidator::~StyleInvalidator()
61 { 68 {
62 } 69 }
63 70
64 void StyleInvalidator::RecursionData::pushInvalidationSet(const DescendantInvali dationSet& invalidationSet) 71 void StyleInvalidator::RecursionData::pushInvalidationSet(const DescendantInvali dationSet& invalidationSet)
65 { 72 {
73 ASSERT(!m_wholeSubtreeInvalid);
74 if (invalidationSet.wholeSubtreeInvalid()) {
75 m_wholeSubtreeInvalid = true;
76 return;
77 }
66 m_invalidationSets.append(&invalidationSet); 78 m_invalidationSets.append(&invalidationSet);
67 m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid(); 79 m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid();
68 m_foundInvalidationSet = true;
69 } 80 }
70 81
71 bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& el ement) 82 bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& el ement)
72 { 83 {
84 ASSERT(!m_wholeSubtreeInvalid);
85
73 if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom) 86 if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom)
74 return true; 87 return true;
75 88
76 for (InvalidationSets::iterator it = m_invalidationSets.begin(); it != m_inv alidationSets.end(); ++it) { 89 for (InvalidationSets::iterator it = m_invalidationSets.begin(); it != m_inv alidationSets.end(); ++it) {
77 if ((*it)->invalidatesElement(element)) 90 if ((*it)->invalidatesElement(element))
78 return true; 91 return true;
79 } 92 }
80 93
81 return false; 94 return false;
82 } 95 }
83 96
84 bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element) 97 bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element)
85 { 98 {
86 bool thisElementNeedsStyleRecalc = false; 99 if (m_recursionData.wholeSubtreeInvalid())
100 return true;
87 if (element.needsStyleInvalidation()) { 101 if (element.needsStyleInvalidation()) {
88 if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&e lement)) { 102 if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&e lement)) {
89 // FIXME: it's really only necessary to clone the render style for t his element, not full style recalc. 103 for (InvalidationList::const_iterator it = invalidationList->begin() ; it != invalidationList->end(); ++it)
90 thisElementNeedsStyleRecalc = true;
91 for (InvalidationList::const_iterator it = invalidationList->begin() ; it != invalidationList->end(); ++it) {
92 m_recursionData.pushInvalidationSet(**it); 104 m_recursionData.pushInvalidationSet(**it);
93 if ((*it)->wholeSubtreeInvalid()) { 105 // FIXME: It's really only necessary to clone the render style for t his element, not full style recalc.
94 element.setNeedsStyleRecalc(SubtreeStyleChange); 106 return true;
95 // Even though we have set needsStyleRecalc on the whole sub tree, we need to keep walking over the subtree
96 // in order to clear the invalidation dirty bits on all elem ents.
97 // FIXME: we can optimize this by having a dedicated functio n that just traverses the tree and removes the dirty bits,
98 // without checking classes etc.
99 break;
100 }
101 }
102 } 107 }
103 } 108 }
104 if (!thisElementNeedsStyleRecalc) 109 return m_recursionData.matchesCurrentInvalidationSets(element);
105 thisElementNeedsStyleRecalc = m_recursionData.matchesCurrentInvalidation Sets(element);
106 return thisElementNeedsStyleRecalc;
107 } 110 }
108 111
109 bool StyleInvalidator::invalidateChildren(Element& element) 112 bool StyleInvalidator::invalidateChildren(Element& element)
110 { 113 {
111 bool someChildrenNeedStyleRecalc = false; 114 bool someChildrenNeedStyleRecalc = false;
112 for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->old erShadowRoot()) { 115 for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->old erShadowRoot()) {
113 for (Element* child = ElementTraversal::firstWithin(*root); child; child = ElementTraversal::nextSibling(*child)) { 116 for (Element* child = ElementTraversal::firstWithin(*root); child; child = ElementTraversal::nextSibling(*child)) {
114 bool childRecalced = invalidate(*child); 117 bool childRecalced = invalidate(*child);
115 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe calced; 118 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe calced;
116 } 119 }
117 root->clearChildNeedsStyleInvalidation(); 120 root->clearChildNeedsStyleInvalidation();
118 root->clearNeedsStyleInvalidation(); 121 root->clearNeedsStyleInvalidation();
119 } 122 }
120 for (Element* child = ElementTraversal::firstWithin(element); child; child = ElementTraversal::nextSibling(*child)) { 123 for (Element* child = ElementTraversal::firstWithin(element); child; child = ElementTraversal::nextSibling(*child)) {
121 bool childRecalced = invalidate(*child); 124 bool childRecalced = invalidate(*child);
122 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc ed; 125 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc ed;
123 } 126 }
124 return someChildrenNeedStyleRecalc; 127 return someChildrenNeedStyleRecalc;
125 } 128 }
126 129
127 bool StyleInvalidator::invalidate(Element& element) 130 bool StyleInvalidator::invalidate(Element& element)
128 { 131 {
129 RecursionCheckpoint checkpoint(&m_recursionData); 132 RecursionCheckpoint checkpoint(&m_recursionData);
130 133
131 bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(eleme nt); 134 bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(eleme nt);
132 135
133 bool someChildrenNeedStyleRecalc = false; 136 bool someChildrenNeedStyleRecalc = false;
134 // foundInvalidationSet() will be true if we are in a subtree of a node with a DescendantInvalidationSet on it. 137 if (m_recursionData.hasInvalidationSets() || element.childNeedsStyleInvalida tion())
135 // We need to check all nodes in the subtree of such a node.
136 if (m_recursionData.foundInvalidationSet() || element.childNeedsStyleInvalid ation())
137 someChildrenNeedStyleRecalc = invalidateChildren(element); 138 someChildrenNeedStyleRecalc = invalidateChildren(element);
138 139
139 if (thisElementNeedsStyleRecalc) { 140 if (thisElementNeedsStyleRecalc) {
140 element.setNeedsStyleRecalc(LocalStyleChange); 141 element.setNeedsStyleRecalc(m_recursionData.wholeSubtreeInvalid() ? Subt reeStyleChange : LocalStyleChange);
141 } else if (m_recursionData.foundInvalidationSet() && someChildrenNeedStyleRe calc) { 142 } else if (m_recursionData.hasInvalidationSets() && someChildrenNeedStyleRec alc) {
142 // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style. 143 // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style.
143 if (RenderObject* renderer = element.renderer()) { 144 if (RenderObject* renderer = element.renderer())
144 ASSERT(renderer->style());
145 renderer->setStyleInternal(RenderStyle::clone(renderer->style())); 145 renderer->setStyleInternal(RenderStyle::clone(renderer->style()));
146 } else { 146 else
147 element.setNeedsStyleRecalc(LocalStyleChange); 147 element.setNeedsStyleRecalc(LocalStyleChange);
148 }
149 } 148 }
150 149
151 element.clearChildNeedsStyleInvalidation(); 150 element.clearChildNeedsStyleInvalidation();
152 element.clearNeedsStyleInvalidation(); 151 element.clearNeedsStyleInvalidation();
153 152
154 return thisElementNeedsStyleRecalc; 153 return thisElementNeedsStyleRecalc;
155 } 154 }
156 155
157 } // namespace WebCore 156 } // namespace WebCore
OLDNEW
« no previous file with comments | « Source/core/css/invalidation/StyleInvalidator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698