Changeset 135421 in webkit


Ignore:
Timestamp:
Nov 21, 2012, 11:05:17 AM (12 years ago)
Author:
akling@apple.com
Message:

Make it possible for elements with different tag names to share attribute data.
<http://webkit.org/b/102845>

Reviewed by Antti Koivisto.

Allow all elements to share ElementAttributeData with one another. This means that the elements
in this hypothetical markup will all point to the same attribute data:

<div class="foo">

<span class="foo">

<hr class="foo"/>

</span>

</div>

This optimization happens at the expense of an old one. We no longer share attribute data
between elements that have presentation attributes, since they map to different CSS properties
depending on what tag they're attached to. These are mostly used in ye olde web 1.0 content
though, and we should prefer optimizing in favor of modern markup. The global cache for
presentation attribute style in StyledElement.cpp still prevents redundant parsing.

On the upside, excluding elements with presentation attributes from the data cache means that
we can move one pointer (m_presentationAttributeStyle) from ImmutableElementAttributeData
to MutableElementAttributeData.

800kB progression on Membuster3.

  • dom/Document.h:
  • dom/Document.cpp:

(WebCore::ImmutableAttributeDataCacheKey::ImmutableAttributeDataCacheKey):
(WebCore::ImmutableAttributeDataCacheKey::operator!=):
(WebCore::ImmutableAttributeDataCacheKey::hash):
(ImmutableAttributeDataCacheKey):
(WebCore::Document::cachedImmutableAttributeData):

  • dom/Element.cpp:

(WebCore::Element::parserSetAttributes):

Don't use the element's tag name in the key for the immutable attribute data cache.

(WebCore::Element::cloneAttributesFromElement):

Prevent cloneNode() from converting mutable attribute data to immutable if it has
presentation attributes.

  • dom/ElementAttributeData.cpp:

(WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData):

Add an assertion that mutable-to-immutable conversion never happens with presentation
attribute style present.

(WebCore::ElementAttributeData::ElementAttributeData):
(WebCore::MutableElementAttributeData::MutableElementAttributeData):
(WebCore::ElementAttributeData::reportMemoryUsage):

  • dom/ElementAttributeData.h:

(ElementAttributeData):
(MutableElementAttributeData):
(WebCore::ElementAttributeData::presentationAttributeStyle):
(WebCore):
(WebCore::ElementAttributeData::setPresentationAttributeStyle):

Move the RefPtr<StylePropertySet> that holds presentation attribute-derived style
from the common ElementAttributeData base class to MutableElementAttributeData.

  • dom/StyledElement.cpp:

(WebCore::StyledElement::attributeChanged):

Always dirty the presentation attribute style when a presentation attribute changes.

(WebCore::StyledElement::rebuildPresentationAttributeStyle):

Force promotion to mutable attribute data when it turns out that we need to hang a
StylePropertySet with the presentation attribute style off of it.

Location:
trunk/Source/WebCore
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r135419 r135421  
     12012-11-21  Andreas Kling  <akling@apple.com>
     2
     3        Make it possible for elements with different tag names to share attribute data.
     4        <http://webkit.org/b/102845>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Allow all elements to share ElementAttributeData with one another. This means that the elements
     9        in this hypothetical markup will all point to the same attribute data:
     10
     11            <div class="foo">
     12                <span class="foo">
     13                    <hr class="foo"/>
     14                </span>
     15            </div>
     16
     17        This optimization happens at the expense of an old one. We no longer share attribute data
     18        between elements that have presentation attributes, since they map to different CSS properties
     19        depending on what tag they're attached to. These are mostly used in ye olde web 1.0 content
     20        though, and we should prefer optimizing in favor of modern markup. The global cache for
     21        presentation attribute style in StyledElement.cpp still prevents redundant parsing.
     22
     23        On the upside, excluding elements with presentation attributes from the data cache means that
     24        we can move one pointer (m_presentationAttributeStyle) from ImmutableElementAttributeData
     25        to MutableElementAttributeData.
     26
     27        800kB progression on Membuster3.
     28
     29        * dom/Document.h:
     30        * dom/Document.cpp:
     31        (WebCore::ImmutableAttributeDataCacheKey::ImmutableAttributeDataCacheKey):
     32        (WebCore::ImmutableAttributeDataCacheKey::operator!=):
     33        (WebCore::ImmutableAttributeDataCacheKey::hash):
     34        (ImmutableAttributeDataCacheKey):
     35        (WebCore::Document::cachedImmutableAttributeData):
     36        * dom/Element.cpp:
     37        (WebCore::Element::parserSetAttributes):
     38
     39            Don't use the element's tag name in the key for the immutable attribute data cache.
     40
     41        (WebCore::Element::cloneAttributesFromElement):
     42
     43            Prevent cloneNode() from converting mutable attribute data to immutable if it has
     44            presentation attributes.
     45
     46        * dom/ElementAttributeData.cpp:
     47        (WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData):
     48
     49            Add an assertion that mutable-to-immutable conversion never happens with presentation
     50            attribute style present.
     51
     52        (WebCore::ElementAttributeData::ElementAttributeData):
     53        (WebCore::MutableElementAttributeData::MutableElementAttributeData):
     54        (WebCore::ElementAttributeData::reportMemoryUsage):
     55        * dom/ElementAttributeData.h:
     56        (ElementAttributeData):
     57        (MutableElementAttributeData):
     58        (WebCore::ElementAttributeData::presentationAttributeStyle):
     59        (WebCore):
     60        (WebCore::ElementAttributeData::setPresentationAttributeStyle):
     61
     62            Move the RefPtr<StylePropertySet> that holds presentation attribute-derived style
     63            from the common ElementAttributeData base class to MutableElementAttributeData.
     64
     65        * dom/StyledElement.cpp:
     66        (WebCore::StyledElement::attributeChanged):
     67
     68            Always dirty the presentation attribute style when a presentation attribute changes.
     69
     70        (WebCore::StyledElement::rebuildPresentationAttributeStyle):
     71
     72            Force promotion to mutable attribute data when it turns out that we need to hang a
     73            StylePropertySet with the presentation attribute style off of it.
     74
    1752012-11-21  Antti Koivisto  <antti@apple.com>
    276
  • trunk/Source/WebCore/dom/Document.cpp

    r135405 r135421  
    59145914class ImmutableAttributeDataCacheKey {
    59155915public:
    5916     ImmutableAttributeDataCacheKey(const QualifiedName& tagName, const Attribute* attributes, unsigned attributeCount)
    5917         : m_tagQName(tagName)
    5918         , m_attributes(attributes)
     5916    ImmutableAttributeDataCacheKey(const Attribute* attributes, unsigned attributeCount)
     5917        : m_attributes(attributes)
    59195918        , m_attributeCount(attributeCount)
    59205919    { }
     
    59225921    bool operator!=(const ImmutableAttributeDataCacheKey& other) const
    59235922    {
    5924         if (m_tagQName != other.m_tagQName)
    5925             return true;
    59265923        if (m_attributeCount != other.m_attributeCount)
    59275924            return true;
     
    59315928    unsigned hash() const
    59325929    {
    5933         unsigned attributeHash = StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute));
    5934         return WTF::pairIntHash(m_tagQName.localName().impl()->existingHash(), attributeHash);
     5930        return StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute));
    59355931    }
    59365932
    59375933private:
    5938     QualifiedName m_tagQName;
    59395934    const Attribute* m_attributes;
    59405935    unsigned m_attributeCount;
     
    59515946};
    59525947
    5953 PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const Element* element, const Vector<Attribute>& attributes)
     5948PassRefPtr<ElementAttributeData> Document::cachedImmutableAttributeData(const Vector<Attribute>& attributes)
    59545949{
    59555950    ASSERT(!attributes.isEmpty());
    59565951
    5957     ImmutableAttributeDataCacheKey cacheKey(element->tagQName(), attributes.data(), attributes.size());
     5952    ImmutableAttributeDataCacheKey cacheKey(attributes.data(), attributes.size());
    59585953    unsigned cacheHash = cacheKey.hash();
    59595954
     
    59715966        return attributeData.release();
    59725967
    5973     cacheIterator->value = adoptPtr(new ImmutableAttributeDataCacheEntry(ImmutableAttributeDataCacheKey(element->tagQName(), attributeData->immutableAttributeArray(), attributeData->length()), attributeData));
     5968    cacheIterator->value = adoptPtr(new ImmutableAttributeDataCacheEntry(ImmutableAttributeDataCacheKey(attributeData->immutableAttributeArray(), attributeData->length()), attributeData));
    59745969
    59755970    return attributeData.release();
  • trunk/Source/WebCore/dom/Document.h

    r135242 r135421  
    11571157    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
    11581158
    1159     PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Element*, const Vector<Attribute>&);
     1159    PassRefPtr<ElementAttributeData> cachedImmutableAttributeData(const Vector<Attribute>&);
    11601160
    11611161    void didRemoveAllPendingStylesheet();
  • trunk/Source/WebCore/dom/Element.cpp

    r135270 r135421  
    10231023
    10241024    // When the document is in parsing state, we cache immutable ElementAttributeData objects with the
    1025     // input attribute vector (and the tag name) as key. (This cache is held by Document.)
     1025    // input attribute vector as key. (This cache is held by Document.)
    10261026    if (!document() || !document()->parsing())
    10271027        m_attributeData = ElementAttributeData::createImmutable(filteredAttributes);
    10281028    else
    1029         m_attributeData = document()->cachedImmutableAttributeData(this, filteredAttributes);
     1029        m_attributeData = document()->cachedImmutableAttributeData(filteredAttributes);
    10301030
    10311031    // Iterate over the set of attributes we already have on the stack in case
     
    25642564
    25652565    // If 'other' has a mutable ElementAttributeData, convert it to an immutable one so we can share it between both elements.
    2566     // We can only do this if there is no CSSOM wrapper for other's inline style (the isMutable() check.)
    2567     if (other.m_attributeData->isMutable() && (!other.m_attributeData->inlineStyle() || !other.m_attributeData->inlineStyle()->isMutable()))
     2566    // We can only do this if there is no CSSOM wrapper for other's inline style, and there are no presentation attributes.
     2567    if (other.m_attributeData->isMutable()
     2568        && !other.m_attributeData->presentationAttributeStyle()
     2569        && (!other.m_attributeData->inlineStyle() || !other.m_attributeData->inlineStyle()->hasCSSOMWrapper()))
    25682570        const_cast<Element&>(other).m_attributeData = other.m_attributeData->makeImmutableCopy();
    25692571
  • trunk/Source/WebCore/dom/ElementAttributeData.cpp

    r135021 r135421  
    3434struct SameSizeAsElementAttributeData : public RefCounted<SameSizeAsElementAttributeData> {
    3535    unsigned bitfield;
    36     void* refPtrs[4];
     36    void* refPtrs[3];
    3737};
    3838
     
    7171    : ElementAttributeData(other, false)
    7272{
     73    ASSERT(!other.m_presentationAttributeStyle);
     74
    7375    if (other.m_inlineStyle) {
    7476        ASSERT(!other.m_inlineStyle->isMutable());
     
    8587    , m_presentationAttributeStyleIsDirty(other.m_presentationAttributeStyleIsDirty)
    8688    , m_styleAttributeIsDirty(other.m_styleAttributeIsDirty)
    87     , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
    8889    , m_classNames(other.m_classNames)
    8990    , m_idForStyleResolution(other.m_idForStyleResolution)
     
    9495MutableElementAttributeData::MutableElementAttributeData(const MutableElementAttributeData& other)
    9596    : ElementAttributeData(other, true)
     97    , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
    9698    , m_attributeVector(other.m_attributeVector)
    9799{
     
    162164    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM, actualSize);
    163165    info.addMember(m_inlineStyle);
    164     info.addMember(m_presentationAttributeStyle);
    165166    info.addMember(m_classNames);
    166167    info.addMember(m_idForStyleResolution);
    167     if (m_isMutable)
     168    if (m_isMutable) {
     169        info.addMember(presentationAttributeStyle());
    168170        info.addMember(mutableAttributeVector());
     171    }
    169172    for (unsigned i = 0, len = length(); i < len; i++)
    170173        info.addMember(*attributeItem(i));
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r135021 r135421  
    5757    const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); }
    5858
    59     const StylePropertySet* presentationAttributeStyle() const { return m_presentationAttributeStyle.get(); }
    60     void setPresentationAttributeStyle(PassRefPtr<StylePropertySet> style) const { m_presentationAttributeStyle = style; }
     59    const StylePropertySet* presentationAttributeStyle() const;
     60    void setPresentationAttributeStyle(PassRefPtr<StylePropertySet>) const;
    6161
    6262    size_t length() const;
     
    108108
    109109    mutable RefPtr<StylePropertySet> m_inlineStyle;
    110     mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
    111110    mutable SpaceSplitString m_classNames;
    112111    mutable AtomicString m_idForStyleResolution;
     
    144143    MutableElementAttributeData(const MutableElementAttributeData&);
    145144
     145    mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
    146146    Vector<Attribute, 4> m_attributeVector;
    147147};
     
    170170        return mutableAttributeVector().size();
    171171    return m_arraySize;
     172}
     173
     174inline const StylePropertySet* ElementAttributeData::presentationAttributeStyle() const
     175{
     176    if (!m_isMutable)
     177        return 0;
     178    return static_cast<const MutableElementAttributeData*>(this)->m_presentationAttributeStyle.get();
     179}
     180
     181inline void ElementAttributeData::setPresentationAttributeStyle(PassRefPtr<StylePropertySet> style) const
     182{
     183    ASSERT(m_isMutable);
     184    static_cast<const MutableElementAttributeData*>(this)->m_presentationAttributeStyle = style;
    172185}
    173186
  • trunk/Source/WebCore/dom/StyledElement.cpp

    r135101 r135421  
    162162        styleAttributeChanged(newValue);
    163163    else if (isPresentationAttribute(name)) {
    164         // Avoid dirtying the presentation attribute style if we're using shared attribute data with already generated style.
    165         if (attributeData()->isMutable() || !attributeData()->m_presentationAttributeStyle)
    166             attributeData()->m_presentationAttributeStyleIsDirty = true;
     164        attributeData()->m_presentationAttributeStyleIsDirty = true;
    167165        setNeedsStyleRecalc(InlineStyleChange);
    168166    }
     
    343341    }
    344342
    345     attributeData()->m_presentationAttributeStyleIsDirty = false;
    346     attributeData()->setPresentationAttributeStyle(style->isEmpty() ? 0 : style);
     343    // ImmutableElementAttributeData doesn't store presentation attribute style, so make sure we have a MutableElementAttributeData.
     344    ElementAttributeData* attributeData = mutableAttributeData();
     345
     346    attributeData->m_presentationAttributeStyleIsDirty = false;
     347    attributeData->setPresentationAttributeStyle(style->isEmpty() ? 0 : style);
    347348
    348349    if (!cacheHash || cacheIterator->value)
Note: See TracChangeset for help on using the changeset viewer.