Changeset 132941 in webkit
- Timestamp:
- Oct 30, 2012 1:25:52 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r132935 r132941 1 2012-10-30 Antti Koivisto <antti@apple.com> 2 3 Avoid unnecessary style recalcs on class attribute mutation 4 https://bugs.webkit.org/show_bug.cgi?id=100776 5 6 Reviewed by Andreas Kling. 7 8 There is no need to invalidate element style on class attribute change if neither the added 9 or removed classes featured in any active stylesheet. 10 11 * css/RuleFeature.cpp: 12 (WebCore::RuleFeatureSet::add): 13 (WebCore::RuleFeatureSet::clear): 14 (WebCore::RuleFeatureSet::reportMemoryUsage): 15 * css/RuleFeature.h: 16 (RuleFeatureSet): 17 * css/RuleSet.cpp: 18 (WebCore::collectFeaturesFromSelector): 19 20 Collect classes mentioned in CSS selectors the same way ids and attribute names are 21 already collected. 22 23 * css/StyleResolver.cpp: 24 (WebCore::StyleResolver::hasSelectorForClass): 25 26 Add a method to test if a given class name is mentioned anywhere in stylehseets. 27 28 (WebCore): 29 * css/StyleResolver.h: 30 * css/StyleScopeResolver.h: 31 (WebCore): 32 * dom/Element.cpp: 33 (WebCore::collectAddedAndRemovedClasses): 34 (WebCore): 35 (WebCore::Element::classAttributeChanged): 36 37 Figure out which classes were added and removed. Test if they are present in any style 38 rule and invalidate the style only if they are. 39 40 * dom/SpaceSplitString.cpp: 41 (WebCore::SpaceSplitStringData::add): 42 (WebCore::SpaceSplitStringData::remove): 43 (WebCore::SpaceSplitString::add): 44 (WebCore::SpaceSplitString::remove): 45 46 Added bool return value to indicate if anything was actually removed. Reorganized 47 the code a bit to avoid unnecessary uniquing when nothing changes. 48 49 * dom/SpaceSplitString.h: 50 (SpaceSplitStringData): 51 (SpaceSplitString): 52 1 53 2012-10-30 Robert Hogan <robert@webkit.org> 2 54 -
trunk/Source/WebCore/css/RuleFeature.cpp
r130465 r132941 39 39 void RuleFeatureSet::add(const RuleFeatureSet& other) 40 40 { 41 HashSet<AtomicStringImpl*>:: iterator end = other.idsInRules.end();42 for (HashSet<AtomicStringImpl*>:: iterator it = other.idsInRules.begin(); it != end; ++it)41 HashSet<AtomicStringImpl*>::const_iterator end = other.idsInRules.end(); 42 for (HashSet<AtomicStringImpl*>::const_iterator it = other.idsInRules.begin(); it != end; ++it) 43 43 idsInRules.add(*it); 44 end = other.classesInRules.end(); 45 for (HashSet<AtomicStringImpl*>::const_iterator it = other.classesInRules.begin(); it != end; ++it) 46 classesInRules.add(*it); 44 47 end = other.attrsInRules.end(); 45 for (HashSet<AtomicStringImpl*>:: iterator it = other.attrsInRules.begin(); it != end; ++it)48 for (HashSet<AtomicStringImpl*>::const_iterator it = other.attrsInRules.begin(); it != end; ++it) 46 49 attrsInRules.add(*it); 47 50 siblingRules.append(other.siblingRules); … … 54 57 { 55 58 idsInRules.clear(); 59 classesInRules.clear(); 56 60 attrsInRules.clear(); 57 61 siblingRules.clear(); … … 65 69 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS); 66 70 info.addMember(idsInRules); 71 info.addMember(classesInRules); 67 72 info.addMember(attrsInRules); 68 73 info.addMember(siblingRules); -
trunk/Source/WebCore/css/RuleFeature.h
r130465 r132941 32 32 class StyleRule; 33 33 34 class RuleFeature { 35 public: 34 struct RuleFeature { 36 35 RuleFeature(StyleRule* rule, unsigned selectorIndex, bool hasDocumentSecurityOrigin) 37 36 : rule(rule) … … 45 44 }; 46 45 47 class RuleFeatureSet { 48 public: 46 struct RuleFeatureSet { 49 47 RuleFeatureSet() 50 48 : usesFirstLineRules(false) … … 56 54 void reportMemoryUsage(MemoryObjectInfo*) const; 57 55 HashSet<AtomicStringImpl*> idsInRules; 56 HashSet<AtomicStringImpl*> classesInRules; 58 57 HashSet<AtomicStringImpl*> attrsInRules; 59 58 Vector<RuleFeature> siblingRules; -
trunk/Source/WebCore/css/RuleSet.cpp
r132618 r132941 162 162 if (selector->m_match == CSSSelector::Id) 163 163 features.idsInRules.add(selector->value().impl()); 164 if (selector->isAttributeSelector()) 164 else if (selector->m_match == CSSSelector::Class) 165 features.classesInRules.add(selector->value().impl()); 166 else if (selector->isAttributeSelector()) 165 167 features.attrsInRules.add(selector->attribute().localName().impl()); 166 168 switch (selector->pseudoType()) { -
trunk/Source/WebCore/css/StyleResolver.cpp
r132927 r132941 4255 4255 } 4256 4256 4257 bool StyleResolver::hasSelectorForClass(const AtomicString& classValue) const 4258 { 4259 if (classValue.isEmpty()) 4260 return false; 4261 return m_features.classesInRules.contains(classValue.impl()); 4262 } 4263 4257 4264 bool StyleResolver::hasSelectorForId(const AtomicString& idValue) const 4258 4265 { -
trunk/Source/WebCore/css/StyleResolver.h
r132808 r132941 242 242 243 243 bool hasSelectorForId(const AtomicString&) const; 244 bool hasSelectorForClass(const AtomicString&) const; 244 245 bool hasSelectorForAttribute(const AtomicString&) const; 245 246 -
trunk/Source/WebCore/css/StyleScopeResolver.h
r132618 r132941 40 40 class Element; 41 41 class RuleSet; 42 class RuleFeatureSet;43 42 class ShadowRoot; 44 43 class StyleRuleHost; 44 struct RuleFeatureSet; 45 45 46 46 #if ENABLE(STYLE_SCOPED) || ENABLE(SHADOW_DOM) -
trunk/Source/WebCore/dom/Element.cpp
r132774 r132941 766 766 } 767 767 768 static void collectAddedAndRemovedClasses(Vector<AtomicString, 4>& addedAndRemovedClasses, SpaceSplitString& oldClasses, const SpaceSplitString& newClasses) 769 { 770 for (unsigned i = 0; i < newClasses.size(); ++i) { 771 if (oldClasses.remove(newClasses[i])) 772 continue; 773 addedAndRemovedClasses.append(newClasses[i]); 774 } 775 for (unsigned i = 0; i < oldClasses.size(); ++i) 776 addedAndRemovedClasses.append(oldClasses[i]); 777 } 778 768 779 void Element::classAttributeChanged(const AtomicString& newClassString) 769 780 { 781 bool shouldInvalidateStyle = attached() && document()->styleResolverIfExists(); 782 Vector<AtomicString, 4> addedAndRemovedClasses; 783 770 784 if (classStringHasClassName(newClassString)) { 785 const ElementAttributeData* attributeData = ensureAttributeData(); 771 786 const bool shouldFoldCase = document()->inQuirksMode(); 772 ensureAttributeData()->setClass(newClassString, shouldFoldCase); 773 } else if (attributeData()) 787 SpaceSplitString oldClasses = attributeData->classNames(); 788 attributeData->setClass(newClassString, shouldFoldCase); 789 if (shouldInvalidateStyle) 790 collectAddedAndRemovedClasses(addedAndRemovedClasses, oldClasses, mutableAttributeData()->classNames()); 791 } else if (attributeData()) { 792 if (shouldInvalidateStyle) { 793 const SpaceSplitString& oldClasses = attributeData()->classNames(); 794 for (unsigned i = 0; i < oldClasses.size(); ++i) 795 addedAndRemovedClasses.append(oldClasses[i]); 796 } 774 797 mutableAttributeData()->clearClass(); 798 } 775 799 776 800 if (DOMTokenList* classList = optionalClassList()) 777 801 static_cast<ClassList*>(classList)->reset(newClassString); 778 802 779 setNeedsStyleRecalc(); 803 if (!shouldInvalidateStyle) 804 return; 805 for (unsigned i = 0; i < addedAndRemovedClasses.size(); ++i) { 806 if (document()->styleResolverIfExists()->hasSelectorForClass(addedAndRemovedClasses[i])) { 807 setNeedsStyleRecalc(); 808 break; 809 } 810 } 780 811 } 781 812 -
trunk/Source/WebCore/dom/SpaceSplitString.cpp
r130612 r132941 108 108 { 109 109 ASSERT(hasOneRef()); 110 ASSERT(!contains(string)); 111 m_vector.append(string); 112 } 113 114 void SpaceSplitStringData::remove(unsigned index) 115 { 116 ASSERT(hasOneRef()); 117 m_vector.remove(index); 118 } 119 120 void SpaceSplitString::add(const AtomicString& string) 121 { 122 // FIXME: add() does not allow duplicates but createVector() does. 110 123 if (contains(string)) 111 124 return; 112 113 m_vector.append(string);114 }115 116 void SpaceSplitStringData::remove(const AtomicString& string)117 {118 ASSERT(hasOneRef());119 size_t position = 0;120 while (position < m_vector.size()) {121 if (m_vector[position] == string)122 m_vector.remove(position);123 else124 ++position;125 }126 }127 128 void SpaceSplitString::add(const AtomicString& string)129 {130 125 ensureUnique(); 131 126 if (m_data) … … 133 128 } 134 129 135 void SpaceSplitString::remove(const AtomicString& string) 136 { 137 ensureUnique(); 138 if (m_data) 139 m_data->remove(string); 130 bool SpaceSplitString::remove(const AtomicString& string) 131 { 132 if (!m_data) 133 return false; 134 unsigned i = 0; 135 bool changed = false; 136 while (i < m_data->size()) { 137 if ((*m_data)[i] == string) { 138 if (!changed) 139 ensureUnique(); 140 m_data->remove(i); 141 changed = true; 142 continue; 143 } 144 ++i; 145 } 146 return changed; 140 147 } 141 148 -
trunk/Source/WebCore/dom/SpaceSplitString.h
r128694 r132941 48 48 49 49 void add(const AtomicString&); 50 void remove( const AtomicString&);50 void remove(unsigned index); 51 51 52 52 bool isUnique() const { return m_keyString.isNull(); } … … 77 77 bool containsAll(const SpaceSplitString& names) const { return !names.m_data || (m_data && m_data->containsAll(*names.m_data)); } 78 78 void add(const AtomicString&); 79 voidremove(const AtomicString&);79 bool remove(const AtomicString&); 80 80 81 81 size_t size() const { return m_data ? m_data->size() : 0; }
Note: See TracChangeset
for help on using the changeset viewer.