Changeset 135421 in webkit
- Timestamp:
- Nov 21, 2012, 11:05:17 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r135419 r135421 1 2012-11-21 Andreas Kling <akling@apple.com> 2 3 Make it possible for elements with different tag names to share attribute data. 4 <http://webkit.org/b/102845> 5 6 Reviewed by Antti Koivisto. 7 8 Allow all elements to share ElementAttributeData with one another. This means that the elements 9 in this hypothetical markup will all point to the same attribute data: 10 11 <div class="foo"> 12 <span class="foo"> 13 <hr class="foo"/> 14 </span> 15 </div> 16 17 This optimization happens at the expense of an old one. We no longer share attribute data 18 between elements that have presentation attributes, since they map to different CSS properties 19 depending on what tag they're attached to. These are mostly used in ye olde web 1.0 content 20 though, and we should prefer optimizing in favor of modern markup. The global cache for 21 presentation attribute style in StyledElement.cpp still prevents redundant parsing. 22 23 On the upside, excluding elements with presentation attributes from the data cache means that 24 we can move one pointer (m_presentationAttributeStyle) from ImmutableElementAttributeData 25 to MutableElementAttributeData. 26 27 800kB progression on Membuster3. 28 29 * dom/Document.h: 30 * dom/Document.cpp: 31 (WebCore::ImmutableAttributeDataCacheKey::ImmutableAttributeDataCacheKey): 32 (WebCore::ImmutableAttributeDataCacheKey::operator!=): 33 (WebCore::ImmutableAttributeDataCacheKey::hash): 34 (ImmutableAttributeDataCacheKey): 35 (WebCore::Document::cachedImmutableAttributeData): 36 * dom/Element.cpp: 37 (WebCore::Element::parserSetAttributes): 38 39 Don't use the element's tag name in the key for the immutable attribute data cache. 40 41 (WebCore::Element::cloneAttributesFromElement): 42 43 Prevent cloneNode() from converting mutable attribute data to immutable if it has 44 presentation attributes. 45 46 * dom/ElementAttributeData.cpp: 47 (WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData): 48 49 Add an assertion that mutable-to-immutable conversion never happens with presentation 50 attribute style present. 51 52 (WebCore::ElementAttributeData::ElementAttributeData): 53 (WebCore::MutableElementAttributeData::MutableElementAttributeData): 54 (WebCore::ElementAttributeData::reportMemoryUsage): 55 * dom/ElementAttributeData.h: 56 (ElementAttributeData): 57 (MutableElementAttributeData): 58 (WebCore::ElementAttributeData::presentationAttributeStyle): 59 (WebCore): 60 (WebCore::ElementAttributeData::setPresentationAttributeStyle): 61 62 Move the RefPtr<StylePropertySet> that holds presentation attribute-derived style 63 from the common ElementAttributeData base class to MutableElementAttributeData. 64 65 * dom/StyledElement.cpp: 66 (WebCore::StyledElement::attributeChanged): 67 68 Always dirty the presentation attribute style when a presentation attribute changes. 69 70 (WebCore::StyledElement::rebuildPresentationAttributeStyle): 71 72 Force promotion to mutable attribute data when it turns out that we need to hang a 73 StylePropertySet with the presentation attribute style off of it. 74 1 75 2012-11-21 Antti Koivisto <antti@apple.com> 2 76 -
trunk/Source/WebCore/dom/Document.cpp
r135405 r135421 5914 5914 class ImmutableAttributeDataCacheKey { 5915 5915 public: 5916 ImmutableAttributeDataCacheKey(const QualifiedName& tagName, const Attribute* attributes, unsigned attributeCount) 5917 : m_tagQName(tagName) 5918 , m_attributes(attributes) 5916 ImmutableAttributeDataCacheKey(const Attribute* attributes, unsigned attributeCount) 5917 : m_attributes(attributes) 5919 5918 , m_attributeCount(attributeCount) 5920 5919 { } … … 5922 5921 bool operator!=(const ImmutableAttributeDataCacheKey& other) const 5923 5922 { 5924 if (m_tagQName != other.m_tagQName)5925 return true;5926 5923 if (m_attributeCount != other.m_attributeCount) 5927 5924 return true; … … 5931 5928 unsigned hash() const 5932 5929 { 5933 unsigned attributeHash = StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute)); 5934 return WTF::pairIntHash(m_tagQName.localName().impl()->existingHash(), attributeHash); 5930 return StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute)); 5935 5931 } 5936 5932 5937 5933 private: 5938 QualifiedName m_tagQName;5939 5934 const Attribute* m_attributes; 5940 5935 unsigned m_attributeCount; … … 5951 5946 }; 5952 5947 5953 PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const Element* element, constVector<Attribute>& attributes)5948 PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const Vector<Attribute>& attributes) 5954 5949 { 5955 5950 ASSERT(!attributes.isEmpty()); 5956 5951 5957 ImmutableAttributeDataCacheKey cacheKey( element->tagQName(),attributes.data(), attributes.size());5952 ImmutableAttributeDataCacheKey cacheKey(attributes.data(), attributes.size()); 5958 5953 unsigned cacheHash = cacheKey.hash(); 5959 5954 … … 5971 5966 return attributeData.release(); 5972 5967 5973 cacheIterator->value = adoptPtr(new ImmutableAttributeDataCacheEntry(ImmutableAttributeDataCacheKey( element->tagQName(),attributeData->immutableAttributeArray(), attributeData->length()), attributeData));5968 cacheIterator->value = adoptPtr(new ImmutableAttributeDataCacheEntry(ImmutableAttributeDataCacheKey(attributeData->immutableAttributeArray(), attributeData->length()), attributeData)); 5974 5969 5975 5970 return attributeData.release(); -
trunk/Source/WebCore/dom/Document.h
r135242 r135421 1157 1157 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE; 1158 1158 1159 PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Element*, constVector<Attribute>&);1159 PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Vector<Attribute>&); 1160 1160 1161 1161 void didRemoveAllPendingStylesheet(); -
trunk/Source/WebCore/dom/Element.cpp
r135270 r135421 1023 1023 1024 1024 // When the document is in parsing state, we cache immutable ElementAttributeData objects with the 1025 // input attribute vector (and the tag name)as key. (This cache is held by Document.)1025 // input attribute vector as key. (This cache is held by Document.) 1026 1026 if (!document() || !document()->parsing()) 1027 1027 m_attributeData = ElementAttributeData::createImmutable(filteredAttributes); 1028 1028 else 1029 m_attributeData = document()->cachedImmutableAttributeData( this,filteredAttributes);1029 m_attributeData = document()->cachedImmutableAttributeData(filteredAttributes); 1030 1030 1031 1031 // Iterate over the set of attributes we already have on the stack in case … … 2564 2564 2565 2565 // If 'other' has a mutable ElementAttributeData, convert it to an immutable one so we can share it between both elements. 2566 // We can only do this if there is no CSSOM wrapper for other's inline style (the isMutable() check.) 2567 if (other.m_attributeData->isMutable() && (!other.m_attributeData->inlineStyle() || !other.m_attributeData->inlineStyle()->isMutable())) 2566 // We can only do this if there is no CSSOM wrapper for other's inline style, and there are no presentation attributes. 2567 if (other.m_attributeData->isMutable() 2568 && !other.m_attributeData->presentationAttributeStyle() 2569 && (!other.m_attributeData->inlineStyle() || !other.m_attributeData->inlineStyle()->hasCSSOMWrapper())) 2568 2570 const_cast<Element&>(other).m_attributeData = other.m_attributeData->makeImmutableCopy(); 2569 2571 -
trunk/Source/WebCore/dom/ElementAttributeData.cpp
r135021 r135421 34 34 struct SameSizeAsElementAttributeData : public RefCounted<SameSizeAsElementAttributeData> { 35 35 unsigned bitfield; 36 void* refPtrs[ 4];36 void* refPtrs[3]; 37 37 }; 38 38 … … 71 71 : ElementAttributeData(other, false) 72 72 { 73 ASSERT(!other.m_presentationAttributeStyle); 74 73 75 if (other.m_inlineStyle) { 74 76 ASSERT(!other.m_inlineStyle->isMutable()); … … 85 87 , m_presentationAttributeStyleIsDirty(other.m_presentationAttributeStyleIsDirty) 86 88 , m_styleAttributeIsDirty(other.m_styleAttributeIsDirty) 87 , m_presentationAttributeStyle(other.m_presentationAttributeStyle)88 89 , m_classNames(other.m_classNames) 89 90 , m_idForStyleResolution(other.m_idForStyleResolution) … … 94 95 MutableElementAttributeData::MutableElementAttributeData(const MutableElementAttributeData& other) 95 96 : ElementAttributeData(other, true) 97 , m_presentationAttributeStyle(other.m_presentationAttributeStyle) 96 98 , m_attributeVector(other.m_attributeVector) 97 99 { … … 162 164 MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM, actualSize); 163 165 info.addMember(m_inlineStyle); 164 info.addMember(m_presentationAttributeStyle);165 166 info.addMember(m_classNames); 166 167 info.addMember(m_idForStyleResolution); 167 if (m_isMutable) 168 if (m_isMutable) { 169 info.addMember(presentationAttributeStyle()); 168 170 info.addMember(mutableAttributeVector()); 171 } 169 172 for (unsigned i = 0, len = length(); i < len; i++) 170 173 info.addMember(*attributeItem(i)); -
trunk/Source/WebCore/dom/ElementAttributeData.h
r135021 r135421 57 57 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } 58 58 59 const StylePropertySet* presentationAttributeStyle() const { return m_presentationAttributeStyle.get(); }60 void setPresentationAttributeStyle(PassRefPtr<StylePropertySet> style) const { m_presentationAttributeStyle = style; }59 const StylePropertySet* presentationAttributeStyle() const; 60 void setPresentationAttributeStyle(PassRefPtr<StylePropertySet>) const; 61 61 62 62 size_t length() const; … … 108 108 109 109 mutable RefPtr<StylePropertySet> m_inlineStyle; 110 mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;111 110 mutable SpaceSplitString m_classNames; 112 111 mutable AtomicString m_idForStyleResolution; … … 144 143 MutableElementAttributeData(const MutableElementAttributeData&); 145 144 145 mutable RefPtr<StylePropertySet> m_presentationAttributeStyle; 146 146 Vector<Attribute, 4> m_attributeVector; 147 147 }; … … 170 170 return mutableAttributeVector().size(); 171 171 return m_arraySize; 172 } 173 174 inline const StylePropertySet* ElementAttributeData::presentationAttributeStyle() const 175 { 176 if (!m_isMutable) 177 return 0; 178 return static_cast<const MutableElementAttributeData*>(this)->m_presentationAttributeStyle.get(); 179 } 180 181 inline void ElementAttributeData::setPresentationAttributeStyle(PassRefPtr<StylePropertySet> style) const 182 { 183 ASSERT(m_isMutable); 184 static_cast<const MutableElementAttributeData*>(this)->m_presentationAttributeStyle = style; 172 185 } 173 186 -
trunk/Source/WebCore/dom/StyledElement.cpp
r135101 r135421 162 162 styleAttributeChanged(newValue); 163 163 else if (isPresentationAttribute(name)) { 164 // Avoid dirtying the presentation attribute style if we're using shared attribute data with already generated style. 165 if (attributeData()->isMutable() || !attributeData()->m_presentationAttributeStyle) 166 attributeData()->m_presentationAttributeStyleIsDirty = true; 164 attributeData()->m_presentationAttributeStyleIsDirty = true; 167 165 setNeedsStyleRecalc(InlineStyleChange); 168 166 } … … 343 341 } 344 342 345 attributeData()->m_presentationAttributeStyleIsDirty = false; 346 attributeData()->setPresentationAttributeStyle(style->isEmpty() ? 0 : style); 343 // ImmutableElementAttributeData doesn't store presentation attribute style, so make sure we have a MutableElementAttributeData. 344 ElementAttributeData* attributeData = mutableAttributeData(); 345 346 attributeData->m_presentationAttributeStyleIsDirty = false; 347 attributeData->setPresentationAttributeStyle(style->isEmpty() ? 0 : style); 347 348 348 349 if (!cacheHash || cacheIterator->value)
Note:
See TracChangeset
for help on using the changeset viewer.