Home | History | Annotate | Download | only in dom
      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 
     47 static size_t sizeForShareableElementDataWithAttributeCount(unsigned count)
     48 {
     49     return sizeof(ShareableElementData) + sizeof(Attribute) * count;
     50 }
     51 
     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 
     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 
     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)
     83 void ElementData::finalizeGarbageCollectedObject()
     84 {
     85     if (m_isUnique)
     86         toUniqueElementData(this)->~UniqueElementData();
     87     else
     88         toShareableElementData(this)->~ShareableElementData();
     89 }
     90 #else
     91 void ElementData::destroy()
     92 {
     93     if (m_isUnique)
     94         delete toUniqueElementData(this);
     95     else
     96         delete toShareableElementData(this);
     97 }
     98 #endif
     99 
    100 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 
    107 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 
    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 
    134 void ElementData::traceAfterDispatch(Visitor* visitor)
    135 {
    136     visitor->trace(m_inlineStyle);
    137 }
    138 
    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 
    146 ShareableElementData::~ShareableElementData()
    147 {
    148     for (unsigned i = 0; i < m_arraySize; ++i)
    149         m_attributeArray[i].~Attribute();
    150 }
    151 
    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 
    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 
    175 UniqueElementData::UniqueElementData()
    176 {
    177 }
    178 
    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 
    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 
    200 PassRefPtrWillBeRawPtr<UniqueElementData> UniqueElementData::create()
    201 {
    202     return adoptRefWillBeNoop(new UniqueElementData);
    203 }
    204 
    205 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 
    215 void UniqueElementData::traceAfterDispatch(Visitor* visitor)
    216 {
    217     visitor->trace(m_presentationAttributeStyle);
    218     ElementData::traceAfterDispatch(visitor);
    219 }
    220 
    221 } // namespace blink
    222