Changeset 133286 in webkit


Ignore:
Timestamp:
Nov 2, 2012 5:09:27 AM (11 years ago)
Author:
kling@webkit.org
Message:

Only resolve attribute-derived style once per shared ElementAttributeData.
<http://webkit.org/b/100990>

Reviewed by Antti Koivisto.

Track the serialization of the "style" attribute, and the dirtiness of the presentation attribute style
on ElementAttributeData instead of in Node flags.

This allows us to avoid duplicate work for ElementAttributeData that are shared between multiple elements,
since the state is no longer per-Element.

I've left the presentation attribute cache in there for now, since it covers two additional cases:

  • Elements with the same attributes in different order.
  • Elements with the same presentation attributes, but with differing non-presentation attributes.

It's likely that we're not gaining much from it anymore, but that's a topic for another patch.

  • dom/Node.h:
  • dom/ElementAttributeData.h:

(WebCore::ElementAttributeData::presentationAttributeStyle):
(WebCore::ElementAttributeData::setPresentationAttributeStyle):
(WebCore::ElementAttributeData::styleAttributeIsDirty):
(WebCore::ElementAttributeData::setStyleAttributeIsDirty):
(WebCore::ElementAttributeData::presentationAttributeStyleIsDirty):
(WebCore::ElementAttributeData::setPresentationAttributeStyleIsDirty):
(ElementAttributeData):
(WebCore::ElementAttributeData::ElementAttributeData):

  • dom/Element.cpp:

(WebCore::Element::getAttribute):

  • dom/Element.h:

(WebCore::Element::styleAttributeIsDirty):
(WebCore::Element::updateInvalidAttributes):

  • dom/StyledElement.cpp:

(WebCore::StyledElement::updateStyleAttribute):
(WebCore::StyledElement::attributeChanged):
(WebCore::StyledElement::styleAttributeChanged):
(WebCore::StyledElement::inlineStyleChanged):

  • dom/StyledElement.h:

(WebCore::StyledElement::invalidateStyleAttribute):

Move the "attribute style dirty" and "style attribute valid" node flags to ElementAttributeData
and change them to both use dirty semantics.

  • dom/ElementAttributeData.cpp:

(WebCore::ElementAttributeData::cloneDataFrom):

Share the presentation attribute style between cloned elements initially.

  • dom/StyledElement.h:

(WebCore::StyledElement::presentationAttributeStyle):

  • css/StyleResolver.cpp:

(WebCore::StyleResolver::sweepMatchedPropertiesCache):
(WebCore::StyleResolver::matchAllRules):
(WebCore::StyleResolver::canShareStyleWithElement):

  • dom/ElementAttributeData.cpp:

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

  • inspector/InspectorCSSAgent.cpp:

(WebCore::InspectorCSSAgent::buildObjectForAttributesStyle):

Renamed StyledElement::attributeStyle() to presentationAttributeStyle(). The old name was too
easily confused with "style attribute".

  • dom/StyledElement.cpp:

(WebCore::StyledElement::rebuildPresentationAttributeStyle):

Renamed from updateAttributeStyle().

Location:
trunk/Source/WebCore
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r133284 r133286  
     12012-11-02  Andreas Kling  <kling@webkit.org>
     2
     3        Only resolve attribute-derived style once per shared ElementAttributeData.
     4        <http://webkit.org/b/100990>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Track the serialization of the "style" attribute, and the dirtiness of the presentation attribute style
     9        on ElementAttributeData instead of in Node flags.
     10
     11        This allows us to avoid duplicate work for ElementAttributeData that are shared between multiple elements,
     12        since the state is no longer per-Element.
     13
     14        I've left the presentation attribute cache in there for now, since it covers two additional cases:
     15
     16            - Elements with the same attributes in different order.
     17            - Elements with the same presentation attributes, but with differing non-presentation attributes.
     18
     19        It's likely that we're not gaining much from it anymore, but that's a topic for another patch.
     20
     21        * dom/Node.h:
     22        * dom/ElementAttributeData.h:
     23        (WebCore::ElementAttributeData::presentationAttributeStyle):
     24        (WebCore::ElementAttributeData::setPresentationAttributeStyle):
     25        (WebCore::ElementAttributeData::styleAttributeIsDirty):
     26        (WebCore::ElementAttributeData::setStyleAttributeIsDirty):
     27        (WebCore::ElementAttributeData::presentationAttributeStyleIsDirty):
     28        (WebCore::ElementAttributeData::setPresentationAttributeStyleIsDirty):
     29        (ElementAttributeData):
     30        (WebCore::ElementAttributeData::ElementAttributeData):
     31        * dom/Element.cpp:
     32        (WebCore::Element::getAttribute):
     33        * dom/Element.h:
     34        (WebCore::Element::styleAttributeIsDirty):
     35        (WebCore::Element::updateInvalidAttributes):
     36        * dom/StyledElement.cpp:
     37        (WebCore::StyledElement::updateStyleAttribute):
     38        (WebCore::StyledElement::attributeChanged):
     39        (WebCore::StyledElement::styleAttributeChanged):
     40        (WebCore::StyledElement::inlineStyleChanged):
     41        * dom/StyledElement.h:
     42        (WebCore::StyledElement::invalidateStyleAttribute):
     43
     44            Move the "attribute style dirty" and "style attribute valid" node flags to ElementAttributeData
     45            and change them to both use dirty semantics.
     46
     47        * dom/ElementAttributeData.cpp:
     48        (WebCore::ElementAttributeData::cloneDataFrom):
     49
     50            Share the presentation attribute style between cloned elements initially.
     51
     52        * dom/StyledElement.h:
     53        (WebCore::StyledElement::presentationAttributeStyle):
     54        * css/StyleResolver.cpp:
     55        (WebCore::StyleResolver::sweepMatchedPropertiesCache):
     56        (WebCore::StyleResolver::matchAllRules):
     57        (WebCore::StyleResolver::canShareStyleWithElement):
     58        * dom/ElementAttributeData.cpp:
     59        (WebCore::MutableElementAttributeData::MutableElementAttributeData):
     60        (WebCore::ElementAttributeData::reportMemoryUsage):
     61        * inspector/InspectorCSSAgent.cpp:
     62        (WebCore::InspectorCSSAgent::buildObjectForAttributesStyle):
     63
     64            Renamed StyledElement::attributeStyle() to presentationAttributeStyle(). The old name was too
     65            easily confused with "style attribute".
     66
     67        * dom/StyledElement.cpp:
     68        (WebCore::StyledElement::rebuildPresentationAttributeStyle):
     69
     70            Renamed from updateAttributeStyle().
     71
    1722012-11-01  Kent Tamura  <tkent@chromium.org>
    273
  • trunk/Source/WebCore/css/StyleResolver.cpp

    r133227 r133286  
    479479{
    480480    // Look for cache entries containing a style declaration with a single ref and remove them.
    481     // This may happen when an element attribute mutation causes it to generate a new attributeStyle(),
     481    // This may happen when an element attribute mutation causes it to generate a new presentationAttributeStyle(),
    482482    // potentially leaving this cache with the last ref on the old one.
    483483    Vector<unsigned, 16> toRemove;
     
    928928    // Now check author rules, beginning first with presentational attributes mapped from HTML.
    929929    if (m_styledElement) {
    930         addElementStyleProperties(result, m_styledElement->attributeStyle());
     930        addElementStyleProperties(result, m_styledElement->presentationAttributeStyle());
    931931
    932932        // Now we check additional mapped declarations.
     
    11801180        return false;
    11811181#endif
    1182     if (!!element->attributeStyle() != !!m_styledElement->attributeStyle())
     1182    if (!!element->presentationAttributeStyle() != !!m_styledElement->presentationAttributeStyle())
    11831183        return false;
    11841184    const StylePropertySet* additionalAttributeStyleA = element->additionalAttributeStyle();
     
    12711271    }
    12721272
    1273     if (element->attributeStyle() && !attributeStylesEqual(element->attributeStyle(), m_styledElement->attributeStyle()))
     1273    if (element->presentationAttributeStyle() && !attributeStylesEqual(element->presentationAttributeStyle(), m_styledElement->presentationAttributeStyle()))
    12741274        return false;
    12751275
  • trunk/Source/WebCore/dom/Element.cpp

    r133275 r133286  
    262262const AtomicString& Element::getAttribute(const QualifiedName& name) const
    263263{
    264     if (UNLIKELY(name == styleAttr) && !isStyleAttributeValid())
     264    if (UNLIKELY(name == styleAttr) && styleAttributeIsDirty())
    265265        updateStyleAttribute();
    266266
     
    620620
    621621    // Update the 'style' attribute if it's invalid and being requested:
    622     if (!isStyleAttributeValid() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
     622    if (styleAttributeIsDirty() && equalPossiblyIgnoringCase(name, styleAttr.localName(), ignoreCase))
    623623        updateStyleAttribute();
    624624
  • trunk/Source/WebCore/dom/Element.h

    r133275 r133286  
    44 *           (C) 2001 Peter Kelly (pmk@post.com)
    55 *           (C) 2001 Dirk Mueller (mueller@kde.org)
    6  * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
     6 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
    77 *
    88 * This library is free software; you can redistribute it and/or
     
    466466    void classAttributeChanged(const AtomicString& newClassString);
    467467
     468    bool styleAttributeIsDirty() const;
     469
    468470private:
    469471    // FIXME: Remove the need for Attr to call willModifyAttribute/didModifyAttribute.
     
    729731}
    730732
     733inline bool Element::styleAttributeIsDirty() const
     734{
     735    return m_attributeData && m_attributeData->styleAttributeIsDirty();
     736}
     737
    731738inline void Element::updateInvalidAttributes() const
    732739{
    733     if (!isStyleAttributeValid())
     740    if (styleAttributeIsDirty())
    734741        updateStyleAttribute();
    735742
  • trunk/Source/WebCore/dom/ElementAttributeData.cpp

    r133160 r133286  
    6464
    6565    m_inlineStyleDecl = baseOther.m_inlineStyleDecl;
    66     m_attributeStyle = baseOther.m_attributeStyle;
     66    m_presentationAttributeStyle = baseOther.m_presentationAttributeStyle;
    6767    m_classNames = baseOther.m_classNames;
    6868    m_idForStyleResolution = baseOther.m_idForStyleResolution;
     
    278278    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::DOM, actualSize);
    279279    info.addMember(m_inlineStyleDecl);
    280     info.addMember(m_attributeStyle);
     280    info.addMember(m_presentationAttributeStyle);
    281281    info.addMember(m_classNames);
    282282    info.addMember(m_idForStyleResolution);
     
    342342    }
    343343
    344     if (targetElement.isStyledElement() && sourceData.m_inlineStyleDecl) {
     344    if (!targetElement.isStyledElement())
     345        return;
     346
     347    m_styleAttributeIsDirty = sourceData.m_styleAttributeIsDirty;
     348    m_presentationAttributeStyleIsDirty = sourceData.m_presentationAttributeStyleIsDirty;
     349
     350    // Clone the source element's inline style unless it's immutable.
     351    if (sourceData.m_inlineStyleDecl)
    345352        m_inlineStyleDecl = sourceData.m_inlineStyleDecl->immutableCopyIfNeeded();
    346         targetElement.setIsStyleAttributeValid(sourceElement.isStyleAttributeValid());
    347     }
     353
     354    // Share the presentation attribute style (no need for cloning since it's not accessible via CSSOM.)
     355    m_presentationAttributeStyle = sourceData.m_presentationAttributeStyle;
    348356}
    349357
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r133021 r133286  
    6464    void detachCSSOMWrapperIfNeeded(StyledElement*);
    6565
    66     const StylePropertySet* attributeStyle() const { return m_attributeStyle.get(); }
    67     void setAttributeStyle(PassRefPtr<StylePropertySet> style) const { m_attributeStyle = style; }
     66    const StylePropertySet* presentationAttributeStyle() const { return m_presentationAttributeStyle.get(); }
     67    void setPresentationAttributeStyle(PassRefPtr<StylePropertySet> style) const { m_presentationAttributeStyle= style; }
    6868
    6969    size_t length() const;
     
    9696    void detachAttrObjectsFromElement(Element*) const;
    9797
     98    bool styleAttributeIsDirty() const { return m_styleAttributeIsDirty; }
     99    void setStyleAttributeIsDirty(bool f) const { m_styleAttributeIsDirty = f; }
     100    bool presentationAttributeStyleIsDirty() const { return m_presentationAttributeStyleIsDirty; }
     101    void setPresentationAttributeStyleIsDirty(bool f) const { m_presentationAttributeStyleIsDirty = f; }
     102
    98103    void reportMemoryUsage(MemoryObjectInfo*) const;
    99104
     
    104109    ElementAttributeData()
    105110        : m_isMutable(true)
     111        , m_styleAttributeIsDirty(false)
     112        , m_presentationAttributeStyleIsDirty(false)
    106113        , m_arraySize(0)
    107114    { }
     
    109116    ElementAttributeData(unsigned arraySize)
    110117        : m_isMutable(false)
     118        , m_styleAttributeIsDirty(false)
     119        , m_presentationAttributeStyleIsDirty(false)
    111120        , m_arraySize(arraySize)
    112121    { }
    113122
    114123    unsigned m_isMutable : 1;
     124    mutable unsigned m_styleAttributeIsDirty : 1;
     125    mutable unsigned m_presentationAttributeStyleIsDirty : 1;
    115126    unsigned m_arraySize : 31;
    116127
    117128    mutable RefPtr<StylePropertySet> m_inlineStyleDecl;
    118     mutable RefPtr<StylePropertySet> m_attributeStyle;
     129    mutable RefPtr<StylePropertySet> m_presentationAttributeStyle;
    119130    mutable SpaceSplitString m_classNames;
    120131    mutable AtomicString m_idForStyleResolution;
  • trunk/Source/WebCore/dom/Node.h

    r133224 r133286  
    100100typedef int ExceptionCode;
    101101
    102 const int nodeStyleChangeShift = 20;
     102const int nodeStyleChangeShift = 19;
    103103
    104104// SyntheticStyleChange means that we need to go through the entire style change logic even though
     
    308308    virtual void startLoadingDynamicSheet() { ASSERT_NOT_REACHED(); }
    309309
    310     bool attributeStyleDirty() const { return getFlag(AttributeStyleDirtyFlag); }
    311310    bool hasName() const { return getFlag(HasNameFlag); }
    312311    bool hasID() const;
     
    323322    bool childNeedsStyleRecalc() const { return getFlag(ChildNeedsStyleRecalcFlag); }
    324323    bool isLink() const { return getFlag(IsLinkFlag); }
    325 
    326     void setAttributeStyleDirty() { setFlag(AttributeStyleDirtyFlag); }
    327     void clearAttributeStyleDirty() { clearFlag(AttributeStyleDirtyFlag); }
    328324
    329325    void setHasName(bool f) { setFlag(f, HasNameFlag); }
     
    695691        // be stored in the same memory word as the Node bits above.
    696692        IsParsingChildrenFinishedFlag = 1 << 15, // Element
    697         IsStyleAttributeValidFlag = 1 << 16, // StyledElement
    698693#if ENABLE(SVG)
    699         AreSVGAttributesValidFlag = 1 << 17, // Element
    700         IsSynchronizingSVGAttributesFlag = 1 << 18, // SVGElement
    701         HasSVGRareDataFlag = 1 << 19, // SVGElement
     694        AreSVGAttributesValidFlag = 1 << 16, // Element
     695        IsSynchronizingSVGAttributesFlag = 1 << 17, // SVGElement
     696        HasSVGRareDataFlag = 1 << 18, // SVGElement
    702697#endif
    703698
    704699        StyleChangeMask = 1 << nodeStyleChangeShift | 1 << (nodeStyleChangeShift + 1),
    705700
    706         SelfOrAncestorHasDirAutoFlag = 1 << 22,
    707 
    708         HasNameFlag = 1 << 23,
    709 
    710         AttributeStyleDirtyFlag = 1 << 24,
     701        SelfOrAncestorHasDirAutoFlag = 1 << 21,
     702
     703        HasNameFlag = 1 << 22,
     704
    711705
    712706#if ENABLE(SVG)
    713         DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag | AreSVGAttributesValidFlag,
     707        DefaultNodeFlags = IsParsingChildrenFinishedFlag | AreSVGAttributesValidFlag,
    714708#else
    715         DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag,
    716 #endif
    717         InNamedFlowFlag = 1 << 26,
    718         HasAttrListFlag = 1 << 27,
    719         HasCustomCallbacksFlag = 1 << 28,
    720         HasScopedHTMLStyleChildFlag = 1 << 29,
    721         HasEventTargetDataFlag = 1 << 30,
     709        DefaultNodeFlags = IsParsingChildrenFinishedFlag,
     710#endif
     711        InNamedFlowFlag = 1 << 23,
     712        HasAttrListFlag = 1 << 24,
     713        HasCustomCallbacksFlag = 1 << 25,
     714        HasScopedHTMLStyleChildFlag = 1 << 26,
     715        HasEventTargetDataFlag = 1 << 27,
    722716    };
    723717
    724     // 2 bits remaining
     718    // 4 bits remaining
    725719
    726720    bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
     
    818812    RenderObject* m_renderer;
    819813
    820 public:
    821     bool isStyleAttributeValid() const { return getFlag(IsStyleAttributeValidFlag); }
    822     void setIsStyleAttributeValid(bool f) { setFlag(f, IsStyleAttributeValidFlag); }
    823     void setIsStyleAttributeValid() const { setFlag(IsStyleAttributeValidFlag); }
    824     void clearIsStyleAttributeValid() { clearFlag(IsStyleAttributeValidFlag); }
    825 
    826814protected:
    827815    bool isParsingChildrenFinished() const { return getFlag(IsParsingChildrenFinishedFlag); }
  • trunk/Source/WebCore/dom/StyledElement.cpp

    r132141 r133286  
    127127void StyledElement::updateStyleAttribute() const
    128128{
    129     ASSERT(!isStyleAttributeValid());
    130     setIsStyleAttributeValid();
    131     if (const StylePropertySet* inlineStyle = this->inlineStyle())
    132         const_cast<StyledElement*>(this)->setSynchronizedLazyAttribute(styleAttr, inlineStyle->asText());
     129    ASSERT(styleAttributeIsDirty());
     130    ASSERT(attributeData());
     131    attributeData()->setStyleAttributeIsDirty(false);
     132    if (inlineStyle())
     133        const_cast<StyledElement*>(this)->setSynchronizedLazyAttribute(styleAttr, inlineStyle()->asText());
    133134}
    134135
     
    152153{
    153154    if (isPresentationAttribute(name)) {
    154         setAttributeStyleDirty();
     155        attributeData()->setPresentationAttributeStyleIsDirty(true);
    155156        setNeedsStyleRecalc(InlineStyleChange);
    156157    }
     
    169170        else if (document()->contentSecurityPolicy()->allowInlineStyle(document()->url(), startLineNumber))
    170171            ensureAttributeData()->updateInlineStyleAvoidingMutation(this, newStyleString);
    171         setIsStyleAttributeValid();
     172
     173        attributeData()->setStyleAttributeIsDirty(false);
    172174    }
    173175    setNeedsStyleRecalc();
     
    186188{
    187189    setNeedsStyleRecalc(InlineStyleChange);
    188     setIsStyleAttributeValid(false);
     190    attributeData()->setStyleAttributeIsDirty(true);
    189191    InspectorInstrumentation::didInvalidateStyleAttr(document(), this);
    190192}
     
    271273}
    272274
    273 void StyledElement::updateAttributeStyle()
     275void StyledElement::rebuildPresentationAttributeStyle()
    274276{
    275277    PresentationAttributeCacheKey cacheKey;
     
    298300        }
    299301    }
    300     clearAttributeStyleDirty();
    301 
    302     attributeData()->setAttributeStyle(style->isEmpty() ? 0 : style);
     302
     303    attributeData()->setPresentationAttributeStyleIsDirty(false);
     304    attributeData()->setPresentationAttributeStyle(style->isEmpty() ? 0 : style);
    303305
    304306    if (!cacheHash || cacheIterator->value)
  • trunk/Source/WebCore/dom/StyledElement.h

    r132141 r133286  
    5252    virtual CSSStyleDeclaration* style() OVERRIDE;
    5353
    54     const StylePropertySet* attributeStyle();
     54    const StylePropertySet* presentationAttributeStyle();
    5555
    5656    virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) { }
     
    7979
    8080    void makePresentationAttributeCacheKey(PresentationAttributeCacheKey&) const;
    81     void updateAttributeStyle();
     81    void rebuildPresentationAttributeStyle();
    8282};
    8383
    8484inline void StyledElement::invalidateStyleAttribute()
    8585{
    86     clearIsStyleAttributeValid();
     86    ASSERT(attributeData());
     87    attributeData()->setStyleAttributeIsDirty(true);
    8788}
    8889
    89 inline const StylePropertySet* StyledElement::attributeStyle()
     90inline const StylePropertySet* StyledElement::presentationAttributeStyle()
    9091{
    91     if (attributeStyleDirty())
    92         updateAttributeStyle();
    93     return attributeData() ? attributeData()->attributeStyle() : 0;
     92    if (!attributeData())
     93        return 0;
     94    if (attributeData()->presentationAttributeStyleIsDirty())
     95        rebuildPresentationAttributeStyle();
     96    return attributeData()->presentationAttributeStyle();
    9497}
    9598
  • trunk/Source/WebCore/inspector/InspectorCSSAgent.cpp

    r130612 r133286  
    11851185        return 0;
    11861186
    1187     const StylePropertySet* attributeStyle = static_cast<StyledElement*>(element)->attributeStyle();
    1188     if (!attributeStyle)
     1187    const StylePropertySet* presentationAttributeStyle = static_cast<StyledElement*>(element)->presentationAttributeStyle();
     1188    if (!presentationAttributeStyle)
    11891189        return 0;
    11901190
    1191     RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), const_cast<StylePropertySet*>(attributeStyle)->ensureCSSStyleDeclaration(), 0);
     1191    RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), const_cast<StylePropertySet*>(presentationAttributeStyle)->ensureCSSStyleDeclaration(), 0);
    11921192    return inspectorStyle->buildObjectForStyle();
    11931193}
Note: See TracChangeset for help on using the changeset viewer.