Changeset 116419 in webkit
- Timestamp:
- May 8, 2012 7:09:37 AM (9 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
-
ChangeLog (modified) (1 diff)
-
dom/ElementAttributeData.cpp (modified) (3 diffs)
-
dom/ElementAttributeData.h (modified) (2 diffs)
-
dom/Node.h (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r116418 r116419 1 2012-05-08 Andreas Kling <kling@webkit.org> 2 3 Shrink ElementAttributeData by factoring out Attr object count. 4 <http://webkit.org/b/85825> 5 6 Reviewed by Antti Koivisto. 7 8 Stop tracking the number of Attr objects that point to a given Element on the 9 Element itself and manage this by having a global hashmap of Element => AttrList, 10 where AttrList is a vector of (pointers to) the associated Attr objects. 11 12 This shrinks ElementAttributeData by one integer, effectively reducing memory 13 consumption by ~530kB when viewing the full HTML5 spec at <http://whatwg.org/c>. 14 15 * dom/ElementAttributeData.h: 16 (ElementAttributeData): 17 18 Remove m_attrCount... 19 20 * dom/Node.h: 21 (WebCore::Node::hasAttrList): 22 (WebCore::Node::setHasAttrList): 23 (WebCore::Node::clearHasAttrList): 24 25 ...replacing it with a Node flag that tells us whether there's an Attr 26 object map for this Node (only applies to Elements.) 27 28 * dom/ElementAttributeData.cpp: 29 (WebCore::attrListMap): 30 (WebCore::attrListForElement): 31 (WebCore::ensureAttrListForElement): 32 (WebCore::removeAttrListForElement): 33 (WebCore::ElementAttributeData::attrIfExists): 34 (WebCore::ElementAttributeData::ensureAttr): 35 (WebCore::ElementAttributeData::setAttr): 36 (WebCore::ElementAttributeData::removeAttr): 37 (WebCore::ElementAttributeData::detachAttributesFromElement): 38 39 Map Element => per-Element AttrList in a global hash. 40 1 41 2012-05-08 Chris Guan <chris.guan@torchmobile.com.cn> 2 42 -
trunk/Source/WebCore/dom/ElementAttributeData.cpp
r115645 r116419 33 33 namespace WebCore { 34 34 35 typedef HashMap<pair<Element*, QualifiedName>, RefPtr<Attr> > AttrMap; 36 static AttrMap& attrMap() 37 { 38 DEFINE_STATIC_LOCAL(AttrMap, map, ()); 35 typedef Vector<RefPtr<Attr> > AttrList; 36 typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap; 37 38 static AttrListMap& attrListMap() 39 { 40 DEFINE_STATIC_LOCAL(AttrListMap, map, ()); 39 41 return map; 40 42 } 41 43 44 static AttrList* attrListForElement(Element* element) 45 { 46 ASSERT(element); 47 if (!element->hasAttrList()) 48 return false; 49 ASSERT(attrListMap().contains(element)); 50 return attrListMap().get(element); 51 } 52 53 static AttrList* ensureAttrListForElement(Element* element) 54 { 55 ASSERT(element); 56 if (element->hasAttrList()) { 57 ASSERT(attrListMap().contains(element)); 58 return attrListMap().get(element); 59 } 60 ASSERT(!attrListMap().contains(element)); 61 element->setHasAttrList(); 62 AttrListMap::AddResult result = attrListMap().add(element, adoptPtr(new AttrList)); 63 return result.iterator->second.get(); 64 } 65 66 static void removeAttrListForElement(Element* element) 67 { 68 ASSERT(element); 69 ASSERT(element->hasAttrList()); 70 ASSERT(attrListMap().contains(element)); 71 attrListMap().remove(element); 72 element->clearHasAttrList(); 73 } 74 75 static Attr* findAttrInList(AttrList* attrList, const QualifiedName& name) 76 { 77 for (unsigned i = 0; i < attrList->size(); ++i) { 78 if (attrList->at(i)->qualifiedName() == name) 79 return attrList->at(i).get(); 80 } 81 return 0; 82 } 83 42 84 PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) 43 85 { 44 if ( !m_attrCount)45 return 0;46 return attrMap().get(std::make_pair(element, name)).get();86 if (AttrList* attrList = attrListForElement(element)) 87 return findAttrInList(attrList, name); 88 return 0; 47 89 } 48 90 49 91 PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) 50 92 { 51 AttrMap::AddResult result = attrMap().add(std::make_pair(element, name), 0); 52 if (result.isNewEntry) { 53 result.iterator->second = Attr::create(element, name); 54 ++m_attrCount; 55 } 56 return result.iterator->second.get(); 93 AttrList* attrList = ensureAttrListForElement(element); 94 RefPtr<Attr> attr = findAttrInList(attrList, name); 95 if (!attr) { 96 attr = Attr::create(element, name); 97 attrList->append(attr); 98 } 99 return attr.release(); 57 100 } 58 101 59 102 void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) 60 103 { 61 ASSERT(!attrMap().contains(std::make_pair(element, name))); 62 attrMap().add(std::make_pair(element, name), attr); 104 AttrList* attrList = ensureAttrListForElement(element); 105 106 if (findAttrInList(attrList, name)) 107 return; 108 109 attrList->append(attr); 63 110 attr->attachToElement(element); 64 ++m_attrCount;65 111 } 66 112 67 113 void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) 68 114 { 69 ASSERT(attrMap().contains(std::make_pair(element, name))); 70 attrMap().remove(std::make_pair(element, name)); 71 --m_attrCount; 115 AttrList* attrList = attrListForElement(element); 116 ASSERT(attrList); 117 118 for (unsigned i = 0; i < attrList->size(); ++i) { 119 if (attrList->at(i)->qualifiedName() == name) { 120 attrList->remove(i); 121 if (attrList->isEmpty()) 122 removeAttrListForElement(element); 123 return; 124 } 125 } 126 127 ASSERT_NOT_REACHED(); 72 128 } 73 129 … … 171 227 void ElementAttributeData::detachAttributesFromElement(Element* element) 172 228 { 173 if (! m_attrCount)229 if (!element->hasAttrList()) 174 230 return; 175 231 … … 178 234 attr->detachFromElementWithValue(m_attributes[i].value()); 179 235 } 236 237 // The loop above should have cleaned out this element's Attr map. 238 ASSERT(!element->hasAttrList()); 180 239 } 181 240 -
trunk/Source/WebCore/dom/ElementAttributeData.h
r115645 r116419 107 107 108 108 ElementAttributeData() 109 : m_attrCount(0)110 109 { 111 110 } … … 126 125 AtomicString m_idForStyleResolution; 127 126 Vector<Attribute> m_attributes; 128 129 unsigned m_attrCount;130 127 }; 131 128 -
trunk/Source/WebCore/dom/Node.h
r116402 r116419 217 217 bool isShadowRoot() const { return getFlag(IsShadowRootFlag); } 218 218 bool inNamedFlow() const { return getFlag(InNamedFlowFlag); } 219 bool hasAttrList() const { return getFlag(HasAttrListFlag); } 219 220 220 221 Node* shadowAncestorNode() const; … … 330 331 void setInNamedFlow() { setFlag(InNamedFlowFlag); } 331 332 void clearInNamedFlow() { clearFlag(InNamedFlowFlag); } 333 334 void setHasAttrList() { setFlag(HasAttrListFlag); } 335 void clearHasAttrList() { clearFlag(HasAttrListFlag); } 332 336 333 337 enum ShouldSetAttached { … … 690 694 DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag, 691 695 #endif 692 InNamedFlowFlag = 1 << 29 696 InNamedFlowFlag = 1 << 29, 697 HasAttrListFlag = 1 << 30 693 698 }; 694 699 695 // 3bits remaining700 // 2 bits remaining 696 701 697 702 bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
Note: See TracChangeset
for help on using the changeset viewer.