Changeset 148961 in webkit


Ignore:
Timestamp:
Apr 23, 2013 7:21:05 AM (11 years ago)
Author:
akling@apple.com
Message:

Speed up ElementData::getAttributeItem(), which is hot.
<http://webkit.org/b/115031>

Reviewed by Antti Koivisto.

From Blink r148622 by <cevans@chromium.org>.

The previous version had a couple of issues:

  • Incurred new WTF::Vector::operator[] checks.
  • Had a branch in _every_ loop iteration that checked whether the storage was Vector or array[] backed.

Both these issues are fixed, and CloneNodes.html seems reliably at +2%.
I also believe GetElement.html is maybe +1%.

For WebKit, also applied the same optimization to getAttributeItemIndex().

  • dom/Element.h:

(WebCore::ElementData::attributeBase):
(WebCore::ElementData::getAttributeItemIndex):
(WebCore::ElementData::getAttributeItem):
(WebCore::ElementData::attributeItem):

Location:
trunk/Source/WebCore
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r148956 r148961  
     12013-04-23  Andreas Kling  <akling@apple.com>
     2
     3        Speed up ElementData::getAttributeItem(), which is hot.
     4        <http://webkit.org/b/115031>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        From Blink r148622 by <cevans@chromium.org>.
     9
     10        The previous version had a couple of issues:
     11        - Incurred new WTF::Vector::operator[] checks.
     12        - Had a branch in _every_ loop iteration that checked whether the storage was Vector or array[] backed.
     13
     14        Both these issues are fixed, and CloneNodes.html seems reliably at +2%.
     15        I also believe GetElement.html is maybe +1%.
     16
     17        For WebKit, also applied the same optimization to getAttributeItemIndex().
     18
     19        * dom/Element.h:
     20        (WebCore::ElementData::attributeBase):
     21        (WebCore::ElementData::getAttributeItemIndex):
     22        (WebCore::ElementData::getAttributeItem):
     23        (WebCore::ElementData::attributeItem):
     24
    1252013-04-23  Antoine Quint  <graouts@apple.com>
    226
  • trunk/Source/WebCore/dom/Element.h

    r148921 r148961  
    111111#endif
    112112
     113    const Attribute* attributeBase() const;
    113114    const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    114115    size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
     
    941942}
    942943
     944inline const Attribute* ElementData::attributeBase() const
     945{
     946    if (m_isUnique)
     947        return static_cast<const UniqueElementData*>(this)->m_attributeVector.data();
     948    return static_cast<const ShareableElementData*>(this)->m_attributeArray;
     949}
     950
    943951inline const StylePropertySet* ElementData::presentationAttributeStyle() const
    944952{
     
    958966inline size_t ElementData::getAttributeItemIndex(const QualifiedName& name) const
    959967{
    960     for (unsigned i = 0; i < length(); ++i) {
    961         if (attributeItem(i)->name().matches(name))
     968    const Attribute* attributes = attributeBase();
     969    for (unsigned i = 0, count = length(); i < count; ++i) {
     970        if (attributes[i].name().matches(name))
    962971            return i;
    963972    }
     
    969978inline size_t ElementData::getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const
    970979{
    971     unsigned len = length();
     980    const Attribute* attributes = attributeBase();
    972981    bool doSlowCheck = shouldIgnoreAttributeCase;
    973 
    974     const AtomicString caseAdjustedName = shouldIgnoreAttributeCase ? name.lower() : name;
     982    const AtomicString& caseAdjustedName = shouldIgnoreAttributeCase ? name.lower() : name;
     983
    975984    // Optimize for the case where the attribute exists and its name exactly matches.
    976     for (unsigned i = 0; i < len; ++i) {
    977         const Attribute* attribute = attributeItem(i);
    978         if (!attribute->name().hasPrefix()) {
    979             if (caseAdjustedName == attribute->localName())
     985    for (unsigned i = 0, count = length(); i < count; ++i) {
     986        if (!attributes[i].name().hasPrefix()) {
     987            if (caseAdjustedName == attributes[i].localName())
    980988                return i;
    981989        } else
     
    990998inline const Attribute* ElementData::getAttributeItem(const QualifiedName& name) const
    991999{
    992     for (unsigned i = 0; i < length(); ++i) {
    993         if (attributeItem(i)->name().matches(name))
    994             return attributeItem(i);
     1000    const Attribute* attributes = attributeBase();
     1001    for (unsigned i = 0, count = length(); i < count; ++i) {
     1002        if (attributes[i].name().matches(name))
     1003            return &attributes[i];
    9951004    }
    9961005    return 0;
     
    10001009{
    10011010    ASSERT_WITH_SECURITY_IMPLICATION(index < length());
    1002     if (m_isUnique)
    1003         return &static_cast<const UniqueElementData*>(this)->m_attributeVector.at(index);
    1004     return &static_cast<const ShareableElementData*>(this)->m_attributeArray[index];
     1011    return attributeBase() + index;
    10051012}
    10061013
Note: See TracChangeset for help on using the changeset viewer.