• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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