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

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: Better with 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 if (invalidationSet.wholeSubtreeInvalid()) {
74 m_wholeSubtreeInvalid = true;
75 return;
76 }
66 m_invalidationSets.append(&invalidationSet); 77 m_invalidationSets.append(&invalidationSet);
67 m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid(); 78 m_invalidateCustomPseudo = invalidationSet.customPseudoInvalid();
68 m_foundInvalidationSet = true;
69 } 79 }
70 80
71 bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& el ement) 81 bool StyleInvalidator::RecursionData::matchesCurrentInvalidationSets(Element& el ement)
72 { 82 {
83 ASSERT(!m_wholeSubtreeInvalid);
84
73 if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom) 85 if (m_invalidateCustomPseudo && element.shadowPseudoId() != nullAtom)
74 return true; 86 return true;
75 87
76 for (InvalidationSets::iterator it = m_invalidationSets.begin(); it != m_inv alidationSets.end(); ++it) { 88 for (InvalidationSets::iterator it = m_invalidationSets.begin(); it != m_inv alidationSets.end(); ++it) {
77 if ((*it)->invalidatesElement(element)) 89 if ((*it)->invalidatesElement(element))
78 return true; 90 return true;
79 } 91 }
80 92
81 return false; 93 return false;
82 } 94 }
83 95
84 bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element) 96 bool StyleInvalidator::checkInvalidationSetsAgainstElement(Element& element)
85 { 97 {
86 bool thisElementNeedsStyleRecalc = false; 98 if (m_recursionData.wholeSubtreeInvalid())
99 return true;
87 if (element.needsStyleInvalidation()) { 100 if (element.needsStyleInvalidation()) {
88 if (InvalidationList* invalidationList = m_pendingInvalidationMap.get(&e lement)) { 101 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. 102 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); 103 m_recursionData.pushInvalidationSet(**it);
rune 2014/04/11 20:40:12 You introduce some invariants here about invalidat
93 if ((*it)->wholeSubtreeInvalid()) { 104 // FIXME: It's really only necessary to clone the render style for t his element, not full style recalc.
94 element.setNeedsStyleRecalc(SubtreeStyleChange); 105 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 } 106 }
103 } 107 }
104 if (!thisElementNeedsStyleRecalc) 108 return m_recursionData.matchesCurrentInvalidationSets(element);
105 thisElementNeedsStyleRecalc = m_recursionData.matchesCurrentInvalidation Sets(element);
106 return thisElementNeedsStyleRecalc;
107 } 109 }
108 110
109 bool StyleInvalidator::invalidateChildren(Element& element) 111 bool StyleInvalidator::invalidateChildren(Element& element)
110 { 112 {
111 bool someChildrenNeedStyleRecalc = false; 113 bool someChildrenNeedStyleRecalc = false;
112 for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->old erShadowRoot()) { 114 for (ShadowRoot* root = element.youngestShadowRoot(); root; root = root->old erShadowRoot()) {
113 for (Element* child = ElementTraversal::firstWithin(*root); child; child = ElementTraversal::nextSibling(*child)) { 115 for (Element* child = ElementTraversal::firstWithin(*root); child; child = ElementTraversal::nextSibling(*child)) {
114 bool childRecalced = invalidate(*child); 116 bool childRecalced = invalidate(*child);
115 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe calced; 117 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRe calced;
116 } 118 }
117 root->clearChildNeedsStyleInvalidation(); 119 root->clearChildNeedsStyleInvalidation();
118 root->clearNeedsStyleInvalidation(); 120 root->clearNeedsStyleInvalidation();
119 } 121 }
120 for (Element* child = ElementTraversal::firstWithin(element); child; child = ElementTraversal::nextSibling(*child)) { 122 for (Element* child = ElementTraversal::firstWithin(element); child; child = ElementTraversal::nextSibling(*child)) {
121 bool childRecalced = invalidate(*child); 123 bool childRecalced = invalidate(*child);
122 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc ed; 124 someChildrenNeedStyleRecalc = someChildrenNeedStyleRecalc || childRecalc ed;
123 } 125 }
124 return someChildrenNeedStyleRecalc; 126 return someChildrenNeedStyleRecalc;
125 } 127 }
126 128
127 bool StyleInvalidator::invalidate(Element& element) 129 bool StyleInvalidator::invalidate(Element& element)
128 { 130 {
129 RecursionCheckpoint checkpoint(&m_recursionData); 131 RecursionCheckpoint checkpoint(&m_recursionData);
130 132
131 bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(eleme nt); 133 bool thisElementNeedsStyleRecalc = checkInvalidationSetsAgainstElement(eleme nt);
132 134
133 bool someChildrenNeedStyleRecalc = false; 135 bool someChildrenNeedStyleRecalc = false;
134 // foundInvalidationSet() will be true if we are in a subtree of a node with a DescendantInvalidationSet on it. 136 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); 137 someChildrenNeedStyleRecalc = invalidateChildren(element);
138 138
139 if (thisElementNeedsStyleRecalc) { 139 if (thisElementNeedsStyleRecalc) {
140 element.setNeedsStyleRecalc(LocalStyleChange); 140 element.setNeedsStyleRecalc(m_recursionData.wholeSubtreeInvalid() ? Subt reeStyleChange : LocalStyleChange);
141 } else if (m_recursionData.foundInvalidationSet() && someChildrenNeedStyleRe calc) { 141 } else if (m_recursionData.hasInvalidationSets() && someChildrenNeedStyleRec alc) {
142 // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style. 142 // Clone the RenderStyle in order to preserve correct style sharing, if possible. Otherwise recalc style.
143 if (RenderObject* renderer = element.renderer()) { 143 if (RenderObject* renderer = element.renderer())
144 ASSERT(renderer->style());
145 renderer->setStyleInternal(RenderStyle::clone(renderer->style())); 144 renderer->setStyleInternal(RenderStyle::clone(renderer->style()));
146 } else { 145 else
147 element.setNeedsStyleRecalc(LocalStyleChange); 146 element.setNeedsStyleRecalc(LocalStyleChange);
148 }
149 } 147 }
150 148
151 element.clearChildNeedsStyleInvalidation(); 149 element.clearChildNeedsStyleInvalidation();
152 element.clearNeedsStyleInvalidation(); 150 element.clearNeedsStyleInvalidation();
153 151
154 return thisElementNeedsStyleRecalc; 152 return thisElementNeedsStyleRecalc;
155 } 153 }
156 154
157 } // namespace WebCore 155 } // 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