Changeset 128109 in webkit


Ignore:
Timestamp:
Sep 10, 2012 2:43:52 PM (12 years ago)
Author:
kling@webkit.org
Message:

ElementAttributeData: Use subclasses to manage varying object layouts.
<http://webkit.org/b/94465>

Reviewed by Antti Koivisto.

Add two ElementAttributeData subclasses:

  • MutableElementAttributeData
  • ImmutableElementAttributeData

The ElementAttributeData::m_isMutable bit determines which subclass to cast to when accessing
the attribute storage. Added mutableAttributeVector() and immutableAttributeArray() helpers
to ElementAttributeData (with appropriate assertions.)

This patch removes one step of indirection in the mutable case, since the Vector<Attribute> is no
longer heap-allocated, but part of MutableElementAttributeData.

Added a WTF::deleteOwnedPtr(ElementAttributeData*) specialization so that the appropriate subclass
destructor is called for these objects.

  • WebCore.exp.in:
  • dom/Element.cpp:

(WebCore::Element::createMutableAttributeData):

  • dom/ElementAttributeData.cpp:

(WebCore::ElementAttributeData::createImmutable):
(WebCore::ElementAttributeData::create):
(WebCore::ElementAttributeData::ElementAttributeData):
(WebCore::MutableElementAttributeData::MutableElementAttributeData):
(WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData):
(WebCore::ImmutableElementAttributeData::~ImmutableElementAttributeData):
(WebCore::ElementAttributeData::makeMutableCopy):
(WebCore::ElementAttributeData::addAttribute):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::reportMemoryUsage):
(WebCore::ElementAttributeData::cloneDataFrom):
(WebCore::ElementAttributeData::clearAttributes):

  • dom/ElementAttributeData.h:

(ElementAttributeData):
(WebCore::ElementAttributeData::isMutable):
(ImmutableElementAttributeData):
(MutableElementAttributeData):
(WebCore::MutableElementAttributeData::MutableElementAttributeData):
(WebCore::ElementAttributeData::immutableAttributeArray):
(WebCore::ElementAttributeData::mutableAttributeVector):
(WebCore::ElementAttributeData::length):
(WebCore::ElementAttributeData::attributeItem):

Location:
trunk/Source/WebCore
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r128107 r128109  
     12012-09-10  Andreas Kling  <kling@webkit.org>
     2
     3        ElementAttributeData: Use subclasses to manage varying object layouts.
     4        <http://webkit.org/b/94465>
     5
     6        Reviewed by Antti Koivisto.
     7
     8        Add two ElementAttributeData subclasses:
     9
     10            - MutableElementAttributeData
     11            - ImmutableElementAttributeData
     12
     13        The ElementAttributeData::m_isMutable bit determines which subclass to cast to when accessing
     14        the attribute storage. Added mutableAttributeVector() and immutableAttributeArray() helpers
     15        to ElementAttributeData (with appropriate assertions.)
     16
     17        This patch removes one step of indirection in the mutable case, since the Vector<Attribute> is no
     18        longer heap-allocated, but part of MutableElementAttributeData.
     19
     20        Added a WTF::deleteOwnedPtr(ElementAttributeData*) specialization so that the appropriate subclass
     21        destructor is called for these objects.
     22
     23        * WebCore.exp.in:
     24        * dom/Element.cpp:
     25        (WebCore::Element::createMutableAttributeData):
     26        * dom/ElementAttributeData.cpp:
     27        (WebCore::ElementAttributeData::createImmutable):
     28        (WebCore::ElementAttributeData::create):
     29        (WebCore::ElementAttributeData::ElementAttributeData):
     30        (WebCore::MutableElementAttributeData::MutableElementAttributeData):
     31        (WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData):
     32        (WebCore::ImmutableElementAttributeData::~ImmutableElementAttributeData):
     33        (WebCore::ElementAttributeData::makeMutableCopy):
     34        (WebCore::ElementAttributeData::addAttribute):
     35        (WebCore::ElementAttributeData::removeAttribute):
     36        (WebCore::ElementAttributeData::reportMemoryUsage):
     37        (WebCore::ElementAttributeData::cloneDataFrom):
     38        (WebCore::ElementAttributeData::clearAttributes):
     39        * dom/ElementAttributeData.h:
     40        (ElementAttributeData):
     41        (WebCore::ElementAttributeData::isMutable):
     42        (ImmutableElementAttributeData):
     43        (MutableElementAttributeData):
     44        (WebCore::MutableElementAttributeData::MutableElementAttributeData):
     45        (WebCore::ElementAttributeData::immutableAttributeArray):
     46        (WebCore::ElementAttributeData::mutableAttributeVector):
     47        (WebCore::ElementAttributeData::length):
     48        (WebCore::ElementAttributeData::attributeItem):
     49
    1502012-09-10  Tony Chang  <tony@chromium.org>
    251
  • trunk/Source/WebCore/WebCore.exp.in

    r127932 r128109  
    231231__ZN7WebCore13toHTMLElementEPNS_21FormAssociatedElementE
    232232__ZN7WebCore13toJSDOMWindowEN3JSC7JSValueE
     233__ZN7WebCore13QualifiedNameD1Ev
    233234__ZN7WebCore14CachedResource12removeClientEPNS_20CachedResourceClientE
    234235__ZN7WebCore14CachedResource16unregisterHandleEPNS_24CachedResourceHandleBaseE
     
    539540__ZN7WebCore20makeRGBA32FromFloatsEffff
    540541__ZN7WebCore20protocolIsJavaScriptERKN3WTF6StringE
     542__ZN7WebCore20SpaceSplitStringDataD1Ev
    541543__ZN7WebCore21BackForwardController11itemAtIndexEi
    542544__ZN7WebCore21MemoryPressureHandler7installEv
  • trunk/Source/WebCore/dom/Element.cpp

    r128009 r128109  
    22472247        m_attributeData = ElementAttributeData::create();
    22482248    else
    2249         m_attributeData = m_attributeData->makeMutable();
     2249        m_attributeData = m_attributeData->makeMutableCopy();
    22502250}
    22512251
  • trunk/Source/WebCore/dom/ElementAttributeData.cpp

    r127869 r128109  
    3737static size_t immutableElementAttributeDataSize(unsigned count)
    3838{
    39     return sizeof(ElementAttributeData) - sizeof(void*) + sizeof(Attribute) * count;
     39    return sizeof(ImmutableElementAttributeData) + sizeof(Attribute) * count;
    4040}
    4141
     
    4343{
    4444    void* slot = WTF::fastMalloc(immutableElementAttributeDataSize(attributes.size()));
    45     return adoptRef(new (slot) ElementAttributeData(attributes));
    46 }
    47 
    48 ElementAttributeData::ElementAttributeData()
    49     : m_isMutable(true)
    50     , m_arraySize(0)
    51     , m_mutableAttributeVector(new Vector<Attribute, 4>)
    52 {
    53 }
    54 
    55 ElementAttributeData::ElementAttributeData(const Vector<Attribute>& attributes)
    56     : m_isMutable(false)
    57     , m_arraySize(attributes.size())
    58 {
    59     Attribute* buffer = reinterpret_cast<Attribute*>(&m_attributes);
    60     for (unsigned i = 0; i < attributes.size(); ++i)
    61         new (&buffer[i]) Attribute(attributes[i]);
    62 }
    63 
    64 ElementAttributeData::ElementAttributeData(const ElementAttributeData& other)
    65     : RefCounted<ElementAttributeData>()
    66     , m_isMutable(true)
    67     , m_arraySize(0)
    68     , m_inlineStyleDecl(other.m_inlineStyleDecl)
    69     , m_attributeStyle(other.m_attributeStyle)
    70     , m_classNames(other.m_classNames)
    71     , m_idForStyleResolution(other.m_idForStyleResolution)
    72     , m_mutableAttributeVector(new Vector<Attribute, 4>)
    73 {
    74     // This copy constructor should only be used by makeMutable() to go from immutable to mutable.
    75     ASSERT(!other.m_isMutable);
    76 
    77     // An immutable ElementAttributeData should never have a mutable inline StylePropertySet attached.
    78     ASSERT(!other.m_inlineStyleDecl || !other.m_inlineStyleDecl->isMutable());
    79 
    80     const Attribute* otherBuffer = reinterpret_cast<const Attribute*>(&other.m_attributes);
    81     for (unsigned i = 0; i < other.m_arraySize; ++i)
    82         m_mutableAttributeVector->append(otherBuffer[i]);
    83 }
    84 
    85 ElementAttributeData::~ElementAttributeData()
    86 {
    87     if (isMutable()) {
    88         ASSERT(!m_arraySize);
    89         delete m_mutableAttributeVector;
    90     } else {
    91         Attribute* buffer = reinterpret_cast<Attribute*>(&m_attributes);
    92         for (unsigned i = 0; i < m_arraySize; ++i)
    93             buffer[i].~Attribute();
    94     }
     45    return adoptRef(new (slot) ImmutableElementAttributeData(attributes));
     46}
     47
     48PassRefPtr<ElementAttributeData> ElementAttributeData::create()
     49{
     50    return adoptRef(new MutableElementAttributeData);
     51}
     52
     53ImmutableElementAttributeData::ImmutableElementAttributeData(const Vector<Attribute>& attributes)
     54    : ElementAttributeData(attributes.size())
     55{
     56    for (unsigned i = 0; i < m_arraySize; ++i)
     57        new (&m_attributeArray[i]) Attribute(attributes[i]);
     58}
     59
     60MutableElementAttributeData::MutableElementAttributeData(const ImmutableElementAttributeData& other)
     61{
     62    const ElementAttributeData& baseOther = static_cast<const ElementAttributeData&>(other);
     63
     64    m_inlineStyleDecl = baseOther.m_inlineStyleDecl;
     65    m_attributeStyle = baseOther.m_attributeStyle;
     66    m_classNames = baseOther.m_classNames;
     67    m_idForStyleResolution = baseOther.m_idForStyleResolution;
     68
     69    // An ImmutableElementAttributeData should never have a mutable inline StylePropertySet attached.
     70    ASSERT(!baseOther.m_inlineStyleDecl || !baseOther.m_inlineStyleDecl->isMutable());
     71
     72    m_attributeVector.reserveCapacity(baseOther.m_arraySize);
     73    for (unsigned i = 0; i < baseOther.m_arraySize; ++i)
     74        m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
     75}
     76
     77ImmutableElementAttributeData::~ImmutableElementAttributeData()
     78{
     79    for (unsigned i = 0; i < m_arraySize; ++i)
     80        m_attributeArray[i].~Attribute();
     81}
     82
     83PassRefPtr<ElementAttributeData> ElementAttributeData::makeMutableCopy() const
     84{
     85    ASSERT(!isMutable());
     86    return adoptRef(new MutableElementAttributeData(static_cast<const ImmutableElementAttributeData&>(*this)));
    9587}
    9688
     
    237229        element->willModifyAttribute(attribute.name(), nullAtom, attribute.value());
    238230
    239     m_mutableAttributeVector->append(attribute);
     231    mutableAttributeVector().append(attribute);
    240232
    241233    if (element && inSynchronizationOfLazyAttribute == NotInSynchronizationOfLazyAttribute)
     
    248240    ASSERT(index < length());
    249241
    250     Attribute& attribute = m_mutableAttributeVector->at(index);
     242    Attribute& attribute = mutableAttributeVector().at(index);
    251243    QualifiedName name = attribute.name();
    252244
     
    257249        attr->detachFromElementWithValue(attribute.value());
    258250
    259     m_mutableAttributeVector->remove(index);
     251    mutableAttributeVector().remove(index);
    260252
    261253    if (element && inSynchronizationOfLazyAttribute == NotInSynchronizationOfLazyAttribute)
     
    305297    info.addInstrumentedMember(m_idForStyleResolution);
    306298    if (m_isMutable)
    307         info.addVectorPtr(m_mutableAttributeVector);
     299        info.addVector(mutableAttributeVector());
    308300    for (unsigned i = 0, len = length(); i < len; i++)
    309301        info.addInstrumentedMember(*attributeItem(i));
     
    349341
    350342    if (sourceData.isMutable())
    351         *m_mutableAttributeVector = *sourceData.m_mutableAttributeVector;
     343        mutableAttributeVector() = sourceData.mutableAttributeVector();
    352344    else {
    353         ASSERT(m_mutableAttributeVector->isEmpty());
    354         m_mutableAttributeVector->reserveInitialCapacity(sourceData.m_arraySize);
    355         const Attribute* sourceBuffer = reinterpret_cast<const Attribute*>(&sourceData.m_attributes);
     345        mutableAttributeVector().reserveInitialCapacity(sourceData.m_arraySize);
    356346        for (unsigned i = 0; i < sourceData.m_arraySize; ++i)
    357             m_mutableAttributeVector->uncheckedAppend(sourceBuffer[i]);
     347            mutableAttributeVector().uncheckedAppend(sourceData.immutableAttributeArray()[i]);
    358348    }
    359349
    360350    for (unsigned i = 0; i < length(); ++i) {
    361         const Attribute& attribute = m_mutableAttributeVector->at(i);
     351        const Attribute& attribute = mutableAttributeVector().at(i);
    362352        if (targetElement.isStyledElement() && attribute.name() == HTMLNames::styleAttr) {
    363353            static_cast<StyledElement&>(targetElement).styleAttributeChanged(attribute.value(), StyledElement::DoNotReparseStyleAttribute);
     
    381371
    382372    clearClass();
    383     m_mutableAttributeVector->clear();
     373    mutableAttributeVector().clear();
    384374}
    385375
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r127438 r128109  
    3636class Attr;
    3737class Element;
     38class ImmutableElementAttributeData;
    3839class MemoryObjectInfo;
     40class MutableElementAttributeData;
    3941
    4042enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute, InSynchronizationOfLazyAttribute };
     
    4345    WTF_MAKE_FAST_ALLOCATED;
    4446public:
    45     static PassRefPtr<ElementAttributeData> create() { return adoptRef(new ElementAttributeData); }
     47    static PassRefPtr<ElementAttributeData> create();
    4648    static PassRefPtr<ElementAttributeData> createImmutable(const Vector<Attribute>&);
    47     ~ElementAttributeData();
    4849
    4950    void clearClass() { m_classNames.clear(); }
     
    9697    void reportMemoryUsage(MemoryObjectInfo*) const;
    9798
     99    bool isMutable() const { return m_isMutable; }
     100
     101protected:
     102    ElementAttributeData()
     103        : m_isMutable(true)
     104        , m_arraySize(0)
     105    { }
     106
     107    ElementAttributeData(unsigned arraySize)
     108        : m_isMutable(false)
     109        , m_arraySize(arraySize)
     110    { }
     111
     112    mutable RefPtr<StylePropertySet> m_inlineStyleDecl;
     113    mutable RefPtr<StylePropertySet> m_attributeStyle;
     114    mutable SpaceSplitString m_classNames;
     115    mutable AtomicString m_idForStyleResolution;
     116
     117    unsigned m_isMutable : 1;
     118    unsigned m_arraySize : 31;
     119
    98120private:
    99121    friend class Element;
    100122    friend class HTMLConstructionSite;
    101 
    102     ElementAttributeData();
    103     ElementAttributeData(const ElementAttributeData&);
    104     ElementAttributeData(const Vector<Attribute>&);
     123    friend class ImmutableElementAttributeData;
     124    friend class MutableElementAttributeData;
    105125
    106126    Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase);
     
    110130    void clearAttributes(Element*);
    111131
    112     bool isMutable() const { return m_isMutable; }
    113     PassRefPtr<ElementAttributeData> makeMutable() const { return adoptRef(new ElementAttributeData(*this)); }
    114 
    115     unsigned m_isMutable : 1;
    116     unsigned m_arraySize : 31;
    117 
    118     mutable RefPtr<StylePropertySet> m_inlineStyleDecl;
    119     mutable RefPtr<StylePropertySet> m_attributeStyle;
    120     mutable SpaceSplitString m_classNames;
    121     mutable AtomicString m_idForStyleResolution;
    122 
    123     union {
    124         Vector<Attribute, 4>* m_mutableAttributeVector;
    125         void* m_attributes;
    126     };
     132    PassRefPtr<ElementAttributeData> makeMutableCopy() const;
     133
     134    Vector<Attribute, 4>& mutableAttributeVector();
     135    const Vector<Attribute, 4>& mutableAttributeVector() const;
     136    const Attribute* immutableAttributeArray() const;
    127137};
    128138
     139class ImmutableElementAttributeData : public ElementAttributeData {
     140public:
     141    ImmutableElementAttributeData(const Vector<Attribute>&);
     142    ~ImmutableElementAttributeData();
     143
     144    Attribute m_attributeArray[0];
     145};
     146
     147class MutableElementAttributeData : public ElementAttributeData {
     148public:
     149    MutableElementAttributeData() { }
     150    MutableElementAttributeData(const ImmutableElementAttributeData&);
     151
     152    Vector<Attribute, 4> m_attributeVector;
     153};
     154
     155inline Vector<Attribute, 4>& ElementAttributeData::mutableAttributeVector()
     156{
     157    ASSERT(m_isMutable);
     158    return static_cast<MutableElementAttributeData*>(this)->m_attributeVector;
     159}
     160
     161inline const Vector<Attribute, 4>& ElementAttributeData::mutableAttributeVector() const
     162{
     163    ASSERT(m_isMutable);
     164    return static_cast<const MutableElementAttributeData*>(this)->m_attributeVector;
     165}
     166
     167inline const Attribute* ElementAttributeData::immutableAttributeArray() const
     168{
     169    ASSERT(!m_isMutable);
     170    return static_cast<const ImmutableElementAttributeData*>(this)->m_attributeArray;
     171}
     172
    129173inline size_t ElementAttributeData::length() const
    130174{
    131175    if (isMutable())
    132         return m_mutableAttributeVector->size();
     176        return mutableAttributeVector().size();
    133177    return m_arraySize;
    134178}
     
    202246{
    203247    ASSERT(index < length());
    204     if (isMutable())
    205         return &m_mutableAttributeVector->at(index);
    206     const Attribute* buffer = reinterpret_cast<const Attribute*>(&m_attributes);
    207     return &buffer[index];
     248    if (m_isMutable)
     249        return &mutableAttributeVector().at(index);
     250    return &immutableAttributeArray()[index];
    208251}
    209252
    210253inline Attribute* ElementAttributeData::attributeItem(unsigned index)
    211254{
    212     ASSERT(isMutable());
    213255    ASSERT(index < length());
    214     return &m_mutableAttributeVector->at(index);
     256    return &mutableAttributeVector().at(index);
     257}
     258
     259}
     260
     261namespace WTF {
     262
     263template <> inline void deleteOwnedPtr<WebCore::ElementAttributeData>(WebCore::ElementAttributeData* ptr)
     264{
     265    if (!ptr)
     266        return;
     267    if (ptr->isMutable())
     268        delete static_cast<WebCore::MutableElementAttributeData*>(ptr);
     269    else
     270        delete static_cast<WebCore::ImmutableElementAttributeData*>(ptr);
    215271}
    216272
Note: See TracChangeset for help on using the changeset viewer.