Changeset 96393 in webkit
- Timestamp:
- Sep 30, 2011 12:07:17 AM (13 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r96392 r96393 1 2011-09-29 Antti Koivisto <antti@apple.com> 2 3 https://bugs.webkit.org/show_bug.cgi?id=69106 4 Universal attribute selectors disable style sharing 5 6 Reviewed by Dave Hyatt. 7 8 Selectors of type [foo="bar"] ended up marking every element style with the affectedByAttributeSelectors bit 9 rendering style sharing inoperative. This happens on http://www.whatwg.org/specs/web-apps/current-work/ for example. 10 11 Instead we now mark style with affectedByUncommonAttributeSelectors bit only if an attribute selector actually 12 matches the element. Before sharing, we also check the current element against collected attribute rules. 13 We can share the style if neither element was affected. 14 15 This speeds up style matching and applying ~15% on full HTML5 spec (=~0.7s). Sharing percentage goes from 0% to ~30%. 16 Increased sharing should also save a substantial amount of memory. 17 18 * css/CSSSelector.h: 19 (WebCore::CSSSelector::isAttributeSelector): 20 * css/CSSStyleSelector.cpp: 21 (WebCore::RuleData::containsUncommonAttributeSelector): 22 (WebCore::collectSpecialRulesInDefaultStyle): 23 (WebCore::assertNoSiblingRulesInDefaultStyle): 24 (WebCore::CSSStyleSelector::CSSStyleSelector): 25 (WebCore::CSSStyleSelector::matchRules): 26 (WebCore::CSSStyleSelector::matchesRuleSet): 27 (WebCore::CSSStyleSelector::canShareStyleWithElement): 28 (WebCore::CSSStyleSelector::locateSharedStyle): 29 (WebCore::CSSStyleSelector::styleForElement): 30 (WebCore::selectorListContainsUncommonAttributeSelector): 31 (WebCore::isCommonAttributeSelectorAttribute): 32 (WebCore::containsUncommonAttributeSelector): 33 (WebCore::RuleData::RuleData): 34 (WebCore::collectFeaturesFromSelector): 35 (WebCore::collectFeaturesFromList): 36 * css/CSSStyleSelector.h: 37 * css/SelectorChecker.cpp: 38 (WebCore::SelectorChecker::checkOneSelector): 39 * rendering/style/RenderStyle.cpp: 40 (WebCore::RenderStyle::RenderStyle): 41 * rendering/style/RenderStyle.h: 42 (WebCore::InheritedFlags::affectedByUncommonAttributeSelectors): 43 (WebCore::InheritedFlags::setAffectedByUncommonAttributeSelectors): 44 1 45 2011-09-30 James Robinson <jamesr@chromium.org> 2 46 -
trunk/Source/WebCore/css/CSSSelector.h
r93952 r96393 243 243 bool isUnknownPseudoElement() const; 244 244 bool isSiblingSelector() const; 245 bool isAttributeSelector() const; 245 246 246 247 Relation relation() const { return static_cast<Relation>(m_relation); } … … 327 328 || type == PseudoNthLastOfType; 328 329 } 329 330 331 inline bool CSSSelector::isAttributeSelector() const 332 { 333 if (!hasAttribute()) 334 return false; 335 return m_match == CSSSelector::Exact 336 || m_match == CSSSelector::Set 337 || m_match == CSSSelector::List 338 || m_match == CSSSelector::Hyphen 339 || m_match == CSSSelector::Contain 340 || m_match == CSSSelector::Begin 341 || m_match == CSSSelector::End; 342 } 343 330 344 inline void CSSSelector::setValue(const AtomicString& value) 331 345 { -
trunk/Source/WebCore/css/CSSStyleSelector.cpp
r96281 r96393 190 190 bool hasMultipartSelector() const { return m_hasMultipartSelector; } 191 191 bool hasRightmostSelectorMatchingHTMLBasedOnRuleHash() const { return m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash; } 192 bool containsUncommonAttributeSelector() const { return m_containsUncommonAttributeSelector; } 192 193 unsigned specificity() const { return m_specificity; } 193 194 … … 200 201 CSSSelector* m_selector; 201 202 unsigned m_specificity; 202 unsigned m_position : 2 9;203 unsigned m_position : 28; 203 204 bool m_hasFastCheckableSelector : 1; 204 205 bool m_hasMultipartSelector : 1; 205 206 bool m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash : 1; 207 bool m_containsUncommonAttributeSelector : 1; 206 208 // Use plain array instead of a Vector to minimize memory overhead. 207 209 unsigned m_descendantSelectorIdentifierHashes[maximumIdentifierCount]; … … 259 261 260 262 static RuleSet* siblingRulesInDefaultStyle; 263 static RuleSet* uncommonAttributeRulesInDefaultStyle; 261 264 262 265 RenderStyle* CSSStyleSelector::s_styleNotYetAvailable; … … 272 275 } 273 276 274 static inline void collectS iblingRulesInDefaultStyle()277 static inline void collectSpecialRulesInDefaultStyle() 275 278 { 276 279 CSSStyleSelector::Features features; … … 278 281 ASSERT(features.idsInRules.isEmpty()); 279 282 delete siblingRulesInDefaultStyle; 283 delete uncommonAttributeRulesInDefaultStyle; 280 284 siblingRulesInDefaultStyle = features.siblingRules.leakPtr(); 285 uncommonAttributeRulesInDefaultStyle = features.uncommonAttributeRules.leakPtr(); 281 286 } 282 287 … … 286 291 if (siblingRulesInDefaultStyle) 287 292 return; 288 collectS iblingRulesInDefaultStyle();293 collectSpecialRulesInDefaultStyle(); 289 294 ASSERT(!siblingRulesInDefaultStyle); 290 295 #endif … … 412 417 if (siblingRulesInDefaultStyle) 413 418 siblingRulesInDefaultStyle->collectFeatures(m_features); 419 if (uncommonAttributeRulesInDefaultStyle) 420 uncommonAttributeRulesInDefaultStyle->collectFeatures(m_features); 414 421 m_authorStyle->collectFeatures(m_features); 415 422 if (m_userStyle) … … 419 426 if (m_features.siblingRules) 420 427 m_features.siblingRules->shrinkToFit(); 428 if (m_features.uncommonAttributeRules) 429 m_features.uncommonAttributeRules->shrinkToFit(); 421 430 422 431 if (document->renderer() && document->renderer()->style()) … … 560 569 // Now transfer the set of matched rules over to our list of decls. 561 570 if (!m_checker.isCollectingRulesOnly()) { 562 for (unsigned i = 0; i < m_matchedRules.size(); i++) 571 for (unsigned i = 0; i < m_matchedRules.size(); i++) { 572 if (m_style && m_matchedRules[i]->containsUncommonAttributeSelector()) 573 m_style->setAffectedByUncommonAttributeSelectors(); 563 574 addMatchedDeclaration(m_matchedRules[i]->rule()->declaration()); 575 } 564 576 } else { 565 577 for (unsigned i = 0; i < m_matchedRules.size(); i++) { … … 741 753 } 742 754 743 bool CSSStyleSelector::matches SiblingRules()755 bool CSSStyleSelector::matchesRuleSet(RuleSet* ruleSet) 744 756 { 745 757 int firstSiblingRule = -1, lastSiblingRule = -1; 746 matchRules( m_features.siblingRules.get(), firstSiblingRule, lastSiblingRule, false);758 matchRules(ruleSet, firstSiblingRule, lastSiblingRule, false); 747 759 if (m_matchedDecls.isEmpty()) 748 760 return false; … … 828 840 if (element->isLink() != m_element->isLink()) 829 841 return false; 830 if (style->affectedBy AttributeSelectors())842 if (style->affectedByUncommonAttributeSelectors()) 831 843 return false; 832 844 if (element->hovered() != m_element->hovered()) … … 912 924 } 913 925 914 ALWAYS_INLINERenderStyle* CSSStyleSelector::locateSharedStyle()926 RenderStyle* CSSStyleSelector::locateSharedStyle() 915 927 { 916 928 if (!m_styledElement || !m_parentStyle) … … 942 954 943 955 // Can't share if sibling rules apply. This is checked at the end as it should rarely fail. 944 if (matchesSiblingRules()) 956 if (matchesRuleSet(m_features.siblingRules.get())) 957 return 0; 958 // Can't share if attribute rules apply. 959 if (matchesRuleSet(m_features.uncommonAttributeRules.get())) 945 960 return 0; 946 961 // Tracking child index requires unique style for each node. This may get set by the sibling rule match above. … … 1113 1128 loadFullDefaultStyle(); 1114 1129 assertNoSiblingRulesInDefaultStyle(); 1130 collectSpecialRulesInDefaultStyle(); 1115 1131 } 1116 1132 … … 1124 1140 defaultPrintStyle->addRulesFromSheet(svgSheet, printEval()); 1125 1141 assertNoSiblingRulesInDefaultStyle(); 1142 collectSpecialRulesInDefaultStyle(); 1126 1143 } 1127 1144 #endif … … 1135 1152 defaultStyle->addRulesFromSheet(mathMLSheet, screenEval()); 1136 1153 defaultPrintStyle->addRulesFromSheet(mathMLSheet, printEval()); 1137 // There are some sibling rules here.1138 collectS iblingRulesInDefaultStyle();1154 // There are some sibling and uncommon attribute rules here. 1155 collectSpecialRulesInDefaultStyle(); 1139 1156 } 1140 1157 #endif … … 1148 1165 defaultStyle->addRulesFromSheet(mediaControlsSheet, screenEval()); 1149 1166 defaultPrintStyle->addRulesFromSheet(mediaControlsSheet, printEval()); 1150 assertNoSiblingRulesInDefaultStyle();1167 collectSpecialRulesInDefaultStyle(); 1151 1168 } 1152 1169 #endif … … 1160 1177 defaultStyle->addRulesFromSheet(fullscreenSheet, screenEval()); 1161 1178 defaultQuirksStyle->addRulesFromSheet(fullscreenSheet, screenEval()); 1179 collectSpecialRulesInDefaultStyle(); 1162 1180 } 1163 1181 #endif … … 1839 1857 } 1840 1858 1859 static inline bool selectorListContainsUncommonAttributeSelector(const CSSSelector* selector) 1860 { 1861 CSSSelectorList* selectorList = selector->selectorList(); 1862 if (!selectorList) 1863 return false; 1864 for (CSSSelector* subSelector = selectorList->first(); subSelector; subSelector = CSSSelectorList::next(subSelector)) { 1865 if (subSelector->isAttributeSelector()) 1866 return true; 1867 } 1868 return false; 1869 } 1870 1871 static inline bool isCommonAttributeSelectorAttribute(const QualifiedName& attribute) 1872 { 1873 // These are explicitly tested for equality in canShareStyleWithElement. 1874 return attribute == typeAttr || attribute == readonlyAttr; 1875 } 1876 1877 static inline bool containsUncommonAttributeSelector(const CSSSelector* selector) 1878 { 1879 while (selector) { 1880 // Allow certain common attributes (used in the default style) in the selectors that match the current element. 1881 if (selector->isAttributeSelector() && !isCommonAttributeSelectorAttribute(selector->attribute())) 1882 return true; 1883 if (selectorListContainsUncommonAttributeSelector(selector)) 1884 return true; 1885 if (selector->relation() != CSSSelector::SubSelector) 1886 break; 1887 selector = selector->tagHistory(); 1888 }; 1889 1890 for (selector = selector->tagHistory(); selector; selector = selector->tagHistory()) { 1891 if (selector->isAttributeSelector()) 1892 return true; 1893 if (selectorListContainsUncommonAttributeSelector(selector)) 1894 return true; 1895 } 1896 return false; 1897 } 1898 1841 1899 RuleData::RuleData(CSSStyleRule* rule, CSSSelector* selector, unsigned position) 1842 1900 : m_rule(rule) … … 1847 1905 , m_hasMultipartSelector(selector->tagHistory()) 1848 1906 , m_hasRightmostSelectorMatchingHTMLBasedOnRuleHash(isSelectorMatchingHTMLBasedOnRuleHash(selector)) 1907 , m_containsUncommonAttributeSelector(WebCore::containsUncommonAttributeSelector(selector)) 1849 1908 { 1850 1909 SelectorChecker::collectIdentifierHashes(m_selector, m_descendantSelectorIdentifierHashes, maximumIdentifierCount); … … 1996 2055 if (selector->m_match == CSSSelector::Id && !selector->value().isEmpty()) 1997 2056 features.idsInRules.add(selector->value().impl()); 1998 if (selector->hasAttribute()) { 1999 switch (selector->m_match) { 2000 case CSSSelector::Exact: 2001 case CSSSelector::Set: 2002 case CSSSelector::List: 2003 case CSSSelector::Hyphen: 2004 case CSSSelector::Contain: 2005 case CSSSelector::Begin: 2006 case CSSSelector::End: 2007 features.attrsInRules.add(selector->attribute().localName().impl()); 2008 break; 2009 default: 2010 break; 2011 } 2012 } 2057 if (selector->isAttributeSelector()) 2058 features.attrsInRules.add(selector->attribute().localName().impl()); 2013 2059 switch (selector->pseudoType()) { 2014 2060 case CSSSelector::PseudoFirstLine: … … 2050 2096 features.siblingRules = adoptPtr(new RuleSet); 2051 2097 features.siblingRules->addRule(ruleData.rule(), ruleData.selector()); 2098 } 2099 if (ruleData.containsUncommonAttributeSelector()) { 2100 if (!features.uncommonAttributeRules) 2101 features.uncommonAttributeRules = adoptPtr(new RuleSet); 2102 features.uncommonAttributeRules->addRule(ruleData.rule(), ruleData.selector()); 2052 2103 } 2053 2104 } -
trunk/Source/WebCore/css/CSSStyleSelector.h
r95052 r96393 123 123 void initElement(Element*); 124 124 RenderStyle* locateSharedStyle(); 125 bool matches SiblingRules();125 bool matchesRuleSet(RuleSet*); 126 126 Node* locateCousinList(Element* parent, unsigned& visitedNodeCount) const; 127 127 Node* findSiblingForStyleSharing(Node*, unsigned& count) const; … … 203 203 HashSet<AtomicStringImpl*> attrsInRules; 204 204 OwnPtr<RuleSet> siblingRules; 205 OwnPtr<RuleSet> uncommonAttributeRules; 205 206 bool usesFirstLineRules; 206 207 bool usesBeforeAfterRules; -
trunk/Source/WebCore/css/SelectorChecker.cpp
r95966 r96393 687 687 const QualifiedName& attr = sel->attribute(); 688 688 689 // FIXME: Handle the case were elementStyle is 0.690 if (elementStyle && (!e->isStyledElement() || (!static_cast<StyledElement*>(e)->isMappedAttribute(attr) && attr != typeAttr && attr != readonlyAttr)))691 elementStyle->setAffectedByAttributeSelectors(); // Special-case the "type" and "readonly" attributes so input form controls can share style.692 693 689 NamedNodeMap* attributes = e->attributes(true); 694 690 if (!attributes) -
trunk/Source/WebCore/rendering/style/RenderStyle.cpp
r96142 r96393 72 72 73 73 ALWAYS_INLINE RenderStyle::RenderStyle() 74 : m_affectedBy AttributeSelectors(false)74 : m_affectedByUncommonAttributeSelectors(false) 75 75 , m_unique(false) 76 76 , m_affectedByEmpty(false) … … 99 99 100 100 ALWAYS_INLINE RenderStyle::RenderStyle(bool) 101 : m_affectedBy AttributeSelectors(false)101 : m_affectedByUncommonAttributeSelectors(false) 102 102 , m_unique(false) 103 103 , m_affectedByEmpty(false) … … 139 139 ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o) 140 140 : RefCounted<RenderStyle>() 141 , m_affectedBy AttributeSelectors(false)141 , m_affectedByUncommonAttributeSelectors(false) 142 142 , m_unique(false) 143 143 , m_affectedByEmpty(false) -
trunk/Source/WebCore/rendering/style/RenderStyle.h
r96142 r96393 128 128 // The following bitfield is 32-bits long, which optimizes padding with the 129 129 // int refCount in the base class. Beware when adding more bits. 130 bool m_affectedBy AttributeSelectors : 1;130 bool m_affectedByUncommonAttributeSelectors : 1; 131 131 bool m_unique : 1; 132 132 … … 1307 1307 1308 1308 // To tell if this style matched attribute selectors. This makes it impossible to share. 1309 bool affectedBy AttributeSelectors() const { return m_affectedByAttributeSelectors; }1310 void setAffectedBy AttributeSelectors() { m_affectedByAttributeSelectors = true; }1309 bool affectedByUncommonAttributeSelectors() const { return m_affectedByUncommonAttributeSelectors; } 1310 void setAffectedByUncommonAttributeSelectors() { m_affectedByUncommonAttributeSelectors = true; } 1311 1311 1312 1312 bool affectedByDirectAdjacentRules() const { return m_affectedByDirectAdjacentRules; }
Note: See TracChangeset
for help on using the changeset viewer.