Changeset 225596 in webkit
- Timestamp:
- Dec 6, 2017 2:24:06 PM (6 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r225594 r225596 1 2017-12-06 Antti Koivisto <antti@apple.com> 2 3 Prefer ids and classes over tag names in selector filter 4 https://bugs.webkit.org/show_bug.cgi?id=180433 5 <rdar://problem/35859103> 6 7 Reviewed by Zalan Bujtas. 8 9 There are only four slots in the filter and currently we just pick whatever identifiers we find traversing the selector 10 from right to left. More specific selector types are on average more valuable (id > class > tag) so we should prefer them. 11 12 This appears to be 4-5% StyleBench progression. 13 14 * css/RuleSet.cpp: 15 (WebCore::RuleData::RuleData): 16 * css/SelectorFilter.cpp: 17 (WebCore::collectSimpleSelectorHash): 18 (WebCore::collectSelectorHashes): 19 20 This function collects all hashes from the selector. 21 22 (WebCore::chooseSelectorHashesForFilter): 23 24 This function chooses the most valuable hashes to use with the filter. 25 26 (WebCore::SelectorFilter::collectHashes): 27 28 Factor into two separate steps. 29 30 (WebCore::collectDescendantSelectorIdentifierHashes): Deleted. 31 (WebCore::SelectorFilter::collectIdentifierHashes): Deleted. 32 * css/SelectorFilter.h: 33 (WebCore::SelectorFilter::fastRejectSelector const): 34 1 35 2017-12-06 Jer Noble <jer.noble@apple.com> 2 36 -
trunk/Source/WebCore/css/RuleSet.cpp
r225482 r225596 159 159 , m_linkMatchType(SelectorChecker::determineLinkMatchType(selector())) 160 160 , m_propertyWhitelistType(determinePropertyWhitelistType(selector())) 161 , m_descendantSelectorIdentifierHashes(SelectorFilter::collectHashes(*selector())) 161 162 #if ENABLE(CSS_SELECTOR_JIT) && CSS_SELECTOR_JIT_PROFILING 162 163 , m_compiledSelectorUseCount(0) … … 165 166 ASSERT(m_position == position); 166 167 ASSERT(m_selectorIndex == selectorIndex); 167 SelectorFilter::collectIdentifierHashes(*selector(), m_descendantSelectorIdentifierHashes);168 168 } 169 169 -
trunk/Source/WebCore/css/SelectorFilter.cpp
r225482 r225596 97 97 } 98 98 99 static inline void collectDescendantSelectorIdentifierHashes(const CSSSelector& selector, const SelectorFilter::Hashes& hashes, SelectorFilter::Hashes::iterator& hashIt) 100 { 101 auto addIfNew = [&] (unsigned hash) { 102 for (auto it = hashes.begin(); it != hashIt; ++it) { 103 if (*it == hash) 104 return; 105 } 106 *hashIt = hash; 107 hashIt++; 108 }; 109 99 struct CollectedSelectorHashes { 100 using HashVector = Vector<unsigned, 8>; 101 HashVector ids; 102 HashVector classes; 103 HashVector tags; 104 }; 105 106 static inline void collectSimpleSelectorHash(CollectedSelectorHashes& collectedHashes, const CSSSelector& selector) 107 { 110 108 switch (selector.match()) { 111 109 case CSSSelector::Id: 112 110 if (!selector.value().isEmpty()) 113 addIfNew(selector.value().impl()->existingHash() * IdAttributeSalt);111 collectedHashes.ids.append(selector.value().impl()->existingHash() * IdAttributeSalt); 114 112 break; 115 113 case CSSSelector::Class: 116 114 if (!selector.value().isEmpty()) 117 addIfNew(selector.value().impl()->existingHash() * ClassAttributeSalt);115 collectedHashes.classes.append(selector.value().impl()->existingHash() * ClassAttributeSalt); 118 116 break; 119 117 case CSSSelector::Tag: { 120 118 auto& tagLowercaseLocalName = selector.tagLowercaseLocalName(); 121 119 if (tagLowercaseLocalName != starAtom()) 122 addIfNew(tagLowercaseLocalName.impl()->existingHash() * TagNameSalt);120 collectedHashes.tags.append(tagLowercaseLocalName.impl()->existingHash() * TagNameSalt); 123 121 break; 124 122 } … … 128 126 } 129 127 130 void SelectorFilter::collectIdentifierHashes(const CSSSelector& rightmostSelector, Hashes& hashes) 131 { 128 static CollectedSelectorHashes collectSelectorHashes(const CSSSelector& rightmostSelector) 129 { 130 CollectedSelectorHashes collectedHashes; 131 132 132 auto* selector = &rightmostSelector; 133 133 auto relation = selector->relation(); 134 135 auto hashIt = hashes.begin();136 134 137 135 // Skip the topmost selector. It is handled quickly by the rule hashes. … … 142 140 case CSSSelector::Subselector: 143 141 if (!skipOverSubselectors) 144 collect DescendantSelectorIdentifierHashes(*selector, hashes, hashIt);142 collectSimpleSelectorHash(collectedHashes, *selector); 145 143 break; 146 144 case CSSSelector::DirectAdjacent: … … 152 150 case CSSSelector::Child: 153 151 skipOverSubselectors = false; 154 collect DescendantSelectorIdentifierHashes(*selector, hashes, hashIt);152 collectSimpleSelectorHash(collectedHashes, *selector); 155 153 break; 156 154 } 157 if (hashIt == hashes.end())158 return;159 155 relation = selector->relation(); 160 156 } 161 162 *hashIt = 0; 163 } 164 165 } 166 157 return collectedHashes; 158 } 159 160 static SelectorFilter::Hashes chooseSelectorHashesForFilter(const CollectedSelectorHashes& collectedSelectorHashes) 161 { 162 SelectorFilter::Hashes resultHashes; 163 unsigned index = 0; 164 165 auto addIfNew = [&] (unsigned hash) { 166 for (unsigned i = 0; i < index; ++i) { 167 if (resultHashes[i] == hash) 168 return; 169 } 170 resultHashes[index++] = hash; 171 }; 172 173 auto copyHashes = [&] (auto& hashes) { 174 for (auto& hash : hashes) { 175 addIfNew(hash); 176 if (index == resultHashes.size()) 177 return true; 178 } 179 return false; 180 }; 181 182 // There is a limited number of slots. Prefer more specific selector types. 183 if (copyHashes(collectedSelectorHashes.ids)) 184 return resultHashes; 185 if (copyHashes(collectedSelectorHashes.classes)) 186 return resultHashes; 187 if (copyHashes(collectedSelectorHashes.tags)) 188 return resultHashes; 189 190 // Null-terminate if not full. 191 resultHashes[index] = 0; 192 return resultHashes; 193 } 194 195 SelectorFilter::Hashes SelectorFilter::collectHashes(const CSSSelector& selector) 196 { 197 auto hashes = collectSelectorHashes(selector); 198 return chooseSelectorHashesForFilter(hashes); 199 } 200 201 } 202 -
trunk/Source/WebCore/css/SelectorFilter.h
r225482 r225596 50 50 using Hashes = std::array<unsigned, 4>; 51 51 bool fastRejectSelector(const Hashes&) const; 52 static void collectIdentifierHashes(const CSSSelector&, Hashes&);52 static Hashes collectHashes(const CSSSelector&); 53 53 54 54 private: … … 68 68 inline bool SelectorFilter::fastRejectSelector(const Hashes& hashes) const 69 69 { 70 for (unsigned n = 0; n < hashes.size() && hashes[n]; ++n) { 71 if (!m_ancestorIdentifierFilter.mayContain(hashes[n])) 70 for (auto& hash : hashes) { 71 if (!hash) 72 return false; 73 if (!m_ancestorIdentifierFilter.mayContain(hash)) 72 74 return true; 73 75 }
Note: See TracChangeset
for help on using the changeset viewer.