1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * Copyright (C) 2014 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * * Redistributions in binary form must reproduce the above 12 * copyright notice, this list of conditions and the following disclaimer 13 * in the documentation and/or other materials provided with the 14 * distribution. 15 * * Neither the name of Google Inc. nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #ifndef ElementData_h 33 #define ElementData_h 34 35 #include "core/dom/Attribute.h" 36 #include "core/dom/AttributeCollection.h" 37 #include "core/dom/SpaceSplitString.h" 38 #include "platform/heap/Handle.h" 39 #include "wtf/text/AtomicString.h" 40 41 namespace blink { 42 43 class ShareableElementData; 44 class StylePropertySet; 45 class UniqueElementData; 46 47 // ElementData represents very common, but not necessarily unique to an element, 48 // data such as attributes, inline style, and parsed class names and ids. 49 class ElementData : public RefCountedWillBeGarbageCollectedFinalized<ElementData> { 50 WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED; 51 public: 52 #if ENABLE(OILPAN) 53 // Override GarbageCollectedFinalized's finalizeGarbageCollectedObject to 54 // dispatch to the correct subclass destructor. 55 void finalizeGarbageCollectedObject(); 56 #else 57 // Override RefCounted's deref() to ensure operator delete is called on 58 // the appropriate subclass type. 59 void deref(); 60 #endif 61 62 void clearClass() const { m_classNames.clear(); } 63 void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); } 64 const SpaceSplitString& classNames() const { return m_classNames; } 65 66 const AtomicString& idForStyleResolution() const { return m_idForStyleResolution; } 67 void setIdForStyleResolution(const AtomicString& newId) const { m_idForStyleResolution = newId; } 68 69 const StylePropertySet* inlineStyle() const { return m_inlineStyle.get(); } 70 71 const StylePropertySet* presentationAttributeStyle() const; 72 73 AttributeCollection attributes() const; 74 75 bool hasID() const { return !m_idForStyleResolution.isNull(); } 76 bool hasClass() const { return !m_classNames.isNull(); } 77 78 bool isEquivalent(const ElementData* other) const; 79 80 bool isUnique() const { return m_isUnique; } 81 82 void traceAfterDispatch(Visitor*); 83 void trace(Visitor*); 84 85 protected: 86 ElementData(); 87 explicit ElementData(unsigned arraySize); 88 ElementData(const ElementData&, bool isUnique); 89 90 // Keep the type in a bitfield instead of using virtual destructors to avoid adding a vtable. 91 unsigned m_isUnique : 1; 92 unsigned m_arraySize : 28; 93 mutable unsigned m_presentationAttributeStyleIsDirty : 1; 94 mutable unsigned m_styleAttributeIsDirty : 1; 95 mutable unsigned m_animatedSVGAttributesAreDirty : 1; 96 97 mutable RefPtrWillBeMember<StylePropertySet> m_inlineStyle; 98 mutable SpaceSplitString m_classNames; 99 mutable AtomicString m_idForStyleResolution; 100 101 private: 102 friend class Element; 103 friend class ShareableElementData; 104 friend class UniqueElementData; 105 friend class SVGElement; 106 107 #if !ENABLE(OILPAN) 108 void destroy(); 109 #endif 110 111 PassRefPtrWillBeRawPtr<UniqueElementData> makeUniqueCopy() const; 112 }; 113 114 #define DEFINE_ELEMENT_DATA_TYPE_CASTS(thisType, pointerPredicate, referencePredicate) \ 115 template<typename T> inline thisType* to##thisType(const RefPtr<T>& data) { return to##thisType(data.get()); } \ 116 DEFINE_TYPE_CASTS(thisType, ElementData, data, pointerPredicate, referencePredicate) 117 118 #if COMPILER(MSVC) 119 #pragma warning(push) 120 #pragma warning(disable: 4200) // Disable "zero-sized array in struct/union" warning 121 #endif 122 123 // SharableElementData is managed by ElementDataCache and is produced by 124 // the parser during page load for elements that have identical attributes. This 125 // is a memory optimization since it's very common for many elements to have 126 // duplicate sets of attributes (ex. the same classes). 127 class ShareableElementData FINAL : public ElementData { 128 public: 129 static PassRefPtrWillBeRawPtr<ShareableElementData> createWithAttributes(const Vector<Attribute>&); 130 131 explicit ShareableElementData(const Vector<Attribute>&); 132 explicit ShareableElementData(const UniqueElementData&); 133 ~ShareableElementData(); 134 135 void traceAfterDispatch(Visitor* visitor) { ElementData::traceAfterDispatch(visitor); } 136 137 // Add support for placement new as ShareableElementData is not allocated 138 // with a fixed size. Instead the allocated memory size is computed based on 139 // the number of attributes. This requires us to use Heap::allocate directly 140 // with the computed size and subsequently call placement new with the 141 // allocated memory address. 142 void* operator new(std::size_t, void* location) 143 { 144 return location; 145 } 146 147 AttributeCollection attributes() const; 148 149 Attribute m_attributeArray[0]; 150 }; 151 152 DEFINE_ELEMENT_DATA_TYPE_CASTS(ShareableElementData, !data->isUnique(), !data.isUnique()); 153 154 #if COMPILER(MSVC) 155 #pragma warning(pop) 156 #endif 157 158 // UniqueElementData is created when an element needs to mutate its attributes 159 // or gains presentation attribute style (ex. width="10"). It does not need to 160 // be created to fill in values in the ElementData that are derived from 161 // attributes. For example populating the m_inlineStyle from the style attribute 162 // doesn't require a UniqueElementData as all elements with the same style 163 // attribute will have the same inline style. 164 class UniqueElementData FINAL : public ElementData { 165 public: 166 static PassRefPtrWillBeRawPtr<UniqueElementData> create(); 167 PassRefPtrWillBeRawPtr<ShareableElementData> makeShareableCopy() const; 168 169 MutableAttributeCollection attributes(); 170 AttributeCollection attributes() const; 171 172 UniqueElementData(); 173 explicit UniqueElementData(const ShareableElementData&); 174 explicit UniqueElementData(const UniqueElementData&); 175 176 void traceAfterDispatch(Visitor*); 177 178 // FIXME: We might want to support sharing element data for elements with 179 // presentation attribute style. Lots of table cells likely have the same 180 // attributes. Most modern pages don't use presentation attributes though 181 // so this might not make sense. 182 mutable RefPtrWillBeMember<StylePropertySet> m_presentationAttributeStyle; 183 AttributeVector m_attributeVector; 184 }; 185 186 DEFINE_ELEMENT_DATA_TYPE_CASTS(UniqueElementData, data->isUnique(), data.isUnique()); 187 188 #if !ENABLE(OILPAN) 189 inline void ElementData::deref() 190 { 191 if (!derefBase()) 192 return; 193 destroy(); 194 } 195 #endif 196 197 inline const StylePropertySet* ElementData::presentationAttributeStyle() const 198 { 199 if (!m_isUnique) 200 return 0; 201 return toUniqueElementData(this)->m_presentationAttributeStyle.get(); 202 } 203 204 inline AttributeCollection ElementData::attributes() const 205 { 206 if (isUnique()) 207 return toUniqueElementData(this)->attributes(); 208 return toShareableElementData(this)->attributes(); 209 } 210 211 inline AttributeCollection ShareableElementData::attributes() const 212 { 213 return AttributeCollection(m_attributeArray, m_arraySize); 214 } 215 216 inline AttributeCollection UniqueElementData::attributes() const 217 { 218 return AttributeCollection(m_attributeVector.data(), m_attributeVector.size()); 219 } 220 221 inline MutableAttributeCollection UniqueElementData::attributes() 222 { 223 return MutableAttributeCollection(m_attributeVector); 224 } 225 226 } // namespace blink 227 228 #endif // ElementData_h 229