Changeset 227787 in webkit
- Timestamp:
- Jan 30, 2018 8:13:15 AM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r227786 r227787 1 2018-01-30 Antti Koivisto <antti@apple.com> 2 3 Avoid traversing too much when doing class change invalidation 4 https://bugs.webkit.org/show_bug.cgi?id=181604 5 6 Reviewed by Zalan Bujtas. 7 8 We are now collecting information about which part of the tree a change in class can potentially affect. 9 Use the information to traverse only the required elements in Style::Invalidator. 10 11 The same mechanism can be later used for attribute and id change invalidation. 12 13 * css/DocumentRuleSets.cpp: 14 (WebCore::DocumentRuleSets::collectFeatures const): 15 (WebCore::DocumentRuleSets::classInvalidationRuleSets const): 16 (WebCore::DocumentRuleSets::subjectClassRules const): Deleted. 17 (WebCore::DocumentRuleSets::ancestorClassRules const): Deleted. 18 19 Remove separate subject and ancestor invalidation RuleSets. Instead collect all invalidation rulesets 20 to a vector along with their MatchElements. 21 22 * css/DocumentRuleSets.h: 23 * css/RuleFeature.cpp: 24 (WebCore::RuleFeatureSet::computeNextMatchElement): 25 (WebCore::RuleFeatureSet::computeSubSelectorMatchElement): 26 (WebCore::RuleFeatureSet::collectFeatures): 27 28 Similarly collect all class invalidation RuleFeatures to a general HashMap along with the MatchElement. 29 30 (WebCore::RuleFeatureSet::add): 31 (WebCore::RuleFeatureSet::clear): 32 (WebCore::RuleFeatureSet::shrinkToFit): 33 * css/RuleFeature.h: 34 (WebCore::RuleFeature::RuleFeature): 35 * style/ClassChangeInvalidation.cpp: 36 (WebCore::Style::ClassChangeInvalidation::computeInvalidation): 37 38 Find out InvalidationRuleSets to use. 39 40 (WebCore::Style::ClassChangeInvalidation::invalidateStyleWithRuleSets): 41 42 Pass them to Style::Invalidator. 43 44 * style/ClassChangeInvalidation.h: 45 * style/StyleInvalidator.cpp: 46 (WebCore::Style::Invalidator::invalidateStyleForTree): 47 (WebCore::Style::Invalidator::invalidateStyleForDescendants): 48 (WebCore::Style::Invalidator::invalidateStyleWithMatchElement): 49 50 Traverse only the part of the tree needed by the given MatchElement. 51 52 * style/StyleInvalidator.h: 53 * style/StyleSharingResolver.cpp: 54 (WebCore::Style::SharingResolver::classNamesAffectedByRules const): 55 1 56 2018-01-30 Javier Fernandez <jfernandez@igalia.com> 2 57 -
trunk/Source/WebCore/css/DocumentRuleSets.cpp
r226703 r227787 168 168 m_uncommonAttributeRuleSet = makeRuleSet(m_features.uncommonAttributeRules); 169 169 170 m_subjectClassRuleSets.clear(); 171 m_ancestorClassRuleSets.clear(); 170 m_classInvalidationRuleSets.clear(); 172 171 m_ancestorAttributeRuleSetsForHTML.clear(); 173 172 … … 175 174 } 176 175 177 RuleSet* DocumentRuleSets::subjectClassRules(const AtomicString& className) const 178 { 179 return m_subjectClassRuleSets.ensure(className, [&] { 180 auto* rules = m_features.subjectClassRules.get(className); 181 return rules ? makeRuleSet(*rules) : nullptr; 182 }).iterator->value.get(); 183 } 184 185 RuleSet* DocumentRuleSets::ancestorClassRules(const AtomicString& className) const 186 { 187 return m_ancestorClassRuleSets.ensure(className, [&] { 188 auto* rules = m_features.ancestorClassRules.get(className); 189 return rules ? makeRuleSet(*rules) : nullptr; 176 const Vector<InvalidationRuleSet>* DocumentRuleSets::classInvalidationRuleSets(const AtomicString& className) const 177 { 178 return m_classInvalidationRuleSets.ensure(className, [&] () -> std::unique_ptr<Vector<InvalidationRuleSet>> { 179 auto* features = m_features.classRules.get(className); 180 if (!features) 181 return nullptr; 182 std::array<std::unique_ptr<RuleSet>, matchElementCount> matchElementArray; 183 for (auto& feature : *features) { 184 auto& ruleSet = matchElementArray[static_cast<unsigned>(*feature.matchElement)]; 185 if (!ruleSet) 186 ruleSet = std::make_unique<RuleSet>(); 187 ruleSet->addRule(feature.rule, feature.selectorIndex); 188 } 189 auto invalidationRuleSets = std::make_unique<Vector<InvalidationRuleSet>>(); 190 for (unsigned i = 0; i < matchElementArray.size(); ++i) { 191 if (matchElementArray[i]) 192 invalidationRuleSets->append({ static_cast<MatchElement>(i), WTFMove(matchElementArray[i]) }); 193 } 194 return invalidationRuleSets; 190 195 }).iterator->value.get(); 191 196 } -
trunk/Source/WebCore/css/DocumentRuleSets.h
r226703 r227787 39 39 class MediaQueryEvaluator; 40 40 41 struct InvalidationRuleSet { 42 MatchElement matchElement; 43 std::unique_ptr<RuleSet> ruleSet; 44 45 WTF_MAKE_FAST_ALLOCATED; 46 }; 47 41 48 class DocumentRuleSets { 42 49 public: … … 51 58 RuleSet* sibling() const { return m_siblingRuleSet.get(); } 52 59 RuleSet* uncommonAttribute() const { return m_uncommonAttributeRuleSet.get(); } 53 RuleSet* subjectClassRules(const AtomicString& className) const; 54 RuleSet* ancestorClassRules(const AtomicString& className) const;60 61 const Vector<InvalidationRuleSet>* classInvalidationRuleSets(const AtomicString& className) const; 55 62 56 63 struct AttributeRules { … … 92 99 mutable std::unique_ptr<RuleSet> m_siblingRuleSet; 93 100 mutable std::unique_ptr<RuleSet> m_uncommonAttributeRuleSet; 94 mutable HashMap<AtomicString, std::unique_ptr<RuleSet>> m_subjectClassRuleSets; 95 mutable HashMap<AtomicString, std::unique_ptr<RuleSet>> m_ancestorClassRuleSets; 101 mutable HashMap<AtomicString, std::unique_ptr<Vector<InvalidationRuleSet>>> m_classInvalidationRuleSets; 96 102 mutable HashMap<AtomicString, std::unique_ptr<AttributeRules>> m_ancestorAttributeRuleSetsForHTML; 97 103 }; -
trunk/Source/WebCore/css/RuleFeature.cpp
r226718 r227787 36 36 namespace WebCore { 37 37 38 RuleFeatureSet::MatchElement RuleFeatureSet::computeNextMatchElement(MatchElement matchElement, CSSSelector::RelationType relation)38 MatchElement RuleFeatureSet::computeNextMatchElement(MatchElement matchElement, CSSSelector::RelationType relation) 39 39 { 40 40 if (matchElement == MatchElement::Subject || matchElement == MatchElement::IndirectSibling || matchElement == MatchElement::DirectSibling) { … … 70 70 }; 71 71 72 RuleFeatureSet::MatchElement RuleFeatureSet::computeSubSelectorMatchElement(MatchElement matchElement, const CSSSelector& selector)72 MatchElement RuleFeatureSet::computeSubSelectorMatchElement(MatchElement matchElement, const CSSSelector& selector) 73 73 { 74 74 ASSERT(selector.selectorList()); … … 158 158 if (ruleData.containsUncommonAttributeSelector()) 159 159 uncommonAttributeRules.append(RuleFeature(ruleData.rule(), ruleData.selectorIndex())); 160 for (auto& classNameAndMatchElement : selectorFeatures.classes) { 161 auto& className = classNameAndMatchElement.first; 162 switch (classNameAndMatchElement.second) { 163 case MatchElement::Subject: 164 subjectClassRules.ensure(className, [] { 165 return std::make_unique<Vector<RuleFeature>>(); 166 }).iterator->value->append(RuleFeature(ruleData.rule(), ruleData.selectorIndex())); 167 break; 168 case MatchElement::Parent: 169 case MatchElement::Ancestor: 170 ancestorClassRules.ensure(className, [] { 171 return std::make_unique<Vector<RuleFeature>>(); 172 }).iterator->value->append(RuleFeature(ruleData.rule(), ruleData.selectorIndex())); 173 break; 174 case MatchElement::DirectSibling: 175 case MatchElement::IndirectSibling: 176 case MatchElement::ParentSibling: 177 case MatchElement::AncestorSibling: 178 case MatchElement::Host: 179 otherClassesInRules.add(className); 180 break; 181 }; 160 for (auto& nameAndMatch : selectorFeatures.classes) { 161 classRules.ensure(nameAndMatch.first, [] { 162 return std::make_unique<Vector<RuleFeature>>(); 163 }).iterator->value->append(RuleFeature(ruleData.rule(), ruleData.selectorIndex(), nameAndMatch.second)); 164 if (nameAndMatch.second == MatchElement::Host) 165 classesAffectingHost.add(nameAndMatch.first); 182 166 } 183 167 for (auto* selector : selectorFeatures.attributeSelectorsMatchingAncestors) { … … 197 181 idsInRules.add(other.idsInRules.begin(), other.idsInRules.end()); 198 182 idsMatchingAncestorsInRules.add(other.idsMatchingAncestorsInRules.begin(), other.idsMatchingAncestorsInRules.end()); 199 otherClassesInRules.add(other.otherClassesInRules.begin(), other.otherClassesInRules.end());200 183 attributeCanonicalLocalNamesInRules.add(other.attributeCanonicalLocalNamesInRules.begin(), other.attributeCanonicalLocalNamesInRules.end()); 201 184 attributeLocalNamesInRules.add(other.attributeLocalNamesInRules.begin(), other.attributeLocalNamesInRules.end()); 202 185 siblingRules.appendVector(other.siblingRules); 203 186 uncommonAttributeRules.appendVector(other.uncommonAttributeRules); 204 for (auto& keyValuePair : other. ancestorClassRules) {205 ancestorClassRules.ensure(keyValuePair.key, [] {187 for (auto& keyValuePair : other.classRules) { 188 classRules.ensure(keyValuePair.key, [] { 206 189 return std::make_unique<Vector<RuleFeature>>(); 207 190 }).iterator->value->appendVector(*keyValuePair.value); 208 191 } 209 for (auto& keyValuePair : other.subjectClassRules) { 210 subjectClassRules.ensure(keyValuePair.key, [] { 211 return std::make_unique<Vector<RuleFeature>>(); 212 }).iterator->value->appendVector(*keyValuePair.value); 213 } 192 classesAffectingHost.add(other.classesAffectingHost.begin(), other.classesAffectingHost.end()); 214 193 215 194 for (auto& keyValuePair : other.ancestorAttributeRulesForHTML) { … … 230 209 idsInRules.clear(); 231 210 idsMatchingAncestorsInRules.clear(); 232 otherClassesInRules.clear();233 211 attributeCanonicalLocalNamesInRules.clear(); 234 212 attributeLocalNamesInRules.clear(); 235 213 siblingRules.clear(); 236 214 uncommonAttributeRules.clear(); 237 ancestorClassRules.clear();238 subjectClassRules.clear();215 classRules.clear(); 216 classesAffectingHost.clear(); 239 217 ancestorAttributeRulesForHTML.clear(); 240 218 usesFirstLineRules = false; … … 246 224 siblingRules.shrinkToFit(); 247 225 uncommonAttributeRules.shrinkToFit(); 248 for (auto& rules : ancestorClassRules.values()) 249 rules->shrinkToFit(); 250 for (auto& rules : subjectClassRules.values()) 226 for (auto& rules : classRules.values()) 251 227 rules->shrinkToFit(); 252 228 for (auto& rules : ancestorAttributeRulesForHTML.values()) -
trunk/Source/WebCore/css/RuleFeature.h
r226703 r227787 34 34 class StyleRule; 35 35 36 enum class MatchElement { Subject, Parent, Ancestor, DirectSibling, IndirectSibling, ParentSibling, AncestorSibling, Host }; 37 constexpr unsigned matchElementCount = static_cast<unsigned>(MatchElement::Host) + 1; 38 36 39 struct RuleFeature { 37 RuleFeature(StyleRule* rule, unsigned selectorIndex )40 RuleFeature(StyleRule* rule, unsigned selectorIndex, std::optional<MatchElement> matchElement = std::nullopt) 38 41 : rule(rule) 39 42 , selectorIndex(selectorIndex) 43 , matchElement(matchElement) 40 44 { 41 45 } 42 46 StyleRule* rule; 43 47 unsigned selectorIndex; 48 std::optional<MatchElement> matchElement; 44 49 }; 45 50 … … 56 61 Vector<RuleFeature> siblingRules; 57 62 Vector<RuleFeature> uncommonAttributeRules; 58 HashMap<AtomicString, std::unique_ptr<Vector<RuleFeature>>> ancestorClassRules;59 HashMap<AtomicString, std::unique_ptr<Vector<RuleFeature>>> subjectClassRules;60 HashSet<AtomicString> otherClassesInRules;63 64 HashMap<AtomicString, std::unique_ptr<Vector<RuleFeature>>> classRules; 65 HashSet<AtomicString> classesAffectingHost; 61 66 62 67 struct AttributeRules { … … 72 77 73 78 private: 74 enum class MatchElement { Subject, Parent, Ancestor, DirectSibling, IndirectSibling, ParentSibling, AncestorSibling, Host };75 76 79 static MatchElement computeNextMatchElement(MatchElement, CSSSelector::RelationType); 77 80 static MatchElement computeSubSelectorMatchElement(MatchElement, const CSSSelector&); -
trunk/Source/WebCore/style/ClassChangeInvalidation.cpp
r226703 r227787 90 90 bool shouldInvalidateCurrent = false; 91 91 bool mayAffectStyleInShadowTree = false; 92 ClassChangeVector classesAffectingDescendant;93 ClassChangeVector classesAffectingCurrent;94 92 95 93 traverseRuleFeatures(m_element, [&] (const RuleFeatureSet& features, bool mayAffectShadowTree) { 96 94 for (auto* changedClass : changedClasses) { 97 bool mayAffectStyle = false; 98 if (features.otherClassesInRules.contains(changedClass)) { 95 if (mayAffectShadowTree && features.classRules.contains(changedClass)) 96 mayAffectStyleInShadowTree = true; 97 if (features.classesAffectingHost.contains(changedClass)) 99 98 shouldInvalidateCurrent = true; 100 mayAffectStyle = true;101 }102 if (features.ancestorClassRules.contains(changedClass)) {103 classesAffectingDescendant.append(changedClass);104 mayAffectStyle = true;105 }106 if (features.subjectClassRules.contains(changedClass)) {107 classesAffectingCurrent.append(changedClass);108 mayAffectStyle = true;109 }110 if (mayAffectStyle && mayAffectShadowTree)111 mayAffectStyleInShadowTree = true;112 99 } 113 100 }); … … 119 106 } 120 107 108 if (shouldInvalidateCurrent) 109 m_element.invalidateStyle(); 110 121 111 auto& ruleSets = m_element.styleResolver().ruleSets(); 122 112 123 if (childrenOfType<Element>(m_element).first()) {124 for (auto* changedClass : classesAffectingDescendant) {125 if (auto* rules = ruleSets.ancestorClassRules(changedClass))126 m_invalidationRuleSets.append( rules);113 for (auto* changedClass : changedClasses) { 114 if (auto* invalidationRuleSets = ruleSets.classInvalidationRuleSets(changedClass)) { 115 for (auto& invalidationRuleSet : *invalidationRuleSets) 116 m_invalidationRuleSets.append(&invalidationRuleSet); 127 117 } 128 }129 130 if (shouldInvalidateCurrent) {131 m_element.invalidateStyle();132 return;133 }134 135 for (auto* changedClass : classesAffectingCurrent) {136 if (auto* rules = ruleSets.subjectClassRules(changedClass))137 m_invalidationRuleSets.append(rules);138 118 } 139 119 } … … 141 121 void ClassChangeInvalidation::invalidateStyleWithRuleSets() 142 122 { 143 for (auto* rules: m_invalidationRuleSets) {144 Invalidator invalidator(* rules);145 invalidator.invalidateStyle (m_element);123 for (auto* invalidationRuleSet : m_invalidationRuleSets) { 124 Invalidator invalidator(*invalidationRuleSet->ruleSet); 125 invalidator.invalidateStyleWithMatchElement(m_element, invalidationRuleSet->matchElement); 146 126 } 147 127 } -
trunk/Source/WebCore/style/ClassChangeInvalidation.h
r226703 r227787 34 34 class RuleSet; 35 35 class SpaceSplitString; 36 struct InvalidationRuleSet; 36 37 37 38 namespace Style { … … 49 50 Element& m_element; 50 51 51 Vector<const RuleSet*, 4> m_invalidationRuleSets;52 Vector<const InvalidationRuleSet*, 4> m_invalidationRuleSets; 52 53 }; 53 54 -
trunk/Source/WebCore/style/StyleInvalidator.cpp
r216117 r227787 144 144 if (invalidateIfNeeded(root, filter) == CheckDescendants::No) 145 145 return; 146 146 invalidateStyleForDescendants(root, filter); 147 } 148 149 void Invalidator::invalidateStyleForDescendants(Element& root, SelectorFilter* filter) 150 { 147 151 Vector<Element*, 20> parentStack; 148 152 Element* previousElement = &root; … … 206 210 } 207 211 208 } 209 } 212 void Invalidator::invalidateStyleWithMatchElement(Element& element, MatchElement matchElement) 213 { 214 switch (matchElement) { 215 case MatchElement::Subject: { 216 invalidateIfNeeded(element, nullptr); 217 break; 218 } 219 case MatchElement::Parent: { 220 auto children = childrenOfType<Element>(element); 221 for (auto& child : children) 222 invalidateIfNeeded(child, nullptr); 223 break; 224 } 225 case MatchElement::Ancestor: { 226 invalidateStyleForDescendants(element, nullptr); 227 break; 228 } 229 case MatchElement::DirectSibling: 230 case MatchElement::IndirectSibling: 231 case MatchElement::ParentSibling: 232 case MatchElement::AncestorSibling: 233 // FIXME: Currently sibling invalidation happens during style resolution tree walk. It should be done here too. 234 element.invalidateStyle(); 235 break; 236 case MatchElement::Host: 237 // FIXME: Handle this here as well. 238 break; 239 } 240 } 241 242 } 243 } -
trunk/Source/WebCore/style/StyleInvalidator.h
r222113 r227787 26 26 #pragma once 27 27 28 #include "RuleFeature.h" 28 29 #include <wtf/Forward.h> 29 30 … … 50 51 void invalidateStyle(ShadowRoot&); 51 52 void invalidateStyle(Element&); 53 void invalidateStyleWithMatchElement(Element&, MatchElement); 52 54 53 55 private: … … 55 57 CheckDescendants invalidateIfNeeded(Element&, const SelectorFilter*); 56 58 void invalidateStyleForTree(Element&, SelectorFilter*); 59 void invalidateStyleForDescendants(Element&, SelectorFilter*); 57 60 58 61 std::unique_ptr<RuleSet> m_ownedRuleSet; -
trunk/Source/WebCore/style/StyleSharingResolver.cpp
r226703 r227787 341 341 { 342 342 for (unsigned i = 0; i < classNames.size(); ++i) { 343 if (m_ruleSets.features(). otherClassesInRules.contains(classNames[i]))343 if (m_ruleSets.features().classRules.contains(classNames[i])) 344 344 return true; 345 if (m_ruleSets.features().ancestorClassRules.contains(classNames[i]))346 return true;347 if (m_ruleSets.features().subjectClassRules.contains(classNames[i]))348 return true;349 350 345 } 351 346 return false;
Note: See TracChangeset
for help on using the changeset viewer.