Changeset 110172 in webkit


Ignore:
Timestamp:
Mar 8, 2012 9:42:28 AM (12 years ago)
Author:
caio.oliveira@openbossa.org
Message:

Make elements with attributes smaller by eliminating the m_element back pointer in NamedNodeMap
https://bugs.webkit.org/show_bug.cgi?id=75069

Reviewed by Ryosuke Niwa.

Source/WebCore:

NamedNodeMap is an exposed DOM representation of an element's attribute storage. As part of
its implementation it keeps a pointer to its associated Element plus all the attribute
storage.

This commit separate the two things: NamedNodeMap is now a wrapper to Element, containing
only the pointer, and the attribute storage is now owned by Element directly. Since usage
of NamedNodeMap is not very common, it can be stored in ElementRareData. As a result, most
elements with attributes now don't need to allocate memory for that extra pointer in
NamedNodeMap.

One consequence of this implementation is that now we explicitly don't support
DocumentType.notations and DocumentType.entities. They weren't supported before, a
NamedNodeMap was never created for those attributes -- and some NamedNodeMap functions
wouldn't work correctly without an associated Element.

NamedNodeMap itself was cleaned up, as well as unnecessary references to it removed in the
code and comments.

No new tests and should not change results for existing tests.

  • dom/Attribute.h:

(WebCore):

  • dom/DocumentType.h:

(DocumentType): Point out that we don't support does attributes yet.

  • dom/Element.cpp:

(WebCore::Element::~Element): Detaching the NamedNodeMap is no longer necessary because it
will be destroyed. We still detach the potential Attrs inside our Attributes by using
clearAttributes().
(WebCore::Element::attributes): Looks in ElementRareData now. Note we ensure the creation
of the attribute storage.
(WebCore):
(WebCore::Element::getAttribute):
(WebCore::Element::setAttributeInternal):
(WebCore::Element::parserSetAttributes):
(WebCore::Element::hasAttributes):
(WebCore::Element::createAttributeData):
(WebCore::Element::insertedIntoDocument):
(WebCore::Element::removedFromDocument):
(WebCore::Element::getURLAttribute):
(WebCore::Element::getNonEmptyURLAttribute):
(WebCore::Element::hasNamedNodeMap): Helper function for Node::dumpStatistics().

  • dom/Element.h:

(Element):
(WebCore::Element::attributeData):
(WebCore::Element::ensureAttributeData):
(WebCore::Element::fastHasAttribute):
(WebCore::Element::fastGetAttribute):
(WebCore::Element::hasAttributesWithoutUpdate):
(WebCore::Element::idForStyleResolution):
(WebCore::Element::attributeCount):
(WebCore::Element::attributeItem):
(WebCore::Element::getAttributeItem):

  • dom/ElementAttributeData.h:

(WebCore::ElementAttributeData::create):
(ElementAttributeData):

  • dom/ElementRareData.h:

(ElementRareData):

  • dom/NamedNodeMap.cpp: Rewriting now that m_attributeData is not a member, using m_element

methods when possible.
(WebCore::NamedNodeMap::ref):
(WebCore::NamedNodeMap::deref):
(WebCore::NamedNodeMap::getNamedItem):
(WebCore::NamedNodeMap::getNamedItemNS):
(WebCore::NamedNodeMap::removeNamedItem):
(WebCore::NamedNodeMap::removeNamedItemNS):
(WebCore::NamedNodeMap::setNamedItem):
(WebCore::NamedNodeMap::item):
(WebCore::NamedNodeMap::length):

  • dom/NamedNodeMap.h:

(WebCore):
(WebCore::NamedNodeMap::create):
(NamedNodeMap):
(WebCore::NamedNodeMap::NamedNodeMap): Instead of asserting m_element in every function, we
now assert only in the constructor.

  • dom/Node.cpp:

(WebCore::Node::dumpStatistics): Add a counter for elements with rare data, this allows us
compare more clearly the impact of moving NamedNodeMap there.
(WebCore::Node::isEqualNode): Remove use of mapsEquivalent(). It was dead code, because
both entities and notations were always NULL.
(WebCore::Node::compareDocumentPosition):

  • inspector/DOMPatchSupport.h:

(WebCore):

  • svg/SVGElement.cpp:

(WebCore::SVGElement::attributeChanged):

Source/WebKit/chromium:

  • src/WebElement.cpp: Include NamedNodeMap.h since Element.h doesn't include it anymore.
Location:
trunk/Source
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r110171 r110172  
     12012-03-08  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
     2
     3        Make elements with attributes smaller by eliminating the m_element back pointer in NamedNodeMap
     4        https://bugs.webkit.org/show_bug.cgi?id=75069
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        NamedNodeMap is an exposed DOM representation of an element's attribute storage. As part of
     9        its implementation it keeps a pointer to its associated Element plus all the attribute
     10        storage.
     11
     12        This commit separate the two things: NamedNodeMap is now a wrapper to Element, containing
     13        only the pointer, and the attribute storage is now owned by Element directly. Since usage
     14        of NamedNodeMap is not very common, it can be stored in ElementRareData. As a result, most
     15        elements with attributes now don't need to allocate memory for that extra pointer in
     16        NamedNodeMap.
     17
     18        One consequence of this implementation is that now we explicitly don't support
     19        DocumentType.notations and DocumentType.entities. They weren't supported before, a
     20        NamedNodeMap was never created for those attributes -- and some NamedNodeMap functions
     21        wouldn't work correctly without an associated Element.
     22
     23        NamedNodeMap itself was cleaned up, as well as unnecessary references to it removed in the
     24        code and comments.
     25
     26        No new tests and should not change results for existing tests.
     27
     28        * dom/Attribute.h:
     29        (WebCore):
     30        * dom/DocumentType.h:
     31        (DocumentType): Point out that we don't support does attributes yet.
     32        * dom/Element.cpp:
     33        (WebCore::Element::~Element): Detaching the NamedNodeMap is no longer necessary because it
     34        will be destroyed. We still detach the potential Attrs inside our Attributes by using
     35        clearAttributes().
     36        (WebCore::Element::attributes): Looks in ElementRareData now. Note we ensure the creation
     37        of the attribute storage.
     38        (WebCore):
     39        (WebCore::Element::getAttribute):
     40        (WebCore::Element::setAttributeInternal):
     41        (WebCore::Element::parserSetAttributes):
     42        (WebCore::Element::hasAttributes):
     43        (WebCore::Element::createAttributeData):
     44        (WebCore::Element::insertedIntoDocument):
     45        (WebCore::Element::removedFromDocument):
     46        (WebCore::Element::getURLAttribute):
     47        (WebCore::Element::getNonEmptyURLAttribute):
     48        (WebCore::Element::hasNamedNodeMap): Helper function for Node::dumpStatistics().
     49        * dom/Element.h:
     50        (Element):
     51        (WebCore::Element::attributeData):
     52        (WebCore::Element::ensureAttributeData):
     53        (WebCore::Element::fastHasAttribute):
     54        (WebCore::Element::fastGetAttribute):
     55        (WebCore::Element::hasAttributesWithoutUpdate):
     56        (WebCore::Element::idForStyleResolution):
     57        (WebCore::Element::attributeCount):
     58        (WebCore::Element::attributeItem):
     59        (WebCore::Element::getAttributeItem):
     60        * dom/ElementAttributeData.h:
     61        (WebCore::ElementAttributeData::create):
     62        (ElementAttributeData):
     63        * dom/ElementRareData.h:
     64        (ElementRareData):
     65        * dom/NamedNodeMap.cpp: Rewriting now that m_attributeData is not a member, using m_element
     66        methods when possible.
     67        (WebCore::NamedNodeMap::ref):
     68        (WebCore::NamedNodeMap::deref):
     69        (WebCore::NamedNodeMap::getNamedItem):
     70        (WebCore::NamedNodeMap::getNamedItemNS):
     71        (WebCore::NamedNodeMap::removeNamedItem):
     72        (WebCore::NamedNodeMap::removeNamedItemNS):
     73        (WebCore::NamedNodeMap::setNamedItem):
     74        (WebCore::NamedNodeMap::item):
     75        (WebCore::NamedNodeMap::length):
     76        * dom/NamedNodeMap.h:
     77        (WebCore):
     78        (WebCore::NamedNodeMap::create):
     79        (NamedNodeMap):
     80        (WebCore::NamedNodeMap::NamedNodeMap): Instead of asserting m_element in every function, we
     81        now assert only in the constructor.
     82        * dom/Node.cpp:
     83        (WebCore::Node::dumpStatistics): Add a counter for elements with rare data, this allows us
     84        compare more clearly the impact of moving NamedNodeMap there.
     85        (WebCore::Node::isEqualNode): Remove use of mapsEquivalent(). It was dead code, because
     86        both entities and notations were always NULL.
     87        (WebCore::Node::compareDocumentPosition):
     88        * inspector/DOMPatchSupport.h:
     89        (WebCore):
     90        * svg/SVGElement.cpp:
     91        (WebCore::SVGElement::attributeChanged):
     92
    1932012-03-08  Robin Cao  <robin.cao@torchmobile.com.cn>
    294
  • trunk/Source/WebCore/dom/Attribute.h

    r106769 r110172  
    3232class Attr;
    3333class Element;
    34 class NamedNodeMap;
    3534
    3635// This has no counterpart in DOM.
  • trunk/Source/WebCore/dom/DocumentType.h

    r104130 r110172  
    3838    }
    3939
     40    // FIXME: We never fill m_entities and m_notations. Current implementation of NamedNodeMap doesn't work without an associated Element yet.
    4041    NamedNodeMap* entities() const { return m_entities.get(); }
    4142    NamedNodeMap* notations() const { return m_notations.get(); }
  • trunk/Source/WebCore/dom/Element.cpp

    r110119 r110172  
    5353#include "MutationObserverInterestGroup.h"
    5454#include "MutationRecord.h"
     55#include "NamedNodeMap.h"
    5556#include "NodeList.h"
    5657#include "NodeRenderStyle.h"
     
    126127    if (shadowTree())
    127128        rareData()->m_shadowTree.clear();
    128     if (m_attributeMap)
    129         m_attributeMap->detachFromElement();
     129    if (m_attributeData)
     130        m_attributeData->clearAttributes();
    130131}
    131132
     
    200201}
    201202
     203NamedNodeMap* Element::attributes() const
     204{
     205    ensureUpdatedAttributeData();
     206    ElementRareData* rareData = const_cast<Element*>(this)->ensureRareData();
     207    if (NamedNodeMap* attributeMap = rareData->m_attributeMap.get())
     208        return attributeMap;
     209
     210    rareData->m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
     211    return rareData->m_attributeMap.get();
     212}
     213
    202214Node::NodeType Element::nodeType() const
    203215{
     
    220232#endif
    221233
    222     if (m_attributeMap) {
     234    if (m_attributeData) {
    223235        if (Attribute* attribute = getAttributeItem(name))
    224236            return attribute->value();
     
    597609#endif
    598610
    599     if (m_attributeMap) {
    600         if (Attribute* attribute = m_attributeMap->attributeData()->getAttributeItem(name, ignoreCase))
     611    if (m_attributeData) {
     612        if (Attribute* attribute = m_attributeData->getAttributeItem(name, ignoreCase))
    601613            return attribute->value();
    602614    }
     
    631643inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, bool notifyChanged)
    632644{
    633     ElementAttributeData* attributeData = &m_attributeMap->m_attributeData;
    634     Attribute* old = index != notFound ? attributeData->attributeItem(index) : 0;
     645    Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0;
    635646    if (value.isNull()) {
    636647        if (old)
    637             attributeData->removeAttribute(index, this);
     648            m_attributeData->removeAttribute(index, this);
    638649        return;
    639650    }
    640651
    641652    if (!old) {
    642         attributeData->addAttribute(Attribute::create(name, value), this);
     653        m_attributeData->addAttribute(Attribute::create(name, value), this);
    643654        return;
    644655    }
     
    734745    document()->incDOMTreeVersion();
    735746
    736     ASSERT(!m_attributeMap);
     747    ASSERT(!m_attributeData);
    737748
    738749    if (!attributeVector)
    739750        return;
    740751
    741     m_attributeMap = NamedNodeMap::create(this);
    742     ElementAttributeData* attributeData = m_attributeMap->attributeData();
    743     attributeData->m_attributes.swap(*attributeVector);
    744 
    745     m_attributeMap->m_element = this;
     752    createAttributeData();
     753    m_attributeData->m_attributes.swap(*attributeVector);
     754
    746755    // If the element is created as result of a paste or drag-n-drop operation
    747756    // we want to remove all the script and event handlers.
    748757    if (scriptingPermission == FragmentScriptingNotAllowed) {
    749758        unsigned i = 0;
    750         while (i < m_attributeMap->length()) {
    751             const QualifiedName& attributeName = attributeData->m_attributes[i]->name();
     759        while (i < m_attributeData->length()) {
     760            const QualifiedName& attributeName = m_attributeData->m_attributes[i]->name();
    752761            if (isEventHandlerAttribute(attributeName)) {
    753                 attributeData->m_attributes.remove(i);
     762                m_attributeData->m_attributes.remove(i);
    754763                continue;
    755764            }
    756765
    757             if (isAttributeToRemove(attributeName, attributeData->m_attributes[i]->value()))
    758                 attributeData->m_attributes[i]->setValue(nullAtom);
     766            if (isAttributeToRemove(attributeName, m_attributeData->m_attributes[i]->value()))
     767                m_attributeData->m_attributes[i]->setValue(nullAtom);
    759768            i++;
    760769        }
     
    762771
    763772    // Store the set of attributes that changed on the stack in case
    764     // attributeChanged mutates m_attributeMap.
     773    // attributeChanged mutates m_attributeData.
    765774    Vector<RefPtr<Attribute> > attributes;
    766     attributeData->copyAttributesToVector(attributes);
     775    m_attributeData->copyAttributesToVector(attributes);
    767776    for (Vector<RefPtr<Attribute> >::iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
    768777        attributeChanged(iter->get());
     
    772781{
    773782    updateInvalidAttributes();
    774     return m_attributeMap && m_attributeMap->length();
     783    return m_attributeData && m_attributeData->length();
    775784}
    776785
     
    824833}
    825834
    826 void Element::createAttributeMap() const
    827 {
    828     m_attributeMap = NamedNodeMap::create(const_cast<Element*>(this));
     835void Element::createAttributeData() const
     836{
     837    m_attributeData = ElementAttributeData::create();
    829838}
    830839
     
    879888        tree->insertedIntoDocument();
    880889
    881     if (m_attributeMap) {
     890    if (m_attributeData) {
    882891        if (hasID()) {
    883892            Attribute* idItem = getAttributeItem(document()->idAttributeName());
     
    895904void Element::removedFromDocument()
    896905{
    897     if (m_attributeMap) {
     906    if (m_attributeData) {
    898907        if (hasID()) {
    899908            Attribute* idItem = getAttributeItem(document()->idAttributeName());
     
    17901799{
    17911800#if !ASSERT_DISABLED
    1792     if (m_attributeMap) {
     1801    if (m_attributeData) {
    17931802        if (Attribute* attribute = getAttributeItem(name))
    17941803            ASSERT(isURLAttribute(attribute));
     
    18011810{
    18021811#if !ASSERT_DISABLED
    1803     if (m_attributeMap) {
     1812    if (m_attributeData) {
    18041813        if (Attribute* attribute = getAttributeItem(name))
    18051814            ASSERT(isURLAttribute(attribute));
     
    19691978#endif
    19701979
     1980#ifdef DUMP_NODE_STATISTICS
     1981bool Element::hasNamedNodeMap() const
     1982{
     1983    return hasRareData() && rareData()->m_attributeMap;
     1984}
     1985#endif
     1986
    19711987void Element::willModifyAttribute(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
    19721988{
  • trunk/Source/WebCore/dom/Element.h

    r110086 r110172  
    2828#include "CollectionType.h"
    2929#include "Document.h"
     30#include "ElementAttributeData.h"
    3031#include "FragmentScriptingPermission.h"
    3132#include "HTMLNames.h"
    32 #include "NamedNodeMap.h"
    3333#include "ScrollTypes.h"
    3434
     
    131131#endif
    132132
     133#ifdef DUMP_NODE_STATISTICS
     134    bool hasNamedNodeMap() const;
     135#endif
    133136    bool hasAttributes() const;
    134137    // This variant will not update the potentially invalid attributes. To be used when not interested
     
    230233    NamedNodeMap* attributes() const;
    231234
    232     NamedNodeMap* updatedAttributes() const;
    233 
    234235    // This method is called whenever an attribute is added, changed or removed.
    235236    virtual void attributeChanged(Attribute*);
     
    238239    void parserSetAttributes(PassOwnPtr<AttributeVector>, FragmentScriptingPermission);
    239240
    240     ElementAttributeData* attributeData() const { return m_attributeMap ? m_attributeMap->attributeData() : 0; }
     241    ElementAttributeData* attributeData() const { return m_attributeData.get(); }
    241242    ElementAttributeData* ensureAttributeData() const;
    242243    ElementAttributeData* updatedAttributeData() const;
     
    437438    bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
    438439
    439     void createAttributeMap() const;
     440    void createAttributeData() const;
    440441
    441442    virtual void updateStyleAttribute() const { }
     
    469470
    470471private:
    471     mutable OwnPtr<NamedNodeMap> m_attributeMap;
     472    mutable OwnPtr<ElementAttributeData> m_attributeData;
    472473};
    473474   
     
    529530}
    530531
    531 inline NamedNodeMap* Element::attributes() const
    532 {
    533     updateInvalidAttributes();
    534     if (!m_attributeMap)
    535         createAttributeMap();
    536     return m_attributeMap.get();
    537 }
    538 
    539 inline NamedNodeMap* Element::updatedAttributes() const
    540 {
    541     updateInvalidAttributes();
    542     return m_attributeMap.get();
    543 }
    544 
    545532inline ElementAttributeData* Element::ensureAttributeData() const
    546533{
    547     if (!m_attributeMap)
    548         createAttributeMap();
    549     return m_attributeMap->attributeData();
     534    if (!m_attributeData)
     535        createAttributeData();
     536    return m_attributeData.get();
    550537}
    551538
     
    607594{
    608595    ASSERT(fastAttributeLookupAllowed(name));
    609     return m_attributeMap && getAttributeItem(name);
     596    return m_attributeData && getAttributeItem(name);
    610597}
    611598
     
    613600{
    614601    ASSERT(fastAttributeLookupAllowed(name));
    615     if (m_attributeMap) {
     602    if (m_attributeData) {
    616603        if (Attribute* attribute = getAttributeItem(name))
    617604            return attribute->value();
     
    622609inline bool Element::hasAttributesWithoutUpdate() const
    623610{
    624     return m_attributeMap && !m_attributeMap->attributeData()->isEmpty();
     611    return m_attributeData && !m_attributeData->isEmpty();
    625612}
    626613
     
    628615{
    629616    ASSERT(hasID());
    630     return attributeData()->idForStyleResolution();
     617    return m_attributeData->idForStyleResolution();
    631618}
    632619
     
    657644inline size_t Element::attributeCount() const
    658645{
    659     ASSERT(m_attributeMap);
    660     return m_attributeMap->length();
     646    ASSERT(m_attributeData);
     647    return m_attributeData->length();
    661648}
    662649
    663650inline Attribute* Element::attributeItem(unsigned index) const
    664651{
    665     ASSERT(m_attributeMap);
    666     return m_attributeMap->attributeData()->attributeItem(index);
     652    ASSERT(m_attributeData);
     653    return m_attributeData->attributeItem(index);
    667654}
    668655
    669656inline Attribute* Element::getAttributeItem(const QualifiedName& name) const
    670657{
    671     ASSERT(m_attributeMap);
    672     return m_attributeMap->attributeData()->getAttributeItem(name);
     658    ASSERT(m_attributeData);
     659    return m_attributeData->getAttributeItem(name);
    673660}
    674661
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r110119 r110172  
    8383class ElementAttributeData {
    8484public:
     85    static PassOwnPtr<ElementAttributeData> create()
     86    {
     87        return adoptPtr(new ElementAttributeData);
     88    }
     89
    8590    ~ElementAttributeData();
    8691
     
    109114    Attribute* getAttributeItem(const QualifiedName& name) const { return m_attributes.getAttributeItem(name); }
    110115    size_t getAttributeItemIndex(const QualifiedName& name) const { return m_attributes.getAttributeItemIndex(name); }
     116    size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const;
    111117
    112118    // These functions do no error checking.
     
    123129private:
    124130    friend class Element;
    125     friend class NamedNodeMap;
    126131
    127132    ElementAttributeData()
     
    132137    void copyAttributesToVector(Vector<RefPtr<Attribute> >&);
    133138    Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const;
    134     size_t getAttributeItemIndex(const String& name, bool shouldIgnoreAttributeCase) const;
    135139    size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const;
    136140    void setAttributes(const ElementAttributeData& other, Element*);
  • trunk/Source/WebCore/dom/ElementRareData.h

    r109084 r110172  
    2727#include "Element.h"
    2828#include "HTMLCollection.h"
     29#include "NamedNodeMap.h"
    2930#include "NodeRareData.h"
    3031#include "ShadowTree.h"
     
    7071    OwnPtr<ClassList> m_classList;
    7172    OwnPtr<ShadowTree> m_shadowTree;
     73    OwnPtr<NamedNodeMap> m_attributeMap;
    7274
    7375    bool m_styleAffectedByEmpty;
  • trunk/Source/WebCore/dom/NamedNodeMap.cpp

    r110119 r110172  
    4343void NamedNodeMap::ref()
    4444{
    45     ASSERT(m_element);
    4645    m_element->ref();
    4746}
     
    4948void NamedNodeMap::deref()
    5049{
    51     ASSERT(m_element);
    5250    m_element->deref();
    5351}
     
    5553PassRefPtr<Node> NamedNodeMap::getNamedItem(const String& name) const
    5654{
    57     return m_attributeData.getAttributeNode(name, shouldIgnoreAttributeCase(m_element), m_element);
     55    return m_element->attributeData()->getAttributeNode(name, shouldIgnoreAttributeCase(m_element), m_element);
    5856}
    5957
    6058PassRefPtr<Node> NamedNodeMap::getNamedItemNS(const String& namespaceURI, const String& localName) const
    6159{
    62     return m_attributeData.getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), m_element);
     60    return m_element->attributeData()->getAttributeNode(QualifiedName(nullAtom, localName, namespaceURI), m_element);
    6361}
    6462
    6563PassRefPtr<Node> NamedNodeMap::removeNamedItem(const String& name, ExceptionCode& ec)
    6664{
    67     ASSERT(m_element);
     65    ElementAttributeData* attributeData = m_element->attributeData();
    6866
    69     size_t index = m_attributeData.getAttributeItemIndex(name, shouldIgnoreAttributeCase(m_element));
     67    size_t index = attributeData->getAttributeItemIndex(name, shouldIgnoreAttributeCase(m_element));
    7068    if (index == notFound) {
    7169        ec = NOT_FOUND_ERR;
     
    7371    }
    7472   
    75     return m_attributeData.takeAttribute(index, m_element);
     73    return attributeData->takeAttribute(index, m_element);
    7674}
    7775
    7876PassRefPtr<Node> NamedNodeMap::removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode& ec)
    7977{
    80     return removeNamedItem(QualifiedName(nullAtom, localName, namespaceURI), ec);
     78    ElementAttributeData* attributeData = m_element->attributeData();
     79
     80    size_t index = attributeData->getAttributeItemIndex(QualifiedName(nullAtom, localName, namespaceURI));
     81    if (index == notFound) {
     82        ec = NOT_FOUND_ERR;
     83        return 0;
     84    }
     85
     86    return attributeData->takeAttribute(index, m_element);
    8187}
    8288
    8389PassRefPtr<Node> NamedNodeMap::setNamedItem(Node* node, ExceptionCode& ec)
    8490{
    85     if (!m_element || !node) {
     91    if (!node) {
    8692        ec = NOT_FOUND_ERR;
    8793        return 0;
     
    102108}
    103109
    104 PassRefPtr<Node> NamedNodeMap::removeNamedItem(const QualifiedName& name, ExceptionCode& ec)
    105 {
    106     ASSERT(m_element);
    107 
    108     size_t index = m_attributeData.getAttributeItemIndex(name);
    109     if (index == notFound) {
    110         ec = NOT_FOUND_ERR;
    111         return 0;
    112     }
    113 
    114     return m_attributeData.takeAttribute(index, m_element);
    115 }
    116 
    117110PassRefPtr<Node> NamedNodeMap::item(unsigned index) const
    118111{
    119112    if (index >= length())
    120113        return 0;
    121 
    122     return m_attributeData.m_attributes[index]->createAttrIfNeeded(m_element);
     114    return m_element->attributeItem(index)->createAttrIfNeeded(m_element);
    123115}
    124116
    125 void NamedNodeMap::detachFromElement()
     117size_t NamedNodeMap::length() const
    126118{
    127     // This can't happen if the holder of the map is JavaScript, because we mark the
    128     // element if the map is alive. So it has no impact on web page behavior. Because
    129     // of that, we can simply clear all the attributes to avoid accessing stale
    130     // pointers to do things like create Attr objects.
    131     m_element = 0;
    132     m_attributeData.clearAttributes();
    133 }
    134 
    135 bool NamedNodeMap::mapsEquivalent(const NamedNodeMap* otherMap) const
    136 {
    137     if (!otherMap)
    138         return m_attributeData.isEmpty();
    139     return m_attributeData.isEquivalent(otherMap->attributeData());
     119    return m_element->attributeCount();
    140120}
    141121
  • trunk/Source/WebCore/dom/NamedNodeMap.h

    r110119 r110172  
    2626#define NamedNodeMap_h
    2727
    28 #include "ElementAttributeData.h"
    29 #include "SpaceSplitString.h"
     28#include <wtf/PassOwnPtr.h>
     29#include <wtf/PassRefPtr.h>
     30#include <wtf/text/WTFString.h>
    3031
    3132namespace WebCore {
    3233
    3334class Node;
     35class Element;
    3436
    3537typedef int ExceptionCode;
     
    3840    friend class Element;
    3941public:
    40     static PassOwnPtr<NamedNodeMap> create(Element* element = 0)
     42    static PassOwnPtr<NamedNodeMap> create(Element* element)
    4143    {
    4244        return adoptPtr(new NamedNodeMap(element));
     
    5456    PassRefPtr<Node> removeNamedItemNS(const String& namespaceURI, const String& localName, ExceptionCode&);
    5557
    56     PassRefPtr<Node> removeNamedItem(const QualifiedName& name, ExceptionCode&);
    5758    PassRefPtr<Node> setNamedItem(Node*, ExceptionCode&);
    5859    PassRefPtr<Node> setNamedItemNS(Node*, ExceptionCode&);
    5960
    6061    PassRefPtr<Node> item(unsigned index) const;
    61     size_t length() const { return m_attributeData.length(); }
    62 
    63     bool mapsEquivalent(const NamedNodeMap* otherMap) const;
    64 
    65     // These functions do no error checking.
    66     void addAttribute(PassRefPtr<Attribute> attribute) { m_attributeData.addAttribute(attribute, m_element); }
     62    size_t length() const;
    6763
    6864    Element* element() const { return m_element; }
    69 
    70     ElementAttributeData* attributeData() { return &m_attributeData; }
    71     const ElementAttributeData* attributeData() const { return &m_attributeData; }
    7265
    7366private:
     
    7568        : m_element(element)
    7669    {
     70        // Only supports NamedNodeMaps with Element associated, DocumentType.entities and DocumentType.notations are not supported yet.
     71        ASSERT(m_element);
    7772    }
    78 
    79     void detachFromElement();
    80     Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const { return m_attributeData.getAttributeItem(name, shouldIgnoreAttributeCase); }
    81 
    82     // FIXME: NamedNodeMap is being broken up into two classes, one containing data
    83     //        for elements with attributes, and one for exposure to the DOM.
    84     //        See <http://webkit.org/b/75069> for more information.
    85     ElementAttributeData m_attributeData;
    8673
    8774    Element* m_element;
  • trunk/Source/WebCore/dom/Node.cpp

    r110128 r110172  
    161161    size_t attributesWithAttr = 0;
    162162    size_t elementsWithAttributeStorage = 0;
     163    size_t elementsWithRareData = 0;
    163164    size_t elementsWithNamedNodeMap = 0;
    164165
     
    166167        Node* node = *it;
    167168
    168         if (node->hasRareData())
     169        if (node->hasRareData()) {
    169170            ++nodesWithRareData;
     171            if (node->isElementNode()) {
     172                ++elementsWithRareData;
     173                if (toElement(node)->hasNamedNodeMap())
     174                    ++elementsWithNamedNodeMap;
     175            }
     176        }
    170177
    171178        switch (node->nodeType()) {
     
    182189                    attributes += attributeData->length();
    183190                    ++elementsWithAttributeStorage;
    184                     // FIXME: This will change once attribute storage goes out of NamedNodeMap.
    185                     ++elementsWithNamedNodeMap;
    186191                    for (unsigned i = 0; i < attributeData->length(); ++i) {
    187192                        Attribute* attr = attributeData->attributeItem(i);
     
    273278    printf("  Number of Attributes with an Attr: %zu\n", attributesWithAttr);
    274279    printf("  Number of Elements with attribute storage: %zu [%zu]\n", elementsWithAttributeStorage, sizeof(ElementAttributeData));
     280    printf("  Number of Elements with RareData: %zu\n", elementsWithRareData);
    275281    printf("  Number of Elements with NamedNodeMap: %zu [%zu]\n", elementsWithNamedNodeMap, sizeof(NamedNodeMap));
    276282#endif
     
    18041810            return false;
    18051811
    1806         NamedNodeMap* entities = documentTypeThis->entities();
    1807         NamedNodeMap* otherEntities = documentTypeOther->entities();
    1808         if (!entities && otherEntities)
    1809             return false;
    1810         if (entities && !entities->mapsEquivalent(otherEntities))
    1811             return false;
    1812 
    1813         NamedNodeMap* notations = documentTypeThis->notations();
    1814         NamedNodeMap* otherNotations = documentTypeOther->notations();
    1815         if (!notations && otherNotations)
    1816             return false;
    1817         if (notations && !notations->mapsEquivalent(otherNotations))
    1818             return false;
     1812        // FIXME: We don't compare entities or notations because currently both are always empty.
    18191813    }
    18201814   
     
    21152109        // We are comparing two attributes on the same node. Crawl our attribute map and see which one we hit first.
    21162110        Element* owner1 = attr1->ownerElement();
    2117         owner1->updatedAttributes(); // Force update invalid attributes.
     2111        owner1->updatedAttributeData(); // Force update invalid attributes.
    21182112        unsigned length = owner1->attributeCount();
    21192113        for (unsigned i = 0; i < length; ++i) {
  • trunk/Source/WebCore/inspector/DOMPatchSupport.h

    r107399 r110172  
    4545class DOMEditor;
    4646class Document;
    47 class NamedNodeMap;
    4847class Node;
    4948
  • trunk/Source/WebCore/svg/SVGElement.cpp

    r109342 r110172  
    416416    // When an animated SVG property changes through SVG DOM, svgAttributeChanged() is called, not attributeChanged().
    417417    // Next time someone tries to access the XML attributes, the synchronization code starts. During that synchronization
    418     // SVGAnimatedPropertySynchronizer may call NamedNodeMap::removeAttribute(), which in turn calls attributeChanged().
     418    // SVGAnimatedPropertySynchronizer may call ElementAttributeData::removeAttribute(), which in turn calls attributeChanged().
    419419    // At this point we're not allowed to call svgAttributeChanged() again - it may lead to extra work being done, or crashes
    420420    // see bug https://bugs.webkit.org/show_bug.cgi?id=40994.
  • trunk/Source/WebKit/chromium/ChangeLog

    r110130 r110172  
     12012-03-08  Caio Marcelo de Oliveira Filho  <caio.oliveira@openbossa.org>
     2
     3        Make elements with attributes smaller by eliminating the m_element back pointer in NamedNodeMap
     4        https://bugs.webkit.org/show_bug.cgi?id=75069
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        * src/WebElement.cpp: Include NamedNodeMap.h since Element.h doesn't include it anymore.
     9
    1102012-03-07  Kent Tamura  <tkent@chromium.org>
    211
  • trunk/Source/WebKit/chromium/src/WebElement.cpp

    r102283 r110172  
    3535
    3636#include "Element.h"
     37#include "NamedNodeMap.h"
    3738#include "RenderBoxModelObject.h"
    3839#include "RenderObject.h"
Note: See TracChangeset for help on using the changeset viewer.