- Revision
- 128239
- Author
- kl...@webkit.org
- Date
- 2012-09-11 16:26:12 -0700 (Tue, 11 Sep 2012)
Log Message
ElementAttributeData: Use subclasses to manage varying object layouts.
<http://webkit.org/b/94465>
Reviewed by Antti Koivisto.
Add two ElementAttributeData subclasses:
- MutableElementAttributeData
- ImmutableElementAttributeData
The ElementAttributeData::m_isMutable bit determines which subclass to cast to when accessing
the attribute storage. Added mutableAttributeVector() and immutableAttributeArray() helpers
to ElementAttributeData (with appropriate assertions.)
This patch removes one step of indirection in the mutable case, since the Vector<Attribute> is no
longer heap-allocated, but part of MutableElementAttributeData.
Added a WTF::deleteOwnedPtr(ElementAttributeData*) specialization so that the appropriate subclass
destructor is called for these objects.
* WebCore.exp.in:
* dom/Element.cpp:
(WebCore::Element::createMutableAttributeData):
* dom/ElementAttributeData.cpp:
(WebCore::ElementAttributeData::createImmutable):
(WebCore::ElementAttributeData::create):
(WebCore::ElementAttributeData::ElementAttributeData):
(WebCore::MutableElementAttributeData::MutableElementAttributeData):
(WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData):
(WebCore::ImmutableElementAttributeData::~ImmutableElementAttributeData):
(WebCore::ElementAttributeData::makeMutableCopy):
(WebCore::ElementAttributeData::addAttribute):
(WebCore::ElementAttributeData::removeAttribute):
(WebCore::ElementAttributeData::reportMemoryUsage):
(WebCore::ElementAttributeData::cloneDataFrom):
(WebCore::ElementAttributeData::clearAttributes):
* dom/ElementAttributeData.h:
(ElementAttributeData):
(WebCore::ElementAttributeData::isMutable):
(ImmutableElementAttributeData):
(MutableElementAttributeData):
(WebCore::MutableElementAttributeData::MutableElementAttributeData):
(WebCore::ElementAttributeData::immutableAttributeArray):
(WebCore::ElementAttributeData::mutableAttributeVector):
(WebCore::ElementAttributeData::length):
(WebCore::ElementAttributeData::attributeItem):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (128238 => 128239)
--- trunk/Source/WebCore/ChangeLog 2012-09-11 23:20:44 UTC (rev 128238)
+++ trunk/Source/WebCore/ChangeLog 2012-09-11 23:26:12 UTC (rev 128239)
@@ -1,3 +1,52 @@
+2012-09-11 Andreas Kling <kl...@webkit.org>
+
+ ElementAttributeData: Use subclasses to manage varying object layouts.
+ <http://webkit.org/b/94465>
+
+ Reviewed by Antti Koivisto.
+
+ Add two ElementAttributeData subclasses:
+
+ - MutableElementAttributeData
+ - ImmutableElementAttributeData
+
+ The ElementAttributeData::m_isMutable bit determines which subclass to cast to when accessing
+ the attribute storage. Added mutableAttributeVector() and immutableAttributeArray() helpers
+ to ElementAttributeData (with appropriate assertions.)
+
+ This patch removes one step of indirection in the mutable case, since the Vector<Attribute> is no
+ longer heap-allocated, but part of MutableElementAttributeData.
+
+ Added a WTF::deleteOwnedPtr(ElementAttributeData*) specialization so that the appropriate subclass
+ destructor is called for these objects.
+
+ * WebCore.exp.in:
+ * dom/Element.cpp:
+ (WebCore::Element::createMutableAttributeData):
+ * dom/ElementAttributeData.cpp:
+ (WebCore::ElementAttributeData::createImmutable):
+ (WebCore::ElementAttributeData::create):
+ (WebCore::ElementAttributeData::ElementAttributeData):
+ (WebCore::MutableElementAttributeData::MutableElementAttributeData):
+ (WebCore::ImmutableElementAttributeData::ImmutableElementAttributeData):
+ (WebCore::ImmutableElementAttributeData::~ImmutableElementAttributeData):
+ (WebCore::ElementAttributeData::makeMutableCopy):
+ (WebCore::ElementAttributeData::addAttribute):
+ (WebCore::ElementAttributeData::removeAttribute):
+ (WebCore::ElementAttributeData::reportMemoryUsage):
+ (WebCore::ElementAttributeData::cloneDataFrom):
+ (WebCore::ElementAttributeData::clearAttributes):
+ * dom/ElementAttributeData.h:
+ (ElementAttributeData):
+ (WebCore::ElementAttributeData::isMutable):
+ (ImmutableElementAttributeData):
+ (MutableElementAttributeData):
+ (WebCore::MutableElementAttributeData::MutableElementAttributeData):
+ (WebCore::ElementAttributeData::immutableAttributeArray):
+ (WebCore::ElementAttributeData::mutableAttributeVector):
+ (WebCore::ElementAttributeData::length):
+ (WebCore::ElementAttributeData::attributeItem):
+
2012-09-11 Tony Chang <t...@chromium.org>
Pass the logical height and logical top into RenderBox::computeLogicalHeight
Modified: trunk/Source/WebCore/WebCore.exp.in (128238 => 128239)
--- trunk/Source/WebCore/WebCore.exp.in 2012-09-11 23:20:44 UTC (rev 128238)
+++ trunk/Source/WebCore/WebCore.exp.in 2012-09-11 23:26:12 UTC (rev 128239)
@@ -230,6 +230,7 @@
__ZN7WebCore13directoryNameERKN3WTF6StringE
__ZN7WebCore13toHTMLElementEPNS_21FormAssociatedElementE
__ZN7WebCore13toJSDOMWindowEN3JSC7JSValueE
+__ZN7WebCore13QualifiedNameD1Ev
__ZN7WebCore14CachedResource12removeClientEPNS_20CachedResourceClientE
__ZN7WebCore14CachedResource16unregisterHandleEPNS_24CachedResourceHandleBaseE
__ZN7WebCore14CachedResource9addClientEPNS_20CachedResourceClientE
@@ -538,6 +539,7 @@
__ZN7WebCore20UserGestureIndicatorD1Ev
__ZN7WebCore20makeRGBA32FromFloatsEffff
__ZN7WebCore20protocolIsJavaScriptERKN3WTF6StringE
+__ZN7WebCore20SpaceSplitStringDataD1Ev
__ZN7WebCore21BackForwardController11itemAtIndexEi
__ZN7WebCore21MemoryPressureHandler7installEv
__ZN7WebCore21PlatformKeyboardEvent24disambiguateKeyDownEventENS_13PlatformEvent4TypeEb
Modified: trunk/Source/WebCore/dom/Element.cpp (128238 => 128239)
--- trunk/Source/WebCore/dom/Element.cpp 2012-09-11 23:20:44 UTC (rev 128238)
+++ trunk/Source/WebCore/dom/Element.cpp 2012-09-11 23:26:12 UTC (rev 128239)
@@ -2246,7 +2246,7 @@
if (!m_attributeData)
m_attributeData = ElementAttributeData::create();
else
- m_attributeData = m_attributeData->makeMutable();
+ m_attributeData = m_attributeData->makeMutableCopy();
}
} // namespace WebCore
Modified: trunk/Source/WebCore/dom/ElementAttributeData.cpp (128238 => 128239)
--- trunk/Source/WebCore/dom/ElementAttributeData.cpp 2012-09-11 23:20:44 UTC (rev 128238)
+++ trunk/Source/WebCore/dom/ElementAttributeData.cpp 2012-09-11 23:26:12 UTC (rev 128239)
@@ -36,64 +36,56 @@
static size_t immutableElementAttributeDataSize(unsigned count)
{
- return sizeof(ElementAttributeData) - sizeof(void*) + sizeof(Attribute) * count;
+ return sizeof(ImmutableElementAttributeData) + sizeof(Attribute) * count;
}
PassRefPtr<ElementAttributeData> ElementAttributeData::createImmutable(const Vector<Attribute>& attributes)
{
void* slot = WTF::fastMalloc(immutableElementAttributeDataSize(attributes.size()));
- return adoptRef(new (slot) ElementAttributeData(attributes));
+ return adoptRef(new (slot) ImmutableElementAttributeData(attributes));
}
-ElementAttributeData::ElementAttributeData()
- : m_isMutable(true)
- , m_arraySize(0)
- , m_mutableAttributeVector(new Vector<Attribute, 4>)
+PassRefPtr<ElementAttributeData> ElementAttributeData::create()
{
+ return adoptRef(new MutableElementAttributeData);
}
-ElementAttributeData::ElementAttributeData(const Vector<Attribute>& attributes)
- : m_isMutable(false)
- , m_arraySize(attributes.size())
+ImmutableElementAttributeData::ImmutableElementAttributeData(const Vector<Attribute>& attributes)
+ : ElementAttributeData(attributes.size())
{
- Attribute* buffer = reinterpret_cast<Attribute*>(&m_attributes);
- for (unsigned i = 0; i < attributes.size(); ++i)
- new (&buffer[i]) Attribute(attributes[i]);
+ for (unsigned i = 0; i < m_arraySize; ++i)
+ new (&reinterpret_cast<Attribute*>(&m_attributeArray)[i]) Attribute(attributes[i]);
}
-ElementAttributeData::ElementAttributeData(const ElementAttributeData& other)
- : RefCounted<ElementAttributeData>()
- , m_isMutable(true)
- , m_arraySize(0)
- , m_inlineStyleDecl(other.m_inlineStyleDecl)
- , m_attributeStyle(other.m_attributeStyle)
- , m_classNames(other.m_classNames)
- , m_idForStyleResolution(other.m_idForStyleResolution)
- , m_mutableAttributeVector(new Vector<Attribute, 4>)
+MutableElementAttributeData::MutableElementAttributeData(const ImmutableElementAttributeData& other)
{
- // This copy constructor should only be used by makeMutable() to go from immutable to mutable.
- ASSERT(!other.m_isMutable);
+ const ElementAttributeData& baseOther = static_cast<const ElementAttributeData&>(other);
- // An immutable ElementAttributeData should never have a mutable inline StylePropertySet attached.
- ASSERT(!other.m_inlineStyleDecl || !other.m_inlineStyleDecl->isMutable());
+ m_inlineStyleDecl = baseOther.m_inlineStyleDecl;
+ m_attributeStyle = baseOther.m_attributeStyle;
+ m_classNames = baseOther.m_classNames;
+ m_idForStyleResolution = baseOther.m_idForStyleResolution;
- const Attribute* otherBuffer = reinterpret_cast<const Attribute*>(&other.m_attributes);
- for (unsigned i = 0; i < other.m_arraySize; ++i)
- m_mutableAttributeVector->append(otherBuffer[i]);
+ // An ImmutableElementAttributeData should never have a mutable inline StylePropertySet attached.
+ ASSERT(!baseOther.m_inlineStyleDecl || !baseOther.m_inlineStyleDecl->isMutable());
+
+ m_attributeVector.reserveCapacity(baseOther.m_arraySize);
+ for (unsigned i = 0; i < baseOther.m_arraySize; ++i)
+ m_attributeVector.uncheckedAppend(other.immutableAttributeArray()[i]);
}
-ElementAttributeData::~ElementAttributeData()
+ImmutableElementAttributeData::~ImmutableElementAttributeData()
{
- if (isMutable()) {
- ASSERT(!m_arraySize);
- delete m_mutableAttributeVector;
- } else {
- Attribute* buffer = reinterpret_cast<Attribute*>(&m_attributes);
- for (unsigned i = 0; i < m_arraySize; ++i)
- buffer[i].~Attribute();
- }
+ for (unsigned i = 0; i < m_arraySize; ++i)
+ (reinterpret_cast<Attribute*>(&m_attributeArray)[i]).~Attribute();
}
+PassRefPtr<ElementAttributeData> ElementAttributeData::makeMutableCopy() const
+{
+ ASSERT(!isMutable());
+ return adoptRef(new MutableElementAttributeData(static_cast<const ImmutableElementAttributeData&>(*this)));
+}
+
typedef Vector<RefPtr<Attr> > AttrList;
typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;
@@ -236,7 +228,7 @@
if (element && inSynchronizationOfLazyAttribute == NotInSynchronizationOfLazyAttribute)
element->willModifyAttribute(attribute.name(), nullAtom, attribute.value());
- m_mutableAttributeVector->append(attribute);
+ mutableAttributeVector().append(attribute);
if (element && inSynchronizationOfLazyAttribute == NotInSynchronizationOfLazyAttribute)
element->didAddAttribute(attribute);
@@ -247,7 +239,7 @@
ASSERT(isMutable());
ASSERT(index < length());
- Attribute& attribute = m_mutableAttributeVector->at(index);
+ Attribute& attribute = mutableAttributeVector().at(index);
QualifiedName name = attribute.name();
if (element && inSynchronizationOfLazyAttribute == NotInSynchronizationOfLazyAttribute)
@@ -256,7 +248,7 @@
if (RefPtr<Attr> attr = attrIfExists(element, name))
attr->detachFromElementWithValue(attribute.value());
- m_mutableAttributeVector->remove(index);
+ mutableAttributeVector().remove(index);
if (element && inSynchronizationOfLazyAttribute == NotInSynchronizationOfLazyAttribute)
element->didRemoveAttribute(name);
@@ -304,7 +296,7 @@
info.addMember(m_classNames);
info.addInstrumentedMember(m_idForStyleResolution);
if (m_isMutable)
- info.addVectorPtr(m_mutableAttributeVector);
+ info.addVector(mutableAttributeVector());
for (unsigned i = 0, len = length(); i < len; i++)
info.addInstrumentedMember(*attributeItem(i));
}
@@ -348,17 +340,15 @@
clearAttributes(&targetElement);
if (sourceData.isMutable())
- *m_mutableAttributeVector = *sourceData.m_mutableAttributeVector;
+ mutableAttributeVector() = sourceData.mutableAttributeVector();
else {
- ASSERT(m_mutableAttributeVector->isEmpty());
- m_mutableAttributeVector->reserveInitialCapacity(sourceData.m_arraySize);
- const Attribute* sourceBuffer = reinterpret_cast<const Attribute*>(&sourceData.m_attributes);
+ mutableAttributeVector().reserveInitialCapacity(sourceData.m_arraySize);
for (unsigned i = 0; i < sourceData.m_arraySize; ++i)
- m_mutableAttributeVector->uncheckedAppend(sourceBuffer[i]);
+ mutableAttributeVector().uncheckedAppend(sourceData.immutableAttributeArray()[i]);
}
for (unsigned i = 0; i < length(); ++i) {
- const Attribute& attribute = m_mutableAttributeVector->at(i);
+ const Attribute& attribute = mutableAttributeVector().at(i);
if (targetElement.isStyledElement() && attribute.name() == HTMLNames::styleAttr) {
static_cast<StyledElement&>(targetElement).styleAttributeChanged(attribute.value(), StyledElement::DoNotReparseStyleAttribute);
continue;
@@ -380,7 +370,7 @@
detachAttrObjectsFromElement(element);
clearClass();
- m_mutableAttributeVector->clear();
+ mutableAttributeVector().clear();
}
PassRefPtr<Attr> ElementAttributeData::getAttributeNode(const String& name, bool shouldIgnoreAttributeCase, Element* element) const
Modified: trunk/Source/WebCore/dom/ElementAttributeData.h (128238 => 128239)
--- trunk/Source/WebCore/dom/ElementAttributeData.h 2012-09-11 23:20:44 UTC (rev 128238)
+++ trunk/Source/WebCore/dom/ElementAttributeData.h 2012-09-11 23:26:12 UTC (rev 128239)
@@ -35,16 +35,17 @@
class Attr;
class Element;
+class ImmutableElementAttributeData;
class MemoryObjectInfo;
+class MutableElementAttributeData;
enum SynchronizationOfLazyAttribute { NotInSynchronizationOfLazyAttribute, InSynchronizationOfLazyAttribute };
class ElementAttributeData : public RefCounted<ElementAttributeData> {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<ElementAttributeData> create() { return adoptRef(new ElementAttributeData); }
+ static PassRefPtr<ElementAttributeData> create();
static PassRefPtr<ElementAttributeData> createImmutable(const Vector<Attribute>&);
- ~ElementAttributeData();
void clearClass() { m_classNames.clear(); }
void setClass(const AtomicString& className, bool shouldFoldCase) const { m_classNames.set(className, shouldFoldCase); }
@@ -95,41 +96,84 @@
void reportMemoryUsage(MemoryObjectInfo*) const;
+ bool isMutable() const { return m_isMutable; }
+
+protected:
+ ElementAttributeData()
+ : m_isMutable(true)
+ , m_arraySize(0)
+ { }
+
+ ElementAttributeData(unsigned arraySize)
+ : m_isMutable(false)
+ , m_arraySize(arraySize)
+ { }
+
+ mutable RefPtr<StylePropertySet> m_inlineStyleDecl;
+ mutable RefPtr<StylePropertySet> m_attributeStyle;
+ mutable SpaceSplitString m_classNames;
+ mutable AtomicString m_idForStyleResolution;
+
+ unsigned m_isMutable : 1;
+ unsigned m_arraySize : 31;
+
private:
friend class Element;
friend class HTMLConstructionSite;
+ friend class ImmutableElementAttributeData;
+ friend class MutableElementAttributeData;
- ElementAttributeData();
- ElementAttributeData(const ElementAttributeData&);
- ElementAttributeData(const Vector<Attribute>&);
-
Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase);
const Attribute* getAttributeItem(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
size_t getAttributeItemIndexSlowCase(const AtomicString& name, bool shouldIgnoreAttributeCase) const;
void cloneDataFrom(const ElementAttributeData& sourceData, const Element& sourceElement, Element& targetElement);
void clearAttributes(Element*);
- bool isMutable() const { return m_isMutable; }
- PassRefPtr<ElementAttributeData> makeMutable() const { return adoptRef(new ElementAttributeData(*this)); }
+ PassRefPtr<ElementAttributeData> makeMutableCopy() const;
- unsigned m_isMutable : 1;
- unsigned m_arraySize : 31;
+ Vector<Attribute, 4>& mutableAttributeVector();
+ const Vector<Attribute, 4>& mutableAttributeVector() const;
+ const Attribute* immutableAttributeArray() const;
+};
- mutable RefPtr<StylePropertySet> m_inlineStyleDecl;
- mutable RefPtr<StylePropertySet> m_attributeStyle;
- mutable SpaceSplitString m_classNames;
- mutable AtomicString m_idForStyleResolution;
+class ImmutableElementAttributeData : public ElementAttributeData {
+public:
+ ImmutableElementAttributeData(const Vector<Attribute>&);
+ ~ImmutableElementAttributeData();
- union {
- Vector<Attribute, 4>* m_mutableAttributeVector;
- void* m_attributes;
- };
+ void* m_attributeArray;
};
+class MutableElementAttributeData : public ElementAttributeData {
+public:
+ MutableElementAttributeData() { }
+ MutableElementAttributeData(const ImmutableElementAttributeData&);
+
+ Vector<Attribute, 4> m_attributeVector;
+};
+
+inline Vector<Attribute, 4>& ElementAttributeData::mutableAttributeVector()
+{
+ ASSERT(m_isMutable);
+ return static_cast<MutableElementAttributeData*>(this)->m_attributeVector;
+}
+
+inline const Vector<Attribute, 4>& ElementAttributeData::mutableAttributeVector() const
+{
+ ASSERT(m_isMutable);
+ return static_cast<const MutableElementAttributeData*>(this)->m_attributeVector;
+}
+
+inline const Attribute* ElementAttributeData::immutableAttributeArray() const
+{
+ ASSERT(!m_isMutable);
+ return reinterpret_cast<const Attribute*>(&static_cast<const ImmutableElementAttributeData*>(this)->m_attributeArray);
+}
+
inline size_t ElementAttributeData::length() const
{
if (isMutable())
- return m_mutableAttributeVector->size();
+ return mutableAttributeVector().size();
return m_arraySize;
}
@@ -201,19 +245,31 @@
inline const Attribute* ElementAttributeData::attributeItem(unsigned index) const
{
ASSERT(index < length());
- if (isMutable())
- return &m_mutableAttributeVector->at(index);
- const Attribute* buffer = reinterpret_cast<const Attribute*>(&m_attributes);
- return &buffer[index];
+ if (m_isMutable)
+ return &mutableAttributeVector().at(index);
+ return &immutableAttributeArray()[index];
}
inline Attribute* ElementAttributeData::attributeItem(unsigned index)
{
- ASSERT(isMutable());
ASSERT(index < length());
- return &m_mutableAttributeVector->at(index);
+ return &mutableAttributeVector().at(index);
}
}
+namespace WTF {
+
+template <> inline void deleteOwnedPtr<WebCore::ElementAttributeData>(WebCore::ElementAttributeData* ptr)
+{
+ if (!ptr)
+ return;
+ if (ptr->isMutable())
+ delete static_cast<WebCore::MutableElementAttributeData*>(ptr);
+ else
+ delete static_cast<WebCore::ImmutableElementAttributeData*>(ptr);
+}
+
+}
+
#endif // ElementAttributeData_h