Changeset 123636 in webkit


Ignore:
Timestamp:
Jul 25, 2012 11:14:13 AM (12 years ago)
Author:
kling@webkit.org
Message:

Make ElementAttributeData a variable-sized object to reduce memory use.
<http://webkit.org/b/88240>

Reviewed by Ryosuke Niwa.

Source/WebCore:

Take advantage of the fact that we know at ElementAttributeData construction time how many attributes
it needs to accomodate and allocate exactly as much space as needed instead of using a Vector.
For elements that never have their attribute list mutated (the vast majority), this saves a lot of
memory and removes the indirection to Vector<Attribute>'s heap-allocated storage.

Introduced a mutability flag to ElementAttributeData and sprinkled assertions all over to make sure
that nothing tries to mutate an element with a raw attribute array.

When an Element's attribute(s) are mutated, we reconstruct the ElementAttributeData, this time using
a Vector as backing instead. This is triggered when calling Element::mutableAttributeData().

This reduces memory consumption by 3.2MB when viewing the full HTML5 spec at <http://whatwg.org/c/>.
That is a ~35% reduction in DOM attribute memory use.

Furthermore, that page ends up promoting 27% of the elements to mutable attribute storage due to dynamic
adding of "class" attributes. For more static pages, savings are even greater.

Also did away with ElementAttributeData::removeAttribute(name) and do separate index lookup where
needed. Not a big deal but avoids double lookup of attributes when removing them.

  • dom/Element.cpp:

(WebCore::Element::detachAttribute):
(WebCore::Element::removeAttribute):
(WebCore::Element::attributes):
(WebCore::Element::setAttributeInternal):
(WebCore::Element::parserSetAttributes):
(WebCore::Element::hasEquivalentAttributes):
(WebCore::Element::setAttributeNode):
(WebCore::Element::removeAttributeNode):
(WebCore::Element::getAttributeNode):
(WebCore::Element::getAttributeNodeNS):
(WebCore::Element::hasAttribute):
(WebCore::Element::hasAttributeNS):
(WebCore::Element::cloneAttributesFromElement):

Sprinkle const on ElementAttributeData* pointers.
Switch to using mutableAttributeData() in code paths that modify attributes.

(WebCore::Element::normalizeAttributes):

Cleaner iteration over attributes, I removed ElementAttributeData::attributeVector() since that
was just incurring a bunch of extra Vector copying. Since ElementAttributeData already exposes
length() and attributeItem(index), use those to iterate directly over the attributes.

(WebCore::Element::createMutableAttributeData):

Added, converts existing ElementAttributeData to a mutable object. Otherwise creates a new
ElementAttributeData (mutable and empty.)

  • dom/Element.h:

(WebCore::Element::attributeData):
(WebCore::Element::updatedAttributeData):
(WebCore::Element::ensureAttributeData):
(WebCore::Element::ensureUpdatedAttributeData):

Made all of these return "const ElementAttributeData*" to ensure at compile-time that nothing
attempts to modify an ElementAttributeData that may be immutable.

ensureUpdatedAttributeData() is still const, despite possibly calling mutableAttributeData().
The goal of having methods be const is to prevent conversion from one ElementAttributeData
object to another, so that pointers remain intact and no unnecessary work gets done.

(WebCore::Element::mutableAttributeData):

Added, returns a guaranteed mutable ElementAttributeData* pointer.

  • dom/ElementAttributeData.cpp:

(WebCore::ElementAttributeData::createImmutable):

Creates a new ElementAttributeData tailored to fit the provided Vector<Attribute>.

(WebCore::ElementAttributeData::ElementAttributeData):

Moved constructors out-of-line, getting too complex for header files.

ElementAttributeData(const Vector<Attribute>&) creates an immutable ElementAttributeData
containing the provided attributes in an array tacked onto the end of the object.

(WebCore::ElementAttributeData::~ElementAttributeData):

Free the attribute vector if mutable.
For immutable objects, manually invoke destructor on each Attribute object,
since these won't be destroyed automatically by ~ElementAttributeData.

(WebCore::ElementAttributeData::attrIfExists):

(WebCore::ElementAttributeData::ensureAttr):
(WebCore::ElementAttributeData::setAttr):
(WebCore::ElementAttributeData::removeAttr):

Make these const, as they should always have been- they don't affect the ElementAttributeData,
only the global DOM Attr <-> ElementAttributeData mappings.

(WebCore::ElementAttributeData::ensureInlineStyle):
(WebCore::ElementAttributeData::ensureMutableInlineStyle):

Sprinkle ASSERT(isMutable()). This doesn't mean that all Elements with inline styles automatically
have mutable attribute data. There's still inlineStyle() for that, which may return null.
These are only for use where you need a valid StylePropertySet*, even if there is no inline style
attribute, e.g in editing code that wants to add style.

(WebCore::ElementAttributeData::updateInlineStyleAvoidingMutation):
(WebCore::ElementAttributeData::destroyInlineStyle):

Make these const. While destroyInlineStyle() doesn't sound very const-y, immutable objects that
contain a style attribute will have a valid inlineStyle() with that style data. This is just
an interface for ~StyledElement to destroy the style object.
It'd be nice to do that in ~ElementAttributeData(), but we need a StyledElement* pointer to
clean up properly and we don't store one in this class.

(WebCore::ElementAttributeData::addAttribute):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::clearAttributes):
(WebCore::ElementAttributeData::replaceAttribute):

Sprinkle ASSERT(isMutable()).
Always go straight for m_mutableAttributeVector since we know that's the storage being used.

(WebCore::ElementAttributeData::isEquivalent):
(WebCore::ElementAttributeData::detachAttrObjectsFromElement):
(WebCore::ElementAttributeData::getAttributeItemIndexSlowCase):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::getAttributeItem):
(WebCore::ElementAttributeData::getAttributeItemIndex):

Use length() and attributeItem(index) to iterate over the attributes.

(WebCore::ElementAttributeData::cloneDataFrom):

Sprinkle ASSERT(isMutable()). Added a FIXME that cloning elements could create immutable
attribute data. I'm not sure this optimization is worthwhile, as cloning elements is already
a semi-rare occurrence.

Updated code to handle both immutable and mutable source objects. This could

(WebCore::ElementAttributeData::getAttributeNode):

Const correctness.

  • dom/ElementAttributeData.h:

(ElementAttributeData):

Turn attribute storage into what's effectively union { OwnPtr<Vector<Attribute>>; Attribute[]; }
The new m_isMutable bit determines which union member should be used for access.

(WebCore::ElementAttributeData::create):
(WebCore::ElementAttributeData::createImmutable):

Added createImmutable(const Vector<Attribute>&) as a complement to create().

(WebCore::ElementAttributeData::setClass):
(WebCore::ElementAttributeData::setIdForStyleResolution):
(WebCore::ElementAttributeData::inlineStyle):
(WebCore::ElementAttributeData::setAttributeStyle):

Make these const, and their data member counterparts 'mutable'.
An immutable ElementAttributeData object still has m_classNames, m_idForStyleResolution,
m_inlineStyleDecl and m_attributeStyle.

(WebCore::ElementAttributeData::reportMemoryUsage):

Updated for isMutable().

(WebCore::ElementAttributeData::makeMutable):

Returns a mutable clone of itself.

(WebCore::ElementAttributeData::isEmpty):
(WebCore::ElementAttributeData::length):
(WebCore::ElementAttributeData::attributeItem):

Check isMutable() to know how to access attribute storage.

  • dom/StyledElement.cpp:

(WebCore::StyledElement::style):
(WebCore::StyledElement::setInlineStyleProperty):

Simplify by using StyledElement::ensureInlineStyle().

(WebCore::StyledElement::classAttributeChanged):

Use mutableAttributeData() if the attribute is being removed completely.
In other cases, tiptoe around without causing the attribute data to go mutable.

(WebCore::StyledElement::removeInlineStyleProperty):

Use mutableAttributeData() if/when actually removing something.

(WebCore::StyledElement::addSubresourceAttributeURLs):

Const correctness.

  • dom/StyledElement.h:

(WebCore::StyledElement::ensureInlineStyle):

This now implies conversion to mutable attribute data. Used by codepaths that add/remove
properties, so conversion is inevitable.

  • html/parser/HTMLConstructionSite.cpp:

(WebCore::HTMLConstructionSite::mergeAttributesFromTokenIntoElement):
(WebCore::HTMLConstructionSite::createHTMLElementFromSavedElement):

  • svg/properties/SVGAnimatedPropertyMacros.h:

(WebCore::SVGSynchronizableAnimatedProperty::synchronize):

Use mutableAttributeData() as appropriate.

  • xml/parser/XMLDocumentParserQt.cpp:

(WebCore::XMLDocumentParser::XMLDocumentParser):

Const correctness.

LayoutTests:

Extended this test to cover the case where setAttributeNode() returns a lazily serialized value.

  • fast/dom/attr-style-too-lazy-expected.txt:
  • fast/dom/attr-style-too-lazy.html:
Location:
trunk
Files:
27 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r123634 r123636  
     12012-07-25  Andreas Kling  <kling@webkit.org>
     2
     3        Make ElementAttributeData a variable-sized object to reduce memory use.
     4        <http://webkit.org/b/88240>
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Extended this test to cover the case where setAttributeNode() returns a lazily serialized value.
     9
     10        * fast/dom/attr-style-too-lazy-expected.txt:
     11        * fast/dom/attr-style-too-lazy.html:
     12
    1132012-07-25  Konrad Piascik  <kpiascik@rim.com>
    214
  • trunk/LayoutTests/fast/dom/attr-style-too-lazy-expected.txt

    r117956 r123636  
    66PASS styleAttr.value is 'background-color: white; '
    77PASS styleAttr.value is 'background-color: green; '
     8PASS oldStyleAttr.value is 'background-color: red; '
    89PASS successfullyParsed is true
    910
  • trunk/LayoutTests/fast/dom/attr-style-too-lazy.html

    r117956 r123636  
    1717shouldBe("styleAttr.value", "'background-color: green; '");
    1818
     19e.style.backgroundColor = 'red';
     20var oldStyleAttr = e.setAttributeNode(document.createAttribute("style"));
     21shouldBe("oldStyleAttr.value", "'background-color: red; '");
     22
    1923</script>
    2024<script src="../js/resources/js-test-post.js"></script>
  • trunk/Source/WebCore/ChangeLog

    r123635 r123636  
     12012-07-25  Andreas Kling  <kling@webkit.org>
     2
     3        Make ElementAttributeData a variable-sized object to reduce memory use.
     4        <http://webkit.org/b/88240>
     5
     6        Reviewed by Ryosuke Niwa.
     7
     8        Take advantage of the fact that we know at ElementAttributeData construction time how many attributes
     9        it needs to accomodate and allocate exactly as much space as needed instead of using a Vector.
     10        For elements that never have their attribute list mutated (the vast majority), this saves a lot of
     11        memory and removes the indirection to Vector<Attribute>'s heap-allocated storage.
     12
     13        Introduced a mutability flag to ElementAttributeData and sprinkled assertions all over to make sure
     14        that nothing tries to mutate an element with a raw attribute array.
     15
     16        When an Element's attribute(s) are mutated, we reconstruct the ElementAttributeData, this time using
     17        a Vector as backing instead. This is triggered when calling Element::mutableAttributeData().
     18
     19        This reduces memory consumption by 3.2MB when viewing the full HTML5 spec at <http://whatwg.org/c/>.
     20        That is a ~35% reduction in DOM attribute memory use.
     21
     22        Furthermore, that page ends up promoting 27% of the elements to mutable attribute storage due to dynamic
     23        adding of "class" attributes. For more static pages, savings are even greater.
     24
     25        Also did away with ElementAttributeData::removeAttribute(name) and do separate index lookup where
     26        needed. Not a big deal but avoids double lookup of attributes when removing them.
     27
     28        * dom/Element.cpp:
     29        (WebCore::Element::detachAttribute):
     30        (WebCore::Element::removeAttribute):
     31        (WebCore::Element::attributes):
     32        (WebCore::Element::setAttributeInternal):
     33        (WebCore::Element::parserSetAttributes):
     34        (WebCore::Element::hasEquivalentAttributes):
     35        (WebCore::Element::setAttributeNode):
     36        (WebCore::Element::removeAttributeNode):
     37        (WebCore::Element::getAttributeNode):
     38        (WebCore::Element::getAttributeNodeNS):
     39        (WebCore::Element::hasAttribute):
     40        (WebCore::Element::hasAttributeNS):
     41        (WebCore::Element::cloneAttributesFromElement):
     42
     43            Sprinkle const on ElementAttributeData* pointers.
     44            Switch to using mutableAttributeData() in code paths that modify attributes.
     45
     46        (WebCore::Element::normalizeAttributes):
     47
     48            Cleaner iteration over attributes, I removed ElementAttributeData::attributeVector() since that
     49            was just incurring a bunch of extra Vector copying. Since ElementAttributeData already exposes
     50            length() and attributeItem(index), use those to iterate directly over the attributes.
     51
     52        (WebCore::Element::createMutableAttributeData):
     53
     54            Added, converts existing ElementAttributeData to a mutable object. Otherwise creates a new
     55            ElementAttributeData (mutable and empty.)
     56
     57        * dom/Element.h:
     58        (WebCore::Element::attributeData):
     59        (WebCore::Element::updatedAttributeData):
     60        (WebCore::Element::ensureAttributeData):
     61        (WebCore::Element::ensureUpdatedAttributeData):
     62
     63            Made all of these return "const ElementAttributeData*" to ensure at compile-time that nothing
     64            attempts to modify an ElementAttributeData that may be immutable.
     65
     66            ensureUpdatedAttributeData() is still const, despite possibly calling mutableAttributeData().
     67            The goal of having methods be const is to prevent conversion from one ElementAttributeData
     68            object to another, so that pointers remain intact and no unnecessary work gets done.
     69
     70        (WebCore::Element::mutableAttributeData):
     71
     72            Added, returns a guaranteed mutable ElementAttributeData* pointer.
     73
     74        * dom/ElementAttributeData.cpp:
     75        (WebCore::ElementAttributeData::createImmutable):
     76
     77            Creates a new ElementAttributeData tailored to fit the provided Vector<Attribute>.
     78
     79        (WebCore::ElementAttributeData::ElementAttributeData):
     80
     81            Moved constructors out-of-line, getting too complex for header files.
     82
     83            ElementAttributeData(const Vector<Attribute>&) creates an immutable ElementAttributeData
     84            containing the provided attributes in an array tacked onto the end of the object.
     85
     86        (WebCore::ElementAttributeData::~ElementAttributeData):
     87
     88            Free the attribute vector if mutable.
     89            For immutable objects, manually invoke destructor on each Attribute object,
     90            since these won't be destroyed automatically by ~ElementAttributeData.
     91
     92        (WebCore::ElementAttributeData::attrIfExists):
     93
     94        (WebCore::ElementAttributeData::ensureAttr):
     95        (WebCore::ElementAttributeData::setAttr):
     96        (WebCore::ElementAttributeData::removeAttr):
     97
     98            Make these const, as they should always have been- they don't affect the ElementAttributeData,
     99            only the global DOM Attr <-> ElementAttributeData mappings.
     100
     101        (WebCore::ElementAttributeData::ensureInlineStyle):
     102        (WebCore::ElementAttributeData::ensureMutableInlineStyle):
     103
     104            Sprinkle ASSERT(isMutable()). This doesn't mean that all Elements with inline styles automatically
     105            have mutable attribute data. There's still inlineStyle() for that, which may return null.
     106            These are only for use where you need a valid StylePropertySet*, even if there is no inline style
     107            attribute, e.g in editing code that wants to add style.
     108
     109        (WebCore::ElementAttributeData::updateInlineStyleAvoidingMutation):
     110        (WebCore::ElementAttributeData::destroyInlineStyle):
     111
     112            Make these const. While destroyInlineStyle() doesn't sound very const-y, immutable objects that
     113            contain a style attribute will have a valid inlineStyle() with that style data. This is just
     114            an interface for ~StyledElement to destroy the style object.
     115            It'd be nice to do that in ~ElementAttributeData(), but we need a StyledElement* pointer to
     116            clean up properly and we don't store one in this class.
     117
     118        (WebCore::ElementAttributeData::addAttribute):
     119        (WebCore::ElementAttributeData::removeAttribute):
     120        (WebCore::ElementAttributeData::clearAttributes):
     121        (WebCore::ElementAttributeData::replaceAttribute):
     122
     123            Sprinkle ASSERT(isMutable()).
     124            Always go straight for m_mutableAttributeVector since we know that's the storage being used.
     125
     126        (WebCore::ElementAttributeData::isEquivalent):
     127        (WebCore::ElementAttributeData::detachAttrObjectsFromElement):
     128        (WebCore::ElementAttributeData::getAttributeItemIndexSlowCase):
     129        (WebCore::ElementAttributeData::removeAttribute):
     130        (WebCore::ElementAttributeData::getAttributeItem):
     131        (WebCore::ElementAttributeData::getAttributeItemIndex):
     132
     133            Use length() and attributeItem(index) to iterate over the attributes.
     134
     135        (WebCore::ElementAttributeData::cloneDataFrom):
     136
     137            Sprinkle ASSERT(isMutable()). Added a FIXME that cloning elements could create immutable
     138            attribute data. I'm not sure this optimization is worthwhile, as cloning elements is already
     139            a semi-rare occurrence.
     140
     141            Updated code to handle both immutable and mutable source objects. This could
     142
     143        (WebCore::ElementAttributeData::getAttributeNode):
     144
     145            Const correctness.
     146
     147        * dom/ElementAttributeData.h:
     148        (ElementAttributeData):
     149
     150            Turn attribute storage into what's effectively union { OwnPtr<Vector<Attribute>>; Attribute[]; }
     151            The new m_isMutable bit determines which union member should be used for access.
     152
     153        (WebCore::ElementAttributeData::create):
     154        (WebCore::ElementAttributeData::createImmutable):
     155
     156            Added createImmutable(const Vector<Attribute>&) as a complement to create().
     157
     158        (WebCore::ElementAttributeData::setClass):
     159        (WebCore::ElementAttributeData::setIdForStyleResolution):
     160        (WebCore::ElementAttributeData::inlineStyle):
     161        (WebCore::ElementAttributeData::setAttributeStyle):
     162
     163            Make these const, and their data member counterparts 'mutable'.
     164            An immutable ElementAttributeData object still has m_classNames, m_idForStyleResolution,
     165            m_inlineStyleDecl and m_attributeStyle.
     166
     167        (WebCore::ElementAttributeData::reportMemoryUsage):
     168
     169            Updated for isMutable().
     170
     171        (WebCore::ElementAttributeData::makeMutable):
     172
     173            Returns a mutable clone of itself.
     174
     175        (WebCore::ElementAttributeData::isEmpty):
     176        (WebCore::ElementAttributeData::length):
     177        (WebCore::ElementAttributeData::attributeItem):
     178
     179            Check isMutable() to know how to access attribute storage.
     180
     181        * dom/StyledElement.cpp:
     182        (WebCore::StyledElement::style):
     183        (WebCore::StyledElement::setInlineStyleProperty):
     184
     185            Simplify by using StyledElement::ensureInlineStyle().
     186
     187        (WebCore::StyledElement::classAttributeChanged):
     188
     189            Use mutableAttributeData() if the attribute is being removed completely.
     190            In other cases, tiptoe around without causing the attribute data to go mutable.
     191
     192        (WebCore::StyledElement::removeInlineStyleProperty):
     193
     194            Use mutableAttributeData() if/when actually removing something.
     195
     196        (WebCore::StyledElement::addSubresourceAttributeURLs):
     197
     198            Const correctness.
     199
     200        * dom/StyledElement.h:
     201        (WebCore::StyledElement::ensureInlineStyle):
     202
     203            This now implies conversion to mutable attribute data. Used by codepaths that add/remove
     204            properties, so conversion is inevitable.
     205
     206        * html/parser/HTMLConstructionSite.cpp:
     207        (WebCore::HTMLConstructionSite::mergeAttributesFromTokenIntoElement):
     208        (WebCore::HTMLConstructionSite::createHTMLElementFromSavedElement):
     209        * svg/properties/SVGAnimatedPropertyMacros.h:
     210        (WebCore::SVGSynchronizableAnimatedProperty::synchronize):
     211
     212            Use mutableAttributeData() as appropriate.
     213
     214        * xml/parser/XMLDocumentParserQt.cpp:
     215        (WebCore::XMLDocumentParser::XMLDocumentParser):
     216
     217            Const correctness.
     218
    12192012-07-25  Andrew Wilson  <atwilson@chromium.org>
    2220
  • trunk/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp

    r122600 r123636  
    404404{
    405405    ASSERT(m_propertySet);
     406    ASSERT(m_propertySet->isMutable());
    406407    return m_propertySet;
    407408}
  • trunk/Source/WebCore/css/SelectorChecker.cpp

    r123329 r123636  
    623623}
    624624
    625 static bool attributeValueMatches(Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive)
     625static bool attributeValueMatches(const Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive)
    626626{
    627627    const AtomicString& value = attributeItem->value();
     
    690690    ASSERT(element->hasAttributesWithoutUpdate());
    691691    for (size_t i = 0; i < element->attributeCount(); ++i) {
    692         Attribute* attributeItem = element->attributeItem(i);
     692        const Attribute* attributeItem = element->attributeItem(i);
    693693
    694694        if (!SelectorChecker::attributeNameMatches(attributeItem, selectorAttr))
  • trunk/Source/WebCore/css/SelectorChecker.h

    r115971 r123636  
    215215    unsigned size = element->attributeCount();
    216216    for (unsigned i = 0; i < size; ++i) {
    217         Attribute* attribute = element->attributeItem(i);
     217        const Attribute* attribute = element->attributeItem(i);
    218218        if (attributeNameMatches(attribute, selectorAttributeName) && (!value || attribute->value().impl() == value))
    219219            return true;
  • trunk/Source/WebCore/dom/DatasetDOMStringMap.cpp

    r121539 r123636  
    147147    unsigned length = m_element->attributeCount();
    148148    for (unsigned i = 0; i < length; i++) {
    149         Attribute* attribute = m_element->attributeItem(i);
     149        const Attribute* attribute = m_element->attributeItem(i);
    150150        if (isValidAttributeName(attribute->localName()))
    151151            names.append(convertAttributeNameToPropertyName(attribute->localName()));
     
    160160    unsigned length = m_element->attributeCount();
    161161    for (unsigned i = 0; i < length; i++) {
    162         Attribute* attribute = m_element->attributeItem(i);
     162        const Attribute* attribute = m_element->attributeItem(i);
    163163        if (propertyNameMatchesAttributeName(name, attribute->localName()))
    164164            return attribute->value();
     
    175175    unsigned length = m_element->attributeCount();
    176176    for (unsigned i = 0; i < length; i++) {
    177         Attribute* attribute = m_element->attributeItem(i);
     177        const Attribute* attribute = m_element->attributeItem(i);
    178178        if (propertyNameMatchesAttributeName(name, attribute->localName()))
    179179            return true;
  • trunk/Source/WebCore/dom/Element.cpp

    r123572 r123636  
    202202    ASSERT(attributeData());
    203203
    204     Attribute* attribute = attributeData()->attributeItem(index);
     204    const Attribute* attribute = attributeData()->attributeItem(index);
    205205    ASSERT(attribute);
    206206
     
    211211        attr = Attr::create(document(), attribute->name(), attribute->value());
    212212
    213     attributeData()->removeAttribute(index, this);
     213    mutableAttributeData()->removeAttribute(index, this);
    214214    return attr.release();
    215215}
     
    223223        attr->detachFromElementWithValue(attr->value());
    224224
    225     attributeData()->removeAttribute(name, this);
     225    size_t index = attributeData()->getAttributeItemIndex(name);
     226    if (index == notFound)
     227        return;
     228
     229    mutableAttributeData()->removeAttribute(index, this);
    226230}
    227231
     
    265269#endif
    266270
    267     if (m_attributeData) {
    268         if (Attribute* attribute = getAttributeItem(name))
     271    if (attributeData()) {
     272        if (const Attribute* attribute = getAttributeItem(name))
    269273            return attribute->value();
    270274    }
     
    629633#endif
    630634
    631     if (m_attributeData) {
    632         if (Attribute* attribute = m_attributeData->getAttributeItem(name, ignoreCase))
     635    if (attributeData()) {
     636        if (const Attribute* attribute = attributeData()->getAttributeItem(name, ignoreCase))
    633637            return attribute->value();
    634638    }
     
    663667inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute)
    664668{
    665     Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0;
     669    ElementAttributeData* attributeData = mutableAttributeData();
     670
     671    Attribute* old = index != notFound ? attributeData->attributeItem(index) : 0;
    666672    if (value.isNull()) {
    667673        if (old)
    668             m_attributeData->removeAttribute(index, this, inUpdateStyleAttribute);
     674            attributeData->removeAttribute(index, this, inUpdateStyleAttribute);
    669675        return;
    670676    }
    671677
    672678    if (!old) {
    673         m_attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute);
     679        attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute);
    674680        return;
    675681    }
     
    765771        return;
    766772
    767     createAttributeData();
    768     m_attributeData->m_attributes = attributeVector;
    769     m_attributeData->m_attributes.shrinkToFit();
     773    Vector<Attribute> filteredAttributes = attributeVector;
    770774
    771775    // If the element is created as result of a paste or drag-n-drop operation
     
    773777    if (scriptingPermission == DisallowScriptingContent) {
    774778        unsigned i = 0;
    775         while (i < m_attributeData->length()) {
    776             const QualifiedName& attributeName = m_attributeData->m_attributes[i].name();
    777             if (isEventHandlerAttribute(attributeName)) {
    778                 m_attributeData->m_attributes.remove(i);
     779        while (i < filteredAttributes.size()) {
     780            Attribute& attribute = filteredAttributes[i];
     781            if (isEventHandlerAttribute(attribute.name())) {
     782                filteredAttributes.remove(i);
    779783                continue;
    780784            }
    781785
    782             if (isAttributeToRemove(attributeName, m_attributeData->m_attributes[i].value()))
    783                 m_attributeData->m_attributes[i].setValue(nullAtom);
     786            if (isAttributeToRemove(attribute.name(), attribute.value()))
     787                attribute.setValue(nullAtom);
    784788            i++;
    785789        }
    786790    }
    787791
    788     // Store the set of attributes that changed on the stack in case
     792    m_attributeData = ElementAttributeData::createImmutable(filteredAttributes);
     793
     794    // Iterate over the set of attributes we already have on the stack in case
    789795    // attributeChanged mutates m_attributeData.
    790     Vector<Attribute> clonedAttributes = m_attributeData->clonedAttributeVector();
    791     for (unsigned i = 0; i < clonedAttributes.size(); ++i)
    792         attributeChanged(clonedAttributes[i]);
     796    // FIXME: Find a way so we don't have to do this.
     797    for (unsigned i = 0; i < filteredAttributes.size(); ++i)
     798        attributeChanged(filteredAttributes[i]);
    793799}
    794800
     
    796802{
    797803    updateInvalidAttributes();
    798     return m_attributeData && m_attributeData->length();
     804    return attributeData() && attributeData()->length();
    799805}
    800806
    801807bool Element::hasEquivalentAttributes(const Element* other) const
    802808{
    803     ElementAttributeData* attributeData = updatedAttributeData();
    804     ElementAttributeData* otherAttributeData = other->updatedAttributeData();
     809    const ElementAttributeData* attributeData = updatedAttributeData();
     810    const ElementAttributeData* otherAttributeData = other->updatedAttributeData();
    805811    if (attributeData)
    806812        return attributeData->isEquivalent(otherAttributeData);
     
    846852
    847853    return KURL(parentBase, baseAttribute);
    848 }
    849 
    850 void Element::createAttributeData() const
    851 {
    852     m_attributeData = ElementAttributeData::create();
    853854}
    854855
     
    13991400    }
    14001401
    1401     ElementAttributeData* attributeData = ensureUpdatedAttributeData();
    1402 
    14031402    RefPtr<Attr> oldAttr = attrIfExists(attr->qualifiedName());
    14041403    if (oldAttr.get() == attr)
     
    14121411    }
    14131412
     1413    updateInvalidAttributes();
     1414    ElementAttributeData* attributeData = mutableAttributeData();
     1415
    14141416    size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName());
    14151417    Attribute* oldAttribute = index != notFound ? attributeData->attributeItem(index) : 0;
     
    14491451    ASSERT(document() == attr->document());
    14501452
    1451     ElementAttributeData* attributeData = updatedAttributeData();
     1453    const ElementAttributeData* attributeData = updatedAttributeData();
    14521454    ASSERT(attributeData);
    14531455
     
    14841486    ASSERT(attributeData());
    14851487    ASSERT(index <= attributeCount());
    1486     attributeData()->removeAttribute(index, this);
     1488    mutableAttributeData()->removeAttribute(index, this);
    14871489}
    14881490
    14891491void Element::removeAttribute(const String& name)
    14901492{
    1491     ElementAttributeData* attributeData = this->attributeData();
    1492     if (!attributeData)
     1493    if (!attributeData())
    14931494        return;
    14941495
    14951496    String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    1496     size_t index = attributeData->getAttributeItemIndex(localName, false);
     1497    size_t index = attributeData()->getAttributeItemIndex(localName, false);
    14971498    if (index == notFound)
    14981499        return;
    14991500
    1500     attributeData->removeAttribute(index, this);
     1501    mutableAttributeData()->removeAttribute(index, this);
    15011502}
    15021503
     
    15081509PassRefPtr<Attr> Element::getAttributeNode(const String& name)
    15091510{
    1510     ElementAttributeData* attributeData = updatedAttributeData();
     1511    const ElementAttributeData* attributeData = updatedAttributeData();
    15111512    if (!attributeData)
    15121513        return 0;
     
    15161517PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName)
    15171518{
    1518     ElementAttributeData* attributeData = updatedAttributeData();
     1519    const ElementAttributeData* attributeData = updatedAttributeData();
    15191520    if (!attributeData)
    15201521        return 0;
     
    15241525bool Element::hasAttribute(const String& name) const
    15251526{
    1526     ElementAttributeData* attributeData = updatedAttributeData();
    1527     if (!attributeData)
     1527    if (!attributeData())
    15281528        return false;
    15291529
     
    15311531    // there may be a way to remove it.
    15321532    String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name;
    1533     return attributeData->getAttributeItem(localName, false);
     1533    return updatedAttributeData()->getAttributeItem(localName, false);
    15341534}
    15351535
    15361536bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const
    15371537{
    1538     ElementAttributeData* attributeData = updatedAttributeData();
     1538    const ElementAttributeData* attributeData = updatedAttributeData();
    15391539    if (!attributeData)
    15401540        return false;
     
    17431743        return;
    17441744
    1745     ElementAttributeData* attributeData = updatedAttributeData();
     1745    const ElementAttributeData* attributeData = updatedAttributeData();
    17461746    ASSERT(attributeData);
    17471747
    1748     const Vector<Attribute>& attributes = attributeData->attributeVector();
    1749     for (size_t i = 0; i < attributes.size(); ++i) {
    1750         if (RefPtr<Attr> attr = attrIfExists(attributes[i].name()))
     1748    for (size_t i = 0; i < attributeData->length(); ++i) {
     1749        if (RefPtr<Attr> attr = attrIfExists(attributeData->attributeItem(i)->name()))
    17511750            attr->normalize();
    17521751    }
     
    18171816{
    18181817#if !ASSERT_DISABLED
    1819     if (m_attributeData) {
    1820         if (Attribute* attribute = getAttributeItem(name))
     1818    if (attributeData()) {
     1819        if (const Attribute* attribute = getAttributeItem(name))
    18211820            ASSERT(isURLAttribute(*attribute));
    18221821    }
     
    18281827{
    18291828#if !ASSERT_DISABLED
    1830     if (m_attributeData) {
    1831         if (Attribute* attribute = getAttributeItem(name))
     1829    if (attributeData()) {
     1830        if (const Attribute* attribute = getAttributeItem(name))
    18321831            ASSERT(isURLAttribute(*attribute));
    18331832    }
     
    21732172void Element::cloneAttributesFromElement(const Element& other)
    21742173{
    2175     if (ElementAttributeData* attributeData = other.updatedAttributeData())
    2176         ensureUpdatedAttributeData()->cloneDataFrom(*attributeData, other, *this);
     2174    if (const ElementAttributeData* attributeData = other.updatedAttributeData())
     2175        mutableAttributeData()->cloneDataFrom(*attributeData, other, *this);
    21772176    else if (m_attributeData) {
    21782177        m_attributeData->clearAttributes(this);
     
    21872186}
    21882187
     2188void Element::createMutableAttributeData()
     2189{
     2190    if (!m_attributeData)
     2191        m_attributeData = ElementAttributeData::create();
     2192    else
     2193        m_attributeData = m_attributeData->makeMutable();
     2194}
     2195
    21892196} // namespace WebCore
  • trunk/Source/WebCore/dom/Element.h

    r123071 r123636  
    163163    // before calling them.
    164164    size_t attributeCount() const;
    165     Attribute* attributeItem(unsigned index) const;
    166     Attribute* getAttributeItem(const QualifiedName&) const;
     165    const Attribute* attributeItem(unsigned index) const;
     166    const Attribute* getAttributeItem(const QualifiedName&) const;
     167    Attribute* getAttributeItem(const QualifiedName&);
    167168    size_t getAttributeItemIndex(const QualifiedName& name) const { return attributeData()->getAttributeItemIndex(name); }
    168169    size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return attributeData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); }
     
    247248    void parserSetAttributes(const Vector<Attribute>&, FragmentScriptingPermission);
    248249
    249     ElementAttributeData* attributeData() const { return m_attributeData.get(); }
    250     ElementAttributeData* ensureAttributeData() const;
    251     ElementAttributeData* updatedAttributeData() const;
    252     ElementAttributeData* ensureUpdatedAttributeData() const;
     250    const ElementAttributeData* attributeData() const { return m_attributeData.get(); }
     251    ElementAttributeData* mutableAttributeData();
     252    const ElementAttributeData* ensureAttributeData();
     253    const ElementAttributeData* updatedAttributeData() const;
     254    const ElementAttributeData* ensureUpdatedAttributeData() const;
    253255
    254256    // Clones attributes only.
     
    435437        info.visitBaseClass<ContainerNode>(this);
    436438        info.addInstrumentedMember(m_tagName);
    437         info.addInstrumentedMember(m_attributeData.get());
     439        info.addInstrumentedMember(attributeData());
    438440    }
    439441
     
    476478    bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle);
    477479
    478     void createAttributeData() const;
    479 
    480480    virtual void updateStyleAttribute() const { }
    481481
     
    506506    void unregisterNamedFlowContentNode();
    507507
     508    void createMutableAttributeData();
     509
    508510private:
    509511    ElementRareData* elementRareData() const;
    510512    ElementRareData* ensureElementRareData();
    511513
    512     mutable OwnPtr<ElementAttributeData> m_attributeData;
     514    OwnPtr<ElementAttributeData> m_attributeData;
    513515};
    514516   
     
    570572}
    571573
    572 inline ElementAttributeData* Element::ensureAttributeData() const
    573 {
    574     if (!m_attributeData)
    575         createAttributeData();
    576     return m_attributeData.get();
    577 }
    578 
    579 inline ElementAttributeData* Element::updatedAttributeData() const
     574inline const ElementAttributeData* Element::updatedAttributeData() const
    580575{
    581576    updateInvalidAttributes();
     
    583578}
    584579
    585 inline ElementAttributeData* Element::ensureUpdatedAttributeData() const
     580inline const ElementAttributeData* Element::ensureAttributeData()
     581{
     582    if (attributeData())
     583        return attributeData();
     584    return mutableAttributeData();
     585}
     586
     587inline const ElementAttributeData* Element::ensureUpdatedAttributeData() const
    586588{
    587589    updateInvalidAttributes();
    588     return ensureAttributeData();
     590    if (attributeData())
     591        return attributeData();
     592    return const_cast<Element*>(this)->mutableAttributeData();
    589593}
    590594
     
    635639{
    636640    ASSERT(fastAttributeLookupAllowed(name));
    637     return m_attributeData && getAttributeItem(name);
     641    return attributeData() && getAttributeItem(name);
    638642}
    639643
     
    641645{
    642646    ASSERT(fastAttributeLookupAllowed(name));
    643     if (m_attributeData) {
    644         if (Attribute* attribute = getAttributeItem(name))
     647    if (attributeData()) {
     648        if (const Attribute* attribute = getAttributeItem(name))
    645649            return attribute->value();
    646650    }
     
    650654inline bool Element::hasAttributesWithoutUpdate() const
    651655{
    652     return m_attributeData && !m_attributeData->isEmpty();
     656    return attributeData() && !attributeData()->isEmpty();
    653657}
    654658
     
    656660{
    657661    ASSERT(hasID());
    658     return m_attributeData->idForStyleResolution();
     662    return attributeData()->idForStyleResolution();
    659663}
    660664
     
    685689inline size_t Element::attributeCount() const
    686690{
    687     ASSERT(m_attributeData);
    688     return m_attributeData->length();
    689 }
    690 
    691 inline Attribute* Element::attributeItem(unsigned index) const
    692 {
    693     ASSERT(m_attributeData);
    694     return m_attributeData->attributeItem(index);
    695 }
    696 
    697 inline Attribute* Element::getAttributeItem(const QualifiedName& name) const
    698 {
    699     ASSERT(m_attributeData);
    700     return m_attributeData->getAttributeItem(name);
     691    ASSERT(attributeData());
     692    return attributeData()->length();
     693}
     694
     695inline const Attribute* Element::attributeItem(unsigned index) const
     696{
     697    ASSERT(attributeData());
     698    return attributeData()->attributeItem(index);
     699}
     700
     701inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const
     702{
     703    ASSERT(attributeData());
     704    return attributeData()->getAttributeItem(name);
     705}
     706
     707inline Attribute* Element::getAttributeItem(const QualifiedName& name)
     708{
     709    ASSERT(attributeData());
     710    return mutableAttributeData()->getAttributeItem(name);
    701711}
    702712
     
    731741}
    732742
     743inline ElementAttributeData* Element::mutableAttributeData()
     744{
     745    if (!attributeData() || !attributeData()->isMutable())
     746        createMutableAttributeData();
     747    return m_attributeData.get();
     748}
     749
    733750// Put here to make them inline.
    734751inline bool Node::hasID() const
  • trunk/Source/WebCore/dom/ElementAttributeData.cpp

    r122600 r123636  
    3333namespace WebCore {
    3434
     35PassOwnPtr<ElementAttributeData> ElementAttributeData::createImmutable(const Vector<Attribute>& attributes)
     36{
     37    void* slot = WTF::fastMalloc(sizeof(ElementAttributeData) - sizeof(void*) + sizeof(Attribute) * attributes.size());
     38    return adoptPtr(new (slot) ElementAttributeData(attributes));
     39}
     40
     41ElementAttributeData::ElementAttributeData()
     42    : m_isMutable(true)
     43    , m_arraySize(0)
     44    , m_mutableAttributeVector(new Vector<Attribute, 4>)
     45{
     46}
     47
     48ElementAttributeData::ElementAttributeData(const Vector<Attribute>& attributes)
     49    : m_isMutable(false)
     50    , m_arraySize(attributes.size())
     51{
     52    Attribute* buffer = reinterpret_cast<Attribute*>(&m_attributes);
     53    for (unsigned i = 0; i < attributes.size(); ++i)
     54        new (&buffer[i]) Attribute(attributes[i]);
     55}
     56
     57ElementAttributeData::ElementAttributeData(const ElementAttributeData& other)
     58    : m_inlineStyleDecl(other.m_inlineStyleDecl)
     59    , m_attributeStyle(other.m_attributeStyle)
     60    , m_classNames(other.m_classNames)
     61    , m_idForStyleResolution(other.m_idForStyleResolution)
     62    , m_isMutable(true)
     63    , m_arraySize(0)
     64    , m_mutableAttributeVector(new Vector<Attribute, 4>)
     65{
     66    // This copy constructor should only be used by makeMutable() to go from immutable to mutable.
     67    ASSERT(!other.m_isMutable);
     68
     69    const Attribute* otherBuffer = reinterpret_cast<const Attribute*>(&other.m_attributes);
     70    for (unsigned i = 0; i < other.m_arraySize; ++i)
     71        m_mutableAttributeVector->append(otherBuffer[i]);
     72}
     73
     74ElementAttributeData::~ElementAttributeData()
     75{
     76    if (isMutable()) {
     77        ASSERT(!m_arraySize);
     78        delete m_mutableAttributeVector;
     79    } else {
     80        Attribute* buffer = reinterpret_cast<Attribute*>(&m_attributes);
     81        for (unsigned i = 0; i < m_arraySize; ++i)
     82            buffer[i].~Attribute();
     83    }
     84}
     85
    3586typedef Vector<RefPtr<Attr> > AttrList;
    3687typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;
     
    82133}
    83134
    84 PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name)
     135PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) const
    85136{
    86137    if (AttrList* attrList = attrListForElement(element))
     
    89140}
    90141
    91 PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name)
     142PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) const
    92143{
    93144    AttrList* attrList = ensureAttrListForElement(element);
     
    100151}
    101152
    102 void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr)
     153void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) const
    103154{
    104155    AttrList* attrList = ensureAttrListForElement(element);
     
    111162}
    112163
    113 void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name)
     164void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) const
    114165{
    115166    AttrList* attrList = attrListForElement(element);
     
    128179}
    129180
    130 void ElementAttributeData::setClass(const String& className, bool shouldFoldCase)
    131 {
    132     m_classNames.set(className, shouldFoldCase);
    133 }
    134    
    135181StylePropertySet* ElementAttributeData::ensureInlineStyle(StyledElement* element)
    136182{
     183    ASSERT(isMutable());
    137184    if (!m_inlineStyleDecl) {
    138185        ASSERT(element->isStyledElement());
     
    144191StylePropertySet* ElementAttributeData::ensureMutableInlineStyle(StyledElement* element)
    145192{
     193    ASSERT(isMutable());
    146194    if (m_inlineStyleDecl && !m_inlineStyleDecl->isMutable()) {
    147195        m_inlineStyleDecl = m_inlineStyleDecl->copy();
     
    151199}
    152200   
    153 void ElementAttributeData::updateInlineStyleAvoidingMutation(StyledElement* element, const String& text)
     201void ElementAttributeData::updateInlineStyleAvoidingMutation(StyledElement* element, const String& text) const
    154202{
    155203    // We reconstruct the property set instead of mutating if there is no CSSOM wrapper.
     
    162210}
    163211
    164 void ElementAttributeData::destroyInlineStyle(StyledElement* element)
     212void ElementAttributeData::destroyInlineStyle(StyledElement* element) const
    165213{
    166214    if (!m_inlineStyleDecl)
     
    172220void ElementAttributeData::addAttribute(const Attribute& attribute, Element* element, EInUpdateStyleAttribute inUpdateStyleAttribute)
    173221{
     222    ASSERT(isMutable());
     223
    174224    if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute)
    175225        element->willModifyAttribute(attribute.name(), nullAtom, attribute.value());
    176226
    177     m_attributes.append(attribute);
     227    m_mutableAttributeVector->append(attribute);
    178228
    179229    if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute)
     
    183233void ElementAttributeData::removeAttribute(size_t index, Element* element, EInUpdateStyleAttribute inUpdateStyleAttribute)
    184234{
     235    ASSERT(isMutable());
    185236    ASSERT(index < length());
    186237
    187     Attribute& attribute = m_attributes[index];
     238    Attribute& attribute = m_mutableAttributeVector->at(index);
    188239    QualifiedName name = attribute.name();
    189240
     
    194245        attr->detachFromElementWithValue(attribute.value());
    195246
    196     m_attributes.remove(index);
     247    m_mutableAttributeVector->remove(index);
    197248
    198249    if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute)
     
    210261
    211262    for (unsigned i = 0; i < len; i++) {
    212         Attribute* otherAttr = other->getAttributeItem(m_attributes[i].name());
    213         if (!otherAttr || m_attributes[i].value() != otherAttr->value())
     263        const Attribute* attribute = attributeItem(i);
     264        const Attribute* otherAttr = other->getAttributeItem(attribute->name());
     265        if (!otherAttr || attribute->value() != otherAttr->value())
    214266            return false;
    215267    }
     
    218270}
    219271
    220 void ElementAttributeData::detachAttrObjectsFromElement(Element* element)
     272void ElementAttributeData::detachAttrObjectsFromElement(Element* element) const
    221273{
    222274    ASSERT(element->hasAttrList());
    223275
    224     for (unsigned i = 0; i < m_attributes.size(); ++i) {
    225         if (RefPtr<Attr> attr = attrIfExists(element, m_attributes[i].name()))
    226             attr->detachFromElementWithValue(m_attributes[i].value());
     276    for (unsigned i = 0; i < length(); ++i) {
     277        const Attribute* attribute = attributeItem(i);
     278        if (RefPtr<Attr> attr = attrIfExists(element, attribute->name()))
     279            attr->detachFromElementWithValue(attribute->value());
    227280    }
    228281
     
    234287{
    235288    // Continue to checking case-insensitively and/or full namespaced names if necessary:
    236     for (unsigned i = 0; i < m_attributes.size(); ++i) {
    237         if (!m_attributes[i].name().hasPrefix()) {
    238             if (shouldIgnoreAttributeCase && equalIgnoringCase(name, m_attributes[i].localName()))
     289    for (unsigned i = 0; i < length(); ++i) {
     290        const Attribute* attribute = attributeItem(i);
     291        if (!attribute->name().hasPrefix()) {
     292            if (shouldIgnoreAttributeCase && equalIgnoringCase(name, attribute->localName()))
    239293                return i;
    240294        } else {
     
    242296            // generates a temporary string by concatenation. But this branch is only reached
    243297            // if the attribute name has a prefix, which is rare in HTML.
    244             if (equalPossiblyIgnoringCase(name, m_attributes[i].name().toString(), shouldIgnoreAttributeCase))
     298            if (equalPossiblyIgnoringCase(name, attribute->name().toString(), shouldIgnoreAttributeCase))
    245299                return i;
    246300        }
     
    251305void ElementAttributeData::cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement)
    252306{
     307    // FIXME: Cloned elements could start out with immutable attribute data.
     308    ASSERT(isMutable());
     309
    253310    const AtomicString& oldID = targetElement.getIdAttribute();
    254311    const AtomicString& newID = sourceElement.getIdAttribute();
     
    264321
    265322    clearAttributes(&targetElement);
    266     m_attributes = sourceData.m_attributes;
    267     for (unsigned i = 0; i < m_attributes.size(); ++i) {
    268         if (targetElement.isStyledElement() && m_attributes[i].name() == HTMLNames::styleAttr) {
    269             static_cast<StyledElement&>(targetElement).styleAttributeChanged(m_attributes[i].value(), StyledElement::DoNotReparseStyleAttribute);
     323
     324    if (sourceData.isMutable())
     325        *m_mutableAttributeVector = *sourceData.m_mutableAttributeVector;
     326    else {
     327        ASSERT(m_mutableAttributeVector->isEmpty());
     328        m_mutableAttributeVector->reserveInitialCapacity(sourceData.m_arraySize);
     329        const Attribute* sourceBuffer = reinterpret_cast<const Attribute*>(&sourceData.m_attributes);
     330        for (unsigned i = 0; i < sourceData.m_arraySize; ++i)
     331            m_mutableAttributeVector->uncheckedAppend(sourceBuffer[i]);
     332    }
     333
     334    for (unsigned i = 0; i < length(); ++i) {
     335        const Attribute& attribute = m_mutableAttributeVector->at(i);
     336        if (targetElement.isStyledElement() && attribute.name() == HTMLNames::styleAttr) {
     337            static_cast<StyledElement&>(targetElement).styleAttributeChanged(attribute.value(), StyledElement::DoNotReparseStyleAttribute);
    270338            continue;
    271339        }
    272         targetElement.attributeChanged(m_attributes[i]);
     340        targetElement.attributeChanged(attribute);
    273341    }
    274342
     
    283351void ElementAttributeData::clearAttributes(Element* element)
    284352{
     353    ASSERT(isMutable());
     354
    285355    if (element->hasAttrList())
    286356        detachAttrObjectsFromElement(element);
    287357
    288358    clearClass();
    289     m_attributes.clear();
     359    m_mutableAttributeVector->clear();
    290360}
    291361
    292362void ElementAttributeData::replaceAttribute(size_t index, const Attribute& attribute, Element* element)
    293363{
     364    ASSERT(isMutable());
    294365    ASSERT(element);
    295366    ASSERT(index < length());
    296367
    297     element->willModifyAttribute(attribute.name(), m_attributes[index].value(), attribute.value());
    298     m_attributes[index] = attribute;
     368    element->willModifyAttribute(attribute.name(), m_mutableAttributeVector->at(index).value(), attribute.value());
     369    (*m_mutableAttributeVector)[index] = attribute;
    299370    element->didModifyAttribute(attribute);
    300371}
     
    303374{
    304375    ASSERT(element);
    305     Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase);
     376    const Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase);
    306377    if (!attribute)
    307378        return 0;
    308     return const_cast<ElementAttributeData*>(this)->ensureAttr(element, attribute->name());
     379    return ensureAttr(element, attribute->name());
    309380}
    310381
     
    312383{
    313384    ASSERT(element);
    314     Attribute* attribute = getAttributeItem(name);
     385    const Attribute* attribute = getAttributeItem(name);
    315386    if (!attribute)
    316387        return 0;
    317     return const_cast<ElementAttributeData*>(this)->ensureAttr(element, attribute->name());
    318 }
    319 
    320 
    321 }
     388    return ensureAttr(element, attribute->name());
     389}
     390
     391}
  • trunk/Source/WebCore/dom/ElementAttributeData.h

    r122735 r123636  
    3838class Element;
    3939
    40 inline Attribute* findAttributeInVector(const Vector<Attribute>& attributes, const QualifiedName& name)
    41 {
    42     for (unsigned i = 0; i < attributes.size(); ++i) {
    43         if (attributes.at(i).name().matches(name))
    44             return &const_cast<Vector<Attribute>& >(attributes).at(i);
    45     }
    46     return 0;
    47 }
    48 
    4940enum EInUpdateStyleAttribute { NotInUpdateStyleAttribute, InUpdateStyleAttribute };
    5041
     
    5243    WTF_MAKE_FAST_ALLOCATED;
    5344public:
    54     static PassOwnPtr<ElementAttributeData> create()
    55     {
    56         return adoptPtr(new ElementAttributeData);
    57     }
     45    static PassOwnPtr<ElementAttributeData> create() { return adoptPtr(new ElementAttributeData); }
     46    static PassOwnPtr<ElementAttributeData> createImmutable(const Vector<Attribute>&);
     47    ~ElementAttributeData();
    5848
    5949    void clearClass() { m_classNames.clear(); }
    60     void setClass(const String& className, bool shouldFoldCase);
     50    void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
    6151    const SpaceSplitString& classNames() const { return m_classNames; }
    6252
    6353    const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; }
    64     void setIdForStyleResolution(const AtomicString& newId) { m_idForStyleResolution = newId; }
    65 
     54    void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; }
     55
     56    const StylePropertySet* inlineStyle() const { return m_inlineStyleDecl.get(); }
    6657    StylePropertySet* inlineStyle() { return m_inlineStyleDecl.get(); }
    6758    StylePropertySet* ensureInlineStyle(StyledElement*);
    6859    StylePropertySet* ensureMutableInlineStyle(StyledElement*);
    69     void updateInlineStyleAvoidingMutation(StyledElement*, const String& text);
    70     void destroyInlineStyle(StyledElement*);
     60    void updateInlineStyleAvoidingMutation(StyledElement*, const String& text) const;
     61    void destroyInlineStyle(StyledElement*) const;
    7162
    7263    StylePropertySet* attributeStyle() const { return m_attributeStyle.get(); }
    73     void setAttributeStyle(PassRefPtr<StylePropertySet> style) { m_attributeStyle = style; }
    74 
    75     size_t length() const { return m_attributes.size(); }
    76     bool isEmpty() const { return m_attributes.isEmpty(); }
     64    void setAttributeStyle(PassRefPtr<StylePropertySet> style) const { m_attributeStyle = style; }
     65
     66    size_t length() const;
     67    bool isEmpty() const { return !length(); }
    7768
    7869    PassRefPtr<Attr> getAttributeNode(const String&, bool shouldIgnoreAttributeCase, Element*) const;
     
    8071
    8172    // Internal interface.
    82     Attribute* attributeItem(unsigned index) const { return &const_cast<ElementAttributeData*>(this)->m_attributes[index]; }
    83     Attribute* getAttributeItem(const QualifiedName& name) const { return findAttributeInVector(m_attributes, name); }
     73    const Attribute* attributeItem(unsigned index) const;
     74    const Attribute* getAttributeItem(const QualifiedName&) const;
     75    Attribute* attributeItem(unsigned index);
     76    Attribute* getAttributeItem(const QualifiedName&);
    8477    size_t getAttributeItemIndex(const QualifiedName&) const;
    8578    size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
     
    9689    bool isEquivalent(const ElementAttributeData* other) const;
    9790
    98     void setAttr(Element*, const QualifiedName&, Attr*);
    99     void removeAttr(Element*, const QualifiedName&);
    100     PassRefPtr<Attr> attrIfExists(Element*, const QualifiedName&);
    101     PassRefPtr<Attr> ensureAttr(Element*, const QualifiedName&);
     91    void setAttr(Element*, const QualifiedName&, Attr*) const;
     92    void removeAttr(Element*, const QualifiedName&) const;
     93    PassRefPtr<Attr> attrIfExists(Element*, const QualifiedName&) const;
     94    PassRefPtr<Attr> ensureAttr(Element*, const QualifiedName&) const;
     95    void detachAttrObjectsFromElement(Element*) const;
    10296
    10397    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
    10498    {
    105         MemoryClassInfo<ElementAttributeData> info(memoryObjectInfo, this, MemoryInstrumentation::DOM);
     99        MemoryClassInfo<ElementAttributeData> info(memoryObjectInfo, this, MemoryInstrumentation::DOM, m_arraySize * sizeof(Attribute));
    106100        info.addInstrumentedMember(m_inlineStyleDecl.get());
    107101        info.addInstrumentedMember(m_attributeStyle.get());
    108102        info.addMember(m_classNames);
    109103        info.addString(m_idForStyleResolution);
    110         info.addVector(m_attributes);
     104        if (m_isMutable)
     105            info.addVector(*m_mutableAttributeVector);
    111106    }
    112107
     
    115110    friend class HTMLConstructionSite;
    116111
    117     ElementAttributeData()
    118     {
    119     }
    120 
    121     const Vector<Attribute>& attributeVector() const { return m_attributes; }
    122     Vector<Attribute> clonedAttributeVector() const { return m_attributes; }
    123 
    124     void detachAttrObjectsFromElement(Element*);
    125     Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
     112    ElementAttributeData();
     113    ElementAttributeData(const ElementAttributeData&);
     114    ElementAttributeData(const Vector<Attribute>&);
     115
     116    Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase);
     117    const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    126118    size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
    127119    void cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement);
     
    129121    void replaceAttribute(size_t index, const Attribute&, Element*);
    130122
    131     RefPtr<StylePropertySet> m_inlineStyleDecl;
    132     RefPtr<StylePropertySet> m_attributeStyle;
    133     SpaceSplitString m_classNames;
    134     AtomicString m_idForStyleResolution;
    135     Vector<Attribute> m_attributes;
     123    bool isMutable() const { return m_isMutable; }
     124    PassOwnPtr<ElementAttributeData> makeMutable() const { return adoptPtr(new ElementAttributeData(*this)); }
     125
     126    mutable RefPtr<StylePropertySet> m_inlineStyleDecl;
     127    mutable RefPtr<StylePropertySet> m_attributeStyle;
     128    mutable SpaceSplitString m_classNames;
     129    mutable AtomicString m_idForStyleResolution;
     130
     131    unsigned m_isMutable : 1;
     132    unsigned m_arraySize : 31;
     133
     134    union {
     135        Vector<Attribute, 4>* m_mutableAttributeVector;
     136        void* m_attributes;
     137    };
    136138};
     139
     140inline size_t ElementAttributeData::length() const
     141{
     142    if (isMutable())
     143        return m_mutableAttributeVector->size();
     144    return m_arraySize;
     145}
    137146
    138147inline void ElementAttributeData::removeAttribute(const QualifiedName& name, Element* element)
     
    143152
    144153    removeAttribute(index, element);
    145     return;
    146 }
    147 
    148 inline Attribute* ElementAttributeData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
     154}
     155
     156inline Attribute* ElementAttributeData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase)
    149157{
    150158    size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
    151159    if (index != notFound)
    152         return &const_cast<ElementAttributeData*>(this)->m_attributes[index];
     160        return attributeItem(index);
     161    return 0;
     162}
     163
     164inline const Attribute* ElementAttributeData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const
     165{
     166    size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase);
     167    if (index != notFound)
     168        return attributeItem(index);
    153169    return 0;
    154170}
     
    156172inline size_t ElementAttributeData::getAttributeItemIndex(const QualifiedName& name) const
    157173{
    158     for (unsigned i = 0; i < m_attributes.size(); ++i) {
    159         if (m_attributes.at(i).name().matches(name))
     174    for (unsigned i = 0; i < length(); ++i) {
     175        if (attributeItem(i)->name().matches(name))
    160176            return i;
    161177    }
     
    172188    // Optimize for the case where the attribute exists and its name exactly matches.
    173189    for (unsigned i = 0; i < len; ++i) {
    174         if (!m_attributes[i].name().hasPrefix()) {
    175             if (name == m_attributes[i].localName())
     190        const Attribute* attribute = attributeItem(i);
     191        if (!attribute->name().hasPrefix()) {
     192            if (name == attribute->localName())
    176193                return i;
    177194        } else
     
    184201}
    185202
     203inline const Attribute* ElementAttributeData::getAttributeItem(const QualifiedName& name) const
     204{
     205    for (unsigned i = 0; i < length(); ++i) {
     206        if (attributeItem(i)->name().matches(name))
     207            return attributeItem(i);
     208    }
     209    return 0;
     210}
     211
     212inline Attribute* ElementAttributeData::getAttributeItem(const QualifiedName& name)
     213{
     214    for (unsigned i = 0; i < length(); ++i) {
     215        if (attributeItem(i)->name().matches(name))
     216            return attributeItem(i);
     217    }
     218    return 0;
     219}
     220
     221inline const Attribute* ElementAttributeData::attributeItem(unsigned index) const
     222{
     223    ASSERT(index < length());
     224    if (isMutable())
     225        return &m_mutableAttributeVector->at(index);
     226    const Attribute* buffer = reinterpret_cast<const Attribute*>(&m_attributes);
     227    return &buffer[index];
     228}
     229
     230inline Attribute* ElementAttributeData::attributeItem(unsigned index)
     231{
     232    ASSERT(isMutable());
     233    ASSERT(index < length());
     234    return &m_mutableAttributeVector->at(index);
     235}
     236
    186237}
    187238
  • trunk/Source/WebCore/dom/Node.cpp

    r123434 r123636  
    17041704            if (elem->hasAttributes()) {
    17051705                for (unsigned i = 0; i < elem->attributeCount(); i++) {
    1706                     Attribute* attr = elem->attributeItem(i);
     1706                    const Attribute* attr = elem->attributeItem(i);
    17071707                   
    17081708                    if (attr->localName() == xmlnsAtom)
     
    17881788            if (elem->hasAttributes()) {
    17891789                for (unsigned i = 0; i < elem->attributeCount(); i++) {
    1790                     Attribute* attr = elem->attributeItem(i);
     1790                    const Attribute* attr = elem->attributeItem(i);
    17911791                   
    17921792                    if (attr->prefix() == xmlnsAtom && attr->localName() == prefix) {
     
    18431843    if (thisElement->hasAttributes()) {
    18441844        for (unsigned i = 0; i < thisElement->attributeCount(); i++) {
    1845             Attribute* attr = thisElement->attributeItem(i);
     1845            const Attribute* attr = thisElement->attributeItem(i);
    18461846           
    18471847            if (attr->prefix() == xmlnsAtom && attr->value() == _namespaceURI
     
    19921992            // when comparing two attributes of the same element, and inserting or removing additional attributes might change
    19931993            // the order between existing attributes.
    1994             Attribute* attribute = owner1->attributeItem(i);
     1994            const Attribute* attribute = owner1->attributeItem(i);
    19951995            if (attr1->qualifiedName() == attribute->name())
    19961996                return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING;
  • trunk/Source/WebCore/dom/StyledElement.cpp

    r123377 r123636  
    143143CSSStyleDeclaration* StyledElement::style()
    144144{
    145     return ensureAttributeData()->ensureMutableInlineStyle(this)->ensureInlineCSSStyleDeclaration(this);
     145    return ensureInlineStyle()->ensureInlineCSSStyleDeclaration(this);
    146146}
    147147
     
    174174            static_cast<ClassList*>(classList)->reset(newClassString);
    175175    } else if (attributeData())
    176         attributeData()->clearClass();
     176        mutableAttributeData()->clearClass();
    177177    setNeedsStyleRecalc();
    178178}
     
    211211bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, int identifier, bool important)
    212212{
    213     ensureAttributeData()->ensureMutableInlineStyle(this)->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
     213    ensureInlineStyle()->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);
    214214    inlineStyleChanged();
    215215    return true;
     
    218218bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important)
    219219{
    220     ensureAttributeData()->ensureMutableInlineStyle(this)->setProperty(propertyID, cssValuePool().createValue(value, unit), important);
     220    ensureInlineStyle()->setProperty(propertyID, cssValuePool().createValue(value, unit), important);
    221221    inlineStyleChanged();
    222222    return true;
     
    225225bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, const String& value, bool important)
    226226{
    227     bool changes = ensureAttributeData()->ensureMutableInlineStyle(this)->setProperty(propertyID, value, important, document()->elementSheet()->contents());
     227    bool changes = ensureInlineStyle()->setProperty(propertyID, value, important, document()->elementSheet()->contents());
    228228    if (changes)
    229229        inlineStyleChanged();
     
    233233bool StyledElement::removeInlineStyleProperty(CSSPropertyID propertyID)
    234234{
    235     StylePropertySet* inlineStyle = attributeData() ? attributeData()->inlineStyle() : 0;
    236     if (!inlineStyle)
     235    if (!attributeData() || !attributeData()->inlineStyle())
    237236        return false;
    238     bool changes = inlineStyle->removeProperty(propertyID);
     237    bool changes = ensureInlineStyle()->removeProperty(propertyID);
    239238    if (changes)
    240239        inlineStyleChanged();
     
    244243void StyledElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const
    245244{
    246     if (StylePropertySet* inlineStyle = attributeData() ? attributeData()->inlineStyle() : 0)
     245    if (const StylePropertySet* inlineStyle = attributeData() ? attributeData()->inlineStyle() : 0)
    247246        inlineStyle->addSubresourceStyleURLs(urls, document()->elementSheet()->contents());
    248247}
     
    264263    unsigned size = attributeCount();
    265264    for (unsigned i = 0; i < size; ++i) {
    266         Attribute* attribute = attributeItem(i);
     265        const Attribute* attribute = attributeItem(i);
    267266        if (!isPresentationAttribute(attribute->name()))
    268267            continue;
     
    314313        unsigned size = attributeCount();
    315314        for (unsigned i = 0; i < size; ++i) {
    316             Attribute* attribute = attributeItem(i);
     315            const Attribute* attribute = attributeItem(i);
    317316            collectStyleForAttribute(*attribute, style.get());
    318317        }
  • trunk/Source/WebCore/dom/StyledElement.h

    r122600 r123636  
    4242
    4343    const StylePropertySet* inlineStyle() const { return attributeData() ? attributeData()->inlineStyle() : 0; }
    44     const StylePropertySet* ensureInlineStyle() { return ensureAttributeData()->ensureInlineStyle(this); }
     44    StylePropertySet* ensureInlineStyle() { return mutableAttributeData()->ensureMutableInlineStyle(this); }
    4545   
    4646    // Unlike StylePropertySet setters, these implement invalidation.
  • trunk/Source/WebCore/editing/markup.cpp

    r120168 r123636  
    111111            unsigned length = e->attributeCount();
    112112            for (unsigned i = 0; i < length; i++) {
    113                 Attribute* attribute = e->attributeItem(i);
     113                const Attribute* attribute = e->attributeItem(i);
    114114                if (e->isURLAttribute(*attribute))
    115115                    changes.append(AttributeChange(e, attribute->name(), KURL(parsedBaseURL, attribute->value()).string()));
     
    295295    const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldApplyWrappingStyle(element);
    296296    for (unsigned int i = 0; i < length; i++) {
    297         Attribute* attribute = element->attributeItem(i);
     297        const Attribute* attribute = element->attributeItem(i);
    298298        // We'll handle the style attribute separately, below.
    299299        if (attribute->name() == styleAttr && shouldOverrideStyleAttr)
  • trunk/Source/WebCore/html/HTMLEmbedElement.cpp

    r118963 r123636  
    121121
    122122    for (unsigned i = 0; i < attributeCount(); ++i) {
    123         Attribute* it = attributeItem(i);
    124         paramNames.append(it->localName().string());
    125         paramValues.append(it->value().string());
     123        const Attribute* attribute = attributeItem(i);
     124        paramNames.append(attribute->localName().string());
     125        paramValues.append(attribute->value().string());
    126126    }
    127127}
  • trunk/Source/WebCore/html/HTMLObjectElement.cpp

    r120049 r123636  
    193193    if (hasAttributes()) {
    194194        for (unsigned i = 0; i < attributeCount(); ++i) {
    195             Attribute* it = attributeItem(i);
    196             const AtomicString& name = it->name().localName();
     195            const Attribute* attribute = attributeItem(i);
     196            const AtomicString& name = attribute->name().localName();
    197197            if (!uniqueParamNames.contains(name.impl())) {
    198198                paramNames.append(name.string());
    199                 paramValues.append(it->value().string());
     199                paramValues.append(attribute->value().string());
    200200            }
    201201        }
  • trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp

    r123581 r123636  
    207207        return;
    208208
    209     ElementAttributeData* elementAttributeData = element->ensureAttributeData();
     209    ElementAttributeData* elementAttributeData = element->mutableAttributeData();
    210210
    211211    for (unsigned i = 0; i < token->attributes().size(); ++i) {
  • trunk/Source/WebCore/inspector/DOMPatchSupport.cpp

    r122652 r123636  
    178178        if (oldElement->hasAttributesWithoutUpdate()) {
    179179            while (oldElement->attributeCount()) {
    180                 Attribute* attr = oldElement->attributeItem(0);
    181                 if (!m_domEditor->removeAttribute(oldElement, attr->localName(), ec))
     180                const Attribute* attribute = oldElement->attributeItem(0);
     181                if (!m_domEditor->removeAttribute(oldElement, attribute->localName(), ec))
    182182                    return false;
    183183            }
  • trunk/Source/WebCore/page/PageSerializer.cpp

    r118934 r123636  
    7474    if (element->hasAttributes()) {
    7575        for (unsigned i = 0; i < element->attributeCount(); ++i) {
    76             Attribute* item = element->attributeItem(i);
     76            const Attribute* attribute = element->attributeItem(i);
    7777            // FIXME: We should deal appropriately with the attribute if they have a namespace.
    78             attributes.append(std::make_pair(item->name().toString(), item->value().string()));
     78            attributes.append(std::make_pair(attribute->name().toString(), attribute->value().string()));
    7979        }
    8080    }
  • trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h

    r118735 r123636  
    6060        // that could cause the SVGElement to erroneously reset its properties.
    6161        // svg/dom/SVGStringList-basics.xhtml exercises this behavior.
    62         ElementAttributeData* attributeData = ownerElement->ensureUpdatedAttributeData();
     62        ElementAttributeData* attributeData = ownerElement->mutableAttributeData();
    6363        Attribute* old = attributeData->getAttributeItem(attrName);
    6464        if (old && value.isNull())
  • trunk/Source/WebCore/xml/XPathFunctions.cpp

    r112555 r123636  
    588588    String lang = arg(0)->evaluate().toString();
    589589
    590     Attribute* languageAttribute = 0;
     590    const Attribute* languageAttribute = 0;
    591591    Node* node = evaluationContext().node.get();
    592592    while (node) {
  • trunk/Source/WebCore/xml/parser/MarkupTokenBase.h

    r123542 r123636  
    3737namespace WebCore {
    3838
     39static inline Attribute* findAttributeInVector(Vector<Attribute>& attributes, const QualifiedName& name)
     40{
     41    for (unsigned i = 0; i < attributes.size(); ++i) {
     42        if (attributes.at(i).name().matches(name))
     43            return &attributes.at(i);
     44    }
     45    return 0;
     46}
     47
     48
    3949class DoctypeDataBase {
    4050    WTF_MAKE_NONCOPYABLE(DoctypeDataBase);
  • trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp

    r117731 r123636  
    606606        if (element->hasAttributes()) {
    607607            for (unsigned i = 0; i < element->attributeCount(); i++) {
    608                 Attribute* attr = element->attributeItem(i);
    609                 if (attr->localName() == xmlnsAtom)
    610                     m_defaultNamespaceURI = attr->value();
    611                 else if (attr->prefix() == xmlnsAtom)
    612                     m_prefixToNamespaceMap.set(attr->localName(), attr->value());
     608                const Attribute* attribute = element->attributeItem(i);
     609                if (attribute->localName() == xmlnsAtom)
     610                    m_defaultNamespaceURI = attribute->value();
     611                else if (attribute->prefix() == xmlnsAtom)
     612                    m_prefixToNamespaceMap.set(attribute->localName(), attribute->value());
    613613            }
    614614        }
  • trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp

    r122600 r123636  
    139139    QXmlStreamNamespaceDeclarations namespaces;
    140140    for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) {
    141         if (ElementAttributeData* attrs = element->updatedAttributeData()) {
     141        if (const ElementAttributeData* attrs = element->updatedAttributeData()) {
    142142            for (unsigned i = 0; i < attrs->length(); i++) {
    143                 Attribute* attr = attrs->attributeItem(i);
     143                const Attribute* attr = attrs->attributeItem(i);
    144144                if (attr->localName() == "xmlns")
    145145                    m_defaultNamespaceURI = attr->value();
  • trunk/Source/WebCore/xml/parser/XMLTreeBuilder.cpp

    r114870 r123636  
    8383        if (element->hasAttributes()) {
    8484            for (size_t i = 0; i < element->attributeCount(); ++i) {
    85                 Attribute* attr = element->attributeItem(i);
    86                 if (attr->localName() == xmlnsAtom)
    87                     stackItem.setNamespaceURI(attr->value());
    88                 else if (attr->prefix() == xmlnsAtom)
    89                     stackItem.setNamespaceURI(attr->localName(), attr->value());
     85                const Attribute* attribute = element->attributeItem(i);
     86                if (attribute->localName() == xmlnsAtom)
     87                    stackItem.setNamespaceURI(attribute->value());
     88                else if (attribute->prefix() == xmlnsAtom)
     89                    stackItem.setNamespaceURI(attribute->localName(), attribute->value());
    9090            }
    9191        }
Note: See TracChangeset for help on using the changeset viewer.