Changeset 116419 in webkit


Ignore:
Timestamp:
May 8, 2012 7:09:37 AM (9 years ago)
Author:
kling@webkit.org
Message:

Shrink ElementAttributeData by factoring out Attr object count.
<http://webkit.org/b/85825>

Reviewed by Antti Koivisto.

Stop tracking the number of Attr objects that point to a given Element on the
Element itself and manage this by having a global hashmap of Element => AttrList,
where AttrList is a vector of (pointers to) the associated Attr objects.

This shrinks ElementAttributeData by one integer, effectively reducing memory
consumption by ~530kB when viewing the full HTML5 spec at <http://whatwg.org/c>.

  • dom/ElementAttributeData.h:

(ElementAttributeData):

Remove m_attrCount...

  • dom/Node.h:

(WebCore::Node::hasAttrList):
(WebCore::Node::setHasAttrList):
(WebCore::Node::clearHasAttrList):

...replacing it with a Node flag that tells us whether there's an Attr
object map for this Node (only applies to Elements.)

  • dom/ElementAttributeData.cpp:

(WebCore::attrListMap):
(WebCore::attrListForElement):
(WebCore::ensureAttrListForElement):
(WebCore::removeAttrListForElement):
(WebCore::ElementAttributeData::attrIfExists):
(WebCore::ElementAttributeData::ensureAttr):
(WebCore::ElementAttributeData::setAttr):
(WebCore::ElementAttributeData::removeAttr):
(WebCore::ElementAttributeData::detachAttributesFromElement):

Map Element => per-Element AttrList in a global hash.

Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r116418 r116419  
     12012-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
    1412012-05-08  Chris Guan  <chris.guan@torchmobile.com.cn>
    242
  • trunk/Source/WebCore/dom/ElementAttributeData.cpp

    r115645 r116419  
    3333namespace WebCore {
    3434
    35 typedef HashMap<pair<Element*, QualifiedName>, RefPtr<Attr> > AttrMap;
    36 static AttrMap& attrMap()
    37 {
    38     DEFINE_STATIC_LOCAL(AttrMap, map, ());
     35typedef Vector<RefPtr<Attr> > AttrList;
     36typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;
     37
     38static AttrListMap& attrListMap()
     39{
     40    DEFINE_STATIC_LOCAL(AttrListMap, map, ());
    3941    return map;
    4042}
    4143
     44static 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
     53static 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
     66static 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
     75static 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
    4284PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name)
    4385{
    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;
    4789}
    4890
    4991PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name)
    5092{
    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();
    57100}
    58101
    59102void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr)
    60103{
    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);
    63110    attr->attachToElement(element);
    64     ++m_attrCount;
    65111}
    66112
    67113void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name)
    68114{
    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();
    72128}
    73129
     
    171227void ElementAttributeData::detachAttributesFromElement(Element* element)
    172228{
    173     if (!m_attrCount)
     229    if (!element->hasAttrList())
    174230        return;
    175231
     
    178234            attr->detachFromElementWithValue(m_attributes[i].value());
    179235    }
     236
     237    // The loop above should have cleaned out this element's Attr map.
     238    ASSERT(!element->hasAttrList());
    180239}
    181240
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r115645 r116419  
    107107
    108108    ElementAttributeData()
    109         : m_attrCount(0)
    110109    {
    111110    }
     
    126125    AtomicString m_idForStyleResolution;
    127126    Vector<Attribute> m_attributes;
    128 
    129     unsigned m_attrCount;
    130127};
    131128
  • trunk/Source/WebCore/dom/Node.h

    r116402 r116419  
    217217    bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
    218218    bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
     219    bool hasAttrList() const { return getFlag(HasAttrListFlag); }
    219220
    220221    Node* shadowAncestorNode() const;
     
    330331    void setInNamedFlow() { setFlag(InNamedFlowFlag); }
    331332    void clearInNamedFlow() { clearFlag(InNamedFlowFlag); }
     333
     334    void setHasAttrList() { setFlag(HasAttrListFlag); }
     335    void clearHasAttrList() { clearFlag(HasAttrListFlag); }
    332336
    333337    enum ShouldSetAttached {
     
    690694        DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag,
    691695#endif
    692         InNamedFlowFlag = 1 << 29
     696        InNamedFlowFlag = 1 << 29,
     697        HasAttrListFlag = 1 << 30
    693698    };
    694699
    695     // 3 bits remaining
     700    // 2 bits remaining
    696701
    697702    bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
Note: See TracChangeset for help on using the changeset viewer.