Title: [164195] trunk/Source/WebCore
Revision
164195
Author
an...@apple.com
Date
2014-02-16 14:18:13 -0800 (Sun, 16 Feb 2014)

Log Message

Move document life time management from TreeScope to Document
https://bugs.webkit.org/show_bug.cgi?id=128877

Reviewed by Andreas Kling.

Document life time is managed in confusing manner by TreeScopes which are also inherited to ShadowRoots.
        
This patches moves the life time management to Document. Nodes in shadow trees selfOnlyRef the Document instead
of the ShadowRoot. ShadowRoot is treated like any other node and selfOnlyRefs the Document as well (which it
also did earlier, indirectly).
        
TreeScope is devirtualized.

* css/ElementRuleCollector.cpp:
(WebCore::ElementRuleCollector::collectMatchingRules):
        
    Author stylesheets never match in UA shadow trees.

* dom/ContainerNode.cpp:
(WebCore::ContainerNode::~ContainerNode):
* dom/Document.cpp:
(WebCore::Document::Document):
(WebCore::Document::~Document):
(WebCore::Document::removedLastRef):
* dom/Document.h:
(WebCore::Document::selfOnlyRef):
(WebCore::Document::selfOnlyDeref):

    To avoid branches Document self-refs itself like all other Nodes. This is why deletion will now happen on ref count of 1.

(WebCore::Node::isDocumentNode):
(WebCore::Node::Node):
* dom/DocumentOrderedMap.cpp:
(WebCore::DocumentOrderedMap::add):
* dom/Element.cpp:
(WebCore::Element::insertedInto):
(WebCore::Element::removedFrom):
* dom/Node.cpp:
(WebCore::Node::~Node):
(WebCore::Node::removedLastRef):
* dom/Node.h:
(WebCore::Node::document):
(WebCore::Node::inDocument):
* dom/ShadowRoot.cpp:
(WebCore::ShadowRoot::ShadowRoot):
(WebCore::ShadowRoot::~ShadowRoot):
* dom/ShadowRoot.h:
* dom/TreeScope.cpp:
(WebCore::TreeScope::TreeScope):
(WebCore::TreeScope::~TreeScope):
(WebCore::TreeScope::setParentTreeScope):
* dom/TreeScope.h:
(WebCore::TreeScope::documentScope):
        
    Document can no longer ever be null.

(WebCore::TreeScope::rootNode):
(WebCore::TreeScope::setDocumentScope):
* dom/TreeScopeAdopter.cpp:
(WebCore::TreeScopeAdopter::moveTreeToNewScope):
(WebCore::TreeScopeAdopter::moveShadowTreeToNewDocument):
        
    Manage Document selfOnlyRefs for nodes in shadow trees too.

(WebCore::TreeScopeAdopter::updateTreeScope):
(WebCore::TreeScopeAdopter::moveNodeToNewDocument):
* dom/TreeScopeAdopter.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (164194 => 164195)


--- trunk/Source/WebCore/ChangeLog	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/ChangeLog	2014-02-16 22:18:13 UTC (rev 164195)
@@ -1,3 +1,73 @@
+2014-02-15  Antti Koivisto  <an...@apple.com>
+
+        Move document life time management from TreeScope to Document
+        https://bugs.webkit.org/show_bug.cgi?id=128877
+
+        Reviewed by Andreas Kling.
+
+        Document life time is managed in confusing manner by TreeScopes which are also inherited to ShadowRoots.
+        
+        This patches moves the life time management to Document. Nodes in shadow trees selfOnlyRef the Document instead
+        of the ShadowRoot. ShadowRoot is treated like any other node and selfOnlyRefs the Document as well (which it
+        also did earlier, indirectly).
+        
+        TreeScope is devirtualized.
+
+        * css/ElementRuleCollector.cpp:
+        (WebCore::ElementRuleCollector::collectMatchingRules):
+        
+            Author stylesheets never match in UA shadow trees.
+
+        * dom/ContainerNode.cpp:
+        (WebCore::ContainerNode::~ContainerNode):
+        * dom/Document.cpp:
+        (WebCore::Document::Document):
+        (WebCore::Document::~Document):
+        (WebCore::Document::removedLastRef):
+        * dom/Document.h:
+        (WebCore::Document::selfOnlyRef):
+        (WebCore::Document::selfOnlyDeref):
+
+            To avoid branches Document self-refs itself like all other Nodes. This is why deletion will now happen on ref count of 1.
+
+        (WebCore::Node::isDocumentNode):
+        (WebCore::Node::Node):
+        * dom/DocumentOrderedMap.cpp:
+        (WebCore::DocumentOrderedMap::add):
+        * dom/Element.cpp:
+        (WebCore::Element::insertedInto):
+        (WebCore::Element::removedFrom):
+        * dom/Node.cpp:
+        (WebCore::Node::~Node):
+        (WebCore::Node::removedLastRef):
+        * dom/Node.h:
+        (WebCore::Node::document):
+        (WebCore::Node::inDocument):
+        * dom/ShadowRoot.cpp:
+        (WebCore::ShadowRoot::ShadowRoot):
+        (WebCore::ShadowRoot::~ShadowRoot):
+        * dom/ShadowRoot.h:
+        * dom/TreeScope.cpp:
+        (WebCore::TreeScope::TreeScope):
+        (WebCore::TreeScope::~TreeScope):
+        (WebCore::TreeScope::setParentTreeScope):
+        * dom/TreeScope.h:
+        (WebCore::TreeScope::documentScope):
+        
+            Document can no longer ever be null.
+
+        (WebCore::TreeScope::rootNode):
+        (WebCore::TreeScope::setDocumentScope):
+        * dom/TreeScopeAdopter.cpp:
+        (WebCore::TreeScopeAdopter::moveTreeToNewScope):
+        (WebCore::TreeScopeAdopter::moveShadowTreeToNewDocument):
+        
+            Manage Document selfOnlyRefs for nodes in shadow trees too.
+
+        (WebCore::TreeScopeAdopter::updateTreeScope):
+        (WebCore::TreeScopeAdopter::moveNodeToNewDocument):
+        * dom/TreeScopeAdopter.h:
+
 2014-02-16  Ryosuke Niwa  <rn...@webkit.org>
 
         setSelectionRange shouldn't directly instantiate VisibleSelection

Modified: trunk/Source/WebCore/css/ElementRuleCollector.cpp (164194 => 164195)


--- trunk/Source/WebCore/css/ElementRuleCollector.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/css/ElementRuleCollector.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -154,11 +154,8 @@
     if (m_element.isWebVTTElement())
         collectMatchingRulesForList(matchRequest.ruleSet->cuePseudoRules(), matchRequest, ruleRange);
 #endif
-    // Check whether other types of rules are applicable in the current tree scope. Criteria for this:
-    // a) it's a UA rule
-    // b) the tree scope allows author rules
-    if (!MatchingUARulesScope::isMatchingUARules()
-        && !m_element.treeScope().applyAuthorStyles())
+    // Only match UA rules in shadow tree.
+    if (!MatchingUARulesScope::isMatchingUARules() && m_element.treeScope().rootNode()->isShadowRoot())
         return;
 
     // We need to collect the rules for id, class, tag, and everything else into a buffer and

Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/ContainerNode.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -150,8 +150,7 @@
 
 ContainerNode::~ContainerNode()
 {
-    if (Document* document = documentInternal())
-        willBeDeletedFrom(document);
+    willBeDeletedFrom(&document());
     removeDetachedChildren();
 }
 

Modified: trunk/Source/WebCore/dom/Document.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/Document.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Document.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -393,8 +393,9 @@
 #endif
 
 Document::Document(Frame* frame, const URL& url, unsigned documentClasses, unsigned constructionFlags)
-    : ContainerNode(nullptr, CreateDocument)
-    , TreeScope(this)
+    : ContainerNode(this, CreateDocument)
+    , TreeScope(*this)
+    , m_selfOnlyRefCount(1)
 #if ENABLE(TOUCH_EVENTS) && PLATFORM(IOS)
     , m_handlingTouchEvent(false)
     , m_touchEventRegionsDirty(false)
@@ -633,43 +634,59 @@
     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(m_nodeListAndCollectionCounts); ++i)
         ASSERT(!m_nodeListAndCollectionCounts[i]);
 
-    clearDocumentScope();
-
     InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
 }
 
-void Document::dropChildren()
+void Document::removedLastRef()
 {
     ASSERT(!m_deletionHasBegun);
+    ASSERT(m_selfOnlyRefCount);
+    if (m_selfOnlyRefCount > 1) {
+        // If removing a child removes the last self-only ref, we don't want the scope to be destroyed
+        // until after removeDetachedChildren returns, so we protect ourselves with an extra self-only ref.
+        selfOnlyRef();
 
-    // We must make sure not to be retaining any of our children through
-    // these extra pointers or we will create a reference cycle.
-    m_focusedElement = nullptr;
-    m_hoveredElement = nullptr;
-    m_activeElement = nullptr;
-    m_titleElement = nullptr;
-    m_documentElement = nullptr;
-    m_userActionElements.documentDidRemoveLastRef();
+        // We must make sure not to be retaining any of our children through
+        // these extra pointers or we will create a reference cycle.
+        m_focusedElement = nullptr;
+        m_hoveredElement = nullptr;
+        m_activeElement = nullptr;
+        m_titleElement = nullptr;
+        m_documentElement = nullptr;
+        m_userActionElements.documentDidRemoveLastRef();
 #if ENABLE(FULLSCREEN_API)
-    m_fullScreenElement = nullptr;
-    m_fullScreenElementStack.clear();
+        m_fullScreenElement = nullptr;
+        m_fullScreenElementStack.clear();
 #endif
 
-    detachParser();
+        detachParser();
 
-    // removeDetachedChildren() doesn't always unregister IDs,
-    // so tear down scope information up front to avoid having
-    // stale references in the map.
+        // removeDetachedChildren() doesn't always unregister IDs,
+        // so tear down scope information up front to avoid having
+        // stale references in the map.
 
-    destroyTreeScopeData();
-    removeDetachedChildren();
-    m_formController.clear();
+        destroyTreeScopeData();
+        removeDetachedChildren();
+        m_formController.clear();
+        
+        m_markers->detach();
+        
+        m_cssCanvasElements.clear();
+        
+        commonTeardown();
 
-    m_markers->detach();
-
-    m_cssCanvasElements.clear();
-
-    commonTeardown();
+#ifndef NDEBUG
+        // We need to do this right now since selfOnlyDeref() can delete this.
+        m_inRemovedLastRefFunction = false;
+#endif
+        selfOnlyDeref();
+    } else {
+#ifndef NDEBUG
+        m_inRemovedLastRefFunction = false;
+        m_deletionHasBegun = true;
+#endif
+        delete this;
+    }
 }
 
 void Document::commonTeardown()

Modified: trunk/Source/WebCore/dom/Document.h (164194 => 164195)


--- trunk/Source/WebCore/dom/Document.h	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Document.h	2014-02-16 22:18:13 UTC (rev 164195)
@@ -263,6 +263,31 @@
 
     virtual ~Document();
 
+    // Nodes belonging to this document hold self-only references -
+    // these are enough to keep the document from being destroyed, but
+    // not enough to keep it from removing its children. This allows a
+    // node that outlives its scope to still have a valid document
+    // pointer without introducing reference cycles.
+    void selfOnlyRef()
+    {
+        ASSERT(!m_deletionHasBegun);
+        ++m_selfOnlyRefCount;
+    }
+
+    void selfOnlyDeref()
+    {
+        ASSERT(!m_deletionHasBegun || m_selfOnlyRefCount == 1);
+        --m_selfOnlyRefCount;
+        if (m_selfOnlyRefCount == 1 && !refCount()) {
+#if !ASSERT_DISABLED
+            m_deletionHasBegun = true;
+#endif
+            delete this;
+        }
+    }
+
+    void removedLastRef();
+
     MediaQueryMatcher& mediaQueryMatcher();
 
     using ContainerNode::ref;
@@ -1254,8 +1279,6 @@
     void createRenderTree();
     void detachParser();
 
-    virtual void dropChildren() override;
-
     typedef void (*ArgumentsCallback)(const String& keyString, const String& valueString, Document*, void* data);
     void processArguments(const String& features, void* data, ArgumentsCallback);
 
@@ -1320,6 +1343,9 @@
     void didAssociateFormControlsTimerFired(Timer<Document>&);
 
     void styleResolverThrowawayTimerFired(DeferrableOneShotTimer<Document>&);
+
+    unsigned m_selfOnlyRefCount;
+
     DeferrableOneShotTimer<Document> m_styleResolverThrowawayTimer;
 
     OwnPtr<StyleResolver> m_styleResolver;
@@ -1679,17 +1705,17 @@
 
 inline bool Node::isDocumentNode() const
 {
-    return this == documentInternal();
+    return this == &document();
 }
 
 inline Node::Node(Document* document, ConstructionType type)
     : m_nodeFlags(type)
     , m_parentNode(0)
-    , m_treeScope(document ? document : &TreeScope::noDocumentInstance())
+    , m_treeScope(document)
     , m_previous(0)
     , m_next(0)
 {
-    m_treeScope->selfOnlyRef();
+    document->selfOnlyRef();
 
 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
     trackForDebugging();

Modified: trunk/Source/WebCore/dom/DocumentOrderedMap.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/DocumentOrderedMap.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/DocumentOrderedMap.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -89,9 +89,10 @@
 
 void DocumentOrderedMap::add(const AtomicStringImpl& key, Element& element, const TreeScope& treeScope)
 {
+    UNUSED_PARAM(treeScope);
     ASSERT_WITH_SECURITY_IMPLICATION(element.isInTreeScope());
     ASSERT_WITH_SECURITY_IMPLICATION(treeScope.rootNode()->containsIncludingShadowDOM(&element));
-    if (!element.isInTreeScope() || &element.document() != treeScope.documentScope())
+    if (!element.isInTreeScope())
         return;
     Map::AddResult addResult = m_map.add(&key, MapEntry(&element));
     if (addResult.isNewEntry)

Modified: trunk/Source/WebCore/dom/Element.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/Element.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Element.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -1353,9 +1353,9 @@
         elementRareData()->clearClassListValueForQuirksMode();
 
     TreeScope* newScope = &insertionPoint.treeScope();
-    HTMLDocument* newDocument = !wasInDocument && inDocument() && newScope->documentScope()->isHTMLDocument() ? toHTMLDocument(newScope->documentScope()) : 0;
+    HTMLDocument* newDocument = !wasInDocument && inDocument() && newScope->documentScope().isHTMLDocument() ? toHTMLDocument(&newScope->documentScope()) : nullptr;
     if (newScope != &treeScope())
-        newScope = 0;
+        newScope = nullptr;
 
     const AtomicString& idValue = getIdAttribute();
     if (!idValue.isNull()) {
@@ -1396,9 +1396,9 @@
 
     if (insertionPoint.isInTreeScope()) {
         TreeScope* oldScope = &insertionPoint.treeScope();
-        HTMLDocument* oldDocument = inDocument() && oldScope->documentScope()->isHTMLDocument() ? toHTMLDocument(oldScope->documentScope()) : 0;
+        HTMLDocument* oldDocument = inDocument() && oldScope->documentScope().isHTMLDocument() ? toHTMLDocument(&oldScope->documentScope()) : nullptr;
         if (oldScope != &treeScope())
-            oldScope = 0;
+            oldScope = nullptr;
 
         const AtomicString& idValue = getIdAttribute();
         if (!idValue.isNull()) {

Modified: trunk/Source/WebCore/dom/Node.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/Node.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Node.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -305,12 +305,10 @@
     if (hasRareData())
         clearRareData();
 
-    if (!isContainerNode()) {
-        if (Document* document = documentInternal())
-            willBeDeletedFrom(document);
-    }
+    if (!isContainerNode())
+        willBeDeletedFrom(&document());
 
-    m_treeScope->selfOnlyDeref();
+    document().selfOnlyDeref();
 
     InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
 }
@@ -2190,31 +2188,6 @@
     return hasEventListeners(eventNames().mousewheelEvent);
 }
 
-// This is here so it can be inlined into Node::removedLastRef.
-// FIXME: Really? Seems like this could be inlined into Node::removedLastRef if it was in TreeScope.h.
-// FIXME: It also not seem important to inline this. Is this really hot?
-inline void TreeScope::removedLastRefToScope()
-{
-    ASSERT(!deletionHasBegun());
-    if (m_selfOnlyRefCount) {
-        // If removing a child removes the last self-only ref, we don't want the scope to be destroyed
-        // until after removeDetachedChildren returns, so we protect ourselves with an extra self-only ref.
-        selfOnlyRef();
-        dropChildren();
-#ifndef NDEBUG
-        // We need to do this right now since selfOnlyDeref() can delete this.
-        rootNode()->m_inRemovedLastRefFunction = false;
-#endif
-        selfOnlyDeref();
-    } else {
-#ifndef NDEBUG
-        rootNode()->m_inRemovedLastRefFunction = false;
-        beginDeletion();
-#endif
-        delete this;
-    }
-}
-
 // It's important not to inline removedLastRef, because we don't want to inline the code to
 // delete a Node at each deref call site.
 void Node::removedLastRef()
@@ -2222,8 +2195,8 @@
     // An explicit check for Document here is better than a virtual function since it is
     // faster for non-Document nodes, and because the call to removedLastRef that is inlined
     // at all deref call sites is smaller if it's a non-virtual function.
-    if (isTreeScope()) {
-        treeScope().removedLastRefToScope();
+    if (isDocumentNode()) {
+        toDocument(*this).removedLastRef();
         return;
     }
 

Modified: trunk/Source/WebCore/dom/Node.h (164194 => 164195)


--- trunk/Source/WebCore/dom/Node.h	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/Node.h	2014-02-16 22:18:13 UTC (rev 164195)
@@ -382,8 +382,7 @@
     Document& document() const
     {
         ASSERT(this);
-        ASSERT(documentInternal());
-        return *documentInternal();
+        return treeScope().documentScope();
     }
 
     TreeScope& treeScope() const
@@ -396,7 +395,6 @@
     // node tree, false otherwise.
     bool inDocument() const 
     { 
-        ASSERT(documentInternal() || !getFlag(InDocumentFlag));
         return getFlag(InDocumentFlag);
     }
     bool isInShadowTree() const { return getFlag(IsInShadowTreeFlag); }
@@ -644,7 +642,6 @@
 
     void setNeedsNodeRenderingTraversalSlowPath(bool flag) { setFlag(flag, NeedsNodeRenderingTraversalSlowPathFlag); }
 
-    Document* documentInternal() const { return treeScope().documentScope(); }
     void setTreeScope(TreeScope& scope) { m_treeScope = &scope; }
 
     void setStyleChange(StyleChangeType changeType) { m_nodeFlags = (m_nodeFlags & ~StyleChangeMask) | changeType; }

Modified: trunk/Source/WebCore/dom/ShadowRoot.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/ShadowRoot.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/ShadowRoot.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -52,9 +52,8 @@
 };
 
 ShadowRoot::ShadowRoot(Document& document, ShadowRootType type)
-    : DocumentFragment(0, CreateShadowRoot)
-    , TreeScope(this, &document)
-    , m_applyAuthorStyles(false)
+    : DocumentFragment(&document, CreateShadowRoot)
+    , TreeScope(*this, document)
     , m_resetStyleInheritance(false)
     , m_type(type)
     , m_hostElement(0)
@@ -67,24 +66,14 @@
     // for this ShadowRoot instance because TreeScope destructor
     // clears Node::m_treeScope thus ContainerNode is no longer able
     // to access it Document reference after that.
-    willBeDeletedFrom(documentInternal());
+    willBeDeletedFrom(&document());
 
     // We must remove all of our children first before the TreeScope destructor
     // runs so we don't go through TreeScopeAdopter for each child with a
     // destructed tree scope in each descendant.
     removeDetachedChildren();
-
-    // We must call clearRareData() here since a ShadowRoot class inherits TreeScope
-    // as well as Node. See a comment on TreeScope.h for the reason.
-    if (hasRareData())
-        clearRareData();
 }
 
-void ShadowRoot::dropChildren()
-{
-    removeDetachedChildren();
-}
-
 PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
 {
     ec = DATA_CLONE_ERR;
@@ -122,17 +111,6 @@
     }
 }
 
-void ShadowRoot::setApplyAuthorStyles(bool value)
-{
-    if (isOrphan())
-        return;
-
-    if (m_applyAuthorStyles != value) {
-        m_applyAuthorStyles = value;
-        hostElement()->setNeedsStyleRecalc();
-    }
-}
-
 void ShadowRoot::setResetStyleInheritance(bool value)
 {
     if (isOrphan())

Modified: trunk/Source/WebCore/dom/ShadowRoot.h (164194 => 164195)


--- trunk/Source/WebCore/dom/ShadowRoot.h	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/ShadowRoot.h	2014-02-16 22:18:13 UTC (rev 164195)
@@ -50,8 +50,6 @@
 
     virtual ~ShadowRoot();
 
-    virtual bool applyAuthorStyles() const override { return m_applyAuthorStyles; }
-    void setApplyAuthorStyles(bool);
     bool resetStyleInheritance() const { return m_resetStyleInheritance; }
     void setResetStyleInheritance(bool);
 
@@ -75,7 +73,6 @@
 private:
     ShadowRoot(Document&, ShadowRootType);
 
-    virtual void dropChildren() override;
     virtual bool childTypeAllowed(NodeType) const override;
     virtual void childrenChanged(const ChildChange&) override;
 
@@ -85,7 +82,6 @@
     // FIXME: This shouldn't happen. https://bugs.webkit.org/show_bug.cgi?id=88834
     bool isOrphan() const { return !hostElement(); }
 
-    unsigned m_applyAuthorStyles : 1;
     unsigned m_resetStyleInheritance : 1;
     unsigned m_type : 1;
 

Modified: trunk/Source/WebCore/dom/TreeScope.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/TreeScope.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScope.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -49,60 +49,37 @@
 namespace WebCore {
 
 struct SameSizeAsTreeScope {
-    virtual ~SameSizeAsTreeScope();
     void* pointers[9];
-    int ints[1];
 };
 
 COMPILE_ASSERT(sizeof(TreeScope) == sizeof(SameSizeAsTreeScope), treescope_should_stay_small);
 
 using namespace HTMLNames;
 
-TreeScope::TreeScope(ContainerNode* rootNode, Document* document)
-    : m_rootNode(rootNode)
-    , m_documentScope(document)
-    , m_parentTreeScope(document)
-    , m_selfOnlyRefCount(0)
+TreeScope::TreeScope(ShadowRoot& shadowRoot, Document& document)
+    : m_rootNode(shadowRoot)
+    , m_documentScope(&document)
+    , m_parentTreeScope(&document)
     , m_idTargetObserverRegistry(std::make_unique<IdTargetObserverRegistry>())
 {
-    ASSERT(rootNode);
-    ASSERT(document);
-    ASSERT(rootNode != document);
-    m_parentTreeScope->selfOnlyRef();
-    m_rootNode->setTreeScope(*this);
+    shadowRoot.setTreeScope(*this);
 }
 
-TreeScope::TreeScope(Document* document)
+TreeScope::TreeScope(Document& document)
     : m_rootNode(document)
-    , m_documentScope(document)
+    , m_documentScope(&document)
     , m_parentTreeScope(nullptr)
-    , m_selfOnlyRefCount(0)
     , m_idTargetObserverRegistry(std::make_unique<IdTargetObserverRegistry>())
 {
-    ASSERT(document);
-    m_rootNode->setTreeScope(*this);
+    document.setTreeScope(*this);
 }
 
-TreeScope::TreeScope()
-    : m_rootNode(nullptr)
-    , m_documentScope(nullptr)
-    , m_parentTreeScope(nullptr)
-    , m_selfOnlyRefCount(0)
-{
-}
-
 TreeScope::~TreeScope()
 {
-    ASSERT(!m_selfOnlyRefCount);
-    m_rootNode->setTreeScope(noDocumentInstance());
-
     if (m_selection) {
         m_selection->clearTreeScope();
         m_selection = nullptr;
     }
-
-    if (m_parentTreeScope)
-        m_parentTreeScope->selfOnlyDeref();
 }
 
 void TreeScope::destroyTreeScopeData()
@@ -112,12 +89,6 @@
     m_labelsByForAttribute = nullptr;
 }
 
-void TreeScope::clearDocumentScope()
-{
-    ASSERT(rootNode()->isDocumentNode());
-    m_documentScope = nullptr;
-}
-
 void TreeScope::setParentTreeScope(TreeScope* newParentScope)
 {
     // A document node cannot be re-parented.
@@ -125,11 +96,8 @@
     // Every scope other than document needs a parent scope.
     ASSERT(newParentScope);
 
-    newParentScope->selfOnlyRef();
-    if (m_parentTreeScope)
-        m_parentTreeScope->selfOnlyDeref();
     m_parentTreeScope = newParentScope;
-    setDocumentScope(newParentScope->documentScope());
+    setDocumentScope(&newParentScope->documentScope());
 }
 
 Element* TreeScope::getElementById(const AtomicString& elementId) const
@@ -345,11 +313,6 @@
     return nullptr;
 }
 
-bool TreeScope::applyAuthorStyles() const
-{
-    return true;
-}
-
 void TreeScope::adoptIfNeeded(Node* node)
 {
     ASSERT(this);
@@ -426,24 +389,4 @@
     return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : nullptr;
 }
 
-#ifndef NDEBUG
-bool TreeScope::deletionHasBegun()
-{
-    return rootNode() && rootNode()->m_deletionHasBegun;
-}
-
-void TreeScope::beginDeletion()
-{
-    ASSERT(this != &noDocumentInstance());
-    rootNode()->m_deletionHasBegun = true;
-}
-#endif
-
-int TreeScope::refCount() const
-{
-    if (Node* root = rootNode())
-        return root->refCount();
-    return 0;
-}
-
 } // namespace WebCore

Modified: trunk/Source/WebCore/dom/TreeScope.h (164194 => 164195)


--- trunk/Source/WebCore/dom/TreeScope.h	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScope.h	2014-02-16 22:18:13 UTC (rev 164195)
@@ -43,10 +43,8 @@
 class LayoutPoint;
 class IdTargetObserverRegistry;
 class Node;
+class ShadowRoot;
 
-// A class which inherits both Node and TreeScope must call clearRareData() in its destructor
-// so that the Node destructor no longer does problematic NodeList cache manipulation in
-// the destructor.
 class TreeScope {
     friend class Document;
     friend class TreeScopeAdopter;
@@ -69,7 +67,7 @@
     void addElementByName(const AtomicStringImpl&, Element&);
     void removeElementByName(const AtomicStringImpl&, Element&);
 
-    Document* documentScope() const { return m_documentScope; }
+    Document& documentScope() const { return *m_documentScope; }
 
     Node* ancestorInThisScope(Node*) const;
 
@@ -94,76 +92,29 @@
     // quirks mode for historical compatibility reasons.
     Element* findAnchor(const String& name);
 
-    virtual bool applyAuthorStyles() const;
-
     // Used by the basic DOM mutation methods (e.g., appendChild()).
     void adoptIfNeeded(Node*);
 
-    ContainerNode* rootNode() const { return m_rootNode; }
+    ContainerNode* rootNode() const { return &m_rootNode; }
 
     IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); }
 
-    static TreeScope& noDocumentInstance()
-    {
-        DEFINE_STATIC_LOCAL(TreeScope, instance, ());
-        return instance;
-    }
-
-    // Nodes belonging to this scope hold self-only references -
-    // these are enough to keep the scope from being destroyed, but
-    // not enough to keep it from removing its children. This allows a
-    // node that outlives its scope to still have a valid document
-    // pointer without introducing reference cycles.
-    void selfOnlyRef()
-    {
-        ASSERT(!deletionHasBegun());
-        ++m_selfOnlyRefCount;
-    }
-
-    void selfOnlyDeref()
-    {
-        ASSERT(!deletionHasBegun());
-        --m_selfOnlyRefCount;
-        if (!m_selfOnlyRefCount && !refCount() && this != &noDocumentInstance()) {
-            beginDeletion();
-            delete this;
-        }
-    }
-
-    void removedLastRefToScope();
-
 protected:
-    TreeScope(ContainerNode*, Document*);
-    explicit TreeScope(Document*);
-    virtual ~TreeScope();
+    TreeScope(ShadowRoot&, Document&);
+    explicit TreeScope(Document&);
+    ~TreeScope();
 
     void destroyTreeScopeData();
-    void clearDocumentScope();
     void setDocumentScope(Document* document)
     {
         ASSERT(document);
-        ASSERT(this != &noDocumentInstance());
         m_documentScope = document;
     }
 
 private:
-    TreeScope();
-
-    virtual void dropChildren() { }
-
-    int refCount() const;
-#ifndef NDEBUG
-    bool deletionHasBegun();
-    void beginDeletion();
-#else
-    bool deletionHasBegun() { return false; }
-    void beginDeletion() { }
-#endif
-
-    ContainerNode* m_rootNode;
+    ContainerNode& m_rootNode;
     Document* m_documentScope;
     TreeScope* m_parentTreeScope;
-    unsigned m_selfOnlyRefCount;
 
     std::unique_ptr<DocumentOrderedMap> m_elementsById;
     std::unique_ptr<DocumentOrderedMap> m_elementsByName;

Modified: trunk/Source/WebCore/dom/TreeScopeAdopter.cpp (164194 => 164195)


--- trunk/Source/WebCore/dom/TreeScopeAdopter.cpp	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScopeAdopter.cpp	2014-02-16 22:18:13 UTC (rev 164195)
@@ -32,27 +32,28 @@
 
 namespace WebCore {
 
+// FIXME: Do we ever change tree scopes except between documents?
 void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
 {
     ASSERT(needsScopeChange());
 
-    m_oldScope.selfOnlyRef();
-
     // If an element is moved from a document and then eventually back again the collection cache for
     // that element may contain stale data as changes made to it will have updated the DOMTreeVersion
     // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
     // we ensure that the collection cache will be invalidated as needed when the element is moved back.
-    Document* oldDocument = m_oldScope.documentScope();
-    Document* newDocument = m_newScope.documentScope();
-    bool willMoveToNewDocument = oldDocument != newDocument;
-    if (oldDocument && willMoveToNewDocument)
-        oldDocument->incDOMTreeVersion();
+    Document& oldDocument = m_oldScope.documentScope();
+    Document& newDocument = m_newScope.documentScope();
+    bool willMoveToNewDocument = &oldDocument != &newDocument;
+    if (willMoveToNewDocument) {
+        oldDocument.selfOnlyRef();
+        oldDocument.incDOMTreeVersion();
+    }
 
     for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
         updateTreeScope(node);
 
         if (willMoveToNewDocument)
-            moveNodeToNewDocument(node, oldDocument, newDocument);
+            moveNodeToNewDocument(node, &oldDocument, &newDocument);
         else if (node->hasRareData()) {
             NodeRareData* rareData = node->rareData();
             if (rareData->nodeLists())
@@ -71,19 +72,20 @@
         if (ShadowRoot* shadow = node->shadowRoot()) {
             shadow->setParentTreeScope(&m_newScope);
             if (willMoveToNewDocument)
-                moveTreeToNewDocument(shadow, oldDocument, newDocument);
+                moveShadowTreeToNewDocument(shadow, &oldDocument, &newDocument);
         }
     }
 
-    m_oldScope.selfOnlyDeref();
+    if (willMoveToNewDocument)
+        oldDocument.selfOnlyDeref();
 }
 
-void TreeScopeAdopter::moveTreeToNewDocument(Node* root, Document* oldDocument, Document* newDocument) const
+void TreeScopeAdopter::moveShadowTreeToNewDocument(ShadowRoot* shadowRoot, Document* oldDocument, Document* newDocument) const
 {
-    for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
+    for (Node* node = shadowRoot; node; node = NodeTraversal::next(node, shadowRoot)) {
         moveNodeToNewDocument(node, oldDocument, newDocument);
         if (ShadowRoot* shadow = node->shadowRoot())
-            moveTreeToNewDocument(shadow, oldDocument, newDocument);
+            moveShadowTreeToNewDocument(shadow, oldDocument, newDocument);
     }
 }
 
@@ -103,8 +105,6 @@
 {
     ASSERT(!node->isTreeScope());
     ASSERT(&node->treeScope() == &m_oldScope);
-    m_newScope.selfOnlyRef();
-    m_oldScope.selfOnlyDeref();
     node->setTreeScope(m_newScope);
 }
 
@@ -112,6 +112,9 @@
 {
     ASSERT(!node->inDocument() || oldDocument != newDocument);
 
+    newDocument->selfOnlyRef();
+    oldDocument->selfOnlyDeref();
+
     if (node->hasRareData()) {
         NodeRareData* rareData = node->rareData();
         if (rareData->nodeLists())

Modified: trunk/Source/WebCore/dom/TreeScopeAdopter.h (164194 => 164195)


--- trunk/Source/WebCore/dom/TreeScopeAdopter.h	2014-02-16 22:00:21 UTC (rev 164194)
+++ trunk/Source/WebCore/dom/TreeScopeAdopter.h	2014-02-16 22:18:13 UTC (rev 164195)
@@ -47,7 +47,7 @@
 private:
     void updateTreeScope(Node*) const;
     void moveTreeToNewScope(Node*) const;
-    void moveTreeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
+    void moveShadowTreeToNewDocument(ShadowRoot*, Document* oldDocument, Document* newDocument) const;
     void moveNodeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
 
     Node* m_toAdopt;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to