Changeset 123636 in webkit
- Timestamp:
- Jul 25, 2012 11:14:13 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r123634 r123636 1 2012-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 1 13 2012-07-25 Konrad Piascik <kpiascik@rim.com> 2 14 -
trunk/LayoutTests/fast/dom/attr-style-too-lazy-expected.txt
r117956 r123636 6 6 PASS styleAttr.value is 'background-color: white; ' 7 7 PASS styleAttr.value is 'background-color: green; ' 8 PASS oldStyleAttr.value is 'background-color: red; ' 8 9 PASS successfullyParsed is true 9 10 -
trunk/LayoutTests/fast/dom/attr-style-too-lazy.html
r117956 r123636 17 17 shouldBe("styleAttr.value", "'background-color: green; '"); 18 18 19 e.style.backgroundColor = 'red'; 20 var oldStyleAttr = e.setAttributeNode(document.createAttribute("style")); 21 shouldBe("oldStyleAttr.value", "'background-color: red; '"); 22 19 23 </script> 20 24 <script src="../js/resources/js-test-post.js"></script> -
trunk/Source/WebCore/ChangeLog
r123635 r123636 1 2012-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 1 219 2012-07-25 Andrew Wilson <atwilson@chromium.org> 2 220 -
trunk/Source/WebCore/css/PropertySetCSSStyleDeclaration.cpp
r122600 r123636 404 404 { 405 405 ASSERT(m_propertySet); 406 ASSERT(m_propertySet->isMutable()); 406 407 return m_propertySet; 407 408 } -
trunk/Source/WebCore/css/SelectorChecker.cpp
r123329 r123636 623 623 } 624 624 625 static bool attributeValueMatches( Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive)625 static bool attributeValueMatches(const Attribute* attributeItem, CSSSelector::Match match, const AtomicString& selectorValue, bool caseSensitive) 626 626 { 627 627 const AtomicString& value = attributeItem->value(); … … 690 690 ASSERT(element->hasAttributesWithoutUpdate()); 691 691 for (size_t i = 0; i < element->attributeCount(); ++i) { 692 Attribute* attributeItem = element->attributeItem(i);692 const Attribute* attributeItem = element->attributeItem(i); 693 693 694 694 if (!SelectorChecker::attributeNameMatches(attributeItem, selectorAttr)) -
trunk/Source/WebCore/css/SelectorChecker.h
r115971 r123636 215 215 unsigned size = element->attributeCount(); 216 216 for (unsigned i = 0; i < size; ++i) { 217 Attribute* attribute = element->attributeItem(i);217 const Attribute* attribute = element->attributeItem(i); 218 218 if (attributeNameMatches(attribute, selectorAttributeName) && (!value || attribute->value().impl() == value)) 219 219 return true; -
trunk/Source/WebCore/dom/DatasetDOMStringMap.cpp
r121539 r123636 147 147 unsigned length = m_element->attributeCount(); 148 148 for (unsigned i = 0; i < length; i++) { 149 Attribute* attribute = m_element->attributeItem(i);149 const Attribute* attribute = m_element->attributeItem(i); 150 150 if (isValidAttributeName(attribute->localName())) 151 151 names.append(convertAttributeNameToPropertyName(attribute->localName())); … … 160 160 unsigned length = m_element->attributeCount(); 161 161 for (unsigned i = 0; i < length; i++) { 162 Attribute* attribute = m_element->attributeItem(i);162 const Attribute* attribute = m_element->attributeItem(i); 163 163 if (propertyNameMatchesAttributeName(name, attribute->localName())) 164 164 return attribute->value(); … … 175 175 unsigned length = m_element->attributeCount(); 176 176 for (unsigned i = 0; i < length; i++) { 177 Attribute* attribute = m_element->attributeItem(i);177 const Attribute* attribute = m_element->attributeItem(i); 178 178 if (propertyNameMatchesAttributeName(name, attribute->localName())) 179 179 return true; -
trunk/Source/WebCore/dom/Element.cpp
r123572 r123636 202 202 ASSERT(attributeData()); 203 203 204 Attribute* attribute = attributeData()->attributeItem(index);204 const Attribute* attribute = attributeData()->attributeItem(index); 205 205 ASSERT(attribute); 206 206 … … 211 211 attr = Attr::create(document(), attribute->name(), attribute->value()); 212 212 213 attributeData()->removeAttribute(index, this);213 mutableAttributeData()->removeAttribute(index, this); 214 214 return attr.release(); 215 215 } … … 223 223 attr->detachFromElementWithValue(attr->value()); 224 224 225 attributeData()->removeAttribute(name, this); 225 size_t index = attributeData()->getAttributeItemIndex(name); 226 if (index == notFound) 227 return; 228 229 mutableAttributeData()->removeAttribute(index, this); 226 230 } 227 231 … … 265 269 #endif 266 270 267 if ( m_attributeData) {268 if ( Attribute* attribute = getAttributeItem(name))271 if (attributeData()) { 272 if (const Attribute* attribute = getAttributeItem(name)) 269 273 return attribute->value(); 270 274 } … … 629 633 #endif 630 634 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)) 633 637 return attribute->value(); 634 638 } … … 663 667 inline void Element::setAttributeInternal(size_t index, const QualifiedName& name, const AtomicString& value, EInUpdateStyleAttribute inUpdateStyleAttribute) 664 668 { 665 Attribute* old = index != notFound ? m_attributeData->attributeItem(index) : 0; 669 ElementAttributeData* attributeData = mutableAttributeData(); 670 671 Attribute* old = index != notFound ? attributeData->attributeItem(index) : 0; 666 672 if (value.isNull()) { 667 673 if (old) 668 m_attributeData->removeAttribute(index, this, inUpdateStyleAttribute);674 attributeData->removeAttribute(index, this, inUpdateStyleAttribute); 669 675 return; 670 676 } 671 677 672 678 if (!old) { 673 m_attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute);679 attributeData->addAttribute(Attribute(name, value), this, inUpdateStyleAttribute); 674 680 return; 675 681 } … … 765 771 return; 766 772 767 createAttributeData(); 768 m_attributeData->m_attributes = attributeVector; 769 m_attributeData->m_attributes.shrinkToFit(); 773 Vector<Attribute> filteredAttributes = attributeVector; 770 774 771 775 // If the element is created as result of a paste or drag-n-drop operation … … 773 777 if (scriptingPermission == DisallowScriptingContent) { 774 778 unsigned i = 0; 775 while (i < m_attributeData->length()) {776 const QualifiedName& attributeName = m_attributeData->m_attributes[i].name();777 if (isEventHandlerAttribute(attribute Name)) {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); 779 783 continue; 780 784 } 781 785 782 if (isAttributeToRemove(attribute Name, 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); 784 788 i++; 785 789 } 786 790 } 787 791 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 789 795 // 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]); 793 799 } 794 800 … … 796 802 { 797 803 updateInvalidAttributes(); 798 return m_attributeData && m_attributeData->length();804 return attributeData() && attributeData()->length(); 799 805 } 800 806 801 807 bool Element::hasEquivalentAttributes(const Element* other) const 802 808 { 803 ElementAttributeData* attributeData = updatedAttributeData();804 ElementAttributeData* otherAttributeData = other->updatedAttributeData();809 const ElementAttributeData* attributeData = updatedAttributeData(); 810 const ElementAttributeData* otherAttributeData = other->updatedAttributeData(); 805 811 if (attributeData) 806 812 return attributeData->isEquivalent(otherAttributeData); … … 846 852 847 853 return KURL(parentBase, baseAttribute); 848 }849 850 void Element::createAttributeData() const851 {852 m_attributeData = ElementAttributeData::create();853 854 } 854 855 … … 1399 1400 } 1400 1401 1401 ElementAttributeData* attributeData = ensureUpdatedAttributeData();1402 1403 1402 RefPtr<Attr> oldAttr = attrIfExists(attr->qualifiedName()); 1404 1403 if (oldAttr.get() == attr) … … 1412 1411 } 1413 1412 1413 updateInvalidAttributes(); 1414 ElementAttributeData* attributeData = mutableAttributeData(); 1415 1414 1416 size_t index = attributeData->getAttributeItemIndex(attr->qualifiedName()); 1415 1417 Attribute* oldAttribute = index != notFound ? attributeData->attributeItem(index) : 0; … … 1449 1451 ASSERT(document() == attr->document()); 1450 1452 1451 ElementAttributeData* attributeData = updatedAttributeData();1453 const ElementAttributeData* attributeData = updatedAttributeData(); 1452 1454 ASSERT(attributeData); 1453 1455 … … 1484 1486 ASSERT(attributeData()); 1485 1487 ASSERT(index <= attributeCount()); 1486 attributeData()->removeAttribute(index, this);1488 mutableAttributeData()->removeAttribute(index, this); 1487 1489 } 1488 1490 1489 1491 void Element::removeAttribute(const String& name) 1490 1492 { 1491 ElementAttributeData* attributeData = this->attributeData(); 1492 if (!attributeData) 1493 if (!attributeData()) 1493 1494 return; 1494 1495 1495 1496 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; 1496 size_t index = attributeData ->getAttributeItemIndex(localName, false);1497 size_t index = attributeData()->getAttributeItemIndex(localName, false); 1497 1498 if (index == notFound) 1498 1499 return; 1499 1500 1500 attributeData->removeAttribute(index, this);1501 mutableAttributeData()->removeAttribute(index, this); 1501 1502 } 1502 1503 … … 1508 1509 PassRefPtr<Attr> Element::getAttributeNode(const String& name) 1509 1510 { 1510 ElementAttributeData* attributeData = updatedAttributeData();1511 const ElementAttributeData* attributeData = updatedAttributeData(); 1511 1512 if (!attributeData) 1512 1513 return 0; … … 1516 1517 PassRefPtr<Attr> Element::getAttributeNodeNS(const String& namespaceURI, const String& localName) 1517 1518 { 1518 ElementAttributeData* attributeData = updatedAttributeData();1519 const ElementAttributeData* attributeData = updatedAttributeData(); 1519 1520 if (!attributeData) 1520 1521 return 0; … … 1524 1525 bool Element::hasAttribute(const String& name) const 1525 1526 { 1526 ElementAttributeData* attributeData = updatedAttributeData(); 1527 if (!attributeData) 1527 if (!attributeData()) 1528 1528 return false; 1529 1529 … … 1531 1531 // there may be a way to remove it. 1532 1532 String localName = shouldIgnoreAttributeCase(this) ? name.lower() : name; 1533 return attributeData->getAttributeItem(localName, false);1533 return updatedAttributeData()->getAttributeItem(localName, false); 1534 1534 } 1535 1535 1536 1536 bool Element::hasAttributeNS(const String& namespaceURI, const String& localName) const 1537 1537 { 1538 ElementAttributeData* attributeData = updatedAttributeData();1538 const ElementAttributeData* attributeData = updatedAttributeData(); 1539 1539 if (!attributeData) 1540 1540 return false; … … 1743 1743 return; 1744 1744 1745 ElementAttributeData* attributeData = updatedAttributeData();1745 const ElementAttributeData* attributeData = updatedAttributeData(); 1746 1746 ASSERT(attributeData); 1747 1747 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())) 1751 1750 attr->normalize(); 1752 1751 } … … 1817 1816 { 1818 1817 #if !ASSERT_DISABLED 1819 if ( m_attributeData) {1820 if ( Attribute* attribute = getAttributeItem(name))1818 if (attributeData()) { 1819 if (const Attribute* attribute = getAttributeItem(name)) 1821 1820 ASSERT(isURLAttribute(*attribute)); 1822 1821 } … … 1828 1827 { 1829 1828 #if !ASSERT_DISABLED 1830 if ( m_attributeData) {1831 if ( Attribute* attribute = getAttributeItem(name))1829 if (attributeData()) { 1830 if (const Attribute* attribute = getAttributeItem(name)) 1832 1831 ASSERT(isURLAttribute(*attribute)); 1833 1832 } … … 2173 2172 void Element::cloneAttributesFromElement(const Element& other) 2174 2173 { 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); 2177 2176 else if (m_attributeData) { 2178 2177 m_attributeData->clearAttributes(this); … … 2187 2186 } 2188 2187 2188 void Element::createMutableAttributeData() 2189 { 2190 if (!m_attributeData) 2191 m_attributeData = ElementAttributeData::create(); 2192 else 2193 m_attributeData = m_attributeData->makeMutable(); 2194 } 2195 2189 2196 } // namespace WebCore -
trunk/Source/WebCore/dom/Element.h
r123071 r123636 163 163 // before calling them. 164 164 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&); 167 168 size_t getAttributeItemIndex(const QualifiedName& name) const { return attributeData()->getAttributeItemIndex(name); } 168 169 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const { return attributeData()->getAttributeItemIndex(name, shouldIgnoreAttributeCase); } … … 247 248 void parserSetAttributes(const Vector<Attribute>&, FragmentScriptingPermission); 248 249 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; 253 255 254 256 // Clones attributes only. … … 435 437 info.visitBaseClass<ContainerNode>(this); 436 438 info.addInstrumentedMember(m_tagName); 437 info.addInstrumentedMember( m_attributeData.get());439 info.addInstrumentedMember(attributeData()); 438 440 } 439 441 … … 476 478 bool pseudoStyleCacheIsInvalid(const RenderStyle* currentStyle, RenderStyle* newStyle); 477 479 478 void createAttributeData() const;479 480 480 virtual void updateStyleAttribute() const { } 481 481 … … 506 506 void unregisterNamedFlowContentNode(); 507 507 508 void createMutableAttributeData(); 509 508 510 private: 509 511 ElementRareData* elementRareData() const; 510 512 ElementRareData* ensureElementRareData(); 511 513 512 mutableOwnPtr<ElementAttributeData> m_attributeData;514 OwnPtr<ElementAttributeData> m_attributeData; 513 515 }; 514 516 … … 570 572 } 571 573 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 574 inline const ElementAttributeData* Element::updatedAttributeData() const 580 575 { 581 576 updateInvalidAttributes(); … … 583 578 } 584 579 585 inline ElementAttributeData* Element::ensureUpdatedAttributeData() const 580 inline const ElementAttributeData* Element::ensureAttributeData() 581 { 582 if (attributeData()) 583 return attributeData(); 584 return mutableAttributeData(); 585 } 586 587 inline const ElementAttributeData* Element::ensureUpdatedAttributeData() const 586 588 { 587 589 updateInvalidAttributes(); 588 return ensureAttributeData(); 590 if (attributeData()) 591 return attributeData(); 592 return const_cast<Element*>(this)->mutableAttributeData(); 589 593 } 590 594 … … 635 639 { 636 640 ASSERT(fastAttributeLookupAllowed(name)); 637 return m_attributeData&& getAttributeItem(name);641 return attributeData() && getAttributeItem(name); 638 642 } 639 643 … … 641 645 { 642 646 ASSERT(fastAttributeLookupAllowed(name)); 643 if ( m_attributeData) {644 if ( Attribute* attribute = getAttributeItem(name))647 if (attributeData()) { 648 if (const Attribute* attribute = getAttributeItem(name)) 645 649 return attribute->value(); 646 650 } … … 650 654 inline bool Element::hasAttributesWithoutUpdate() const 651 655 { 652 return m_attributeData && !m_attributeData->isEmpty();656 return attributeData() && !attributeData()->isEmpty(); 653 657 } 654 658 … … 656 660 { 657 661 ASSERT(hasID()); 658 return m_attributeData->idForStyleResolution();662 return attributeData()->idForStyleResolution(); 659 663 } 660 664 … … 685 689 inline size_t Element::attributeCount() const 686 690 { 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 695 inline const Attribute* Element::attributeItem(unsigned index) const 696 { 697 ASSERT(attributeData()); 698 return attributeData()->attributeItem(index); 699 } 700 701 inline const Attribute* Element::getAttributeItem(const QualifiedName& name) const 702 { 703 ASSERT(attributeData()); 704 return attributeData()->getAttributeItem(name); 705 } 706 707 inline Attribute* Element::getAttributeItem(const QualifiedName& name) 708 { 709 ASSERT(attributeData()); 710 return mutableAttributeData()->getAttributeItem(name); 701 711 } 702 712 … … 731 741 } 732 742 743 inline ElementAttributeData* Element::mutableAttributeData() 744 { 745 if (!attributeData() || !attributeData()->isMutable()) 746 createMutableAttributeData(); 747 return m_attributeData.get(); 748 } 749 733 750 // Put here to make them inline. 734 751 inline bool Node::hasID() const -
trunk/Source/WebCore/dom/ElementAttributeData.cpp
r122600 r123636 33 33 namespace WebCore { 34 34 35 PassOwnPtr<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 41 ElementAttributeData::ElementAttributeData() 42 : m_isMutable(true) 43 , m_arraySize(0) 44 , m_mutableAttributeVector(new Vector<Attribute, 4>) 45 { 46 } 47 48 ElementAttributeData::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 57 ElementAttributeData::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 74 ElementAttributeData::~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 35 86 typedef Vector<RefPtr<Attr> > AttrList; 36 87 typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap; … … 82 133 } 83 134 84 PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) 135 PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name) const 85 136 { 86 137 if (AttrList* attrList = attrListForElement(element)) … … 89 140 } 90 141 91 PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) 142 PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name) const 92 143 { 93 144 AttrList* attrList = ensureAttrListForElement(element); … … 100 151 } 101 152 102 void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) 153 void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr) const 103 154 { 104 155 AttrList* attrList = ensureAttrListForElement(element); … … 111 162 } 112 163 113 void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) 164 void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name) const 114 165 { 115 166 AttrList* attrList = attrListForElement(element); … … 128 179 } 129 180 130 void ElementAttributeData::setClass(const String& className, bool shouldFoldCase)131 {132 m_classNames.set(className, shouldFoldCase);133 }134 135 181 StylePropertySet* ElementAttributeData::ensureInlineStyle(StyledElement* element) 136 182 { 183 ASSERT(isMutable()); 137 184 if (!m_inlineStyleDecl) { 138 185 ASSERT(element->isStyledElement()); … … 144 191 StylePropertySet* ElementAttributeData::ensureMutableInlineStyle(StyledElement* element) 145 192 { 193 ASSERT(isMutable()); 146 194 if (m_inlineStyleDecl && !m_inlineStyleDecl->isMutable()) { 147 195 m_inlineStyleDecl = m_inlineStyleDecl->copy(); … … 151 199 } 152 200 153 void ElementAttributeData::updateInlineStyleAvoidingMutation(StyledElement* element, const String& text) 201 void ElementAttributeData::updateInlineStyleAvoidingMutation(StyledElement* element, const String& text) const 154 202 { 155 203 // We reconstruct the property set instead of mutating if there is no CSSOM wrapper. … … 162 210 } 163 211 164 void ElementAttributeData::destroyInlineStyle(StyledElement* element) 212 void ElementAttributeData::destroyInlineStyle(StyledElement* element) const 165 213 { 166 214 if (!m_inlineStyleDecl) … … 172 220 void ElementAttributeData::addAttribute(const Attribute& attribute, Element* element, EInUpdateStyleAttribute inUpdateStyleAttribute) 173 221 { 222 ASSERT(isMutable()); 223 174 224 if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) 175 225 element->willModifyAttribute(attribute.name(), nullAtom, attribute.value()); 176 226 177 m_ attributes.append(attribute);227 m_mutableAttributeVector->append(attribute); 178 228 179 229 if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) … … 183 233 void ElementAttributeData::removeAttribute(size_t index, Element* element, EInUpdateStyleAttribute inUpdateStyleAttribute) 184 234 { 235 ASSERT(isMutable()); 185 236 ASSERT(index < length()); 186 237 187 Attribute& attribute = m_ attributes[index];238 Attribute& attribute = m_mutableAttributeVector->at(index); 188 239 QualifiedName name = attribute.name(); 189 240 … … 194 245 attr->detachFromElementWithValue(attribute.value()); 195 246 196 m_ attributes.remove(index);247 m_mutableAttributeVector->remove(index); 197 248 198 249 if (element && inUpdateStyleAttribute == NotInUpdateStyleAttribute) … … 210 261 211 262 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()) 214 266 return false; 215 267 } … … 218 270 } 219 271 220 void ElementAttributeData::detachAttrObjectsFromElement(Element* element) 272 void ElementAttributeData::detachAttrObjectsFromElement(Element* element) const 221 273 { 222 274 ASSERT(element->hasAttrList()); 223 275 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()); 227 280 } 228 281 … … 234 287 { 235 288 // 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())) 239 293 return i; 240 294 } else { … … 242 296 // generates a temporary string by concatenation. But this branch is only reached 243 297 // 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)) 245 299 return i; 246 300 } … … 251 305 void ElementAttributeData::cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement) 252 306 { 307 // FIXME: Cloned elements could start out with immutable attribute data. 308 ASSERT(isMutable()); 309 253 310 const AtomicString& oldID = targetElement.getIdAttribute(); 254 311 const AtomicString& newID = sourceElement.getIdAttribute(); … … 264 321 265 322 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); 270 338 continue; 271 339 } 272 targetElement.attributeChanged( m_attributes[i]);340 targetElement.attributeChanged(attribute); 273 341 } 274 342 … … 283 351 void ElementAttributeData::clearAttributes(Element* element) 284 352 { 353 ASSERT(isMutable()); 354 285 355 if (element->hasAttrList()) 286 356 detachAttrObjectsFromElement(element); 287 357 288 358 clearClass(); 289 m_ attributes.clear();359 m_mutableAttributeVector->clear(); 290 360 } 291 361 292 362 void ElementAttributeData::replaceAttribute(size_t index, const Attribute& attribute, Element* element) 293 363 { 364 ASSERT(isMutable()); 294 365 ASSERT(element); 295 366 ASSERT(index < length()); 296 367 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; 299 370 element->didModifyAttribute(attribute); 300 371 } … … 303 374 { 304 375 ASSERT(element); 305 Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase);376 const Attribute* attribute = getAttributeItem(name, shouldIgnoreAttributeCase); 306 377 if (!attribute) 307 378 return 0; 308 return const_cast<ElementAttributeData*>(this)->ensureAttr(element, attribute->name());379 return ensureAttr(element, attribute->name()); 309 380 } 310 381 … … 312 383 { 313 384 ASSERT(element); 314 Attribute* attribute = getAttributeItem(name);385 const Attribute* attribute = getAttributeItem(name); 315 386 if (!attribute) 316 387 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 38 38 class Element; 39 39 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 49 40 enum EInUpdateStyleAttribute { NotInUpdateStyleAttribute, InUpdateStyleAttribute }; 50 41 … … 52 43 WTF_MAKE_FAST_ALLOCATED; 53 44 public: 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(); 58 48 59 49 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); } 61 51 const SpaceSplitString& classNames() const { return m_classNames; } 62 52 63 53 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(); } 66 57 StylePropertySet* inlineStyle() { return m_inlineStyleDecl.get(); } 67 58 StylePropertySet* ensureInlineStyle(StyledElement*); 68 59 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; 71 62 72 63 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(); } 77 68 78 69 PassRefPtr<Attr> getAttributeNode(const String&, bool shouldIgnoreAttributeCase, Element*) const; … … 80 71 81 72 // 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&); 84 77 size_t getAttributeItemIndex(const QualifiedName&) const; 85 78 size_t getAttributeItemIndex(const AtomicString& name, bool shouldIgnoreAttributeCase) const; … … 96 89 bool isEquivalent(const ElementAttributeData* other) const; 97 90 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; 102 96 103 97 void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const 104 98 { 105 MemoryClassInfo<ElementAttributeData> info(memoryObjectInfo, this, MemoryInstrumentation::DOM );99 MemoryClassInfo<ElementAttributeData> info(memoryObjectInfo, this, MemoryInstrumentation::DOM, m_arraySize * sizeof(Attribute)); 106 100 info.addInstrumentedMember(m_inlineStyleDecl.get()); 107 101 info.addInstrumentedMember(m_attributeStyle.get()); 108 102 info.addMember(m_classNames); 109 103 info.addString(m_idForStyleResolution); 110 info.addVector(m_attributes); 104 if (m_isMutable) 105 info.addVector(*m_mutableAttributeVector); 111 106 } 112 107 … … 115 110 friend class HTMLConstructionSite; 116 111 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; 126 118 size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const; 127 119 void cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement); … … 129 121 void replaceAttribute(size_t index, const Attribute&, Element*); 130 122 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 }; 136 138 }; 139 140 inline size_t ElementAttributeData::length() const 141 { 142 if (isMutable()) 143 return m_mutableAttributeVector->size(); 144 return m_arraySize; 145 } 137 146 138 147 inline void ElementAttributeData::removeAttribute(const QualifiedName& name, Element* element) … … 143 152 144 153 removeAttribute(index, element); 145 return; 146 } 147 148 inline Attribute* ElementAttributeData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const 154 } 155 156 inline Attribute* ElementAttributeData::getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) 149 157 { 150 158 size_t index = getAttributeItemIndex(name, shouldIgnoreAttributeCase); 151 159 if (index != notFound) 152 return &const_cast<ElementAttributeData*>(this)->m_attributes[index]; 160 return attributeItem(index); 161 return 0; 162 } 163 164 inline 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); 153 169 return 0; 154 170 } … … 156 172 inline size_t ElementAttributeData::getAttributeItemIndex(const QualifiedName& name) const 157 173 { 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)) 160 176 return i; 161 177 } … … 172 188 // Optimize for the case where the attribute exists and its name exactly matches. 173 189 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()) 176 193 return i; 177 194 } else … … 184 201 } 185 202 203 inline 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 212 inline 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 221 inline 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 230 inline Attribute* ElementAttributeData::attributeItem(unsigned index) 231 { 232 ASSERT(isMutable()); 233 ASSERT(index < length()); 234 return &m_mutableAttributeVector->at(index); 235 } 236 186 237 } 187 238 -
trunk/Source/WebCore/dom/Node.cpp
r123434 r123636 1704 1704 if (elem->hasAttributes()) { 1705 1705 for (unsigned i = 0; i < elem->attributeCount(); i++) { 1706 Attribute* attr = elem->attributeItem(i);1706 const Attribute* attr = elem->attributeItem(i); 1707 1707 1708 1708 if (attr->localName() == xmlnsAtom) … … 1788 1788 if (elem->hasAttributes()) { 1789 1789 for (unsigned i = 0; i < elem->attributeCount(); i++) { 1790 Attribute* attr = elem->attributeItem(i);1790 const Attribute* attr = elem->attributeItem(i); 1791 1791 1792 1792 if (attr->prefix() == xmlnsAtom && attr->localName() == prefix) { … … 1843 1843 if (thisElement->hasAttributes()) { 1844 1844 for (unsigned i = 0; i < thisElement->attributeCount(); i++) { 1845 Attribute* attr = thisElement->attributeItem(i);1845 const Attribute* attr = thisElement->attributeItem(i); 1846 1846 1847 1847 if (attr->prefix() == xmlnsAtom && attr->value() == _namespaceURI … … 1992 1992 // when comparing two attributes of the same element, and inserting or removing additional attributes might change 1993 1993 // the order between existing attributes. 1994 Attribute* attribute = owner1->attributeItem(i);1994 const Attribute* attribute = owner1->attributeItem(i); 1995 1995 if (attr1->qualifiedName() == attribute->name()) 1996 1996 return DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC | DOCUMENT_POSITION_FOLLOWING; -
trunk/Source/WebCore/dom/StyledElement.cpp
r123377 r123636 143 143 CSSStyleDeclaration* StyledElement::style() 144 144 { 145 return ensure AttributeData()->ensureMutableInlineStyle(this)->ensureInlineCSSStyleDeclaration(this);145 return ensureInlineStyle()->ensureInlineCSSStyleDeclaration(this); 146 146 } 147 147 … … 174 174 static_cast<ClassList*>(classList)->reset(newClassString); 175 175 } else if (attributeData()) 176 attributeData()->clearClass();176 mutableAttributeData()->clearClass(); 177 177 setNeedsStyleRecalc(); 178 178 } … … 211 211 bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, int identifier, bool important) 212 212 { 213 ensure AttributeData()->ensureMutableInlineStyle(this)->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important);213 ensureInlineStyle()->setProperty(propertyID, cssValuePool().createIdentifierValue(identifier), important); 214 214 inlineStyleChanged(); 215 215 return true; … … 218 218 bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, double value, CSSPrimitiveValue::UnitTypes unit, bool important) 219 219 { 220 ensure AttributeData()->ensureMutableInlineStyle(this)->setProperty(propertyID, cssValuePool().createValue(value, unit), important);220 ensureInlineStyle()->setProperty(propertyID, cssValuePool().createValue(value, unit), important); 221 221 inlineStyleChanged(); 222 222 return true; … … 225 225 bool StyledElement::setInlineStyleProperty(CSSPropertyID propertyID, const String& value, bool important) 226 226 { 227 bool changes = ensure AttributeData()->ensureMutableInlineStyle(this)->setProperty(propertyID, value, important, document()->elementSheet()->contents());227 bool changes = ensureInlineStyle()->setProperty(propertyID, value, important, document()->elementSheet()->contents()); 228 228 if (changes) 229 229 inlineStyleChanged(); … … 233 233 bool StyledElement::removeInlineStyleProperty(CSSPropertyID propertyID) 234 234 { 235 StylePropertySet* inlineStyle = attributeData() ? attributeData()->inlineStyle() : 0; 236 if (!inlineStyle) 235 if (!attributeData() || !attributeData()->inlineStyle()) 237 236 return false; 238 bool changes = inlineStyle->removeProperty(propertyID);237 bool changes = ensureInlineStyle()->removeProperty(propertyID); 239 238 if (changes) 240 239 inlineStyleChanged(); … … 244 243 void StyledElement::addSubresourceAttributeURLs(ListHashSet<KURL>& urls) const 245 244 { 246 if ( StylePropertySet* inlineStyle = attributeData() ? attributeData()->inlineStyle() : 0)245 if (const StylePropertySet* inlineStyle = attributeData() ? attributeData()->inlineStyle() : 0) 247 246 inlineStyle->addSubresourceStyleURLs(urls, document()->elementSheet()->contents()); 248 247 } … … 264 263 unsigned size = attributeCount(); 265 264 for (unsigned i = 0; i < size; ++i) { 266 Attribute* attribute = attributeItem(i);265 const Attribute* attribute = attributeItem(i); 267 266 if (!isPresentationAttribute(attribute->name())) 268 267 continue; … … 314 313 unsigned size = attributeCount(); 315 314 for (unsigned i = 0; i < size; ++i) { 316 Attribute* attribute = attributeItem(i);315 const Attribute* attribute = attributeItem(i); 317 316 collectStyleForAttribute(*attribute, style.get()); 318 317 } -
trunk/Source/WebCore/dom/StyledElement.h
r122600 r123636 42 42 43 43 const StylePropertySet* inlineStyle() const { return attributeData() ? attributeData()->inlineStyle() : 0; } 44 const StylePropertySet* ensureInlineStyle() { return ensureAttributeData()->ensureInlineStyle(this); }44 StylePropertySet* ensureInlineStyle() { return mutableAttributeData()->ensureMutableInlineStyle(this); } 45 45 46 46 // Unlike StylePropertySet setters, these implement invalidation. -
trunk/Source/WebCore/editing/markup.cpp
r120168 r123636 111 111 unsigned length = e->attributeCount(); 112 112 for (unsigned i = 0; i < length; i++) { 113 Attribute* attribute = e->attributeItem(i);113 const Attribute* attribute = e->attributeItem(i); 114 114 if (e->isURLAttribute(*attribute)) 115 115 changes.append(AttributeChange(e, attribute->name(), KURL(parsedBaseURL, attribute->value()).string())); … … 295 295 const bool shouldOverrideStyleAttr = shouldAnnotateOrForceInline || shouldApplyWrappingStyle(element); 296 296 for (unsigned int i = 0; i < length; i++) { 297 Attribute* attribute = element->attributeItem(i);297 const Attribute* attribute = element->attributeItem(i); 298 298 // We'll handle the style attribute separately, below. 299 299 if (attribute->name() == styleAttr && shouldOverrideStyleAttr) -
trunk/Source/WebCore/html/HTMLEmbedElement.cpp
r118963 r123636 121 121 122 122 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()); 126 126 } 127 127 } -
trunk/Source/WebCore/html/HTMLObjectElement.cpp
r120049 r123636 193 193 if (hasAttributes()) { 194 194 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(); 197 197 if (!uniqueParamNames.contains(name.impl())) { 198 198 paramNames.append(name.string()); 199 paramValues.append( it->value().string());199 paramValues.append(attribute->value().string()); 200 200 } 201 201 } -
trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp
r123581 r123636 207 207 return; 208 208 209 ElementAttributeData* elementAttributeData = element-> ensureAttributeData();209 ElementAttributeData* elementAttributeData = element->mutableAttributeData(); 210 210 211 211 for (unsigned i = 0; i < token->attributes().size(); ++i) { -
trunk/Source/WebCore/inspector/DOMPatchSupport.cpp
r122652 r123636 178 178 if (oldElement->hasAttributesWithoutUpdate()) { 179 179 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)) 182 182 return false; 183 183 } -
trunk/Source/WebCore/page/PageSerializer.cpp
r118934 r123636 74 74 if (element->hasAttributes()) { 75 75 for (unsigned i = 0; i < element->attributeCount(); ++i) { 76 Attribute* item= element->attributeItem(i);76 const Attribute* attribute = element->attributeItem(i); 77 77 // 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())); 79 79 } 80 80 } -
trunk/Source/WebCore/svg/properties/SVGAnimatedPropertyMacros.h
r118735 r123636 60 60 // that could cause the SVGElement to erroneously reset its properties. 61 61 // svg/dom/SVGStringList-basics.xhtml exercises this behavior. 62 ElementAttributeData* attributeData = ownerElement-> ensureUpdatedAttributeData();62 ElementAttributeData* attributeData = ownerElement->mutableAttributeData(); 63 63 Attribute* old = attributeData->getAttributeItem(attrName); 64 64 if (old && value.isNull()) -
trunk/Source/WebCore/xml/XPathFunctions.cpp
r112555 r123636 588 588 String lang = arg(0)->evaluate().toString(); 589 589 590 Attribute* languageAttribute = 0;590 const Attribute* languageAttribute = 0; 591 591 Node* node = evaluationContext().node.get(); 592 592 while (node) { -
trunk/Source/WebCore/xml/parser/MarkupTokenBase.h
r123542 r123636 37 37 namespace WebCore { 38 38 39 static 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 39 49 class DoctypeDataBase { 40 50 WTF_MAKE_NONCOPYABLE(DoctypeDataBase); -
trunk/Source/WebCore/xml/parser/XMLDocumentParserLibxml2.cpp
r117731 r123636 606 606 if (element->hasAttributes()) { 607 607 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()); 613 613 } 614 614 } -
trunk/Source/WebCore/xml/parser/XMLDocumentParserQt.cpp
r122600 r123636 139 139 QXmlStreamNamespaceDeclarations namespaces; 140 140 for (Element* element = elemStack.last(); !elemStack.isEmpty(); elemStack.removeLast()) { 141 if ( ElementAttributeData* attrs = element->updatedAttributeData()) {141 if (const ElementAttributeData* attrs = element->updatedAttributeData()) { 142 142 for (unsigned i = 0; i < attrs->length(); i++) { 143 Attribute* attr = attrs->attributeItem(i);143 const Attribute* attr = attrs->attributeItem(i); 144 144 if (attr->localName() == "xmlns") 145 145 m_defaultNamespaceURI = attr->value(); -
trunk/Source/WebCore/xml/parser/XMLTreeBuilder.cpp
r114870 r123636 83 83 if (element->hasAttributes()) { 84 84 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()); 90 90 } 91 91 }
Note: See TracChangeset
for help on using the changeset viewer.