Modified: branches/safari-536-branch/Source/WebCore/ChangeLog (117103 => 117104)
--- branches/safari-536-branch/Source/WebCore/ChangeLog 2012-05-15 18:16:00 UTC (rev 117103)
+++ branches/safari-536-branch/Source/WebCore/ChangeLog 2012-05-15 18:24:56 UTC (rev 117104)
@@ -1,5 +1,49 @@
2012-05-15 Lucas Forschler <[email protected]>
+ Merge 116419
+
+ 2012-05-08 Andreas Kling <[email protected]>
+
+ Shrink ElementAttributeData by factoring out Attr object count.
+ <http://webkit.org/b/85825>
+
+ Reviewed by Antti Koivisto.
+
+ Stop tracking the number of Attr objects that point to a given Element on the
+ Element itself and manage this by having a global hashmap of Element => AttrList,
+ where AttrList is a vector of (pointers to) the associated Attr objects.
+
+ This shrinks ElementAttributeData by one integer, effectively reducing memory
+ consumption by ~530kB when viewing the full HTML5 spec at <http://whatwg.org/c>.
+
+ * dom/ElementAttributeData.h:
+ (ElementAttributeData):
+
+ Remove m_attrCount...
+
+ * dom/Node.h:
+ (WebCore::Node::hasAttrList):
+ (WebCore::Node::setHasAttrList):
+ (WebCore::Node::clearHasAttrList):
+
+ ...replacing it with a Node flag that tells us whether there's an Attr
+ object map for this Node (only applies to Elements.)
+
+ * dom/ElementAttributeData.cpp:
+ (WebCore::attrListMap):
+ (WebCore::attrListForElement):
+ (WebCore::ensureAttrListForElement):
+ (WebCore::removeAttrListForElement):
+ (WebCore::ElementAttributeData::attrIfExists):
+ (WebCore::ElementAttributeData::ensureAttr):
+ (WebCore::ElementAttributeData::setAttr):
+ (WebCore::ElementAttributeData::removeAttr):
+ (WebCore::ElementAttributeData::detachAttributesFromElement):
+
+ Map Element => per-Element AttrList in a global hash.
+
+2012-05-15 Lucas Forschler <[email protected]>
+
Merge 116395
2012-05-07 Simon Fraser <[email protected]>
Modified: branches/safari-536-branch/Source/WebCore/dom/ElementAttributeData.cpp (117103 => 117104)
--- branches/safari-536-branch/Source/WebCore/dom/ElementAttributeData.cpp 2012-05-15 18:16:00 UTC (rev 117103)
+++ branches/safari-536-branch/Source/WebCore/dom/ElementAttributeData.cpp 2012-05-15 18:24:56 UTC (rev 117104)
@@ -32,43 +32,99 @@
namespace WebCore {
-typedef HashMap<pair<Element*, QualifiedName>, RefPtr<Attr> > AttrMap;
-static AttrMap& attrMap()
+typedef Vector<RefPtr<Attr> > AttrList;
+typedef HashMap<Element*, OwnPtr<AttrList> > AttrListMap;
+
+static AttrListMap& attrListMap()
{
- DEFINE_STATIC_LOCAL(AttrMap, map, ());
+ DEFINE_STATIC_LOCAL(AttrListMap, map, ());
return map;
}
+static AttrList* attrListForElement(Element* element)
+{
+ ASSERT(element);
+ if (!element->hasAttrList())
+ return false;
+ ASSERT(attrListMap().contains(element));
+ return attrListMap().get(element);
+}
+
+static AttrList* ensureAttrListForElement(Element* element)
+{
+ ASSERT(element);
+ if (element->hasAttrList()) {
+ ASSERT(attrListMap().contains(element));
+ return attrListMap().get(element);
+ }
+ ASSERT(!attrListMap().contains(element));
+ element->setHasAttrList();
+ AttrListMap::AddResult result = attrListMap().add(element, adoptPtr(new AttrList));
+ return result.iterator->second.get();
+}
+
+static void removeAttrListForElement(Element* element)
+{
+ ASSERT(element);
+ ASSERT(element->hasAttrList());
+ ASSERT(attrListMap().contains(element));
+ attrListMap().remove(element);
+ element->clearHasAttrList();
+}
+
+static Attr* findAttrInList(AttrList* attrList, const QualifiedName& name)
+{
+ for (unsigned i = 0; i < attrList->size(); ++i) {
+ if (attrList->at(i)->qualifiedName() == name)
+ return attrList->at(i).get();
+ }
+ return 0;
+}
+
PassRefPtr<Attr> ElementAttributeData::attrIfExists(Element* element, const QualifiedName& name)
{
- if (!m_attrCount)
- return 0;
- return attrMap().get(std::make_pair(element, name)).get();
+ if (AttrList* attrList = attrListForElement(element))
+ return findAttrInList(attrList, name);
+ return 0;
}
PassRefPtr<Attr> ElementAttributeData::ensureAttr(Element* element, const QualifiedName& name)
{
- AttrMap::AddResult result = attrMap().add(std::make_pair(element, name), 0);
- if (result.isNewEntry) {
- result.iterator->second = Attr::create(element, name);
- ++m_attrCount;
+ AttrList* attrList = ensureAttrListForElement(element);
+ RefPtr<Attr> attr = findAttrInList(attrList, name);
+ if (!attr) {
+ attr = Attr::create(element, name);
+ attrList->append(attr);
}
- return result.iterator->second.get();
+ return attr.release();
}
void ElementAttributeData::setAttr(Element* element, const QualifiedName& name, Attr* attr)
{
- ASSERT(!attrMap().contains(std::make_pair(element, name)));
- attrMap().add(std::make_pair(element, name), attr);
+ AttrList* attrList = ensureAttrListForElement(element);
+
+ if (findAttrInList(attrList, name))
+ return;
+
+ attrList->append(attr);
attr->attachToElement(element);
- ++m_attrCount;
}
void ElementAttributeData::removeAttr(Element* element, const QualifiedName& name)
{
- ASSERT(attrMap().contains(std::make_pair(element, name)));
- attrMap().remove(std::make_pair(element, name));
- --m_attrCount;
+ AttrList* attrList = attrListForElement(element);
+ ASSERT(attrList);
+
+ for (unsigned i = 0; i < attrList->size(); ++i) {
+ if (attrList->at(i)->qualifiedName() == name) {
+ attrList->remove(i);
+ if (attrList->isEmpty())
+ removeAttrListForElement(element);
+ return;
+ }
+ }
+
+ ASSERT_NOT_REACHED();
}
ElementAttributeData::~ElementAttributeData()
@@ -170,13 +226,16 @@
void ElementAttributeData::detachAttributesFromElement(Element* element)
{
- if (!m_attrCount)
+ if (!element->hasAttrList())
return;
for (unsigned i = 0; i < m_attributes.size(); ++i) {
if (RefPtr<Attr> attr = attrIfExists(element, m_attributes[i].name()))
attr->detachFromElementWithValue(m_attributes[i].value());
}
+
+ // The loop above should have cleaned out this element's Attr map.
+ ASSERT(!element->hasAttrList());
}
size_t ElementAttributeData::getAttributeItemIndexSlowCase(const String& name, bool shouldIgnoreAttributeCase) const
Modified: branches/safari-536-branch/Source/WebCore/dom/ElementAttributeData.h (117103 => 117104)
--- branches/safari-536-branch/Source/WebCore/dom/ElementAttributeData.h 2012-05-15 18:16:00 UTC (rev 117103)
+++ branches/safari-536-branch/Source/WebCore/dom/ElementAttributeData.h 2012-05-15 18:24:56 UTC (rev 117104)
@@ -106,7 +106,6 @@
friend class HTMLConstructionSite;
ElementAttributeData()
- : m_attrCount(0)
{
}
@@ -125,8 +124,6 @@
SpaceSplitString m_classNames;
AtomicString m_idForStyleResolution;
Vector<Attribute> m_attributes;
-
- unsigned m_attrCount;
};
inline void ElementAttributeData::removeAttribute(const QualifiedName& name, Element* element)
Modified: branches/safari-536-branch/Source/WebCore/dom/Node.h (117103 => 117104)
--- branches/safari-536-branch/Source/WebCore/dom/Node.h 2012-05-15 18:16:00 UTC (rev 117103)
+++ branches/safari-536-branch/Source/WebCore/dom/Node.h 2012-05-15 18:24:56 UTC (rev 117104)
@@ -216,6 +216,7 @@
bool isDocumentNode() const;
bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
+ bool hasAttrList() const { return getFlag(HasAttrListFlag); }
Node* shadowAncestorNode() const;
// Returns 0, a ShadowRoot, or a legacy shadow root.
@@ -330,6 +331,9 @@
void setInNamedFlow() { setFlag(InNamedFlowFlag); }
void clearInNamedFlow() { clearFlag(InNamedFlowFlag); }
+ void setHasAttrList() { setFlag(HasAttrListFlag); }
+ void clearHasAttrList() { clearFlag(HasAttrListFlag); }
+
enum ShouldSetAttached {
SetAttached,
DoNotSetAttached
@@ -687,10 +691,11 @@
#else
DefaultNodeFlags = IsParsingChildrenFinishedFlag | IsStyleAttributeValidFlag,
#endif
- InNamedFlowFlag = 1 << 29
+ InNamedFlowFlag = 1 << 29,
+ HasAttrListFlag = 1 << 30
};
- // 3 bits remaining
+ // 2 bits remaining
bool getFlag(NodeFlags mask) const { return m_nodeFlags & mask; }
void setFlag(bool f, NodeFlags mask) const { m_nodeFlags = (m_nodeFlags & ~mask) | (-(int32_t)f & mask); }