1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "config.h"
32 #include "core/dom/ElementData.h"
33
34 #include "core/css/StylePropertySet.h"
35 #include "core/dom/QualifiedName.h"
36 #include "wtf/Vector.h"
37
38 namespace blink {
39
40 struct SameSizeAsElementData : public RefCountedWillBeGarbageCollectedFinalized<SameSizeAsElementData> {
41 unsigned bitfield;
42 void* pointers[3];
43 };
44
45 COMPILE_ASSERT(sizeof(ElementData) == sizeof(SameSizeAsElementData), element_attribute_data_should_stay_small);
46
sizeForShareableElementDataWithAttributeCount(unsigned count)47 static size_t sizeForShareableElementDataWithAttributeCount(unsigned count)
48 {
49 return sizeof(ShareableElementData) + sizeof(Attribute) * count;
50 }
51
ElementData()52 ElementData::ElementData()
53 : m_isUnique(true)
54 , m_arraySize(0)
55 , m_presentationAttributeStyleIsDirty(false)
56 , m_styleAttributeIsDirty(false)
57 , m_animatedSVGAttributesAreDirty(false)
58 {
59 }
60
ElementData(unsigned arraySize)61 ElementData::ElementData(unsigned arraySize)
62 : m_isUnique(false)
63 , m_arraySize(arraySize)
64 , m_presentationAttributeStyleIsDirty(false)
65 , m_styleAttributeIsDirty(false)
66 , m_animatedSVGAttributesAreDirty(false)
67 {
68 }
69
ElementData(const ElementData & other,bool isUnique)70 ElementData::ElementData(const ElementData& other, bool isUnique)
71 : m_isUnique(isUnique)
72 , m_arraySize(isUnique ? 0 : other.attributes().size())
73 , m_presentationAttributeStyleIsDirty(other.m_presentationAttributeStyleIsDirty)
74 , m_styleAttributeIsDirty(other.m_styleAttributeIsDirty)
75 , m_animatedSVGAttributesAreDirty(other.m_animatedSVGAttributesAreDirty)
76 , m_classNames(other.m_classNames)
77 , m_idForStyleResolution(other.m_idForStyleResolution)
78 {
79 // NOTE: The inline style is copied by the subclass copy constructor since we don't know what to do with it here.
80 }
81
82 #if ENABLE(OILPAN)
finalizeGarbageCollectedObject()83 void ElementData::finalizeGarbageCollectedObject()
84 {
85 if (m_isUnique)
86 toUniqueElementData(this)->~UniqueElementData();
87 else
88 toShareableElementData(this)->~ShareableElementData();
89 }
90 #else
destroy()91 void ElementData::destroy()
92 {
93 if (m_isUnique)
94 delete toUniqueElementData(this);
95 else
96 delete toShareableElementData(this);
97 }
98 #endif
99
makeUniqueCopy() const100 PassRefPtrWillBeRawPtr<UniqueElementData> ElementData::makeUniqueCopy() const
101 {
102 if (isUnique())
103 return adoptRefWillBeNoop(new UniqueElementData(toUniqueElementData(*this)));
104 return adoptRefWillBeNoop(new UniqueElementData(toShareableElementData(*this)));
105 }
106
isEquivalent(const ElementData * other) const107 bool ElementData::isEquivalent(const ElementData* other) const
108 {
109 AttributeCollection attributes = this->attributes();
110 if (!other)
111 return attributes.isEmpty();
112
113 AttributeCollection otherAttributes = other->attributes();
114 if (attributes.size() != otherAttributes.size())
115 return false;
116
117 AttributeCollection::iterator end = attributes.end();
118 for (AttributeCollection::iterator it = attributes.begin(); it != end; ++it) {
119 const Attribute* otherAttr = otherAttributes.find(it->name());
120 if (!otherAttr || it->value() != otherAttr->value())
121 return false;
122 }
123 return true;
124 }
125
trace(Visitor * visitor)126 void ElementData::trace(Visitor* visitor)
127 {
128 if (m_isUnique)
129 toUniqueElementData(this)->traceAfterDispatch(visitor);
130 else
131 toShareableElementData(this)->traceAfterDispatch(visitor);
132 }
133
traceAfterDispatch(Visitor * visitor)134 void ElementData::traceAfterDispatch(Visitor* visitor)
135 {
136 visitor->trace(m_inlineStyle);
137 }
138
ShareableElementData(const Vector<Attribute> & attributes)139 ShareableElementData::ShareableElementData(const Vector<Attribute>& attributes)
140 : ElementData(attributes.size())
141 {
142 for (unsigned i = 0; i < m_arraySize; ++i)
143 new (&m_attributeArray[i]) Attribute(attributes[i]);
144 }
145
~ShareableElementData()146 ShareableElementData::~ShareableElementData()
147 {
148 for (unsigned i = 0; i < m_arraySize; ++i)
149 m_attributeArray[i].~Attribute();
150 }
151
ShareableElementData(const UniqueElementData & other)152 ShareableElementData::ShareableElementData(const UniqueElementData& other)
153 : ElementData(other, false)
154 {
155 ASSERT(!other.m_presentationAttributeStyle);
156
157 if (other.m_inlineStyle) {
158 m_inlineStyle = other.m_inlineStyle->immutableCopyIfNeeded();
159 }
160
161 for (unsigned i = 0; i < m_arraySize; ++i)
162 new (&m_attributeArray[i]) Attribute(other.m_attributeVector.at(i));
163 }
164
createWithAttributes(const Vector<Attribute> & attributes)165 PassRefPtrWillBeRawPtr<ShareableElementData> ShareableElementData::createWithAttributes(const Vector<Attribute>& attributes)
166 {
167 #if ENABLE(OILPAN)
168 void* slot = Heap::allocate<ElementData>(sizeForShareableElementDataWithAttributeCount(attributes.size()));
169 #else
170 void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(attributes.size()));
171 #endif
172 return adoptRefWillBeNoop(new (slot) ShareableElementData(attributes));
173 }
174
UniqueElementData()175 UniqueElementData::UniqueElementData()
176 {
177 }
178
UniqueElementData(const UniqueElementData & other)179 UniqueElementData::UniqueElementData(const UniqueElementData& other)
180 : ElementData(other, true)
181 , m_presentationAttributeStyle(other.m_presentationAttributeStyle)
182 , m_attributeVector(other.m_attributeVector)
183 {
184 m_inlineStyle = other.m_inlineStyle ? other.m_inlineStyle->mutableCopy() : nullptr;
185 }
186
UniqueElementData(const ShareableElementData & other)187 UniqueElementData::UniqueElementData(const ShareableElementData& other)
188 : ElementData(other, true)
189 {
190 // An ShareableElementData should never have a mutable inline StylePropertySet attached.
191 ASSERT(!other.m_inlineStyle || !other.m_inlineStyle->isMutable());
192 m_inlineStyle = other.m_inlineStyle;
193
194 unsigned length = other.attributes().size();
195 m_attributeVector.reserveCapacity(length);
196 for (unsigned i = 0; i < length; ++i)
197 m_attributeVector.uncheckedAppend(other.m_attributeArray[i]);
198 }
199
create()200 PassRefPtrWillBeRawPtr<UniqueElementData> UniqueElementData::create()
201 {
202 return adoptRefWillBeNoop(new UniqueElementData);
203 }
204
makeShareableCopy() const205 PassRefPtrWillBeRawPtr<ShareableElementData> UniqueElementData::makeShareableCopy() const
206 {
207 #if ENABLE(OILPAN)
208 void* slot = Heap::allocate<ElementData>(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
209 #else
210 void* slot = WTF::fastMalloc(sizeForShareableElementDataWithAttributeCount(m_attributeVector.size()));
211 #endif
212 return adoptRefWillBeNoop(new (slot) ShareableElementData(*this));
213 }
214
traceAfterDispatch(Visitor * visitor)215 void UniqueElementData::traceAfterDispatch(Visitor* visitor)
216 {
217 visitor->trace(m_presentationAttributeStyle);
218 ElementData::traceAfterDispatch(visitor);
219 }
220
221 } // namespace blink
222