Changeset 127438 in webkit
- Timestamp:
- Sep 3, 2012 7:19:26 PM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r127437 r127438 1 2012-09-03 Andreas Kling <kling@webkit.org> 2 3 Share immutable ElementAttributeData between elements with identical attributes. 4 <http://webkit.org/b/94990> 5 6 Reviewed by Antti Koivisto. 7 8 Keep a cache of ElementAttributeData objects for a given set of attributes and reuse 9 them in elements with identical attribute maps. ElementAttributeData is made ref-counted 10 to facilitate this. A copy-on-write mechanism is already in place, since mutating call 11 sites have to go via Element::mutableAttributeData(). 12 13 The cache is held by Document and cleared in Document::finishedParsing() since the vast 14 majority of immutable ElementAttributeData will be constructed during parsing. 15 16 On the HTML5 spec at <http://whatwg.org/c/>, we get a cache hit rate of nearly 80%, 17 translating into a 3.5MB reduction in memory use. 18 19 * dom/Document.cpp: 20 (WebCore::Document::finishedParsing): 21 (ImmutableAttributeDataCacheKey): 22 (WebCore::ImmutableAttributeDataCacheKey::ImmutableAttributeDataCacheKey): 23 (WebCore::ImmutableAttributeDataCacheKey::operator!=): 24 (WebCore::ImmutableAttributeDataCacheKey::hash): 25 (ImmutableAttributeDataCacheEntry): 26 (WebCore::Document::cachedImmutableAttributeData): 27 * dom/Document.h: 28 * dom/Element.cpp: 29 (WebCore::Element::parserSetAttributes): 30 * dom/Element.h: 31 * dom/ElementAttributeData.cpp: 32 (WebCore::ElementAttributeData::createImmutable): 33 (WebCore::ElementAttributeData::ElementAttributeData): 34 * dom/ElementAttributeData.h: 35 (WebCore::ElementAttributeData::create): 36 (ElementAttributeData): 37 (WebCore::ElementAttributeData::makeMutable): 38 1 39 2012-09-03 Peter Wang <peter.wang@torchmobile.com.cn> 2 40 -
trunk/Source/WebCore/dom/Document.cpp
r127421 r127438 4887 4887 InspectorInstrumentation::domContentLoadedEventFired(f.get()); 4888 4888 } 4889 4890 // The ElementAttributeData sharing cache is only used during parsing since 4891 // that's when the majority of immutable attribute data will be created. 4892 m_immutableAttributeDataCache.clear(); 4889 4893 } 4890 4894 … … 6173 6177 #endif 6174 6178 6179 class ImmutableAttributeDataCacheKey { 6180 public: 6181 ImmutableAttributeDataCacheKey() 6182 : m_localName(0) 6183 , m_attributes(0) 6184 , m_attributeCount(0) 6185 { } 6186 6187 ImmutableAttributeDataCacheKey(const AtomicString& localName, const Attribute* attributes, unsigned attributeCount) 6188 : m_localName(localName.impl()) 6189 , m_attributes(attributes) 6190 , m_attributeCount(attributeCount) 6191 { } 6192 6193 bool operator!=(const ImmutableAttributeDataCacheKey& other) const 6194 { 6195 if (m_localName != other.m_localName) 6196 return true; 6197 if (m_attributeCount != other.m_attributeCount) 6198 return true; 6199 return memcmp(m_attributes, other.m_attributes, sizeof(Attribute) * m_attributeCount); 6200 } 6201 6202 unsigned hash() const 6203 { 6204 unsigned attributeHash = StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute)); 6205 return WTF::intHash((static_cast<uint64_t>(m_localName->existingHash()) << 32 | attributeHash)); 6206 } 6207 6208 private: 6209 AtomicStringImpl* m_localName; 6210 const Attribute* m_attributes; 6211 unsigned m_attributeCount; 6212 }; 6213 6214 struct ImmutableAttributeDataCacheEntry { 6215 ImmutableAttributeDataCacheKey key; 6216 RefPtr<ElementAttributeData> value; 6217 }; 6218 6219 PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const Element* element, const Vector<Attribute>& attributes) 6220 { 6221 ASSERT(!attributes.isEmpty()); 6222 6223 ImmutableAttributeDataCacheKey cacheKey(element->localName(), attributes.data(), attributes.size()); 6224 unsigned cacheHash = cacheKey.hash(); 6225 6226 ImmutableAttributeDataCache::iterator cacheIterator = m_immutableAttributeDataCache.add(cacheHash, nullptr).iterator; 6227 if (cacheIterator->second && cacheIterator->second->key != cacheKey) 6228 cacheHash = 0; 6229 6230 RefPtr<ElementAttributeData> attributeData; 6231 if (cacheHash && cacheIterator->second) 6232 attributeData = cacheIterator->second->value; 6233 else 6234 attributeData = ElementAttributeData::createImmutable(attributes); 6235 6236 if (!cacheHash || cacheIterator->second) 6237 return attributeData.release(); 6238 6239 OwnPtr<ImmutableAttributeDataCacheEntry> newEntry = adoptPtr(new ImmutableAttributeDataCacheEntry); 6240 newEntry->key = ImmutableAttributeDataCacheKey(element->localName(), const_cast<const ElementAttributeData*>(attributeData.get())->attributeItem(0), attributeData->length()); 6241 newEntry->value = attributeData; 6242 6243 cacheIterator->second = newEntry.release(); 6244 6245 return attributeData.release(); 6246 } 6247 6175 6248 } // namespace WebCore -
trunk/Source/WebCore/dom/Document.h
r127228 r127438 84 84 class EditingText; 85 85 class Element; 86 class ElementAttributeData; 86 87 class EntityReference; 87 88 class Event; … … 207 208 const int numNodeListInvalidationTypes = InvalidateOnAnyAttrChange + 1; 208 209 210 struct ImmutableAttributeDataCacheEntry; 211 typedef HashMap<unsigned, OwnPtr<ImmutableAttributeDataCacheEntry>, AlreadyHashed> ImmutableAttributeDataCache; 212 209 213 class Document : public ContainerNode, public TreeScope, public ScriptExecutionContext { 210 214 public: … … 1184 1188 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE; 1185 1189 1190 PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Element*, const Vector<Attribute>&); 1191 1186 1192 protected: 1187 1193 Document(Frame*, const KURL&, bool isXHTML, bool isHTML); … … 1569 1575 #endif 1570 1576 1577 ImmutableAttributeDataCache m_immutableAttributeDataCache; 1578 1571 1579 #ifndef NDEBUG 1572 1580 bool m_didDispatchViewportPropertiesChanged; -
trunk/Source/WebCore/dom/Element.cpp
r127228 r127438 824 824 } 825 825 826 m_attributeData = ElementAttributeData::createImmutable(filteredAttributes); 826 // When the document is in parsing state, we cache immutable ElementAttributeData objects with the 827 // input attribute vector as key. (This cache is held by Document.) 828 if (!document() || !document()->parsing()) 829 m_attributeData = ElementAttributeData::createImmutable(filteredAttributes); 830 else if (!isHTMLElement()) { 831 // FIXME: Support attribute data sharing for non-HTML elements. 832 m_attributeData = ElementAttributeData::createImmutable(filteredAttributes); 833 } else 834 m_attributeData = document()->cachedImmutableAttributeData(this, filteredAttributes); 827 835 828 836 // Iterate over the set of attributes we already have on the stack in case -
trunk/Source/WebCore/dom/Element.h
r127228 r127438 520 520 ElementRareData* ensureElementRareData(); 521 521 522 OwnPtr<ElementAttributeData> m_attributeData;522 RefPtr<ElementAttributeData> m_attributeData; 523 523 }; 524 524 -
trunk/Source/WebCore/dom/ElementAttributeData.cpp
r127375 r127438 40 40 } 41 41 42 Pass OwnPtr<ElementAttributeData> ElementAttributeData::createImmutable(const Vector<Attribute>& attributes)42 PassRefPtr<ElementAttributeData> ElementAttributeData::createImmutable(const Vector<Attribute>& attributes) 43 43 { 44 44 void* slot = WTF::fastMalloc(immutableElementAttributeDataSize(attributes.size())); 45 return adopt Ptr(new (slot) ElementAttributeData(attributes));45 return adoptRef(new (slot) ElementAttributeData(attributes)); 46 46 } 47 47 … … 63 63 64 64 ElementAttributeData::ElementAttributeData(const ElementAttributeData& other) 65 : m_inlineStyleDecl(other.m_inlineStyleDecl) 65 : RefCounted<ElementAttributeData>() 66 , m_isMutable(true) 67 , m_arraySize(0) 68 , m_inlineStyleDecl(other.m_inlineStyleDecl) 66 69 , m_attributeStyle(other.m_attributeStyle) 67 70 , m_classNames(other.m_classNames) 68 71 , m_idForStyleResolution(other.m_idForStyleResolution) 69 , m_isMutable(true)70 , m_arraySize(0)71 72 , m_mutableAttributeVector(new Vector<Attribute, 4>) 72 73 { 73 74 // This copy constructor should only be used by makeMutable() to go from immutable to mutable. 74 75 ASSERT(!other.m_isMutable); 76 77 // An immutable ElementAttributeData should never have a mutable inline StylePropertySet attached. 78 ASSERT(!other.m_inlineStyleDecl || !other.m_inlineStyleDecl->isMutable()); 75 79 76 80 const Attribute* otherBuffer = reinterpret_cast<const Attribute*>(&other.m_attributes); -
trunk/Source/WebCore/dom/ElementAttributeData.h
r127126 r127438 40 40 enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute, InSynchronizationOfLazyAttribute }; 41 41 42 class ElementAttributeData {42 class ElementAttributeData : public RefCounted<ElementAttributeData> { 43 43 WTF_MAKE_FAST_ALLOCATED; 44 44 public: 45 static Pass OwnPtr<ElementAttributeData> create() { return adoptPtr(new ElementAttributeData); }46 static Pass OwnPtr<ElementAttributeData> createImmutable(const Vector<Attribute>&);45 static PassRefPtr<ElementAttributeData> create() { return adoptRef(new ElementAttributeData); } 46 static PassRefPtr<ElementAttributeData> createImmutable(const Vector<Attribute>&); 47 47 ~ElementAttributeData(); 48 48 … … 111 111 112 112 bool isMutable() const { return m_isMutable; } 113 PassOwnPtr<ElementAttributeData> makeMutable() const { return adoptPtr(new ElementAttributeData(*this)); } 113 PassRefPtr<ElementAttributeData> makeMutable() const { return adoptRef(new ElementAttributeData(*this)); } 114 115 unsigned m_isMutable : 1; 116 unsigned m_arraySize : 31; 114 117 115 118 mutable RefPtr<StylePropertySet> m_inlineStyleDecl; … … 117 120 mutable SpaceSplitString m_classNames; 118 121 mutable AtomicString m_idForStyleResolution; 119 120 unsigned m_isMutable : 1;121 unsigned m_arraySize : 31;122 122 123 123 union {
Note: See TracChangeset
for help on using the changeset viewer.