Create only NodeRareDataBase when setting TreeScope
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Dec 2012 20:16:22 +0000 (20:16 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 6 Dec 2012 20:16:22 +0000 (20:16 +0000)
https://bugs.webkit.org/show_bug.cgi?id=104202

Patch by Elliott Sprehn <esprehn@gmail.com> on 2012-12-06
Reviewed by Dimitri Glazkov.

Move many fields from NodeRareData into NodeRareDataBase and rename it
UncommonNodeData and add a flag to determine if a UncommonNodeData is
actually a full NodeRareData instance. By moving fields up from NodeRareData
we ensure that this new flag in the base class doesn't make NodeRareData
grow in size.

We then make setting the tree scope only allocate the UncommonNodeData
instead of creating the full NodeRareData or ElementRareData. This is
important because when putting nodes into ShadowRoot or any descendant
we must associate the node with a tree scope which adds rare data to the
node making NodeRareData and ElementRareData not very rare.

On 64bit, this reduces the overhead per element from 136 bytes to
32 bytes for a 76% savings, and on other nodes from 64 bytes to 32 bytes
for a 50% savings.

No new tests, no change in behavior.

* dom/Document.h:
(WebCore::Node::treeScope):
* dom/Element.cpp:
(WebCore::Element::createRareData):
* dom/ElementRareData.h:
(ElementRareData):
(WebCore::ElementRareData::ElementRareData):
* dom/Node.cpp:
(WebCore::Node::setTreeScope):
(WebCore::Node::ensureRareData):
(WebCore::Node::createRareData):
(WebCore::Node::clearRareData):
* dom/Node.h:
(WebCore::UncommonNodeData::create):
(UncommonNodeData):
(WebCore::UncommonNodeData::~UncommonNodeData):
(WebCore::UncommonNodeData::isNodeRareData):
(WebCore::UncommonNodeData::UncommonNodeData):
(WebCore::Node::renderer):
(WebCore::Node::setRenderer):
(Node):
(WebCore::Node::hasRareData):
(WebCore::Node::hasUncommonNodeData):
* dom/NodeRareData.h:
(WebCore::NodeRareData::NodeRareData):
(NodeRareData):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@136871 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/dom/Document.h
Source/WebCore/dom/Element.cpp
Source/WebCore/dom/ElementRareData.h
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/NodeRareData.h

index 57ddc28..57fe80a 100644 (file)
@@ -1,3 +1,55 @@
+2012-12-06  Elliott Sprehn  <esprehn@gmail.com>
+
+        Create only NodeRareDataBase when setting TreeScope
+        https://bugs.webkit.org/show_bug.cgi?id=104202
+
+        Reviewed by Dimitri Glazkov.
+
+        Move many fields from NodeRareData into NodeRareDataBase and rename it
+        UncommonNodeData and add a flag to determine if a UncommonNodeData is
+        actually a full NodeRareData instance. By moving fields up from NodeRareData
+        we ensure that this new flag in the base class doesn't make NodeRareData
+        grow in size.
+
+        We then make setting the tree scope only allocate the UncommonNodeData
+        instead of creating the full NodeRareData or ElementRareData. This is
+        important because when putting nodes into ShadowRoot or any descendant
+        we must associate the node with a tree scope which adds rare data to the
+        node making NodeRareData and ElementRareData not very rare.
+
+        On 64bit, this reduces the overhead per element from 136 bytes to
+        32 bytes for a 76% savings, and on other nodes from 64 bytes to 32 bytes
+        for a 50% savings.
+
+        No new tests, no change in behavior.
+
+        * dom/Document.h:
+        (WebCore::Node::treeScope):
+        * dom/Element.cpp:
+        (WebCore::Element::createRareData):
+        * dom/ElementRareData.h:
+        (ElementRareData):
+        (WebCore::ElementRareData::ElementRareData):
+        * dom/Node.cpp:
+        (WebCore::Node::setTreeScope):
+        (WebCore::Node::ensureRareData):
+        (WebCore::Node::createRareData):
+        (WebCore::Node::clearRareData):
+        * dom/Node.h:
+        (WebCore::UncommonNodeData::create):
+        (UncommonNodeData):
+        (WebCore::UncommonNodeData::~UncommonNodeData):
+        (WebCore::UncommonNodeData::isNodeRareData):
+        (WebCore::UncommonNodeData::UncommonNodeData):
+        (WebCore::Node::renderer):
+        (WebCore::Node::setRenderer):
+        (Node):
+        (WebCore::Node::hasRareData):
+        (WebCore::Node::hasUncommonNodeData):
+        * dom/NodeRareData.h:
+        (WebCore::NodeRareData::NodeRareData):
+        (NodeRareData):
+
 2012-12-06  Joshua Bell  <jsbell@chromium.org>
 
         IndexedDB: Remove IDBDatabaseException.idl
index 713d9e5..1acd81a 100644 (file)
@@ -1554,7 +1554,7 @@ inline bool Node::isDocumentNode() const
 
 inline TreeScope* Node::treeScope() const
 {
-    return hasRareData() ? m_data.m_rareData->treeScope() : documentInternal();
+    return hasUncommonNodeData() ? m_data.m_rareData->treeScope() : documentInternal();
 }
 
 inline Node::Node(Document* document, ConstructionType type)
index ab199f0..930dbee 100644 (file)
@@ -217,7 +217,7 @@ inline ElementRareData* Element::ensureElementRareData()
 
 PassOwnPtr<NodeRareData> Element::createRareData()
 {
-    return adoptPtr(new ElementRareData(documentInternal()));
+    return adoptPtr(new ElementRareData());
 }
 
 DEFINE_VIRTUAL_ATTRIBUTE_EVENT_LISTENER(Element, blur);
index 7905cb5..88f26bd 100644 (file)
@@ -35,7 +35,7 @@ namespace WebCore {
 
 class ElementRareData : public NodeRareData {
 public:
-    ElementRareData(Document*);
+    ElementRareData();
     virtual ~ElementRareData();
 
     void setPseudoElement(PseudoId, PassRefPtr<PseudoElement>);
@@ -130,9 +130,8 @@ inline IntSize defaultMinimumSizeForResizing()
     return IntSize(LayoutUnit::max(), LayoutUnit::max());
 }
 
-inline ElementRareData::ElementRareData(Document* document)
-    : NodeRareData(document)
-    , m_minimumSizeForResizing(defaultMinimumSizeForResizing())
+inline ElementRareData::ElementRareData()
+    : m_minimumSizeForResizing(defaultMinimumSizeForResizing())
     , m_generatedBefore(0)
     , m_generatedAfter(0)
 {
index 584dbe9..88337fd 100644 (file)
@@ -441,10 +441,14 @@ void Node::setDocument(Document* document)
 
 void Node::setTreeScope(TreeScope* scope)
 {
-    if (!hasRareData() && scope->rootNode()->isDocumentNode())
+    if (!hasUncommonNodeData() && scope->rootNode()->isDocumentNode())
         return;
 
-    ensureRareData()->setTreeScope(scope);
+    if (!hasUncommonNodeData()) {
+        m_data.m_rareData = UncommonNodeData::create(scope, m_data.m_renderer);
+        setFlag(HasUncommonNodeData);
+    } else
+        rareData()->setTreeScope(scope);
 }
 
 Node* Node::pseudoAwarePreviousSibling() const
@@ -488,15 +492,21 @@ NodeRareData* Node::ensureRareData()
 
     NodeRareData* data = createRareData().leakPtr();
     ASSERT(data);
-    data->setRenderer(m_data.m_renderer);
+    data->setRenderer(renderer());
+    data->setTreeScope(treeScope());
+
+    if (hasUncommonNodeData())
+        delete m_data.m_rareData;
+
     m_data.m_rareData = data;
-    setFlag(HasRareDataFlag);
+    setFlag(HasUncommonNodeData);
+
     return data;
 }
 
 PassOwnPtr<NodeRareData> Node::createRareData()
 {
-    return adoptPtr(new NodeRareData(documentInternal()));
+    return adoptPtr(new NodeRareData());
 }
 
 void Node::clearRareData()
@@ -510,7 +520,7 @@ void Node::clearRareData()
     RenderObject* renderer = m_data.m_rareData->renderer();
     delete m_data.m_rareData;
     m_data.m_renderer = renderer;
-    clearFlag(HasRareDataFlag);
+    clearFlag(HasUncommonNodeData);
 }
 
 Node* Node::toNode()
index 7a470ee..6bd483f 100644 (file)
@@ -110,23 +110,85 @@ enum StyleChangeType {
     SyntheticStyleChange = 3 << nodeStyleChangeShift
 };
 
-class NodeRareDataBase {
+class UncommonNodeData {
 public:
+    static UncommonNodeData* create(TreeScope* scope, RenderObject* renderer)
+    {
+        return new UncommonNodeData(scope, renderer);
+    }
+
     RenderObject* renderer() const { return m_renderer; }
     void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
 
     TreeScope* treeScope() const { return m_treeScope; }
     void setTreeScope(TreeScope* scope) { m_treeScope = scope; }
 
-    virtual ~NodeRareDataBase() { }
+    virtual ~UncommonNodeData() { }
+
+    bool isNodeRareData() const { return m_isNodeRareData; }
+
 protected:
-    NodeRareDataBase(TreeScope* scope)
-        : m_treeScope(scope)
+    UncommonNodeData()
+        : m_tabIndex(0)
+        , m_childIndex(0)
+        , m_isNodeRareData(true)
+        , m_tabIndexWasSetExplicitly(false)
+        , m_isFocused(false)
+        , m_needsFocusAppearanceUpdateSoonAfterAttach(false)
+        , m_styleAffectedByEmpty(false)
+        , m_isInCanvasSubtree(false)
+#if ENABLE(FULLSCREEN_API)
+        , m_containsFullScreenElement(false)
+#endif
+#if ENABLE(DIALOG_ELEMENT)
+        , m_isInTopLayer(false)
+#endif
+        , m_childrenAffectedByHover(false)
+        , m_childrenAffectedByActive(false)
+        , m_childrenAffectedByDrag(false)
+        , m_childrenAffectedByFirstChildRules(false)
+        , m_childrenAffectedByLastChildRules(false)
+        , m_childrenAffectedByDirectAdjacentRules(false)
+        , m_childrenAffectedByForwardPositionalRules(false)
+        , m_childrenAffectedByBackwardPositionalRules(false)
     {
     }
 private:
+    UncommonNodeData(TreeScope* scope, RenderObject* renderer)
+        : m_renderer(renderer)
+        , m_treeScope(scope)
+        , m_isNodeRareData(false)
+    {
+    }
+
     RenderObject* m_renderer;
     TreeScope* m_treeScope;
+protected:
+    short m_tabIndex;
+    unsigned short m_childIndex;
+    bool m_isNodeRareData : 1;
+    bool m_tabIndexWasSetExplicitly : 1;
+    bool m_isFocused : 1;
+    bool m_needsFocusAppearanceUpdateSoonAfterAttach : 1;
+    bool m_styleAffectedByEmpty : 1;
+    bool m_isInCanvasSubtree : 1;
+#if ENABLE(FULLSCREEN_API)
+    bool m_containsFullScreenElement : 1;
+#endif
+#if ENABLE(DIALOG_ELEMENT)
+    bool m_isInTopLayer : 1;
+#endif
+    bool m_childrenAffectedByHover : 1;
+    bool m_childrenAffectedByActive : 1;
+    bool m_childrenAffectedByDrag : 1;
+    // Bits for dynamic child matching.
+    // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
+    // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
+    bool m_childrenAffectedByFirstChildRules : 1;
+    bool m_childrenAffectedByLastChildRules : 1;
+    bool m_childrenAffectedByDirectAdjacentRules : 1;
+    bool m_childrenAffectedByForwardPositionalRules : 1;
+    bool m_childrenAffectedByBackwardPositionalRules : 1;
 };
 
 class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node, ContainerNode> {
@@ -523,10 +585,10 @@ public:
     // Integration with rendering tree
 
     // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths.
-    RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
+    RenderObject* renderer() const { return hasUncommonNodeData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
     void setRenderer(RenderObject* renderer)
     {
-        if (hasRareData())
+        if (hasUncommonNodeData())
             m_data.m_rareData->setRenderer(renderer);
         else
             m_data.m_renderer = renderer;
@@ -710,7 +772,7 @@ private:
         IsActiveFlag = 1 << 10,
         IsHoveredFlag = 1 << 11,
         InActiveChainFlag = 1 << 12,
-        HasRareDataFlag = 1 << 13,
+        HasUncommonNodeData = 1 << 13,
         IsDocumentFragmentFlag = 1 << 14,
 
         // These bits are used by derived classes, pulled up here so they can
@@ -774,8 +836,8 @@ protected:
     virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const { }
     void setTabIndexExplicitly(short);
     void clearTabIndexExplicitly();
-    
-    bool hasRareData() const { return getFlag(HasRareDataFlag); }
+
+    bool hasRareData() const { return hasUncommonNodeData() && m_data.m_rareData->isNodeRareData(); }
 
     NodeRareData* rareData() const;
     NodeRareData* ensureRareData();
@@ -808,6 +870,7 @@ private:
     virtual void refEventTarget();
     virtual void derefEventTarget();
 
+    bool hasUncommonNodeData() const { return getFlag(HasUncommonNodeData); }
     virtual PassOwnPtr<NodeRareData> createRareData();
     bool rareDataFocused() const;
 
@@ -844,7 +907,7 @@ private:
     union DataUnion {
         DataUnion() : m_renderer(0) { }
         RenderObject* m_renderer;
-        NodeRareDataBase* m_rareData;
+        UncommonNodeData* m_rareData;
     } m_data;
 
 protected:
index 24ef233..c9049ac 100644 (file)
@@ -196,33 +196,11 @@ private:
     TagNodeListCacheNS m_tagNodeListCacheNS;
 };
 
-class NodeRareData : public NodeRareDataBase {
+class NodeRareData : public UncommonNodeData {
     WTF_MAKE_NONCOPYABLE(NodeRareData); WTF_MAKE_FAST_ALLOCATED;
 public:    
-    NodeRareData(Document* document)
-        : NodeRareDataBase(document)
-        , m_childNodeList(0)
-        , m_tabIndex(0)
-        , m_childIndex(0)
-        , m_tabIndexWasSetExplicitly(false)
-        , m_isFocused(false)
-        , m_needsFocusAppearanceUpdateSoonAfterAttach(false)
-        , m_styleAffectedByEmpty(false)
-        , m_isInCanvasSubtree(false)
-#if ENABLE(FULLSCREEN_API)
-        , m_containsFullScreenElement(false)
-#endif
-#if ENABLE(DIALOG_ELEMENT)
-        , m_isInTopLayer(false)
-#endif
-        , m_childrenAffectedByHover(false)
-        , m_childrenAffectedByActive(false)
-        , m_childrenAffectedByDrag(false)
-        , m_childrenAffectedByFirstChildRules(false)
-        , m_childrenAffectedByLastChildRules(false)
-        , m_childrenAffectedByDirectAdjacentRules(false)
-        , m_childrenAffectedByForwardPositionalRules(false)
-        , m_childrenAffectedByBackwardPositionalRules(false)
+    NodeRareData()
+        : m_childNodeList(0)
     {
     }
 
@@ -326,33 +304,9 @@ public:
 
     virtual void reportMemoryUsage(MemoryObjectInfo*) const;
 
-protected:
+private:
     OwnPtr<NodeListsNodeData> m_nodeLists;
     ChildNodeList* m_childNodeList;
-    short m_tabIndex;
-    unsigned short m_childIndex;
-    bool m_tabIndexWasSetExplicitly : 1;
-    bool m_isFocused : 1;
-    bool m_needsFocusAppearanceUpdateSoonAfterAttach : 1;
-    bool m_styleAffectedByEmpty : 1;
-    bool m_isInCanvasSubtree : 1;
-#if ENABLE(FULLSCREEN_API)
-    bool m_containsFullScreenElement : 1;
-#endif
-#if ENABLE(DIALOG_ELEMENT)
-    bool m_isInTopLayer : 1;
-#endif
-    bool m_childrenAffectedByHover : 1;
-    bool m_childrenAffectedByActive : 1;
-    bool m_childrenAffectedByDrag : 1;
-    // Bits for dynamic child matching.
-    // We optimize for :first-child and :last-child. The other positional child selectors like nth-child or
-    // *-child-of-type, we will just give up and re-evaluate whenever children change at all.
-    bool m_childrenAffectedByFirstChildRules : 1;
-    bool m_childrenAffectedByLastChildRules : 1;
-    bool m_childrenAffectedByDirectAdjacentRules : 1;
-    bool m_childrenAffectedByForwardPositionalRules : 1;
-    bool m_childrenAffectedByBackwardPositionalRules : 1;
 
 #if ENABLE(MUTATION_OBSERVERS)
     OwnPtr<Vector<OwnPtr<MutationObserverRegistration> > > m_mutationObserverRegistry;