Revert r143840 because it caused flaky crashes.
authordglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2013 18:02:42 +0000 (18:02 +0000)
committerdglazkov@chromium.org <dglazkov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 25 Feb 2013 18:02:42 +0000 (18:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=110766

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

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.exp.in
Source/WebCore/dom/Document.cpp
Source/WebCore/dom/Document.h
Source/WebCore/dom/DocumentFragment.cpp
Source/WebCore/dom/Node.cpp
Source/WebCore/dom/Node.h
Source/WebCore/dom/ShadowRoot.cpp
Source/WebCore/dom/ShadowRoot.h
Source/WebCore/dom/TreeScope.cpp
Source/WebCore/dom/TreeScope.h
Source/WebCore/dom/TreeScopeAdopter.cpp
Source/WebCore/dom/TreeScopeAdopter.h

index 37d9e0c..a3bc4b3 100644 (file)
@@ -1,3 +1,8 @@
+2013-02-25  Dimitri Glazkov  <dglazkov@chromium.org>
+
+        Revert r143840 because it caused flaky crashes.
+        https://bugs.webkit.org/show_bug.cgi?id=110766
+
 2013-02-25  Alexey Proskuryakov  <ap@apple.com>
 
         Remove an obsolete workaround for relaxing 3rd party cookie policy
index 8c47c3f..a5e3175 100644 (file)
@@ -1413,6 +1413,7 @@ __ZNK7WebCore4Node11textContentEb
 __ZN7WebCore4Node12insertBeforeEN3WTF10PassRefPtrIS0_EEPS0_Rib
 __ZNK7WebCore4Node13ownerDocumentEv
 __ZNK7WebCore4Node14isDescendantOfEPKS0_
+__ZNK7WebCore4Node11isTreeScopeEv
 __ZNK7WebCore4Node18getSubresourceURLsERN3WTF11ListHashSetINS_4KURLELm256ENS_8KURLHashEEE
 __ZNK7WebCore4Node31numberOfScopedHTMLStyleChildrenEv
 __ZNK7WebCore4Node9nodeIndexEv
index 9b9dccb..2c5df67 100644 (file)
@@ -417,6 +417,7 @@ uint64_t Document::s_globalTreeVersion = 0;
 Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
     : ContainerNode(0, CreateDocument)
     , TreeScope(this)
+    , m_guardRefCount(0)
     , m_styleResolverThrowawayTimer(this, &Document::styleResolverThrowawayTimerFired)
     , m_lastStyleResolverAccessTime(0)
     , m_activeParserCount(0)
@@ -488,6 +489,8 @@ Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
     , m_templateDocumentHost(0)
 #endif
 {
+    setTreeScope(this);
+
     m_printing = false;
     m_paginatedForScreen = false;
 
@@ -587,7 +590,7 @@ Document::~Document()
     ASSERT(m_ranges.isEmpty());
     ASSERT(!m_styleRecalcTimer.isActive());
     ASSERT(!m_parentTreeScope);
-    ASSERT(!hasGuardRefCount());
+    ASSERT(!m_guardRefCount);
 
 #if ENABLE(TEMPLATE_ELEMENT)
     if (m_templateDocument)
@@ -654,44 +657,64 @@ Document::~Document()
     InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
 }
 
-void Document::dispose()
+void Document::removedLastRef()
 {
-    // We must make sure not to be retaining any of our children through
-    // these extra pointers or we will create a reference cycle.
-    m_docType = 0;
-    m_focusedNode = 0;
-    m_hoverNode = 0;
-    m_activeElement = 0;
-    m_titleElement = 0;
-    m_documentElement = 0;
-    m_contextFeatures = ContextFeatures::defaultSwitch();
-    m_userActionElements.documentDidRemoveLastRef();
+    ASSERT(!m_deletionHasBegun);
+    if (m_guardRefCount) {
+        // If removing a child removes the last self-only ref, we don't
+        // want the scope to be destructed until after
+        // removeDetachedChildren returns, so we guard ourselves with an
+        // extra self-only ref.
+        guardRef();
+
+        // We must make sure not to be retaining any of our children through
+        // these extra pointers or we will create a reference cycle.
+        m_docType = 0;
+        m_focusedNode = 0;
+        m_hoverNode = 0;
+        m_activeElement = 0;
+        m_titleElement = 0;
+        m_documentElement = 0;
+        m_contextFeatures = ContextFeatures::defaultSwitch();
+        m_userActionElements.documentDidRemoveLastRef();
 #if ENABLE(FULLSCREEN_API)
-    m_fullScreenElement = 0;
-    m_fullScreenElementStack.clear();
+        m_fullScreenElement = 0;
+        m_fullScreenElementStack.clear();
 #endif
 
-    detachParser();
+        detachParser();
 
 #if ENABLE(CUSTOM_ELEMENTS)
         m_registry.clear();
 #endif
 
-    // removeDetachedChildren() doesn't always unregister IDs,
-    // so tear down scope information upfront to avoid having stale references in the map.
-    destroyTreeScopeData();
-    removeDetachedChildren();
+        // removeDetachedChildren() doesn't always unregister IDs,
+        // so tear down scope information upfront to avoid having stale references in the map.
+        destroyTreeScopeData();
+        removeDetachedChildren();
 
-    m_markers->detach();
+        m_markers->detach();
 
-    m_cssCanvasElements.clear();
+        m_cssCanvasElements.clear();
 
 #if ENABLE(REQUEST_ANIMATION_FRAME)
-    // FIXME: consider using ActiveDOMObject.
-    if (m_scriptedAnimationController)
-        m_scriptedAnimationController->clearDocumentPointer();
-    m_scriptedAnimationController.clear();
+        // FIXME: consider using ActiveDOMObject.
+        if (m_scriptedAnimationController)
+            m_scriptedAnimationController->clearDocumentPointer();
+        m_scriptedAnimationController.clear();
+#endif
+
+#ifndef NDEBUG
+        m_inRemovedLastRefFunction = false;
 #endif
+
+        guardDeref();
+    } else {
+#ifndef NDEBUG 
+        m_deletionHasBegun = true; 
+#endif 
+        delete this;
+    }
 }
 
 Element* Document::getElementById(const AtomicString& id) const
index ec4cec9..d8b9863 100644 (file)
@@ -231,6 +231,29 @@ public:
     using ContainerNode::ref;
     using ContainerNode::deref;
 
+    // Nodes belonging to this document hold guard 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 document to still have a valid document
+    // pointer without introducing reference cycles.
+    void guardRef()
+    {
+        ASSERT(!m_deletionHasBegun);
+        ++m_guardRefCount;
+    }
+
+    void guardDeref()
+    {
+        ASSERT(!m_deletionHasBegun);
+        --m_guardRefCount;
+        if (!m_guardRefCount && !refCount()) {
+#ifndef NDEBUG
+            m_deletionHasBegun = true;
+#endif
+            delete this;
+        }
+    }
+
     Element* getElementById(const AtomicString& id) const;
 
     virtual bool canContainRangeEndPoint() const { return true; }
@@ -1202,8 +1225,8 @@ private:
     friend class Node;
     friend class IgnoreDestructiveWriteCountIncrementer;
 
-    virtual void dispose() OVERRIDE;
-
+    void removedLastRef();
+    
     void detachParser();
 
     typedef void (*ArgumentsCallback)(const String& keyString, const String& valueString, Document*, void* data);
@@ -1271,6 +1294,8 @@ private:
     void addListenerType(ListenerType listenerType) { m_listenerTypes |= listenerType; }
     void addMutationEventListenerTypeIfEnabled(ListenerType);
 
+    int m_guardRefCount;
+
     void styleResolverThrowawayTimerFired(Timer<Document>*);
     Timer<Document> m_styleResolverThrowawayTimer;
     double m_lastStyleResolverAccessTime;
@@ -1590,9 +1615,10 @@ inline Node::Node(Document* document, ConstructionType type)
     , m_previous(0)
     , m_next(0)
 {
-    if (!m_treeScope)
+    if (document)
+        document->guardRef();
+    else
         m_treeScope = TreeScope::noDocumentInstance();
-    m_treeScope->guardRef();
 
 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
     trackForDebugging();
index e660248..85015b2 100644 (file)
@@ -34,11 +34,11 @@ namespace WebCore {
 DocumentFragment::DocumentFragment(Document* document, ConstructionType constructionType)
     : ContainerNode(document, constructionType)
 {
+    ASSERT(document);
 }
 
 PassRefPtr<DocumentFragment> DocumentFragment::create(Document* document)
 {
-    ASSERT(document);
     return adoptRef(new DocumentFragment(document, Node::CreateDocumentFragment));
 }
 
index fa7caa8..e7c4650 100644 (file)
@@ -442,7 +442,8 @@ Node::~Node()
     if (m_next)
         m_next->setPreviousSibling(0);
 
-    m_treeScope->guardDeref();
+    if (doc)
+        doc->guardDeref();
 
     InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
 }
@@ -891,6 +892,11 @@ bool Node::isFocusable() const
     return true;
 }
 
+bool Node::isTreeScope() const
+{
+    return treeScope()->rootNode() == this;
+}
+
 bool Node::isKeyboardFocusable(KeyboardEvent*) const
 {
     return isFocusable() && tabIndex() >= 0;
@@ -2555,31 +2561,6 @@ PassRefPtr<PropertyNodeList> Node::propertyNodeList(const String& name)
 }
 #endif
 
-// This is here for inlining
-inline void TreeScope::removedLastRefToScope()
-{
-    ASSERT(!deletionHasBegun());
-    if (m_guardRefCount) {
-        // If removing a child removes the last self-only ref, we don't
-        // want the scope to be destructed until after
-        // removeDetachedChildren returns, so we guard ourselves with an
-        // extra self-only ref.
-        guardRef();
-        dispose();
-#ifndef NDEBUG
-        // We need to do this right now since guardDeref() can delete this.
-        rootNode()->m_inRemovedLastRefFunction = false;
-#endif
-        guardDeref();
-    } 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()
@@ -2587,11 +2568,10 @@ void Node::removedLastRef()
     // 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()) {
+        static_cast<Document*>(this)->removedLastRef();
         return;
     }
-
 #ifndef NDEBUG
     m_deletionHasBegun = true;
 #endif
index 710c1c6..a836bf0 100644 (file)
@@ -248,7 +248,7 @@ public:
     virtual bool isInsertionPointNode() const { return false; }
 
     bool isDocumentNode() const;
-    bool isTreeScope() const { return treeScope()->rootNode() == this; }
+    bool isTreeScope() const;
     bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); }
     bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); }
     bool isInsertionPoint() const { return getFlag(NeedsShadowTreeWalkerFlag) && isInsertionPointNode(); }
index 1143ba3..b4f2419 100644 (file)
@@ -52,7 +52,7 @@ enum ShadowRootUsageOriginType {
 };
 
 ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
-    : DocumentFragment(0, CreateShadowRoot)
+    : DocumentFragment(document, CreateShadowRoot)
     , TreeScope(this, document)
     , m_prev(0)
     , m_next(0)
@@ -63,6 +63,7 @@ ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
     , m_registeredWithParentShadowRoot(false)
 {
     ASSERT(document);
+    setTreeScope(this);
 
 #if PLATFORM(CHROMIUM)
     if (type == ShadowRoot::AuthorShadowRoot) {
@@ -88,11 +89,6 @@ ShadowRoot::~ShadowRoot()
         clearRareData();
 }
 
-void ShadowRoot::dispose()
-{
-    removeDetachedChildren();
-}
-
 PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
 {
     ec = DATA_CLONE_ERR;
index dbc71dc..2d1cf23 100644 (file)
@@ -100,7 +100,6 @@ private:
     ShadowRoot(Document*, ShadowRootType);
     virtual ~ShadowRoot();
 
-    virtual void dispose() OVERRIDE;
     virtual bool childTypeAllowed(NodeType) const OVERRIDE;
     virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE;
 
index 3809d5d..454af5d 100644 (file)
@@ -59,7 +59,6 @@ namespace WebCore {
 struct SameSizeAsTreeScope {
     virtual ~SameSizeAsTreeScope();
     void* pointers[8];
-    int ints[1];
 };
 
 COMPILE_ASSERT(sizeof(TreeScope) == sizeof(SameSizeAsTreeScope), treescope_should_stay_small);
@@ -70,47 +69,35 @@ TreeScope::TreeScope(ContainerNode* rootNode, Document* document)
     : m_rootNode(rootNode)
     , m_documentScope(document)
     , m_parentTreeScope(document)
-    , m_guardRefCount(0)
     , m_idTargetObserverRegistry(IdTargetObserverRegistry::create())
 {
     ASSERT(rootNode);
     ASSERT(document);
     ASSERT(rootNode != document);
-    m_parentTreeScope->guardRef();
-    m_rootNode->setTreeScope(this);
 }
 
 TreeScope::TreeScope(Document* document)
     : m_rootNode(document)
     , m_documentScope(document)
     , m_parentTreeScope(0)
-    , m_guardRefCount(0)
     , m_idTargetObserverRegistry(IdTargetObserverRegistry::create())
 {
     ASSERT(document);
-    m_rootNode->setTreeScope(this);
 }
 
 TreeScope::TreeScope()
     : m_rootNode(0)
     , m_documentScope(0)
     , m_parentTreeScope(0)
-    , m_guardRefCount(0)
 {
 }
 
 TreeScope::~TreeScope()
 {
-    ASSERT(!m_guardRefCount);
-    m_rootNode->setTreeScope(noDocumentInstance());
-
     if (m_selection) {
         m_selection->clearTreeScope();
         m_selection = 0;
     }
-
-    if (m_parentTreeScope)
-        m_parentTreeScope->guardDeref();
 }
 
 void TreeScope::destroyTreeScopeData()
@@ -133,9 +120,6 @@ void TreeScope::setParentTreeScope(TreeScope* newParentScope)
     // Every scope other than document needs a parent scope.
     ASSERT(newParentScope);
 
-    newParentScope->guardRef();
-    if (m_parentTreeScope)
-        m_parentTreeScope->guardDeref();
     m_parentTreeScope = newParentScope;
     setDocumentScope(newParentScope->documentScope());
 }
@@ -431,24 +415,4 @@ TreeScope* commonTreeScope(Node* nodeA, Node* nodeB)
     return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : 0;
 }
 
-#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
index e540152..be500f1 100644 (file)
@@ -92,7 +92,7 @@ public:
     // Used by the basic DOM mutation methods (e.g., appendChild()).
     void adoptIfNeeded(Node*);
 
-    Node* rootNode() const { return m_rootNode; }
+    ContainerNode* rootNode() const { return m_rootNode; }
 
     IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); }
 
@@ -104,29 +104,6 @@ public:
         return &instance;
     }
 
-    // Nodes belonging to this scope hold guard 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 guardRef()
-    {
-        ASSERT(!deletionHasBegun());
-        ++m_guardRefCount;
-    }
-
-    void guardDeref()
-    {
-        ASSERT(!deletionHasBegun());
-        --m_guardRefCount;
-        if (!m_guardRefCount && !refCount() && this != noDocumentInstance()) {
-            beginDeletion();
-            delete this;
-        }
-    }
-
-    void removedLastRefToScope();
-
 protected:
     TreeScope(ContainerNode*, Document*);
     TreeScope(Document*);
@@ -141,26 +118,12 @@ protected:
         m_documentScope = document;
     }
 
-    bool hasGuardRefCount() const { return m_guardRefCount; }
-
 private:
     TreeScope();
 
-    virtual void dispose() { }
-
-    int refCount() const;
-#ifndef NDEBUG
-    bool deletionHasBegun();
-    void beginDeletion();
-#else
-    bool deletionHasBegun() { return false; }
-    void beginDeletion() { }
-#endif
-
-    Node* m_rootNode;
+    ContainerNode* m_rootNode;
     Document* m_documentScope;
     TreeScope* m_parentTreeScope;
-    int m_guardRefCount;
 
     OwnPtr<DocumentOrderedMap> m_elementsById;
     OwnPtr<DocumentOrderedMap> m_imageMapsByName;
index 2550c2d..41bfd25 100644 (file)
@@ -40,8 +40,6 @@ void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
 {
     ASSERT(needsScopeChange());
 
-    m_oldScope->guardRef();
-
     // 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
@@ -53,7 +51,7 @@ void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
         oldDocument->incDOMTreeVersion();
 
     for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
-        updateTreeScope(node);
+        node->setTreeScope(m_newScope);
 
         if (willMoveToNewDocument)
             moveNodeToNewDocument(node, oldDocument, newDocument);
@@ -78,8 +76,6 @@ void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
                 moveTreeToNewDocument(shadow, oldDocument, newDocument);
         }
     }
-
-    m_oldScope->guardDeref();
 }
 
 void TreeScopeAdopter::moveTreeToNewDocument(Node* root, Document* oldDocument, Document* newDocument) const
@@ -103,15 +99,6 @@ void TreeScopeAdopter::ensureDidMoveToNewDocumentWasCalled(Document* oldDocument
 }
 #endif
 
-inline void TreeScopeAdopter::updateTreeScope(Node* node) const
-{
-    ASSERT(!node->isTreeScope());
-    ASSERT(node->treeScope() == m_oldScope);
-    m_newScope->guardRef();
-    m_oldScope->guardDeref();
-    node->setTreeScope(m_newScope);
-}
-
 inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDocument, Document* newDocument) const
 {
     ASSERT(!node->inDocument() || oldDocument != newDocument);
@@ -122,6 +109,7 @@ inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDoc
             rareData->nodeLists()->adoptDocument(oldDocument, newDocument);
     }
 
+    newDocument->guardRef();
     if (oldDocument)
         oldDocument->moveNodeIteratorsToNewDocument(node, newDocument);
 
@@ -135,6 +123,9 @@ inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDoc
 
     node->didMoveToNewDocument(oldDocument);
     ASSERT(didMoveToNewDocumentWasCalled);
+    
+    if (oldDocument)
+        oldDocument->guardDeref();
 }
 
 }
index cea4dca..4ca4182 100644 (file)
@@ -45,7 +45,6 @@ public:
 #endif
 
 private:
-    void updateTreeScope(Node*) const;
     void moveTreeToNewScope(Node*) const;
     void moveTreeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
     void moveNodeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;