Ignore:
Timestamp:
04/22/12 22:40:02 (2 years ago)
Author:
kling@webkit.org
Message:

Optimize Element attribute storage for the common case (no Attr objects.)
<http://webkit.org/b/83440>

Reviewed by Antti Koivisto.

Source/WebCore:

Reduce Attribute to its smallest possible size; a qname/value pair.
They are no-longer ref-counted, which allows us to store them in Vectors.

Refactored the DOM Attr object to go with the new Attribute:
Attr now wraps either {element, qname} or {qname, value}. The latter is for
the case where a standalone Attr object is instantiated via DOM APIs.

ElementAttributeData.cpp manages a map of pair<element, qname> => Attr.
Each Element (well, ElementAttributeData) keeps track of how many Attr
objects are pointing to it. This is so we can avoid hash lookups during
common operations in the typical case where you have zero Attrs.

Also removed the inline capacity (was 4) from AttributeVector as that
would significantly increase bloat now that we store Attribute (2 pointers)
rather than RefPtr<Attribute>. We trade this one piece of indirection
for the removal of per-Attribute indirection.

  • CMakeLists.txt:
  • GNUmakefile.list.am:
  • Target.pri:
  • WebCore.gypi:
  • WebCore.vcproj/WebCore.vcproj:
  • WebCore.xcodeproj/project.pbxproj:
  • dom/Attr.cpp:

(WebCore::Attr::Attr):
(WebCore):
(WebCore::Attr::create):
(WebCore::Attr::~Attr):
(WebCore::Attr::createTextChild):
(WebCore::Attr::setPrefix):
(WebCore::Attr::setValue):
(WebCore::Attr::cloneNode):
(WebCore::Attr::childrenChanged):
(WebCore::Attr::style):
(WebCore::Attr::value):
(WebCore::Attr::elementAttribute):
(WebCore::Attr::detachFromElementWithValue):
(WebCore::Attr::attachToElement):

  • dom/Attr.h:

(WebCore):
(Attr):
(WebCore::Attr::qualifiedName):
(WebCore::Attr::localName):
(WebCore::Attr::namespaceURI):
(WebCore::Attr::prefix):

  • dom/Attribute.cpp: Removed.
  • dom/Attribute.h:

(WebCore::Attribute::Attribute):
(Attribute):

  • dom/Document.cpp:

(WebCore::Document::importNode):
(WebCore::Document::createAttributeNS):

  • dom/Element.cpp:

(WebCore::Element::~Element):
(WebCore::Element::detachAttribute):
(WebCore):
(WebCore::Element::removeAttribute):
(WebCore::Element::setAttributeInternal):
(WebCore::Element::parserSetAttributes):
(WebCore::Element::setAttributeNode):
(WebCore::Element::removeAttributeNode):
(WebCore::Element::normalizeAttributes):
(WebCore::Element::didRemoveAttribute):
(WebCore::Element::attrIfExists):
(WebCore::Element::ensureAttr):

  • dom/Element.h:

(Element):
(WebCore::Element::getAttributeItemIndex):

  • dom/ElementAttributeData.cpp:

(WebCore):
(WebCore::attrMap):
(WebCore::ElementAttributeData::attrIfExists):
(WebCore::ElementAttributeData::ensureAttr):
(WebCore::ElementAttributeData::setAttr):
(WebCore::ElementAttributeData::removeAttr):
(WebCore::AttributeVector::removeAttribute):
(WebCore::ElementAttributeData::~ElementAttributeData):
(WebCore::ElementAttributeData::addAttribute):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::isEquivalent):
(WebCore::ElementAttributeData::detachAttributesFromElement):
(WebCore::ElementAttributeData::getAttributeItemIndexSlowCase):
(WebCore::ElementAttributeData::setAttributes):
(WebCore::ElementAttributeData::clearAttributes):
(WebCore::ElementAttributeData::replaceAttribute):
(WebCore::ElementAttributeData::getAttributeNode):

  • dom/ElementAttributeData.h:

(WebCore):
(WebCore::AttributeVector::AttributeVector):
(AttributeVector):
(WebCore::AttributeVector::getAttributeItem):
(WebCore::AttributeVector::getAttributeItemIndex):
(WebCore::AttributeVector::insertAttribute):
(WebCore::ElementAttributeData::attributeItem):
(ElementAttributeData):
(WebCore::ElementAttributeData::ElementAttributeData):
(WebCore::ElementAttributeData::attributeVector):
(WebCore::ElementAttributeData::clonedAttributeVector):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::getAttributeItem):
(WebCore::ElementAttributeData::getAttributeItemIndex):

  • dom/NamedNodeMap.cpp:

(WebCore::NamedNodeMap::getNamedItem):
(WebCore::NamedNodeMap::getNamedItemNS):
(WebCore::NamedNodeMap::removeNamedItem):
(WebCore::NamedNodeMap::removeNamedItemNS):
(WebCore::NamedNodeMap::item):

  • dom/Node.cpp:

(WebCore::Node::compareDocumentPosition):

  • html/HTMLAnchorElement.cpp:

(WebCore::HTMLAnchorElement::parseAttribute):

  • html/HTMLSelectElement.cpp:

(WebCore::HTMLSelectElement::parseAttribute):

  • html/parser/HTMLConstructionSite.cpp:

(WebCore::HTMLConstructionSite::insertHTMLHtmlStartTagBeforeHTML):
(WebCore::HTMLConstructionSite::mergeAttributesFromTokenIntoElement):
(WebCore::HTMLConstructionSite::insertScriptElement):
(WebCore::HTMLConstructionSite::createElement):
(WebCore::HTMLConstructionSite::createHTMLElement):
(WebCore::HTMLConstructionSite::createHTMLElementFromSavedElement):

  • html/parser/HTMLToken.h:

(WebCore::AtomicHTMLToken::AtomicHTMLToken):

  • html/parser/HTMLTreeBuilder.cpp:

(WebCore::HTMLTreeBuilder::processFakeStartTag):
(WebCore::HTMLTreeBuilder::attributesForIsindexInput):
(WebCore::HTMLTreeBuilder::processIsindexStartTagForInBody):
(WebCore):
(WebCore::HTMLTreeBuilder::processStartTagForInBody):

  • html/parser/HTMLTreeBuilder.h:
  • html/parser/TextDocumentParser.cpp:

(WebCore::TextDocumentParser::insertFakePreElement):

  • page/PageSerializer.cpp:

(WebCore::SerializerMarkupAccumulator::appendCustomAttributes):

  • svg/SVGFitToViewBox.cpp:
  • svg/properties/SVGAnimatedPropertySynchronizer.h:
  • xml/XMLErrors.cpp:

(WebCore::createXHTMLParserErrorHeader):
(WebCore::XMLErrors::insertErrorMessageBlock):

  • xml/XPathNodeSet.cpp:

(WebCore::XPath::NodeSet::traversalSort):

  • xml/XPathStep.cpp:

(WebCore::XPath::Step::nodesInAxis):

  • xml/parser/MarkupTokenBase.h:

(WebCore::AtomicMarkupTokenBase::AtomicMarkupTokenBase):
(WebCore::AtomicMarkupTokenBase::getAttributeItem):
(WebCore::AtomicMarkupTokenBase::attributes):
(AtomicMarkupTokenBase):
(WebCore::::initializeAttributes):

  • xml/parser/XMLToken.h:

(WebCore::AtomicXMLToken::AtomicXMLToken):

  • xml/parser/XMLTreeBuilder.cpp:

(WebCore::XMLTreeBuilder::processNamespaces):
(WebCore::XMLTreeBuilder::processAttributes):

Source/WebKit/chromium:

Remove the WebNamedNodeMap and WebAttribute API classes since they are no
longer needed by chromium after <http://crrev.com/133299>.

  • WebKit.gyp:
  • public/WebAttribute.h: Removed.
  • public/WebElement.h:
  • public/WebNamedNodeMap.h: Removed.
  • src/WebAttribute.cpp: Removed.
  • src/WebElement.cpp:
  • src/WebNamedNodeMap.cpp: Removed.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r114700 r114870  
    2727#define ElementAttributeData_h 
    2828 
    29 #include "Attr.h" 
    3029#include "Attribute.h" 
    3130#include "SpaceSplitString.h" 
     
    3534namespace WebCore { 
    3635 
     36class Attr; 
    3737class Element; 
    3838 
    39 class AttributeVector : public Vector<RefPtr<Attribute>, 4> { 
    40     friend class ElementAttributeData; 
     39class AttributeVector : public Vector<Attribute> { 
     40public: 
     41    AttributeVector() { } 
    4142 
    42 public: 
    43     static PassOwnPtr<AttributeVector> create() 
    44     { 
    45         return adoptPtr(new AttributeVector()); 
    46     } 
    47  
    48     Attribute* attributeItem(unsigned index) const { return at(index).get(); } 
    4943    Attribute* getAttributeItem(const QualifiedName&) const; 
    5044    size_t getAttributeItemIndex(const QualifiedName&) const; 
    5145 
    5246    // Used during parsing: only inserts if not already there. 
    53     void insertAttribute(PassRefPtr<Attribute> newAttribute); 
     47    void insertAttribute(const Attribute&); 
    5448    void removeAttribute(const QualifiedName&); 
    55  
    56 private: 
    57     AttributeVector() { } 
    5849}; 
    5950 
     
    6253    size_t index = getAttributeItemIndex(name); 
    6354    if (index != notFound) 
    64         return at(index).get(); 
     55        return &const_cast<AttributeVector*>(this)->at(index); 
    6556    return 0; 
    6657} 
     
    6960{ 
    7061    for (unsigned i = 0; i < size(); ++i) { 
    71         if (at(i)->name().matches(name)) 
     62        if (at(i).name().matches(name)) 
    7263            return i; 
    7364    } 
     
    7566} 
    7667 
    77 inline void AttributeVector::insertAttribute(PassRefPtr<Attribute> newAttribute) 
     68inline void AttributeVector::insertAttribute(const Attribute& newAttribute) 
    7869{ 
    79     if (!getAttributeItem(newAttribute->name())) 
     70    if (!getAttributeItem(newAttribute.name())) 
    8071        append(newAttribute); 
    8172} 
     
    116107 
    117108    // Internal interface. 
    118     Attribute* attributeItem(unsigned index) const { return m_attributes.attributeItem(index); } 
     109    Attribute* attributeItem(unsigned index) const { return &const_cast<ElementAttributeData*>(this)->m_attributes[index]; } 
    119110    Attribute* getAttributeItem(const QualifiedName& name) const { return m_attributes.getAttributeItem(name); } 
    120111    size_t getAttributeItemIndex(const QualifiedName& name) const { return m_attributes.getAttributeItemIndex(name); } 
     
    122113 
    123114    // These functions do no error checking. 
    124     void addAttribute(PassRefPtr<Attribute>, Element*, EInUpdateStyleAttribute = NotInUpdateStyleAttribute); 
     115    void addAttribute(const Attribute&, Element*, EInUpdateStyleAttribute = NotInUpdateStyleAttribute); 
    125116    void removeAttribute(const QualifiedName&, Element*); 
    126117    void removeAttribute(size_t index, Element*, EInUpdateStyleAttribute = NotInUpdateStyleAttribute); 
     
    132123    bool isEquivalent(const ElementAttributeData* other) const; 
    133124 
     125    void setAttr(Element*, const QualifiedName&, Attr*); 
     126    void removeAttr(Element*, const QualifiedName&); 
     127    PassRefPtr<Attr> attrIfExists(Element*, const QualifiedName&); 
     128    PassRefPtr<Attr> ensureAttr(Element*, const QualifiedName&); 
     129 
    134130private: 
    135131    friend class Element; 
     132    friend class HTMLConstructionSite; 
    136133 
    137134    ElementAttributeData() 
     135        : m_attrCount(0) 
    138136    { 
    139137    } 
    140138 
    141     void detachAttributesFromElement(); 
    142     void copyAttributesToVector(Vector<RefPtr<Attribute> >&); 
     139    const AttributeVector& attributeVector() const { return m_attributes; } 
     140    AttributeVector clonedAttributeVector() const { return m_attributes; } 
     141 
     142    void detachAttributesFromElement(Element*); 
    143143    Attribute* getAttributeItem(const String& name, bool shouldIgnoreAttributeCase) const; 
    144144    size_t getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const; 
    145145    void setAttributes(const ElementAttributeData& other, Element*); 
    146     void clearAttributes(); 
    147     void replaceAttribute(size_t index, PassRefPtr<Attribute>, Element*); 
     146    void clearAttributes(Element*); 
     147    void replaceAttribute(size_t index, const Attribute&, Element*); 
    148148 
    149149    RefPtr<StylePropertySet> m_inlineStyleDecl; 
     
    152152    AtomicString m_idForStyleResolution; 
    153153    AttributeVector m_attributes; 
     154 
     155    unsigned m_attrCount; 
    154156}; 
    155157 
     
    161163 
    162164    removeAttribute(index, element); 
    163 } 
    164  
    165 inline PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const String& name, bool shouldIgnoreAttributeCase, Element* element) const 
    166 { 
    167     ASSERT(element); 
    168     Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase); 
    169     if (!attribute) 
    170         return 0; 
    171     return attribute->createAttrIfNeeded(element); 
    172 } 
    173  
    174 inline PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const QualifiedName& name, Element* element) const 
    175 { 
    176     ASSERT(element); 
    177     Attribute* attribute = getAttributeItem(name); 
    178     if (!attribute) 
    179         return 0; 
    180     return attribute->createAttrIfNeeded(element); 
     165    return; 
    181166} 
    182167 
     
    185170    size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase); 
    186171    if (index != notFound) 
    187         return m_attributes[index].get(); 
     172        return &const_cast<ElementAttributeData*>(this)->m_attributes[index]; 
    188173    return 0; 
    189174} 
     
    198183    // Optimize for the case where the attribute exists and its name exactly matches. 
    199184    for (unsigned i = 0; i < len; ++i) { 
    200         const QualifiedName& attrName = m_attributes[i]->name(); 
    201         if (!attrName.hasPrefix()) { 
    202             if (name == attrName.localName()) 
     185        if (!m_attributes[i].name().hasPrefix()) { 
     186            if (name == m_attributes[i].localName()) 
    203187                return i; 
    204188        } else 
Note: See TracChangeset for help on using the changeset viewer.