Diff
Modified: branches/chromium/1410/Source/WebCore/WebCore.exp.in (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/WebCore.exp.in 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/WebCore.exp.in 2013-03-12 01:05:41 UTC (rev 145446)
@@ -1401,7 +1401,6 @@
__ZN7WebCore4Node12insertBeforeEN3WTF10PassRefPtrIS0_EEPS0_Rib
__ZNK7WebCore4Node13ownerDocumentEv
__ZNK7WebCore4Node14isDescendantOfEPKS0_
-__ZNK7WebCore4Node11isTreeScopeEv
__ZNK7WebCore4Node18getSubresourceURLsERN3WTF11ListHashSetINS_4KURLELm256ENS_8KURLHashEEE
__ZNK7WebCore4Node31numberOfScopedHTMLStyleChildrenEv
__ZNK7WebCore4Node9nodeIndexEv
Modified: branches/chromium/1410/Source/WebCore/dom/Document.cpp (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/Document.cpp 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/Document.cpp 2013-03-12 01:05:41 UTC (rev 145446)
@@ -409,7 +409,6 @@
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)
@@ -481,8 +480,6 @@
, m_templateDocumentHost(0)
#endif
{
- setTreeScope(this);
-
m_printing = false;
m_paginatedForScreen = false;
@@ -582,7 +579,7 @@
ASSERT(m_ranges.isEmpty());
ASSERT(!m_styleRecalcTimer.isActive());
ASSERT(!m_parentTreeScope);
- ASSERT(!m_guardRefCount);
+ ASSERT(!hasGuardRefCount());
#if ENABLE(TEMPLATE_ELEMENT)
if (m_templateDocument)
@@ -649,60 +646,40 @@
InspectorCounters::decrementCounter(InspectorCounters::DocumentCounter);
}
-void Document::removedLastRef()
+void Document::dispose()
{
- 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();
+ // 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();
- // 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
Modified: branches/chromium/1410/Source/WebCore/dom/Document.h (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/Document.h 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/Document.h 2013-03-12 01:05:41 UTC (rev 145446)
@@ -228,29 +228,6 @@
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; }
@@ -1217,8 +1194,8 @@
friend class Node;
friend class IgnoreDestructiveWriteCountIncrementer;
- void removedLastRef();
-
+ virtual void dispose() OVERRIDE;
+
void detachParser();
typedef void (*ArgumentsCallback)(const String& keyString, const String& valueString, Document*, void* data);
@@ -1286,8 +1263,6 @@
void addListenerType(ListenerType listenerType) { m_listenerTypes |= listenerType; }
void addMutationEventListenerTypeIfEnabled(ListenerType);
- int m_guardRefCount;
-
void styleResolverThrowawayTimerFired(Timer<Document>*);
Timer<Document> m_styleResolverThrowawayTimer;
double m_lastStyleResolverAccessTime;
@@ -1603,10 +1578,9 @@
, m_previous(0)
, m_next(0)
{
- if (document)
- document->guardRef();
- else
+ if (!m_treeScope)
m_treeScope = TreeScope::noDocumentInstance();
+ m_treeScope->guardRef();
#if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS)
trackForDebugging();
Modified: branches/chromium/1410/Source/WebCore/dom/DocumentFragment.cpp (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/DocumentFragment.cpp 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/DocumentFragment.cpp 2013-03-12 01:05:41 UTC (rev 145446)
@@ -34,11 +34,11 @@
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));
}
Modified: branches/chromium/1410/Source/WebCore/dom/Node.cpp (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/Node.cpp 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/Node.cpp 2013-03-12 01:05:41 UTC (rev 145446)
@@ -437,8 +437,7 @@
if (m_next)
m_next->setPreviousSibling(0);
- if (doc)
- doc->guardDeref();
+ m_treeScope->guardDeref();
InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
}
@@ -887,11 +886,6 @@
return true;
}
-bool Node::isTreeScope() const
-{
- return treeScope()->rootNode() == this;
-}
-
bool Node::isKeyboardFocusable(KeyboardEvent*) const
{
return isFocusable() && tabIndex() >= 0;
@@ -2561,6 +2555,31 @@
}
#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()
@@ -2568,10 +2587,11 @@
// 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 (isDocumentNode()) {
- static_cast<Document*>(this)->removedLastRef();
+ if (isTreeScope()) {
+ treeScope()->removedLastRefToScope();
return;
}
+
#ifndef NDEBUG
m_deletionHasBegun = true;
#endif
Modified: branches/chromium/1410/Source/WebCore/dom/Node.h (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/Node.h 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/Node.h 2013-03-12 01:05:41 UTC (rev 145446)
@@ -248,7 +248,7 @@
virtual bool isInsertionPointNode() const { return false; }
bool isDocumentNode() const;
- bool isTreeScope() const;
+ bool isTreeScope() const { return treeScope()->rootNode() == this; }
bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); }
bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); }
bool isInsertionPoint() const { return getFlag(NeedsShadowTreeWalkerFlag) && isInsertionPointNode(); }
Modified: branches/chromium/1410/Source/WebCore/dom/ShadowRoot.cpp (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/ShadowRoot.cpp 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/ShadowRoot.cpp 2013-03-12 01:05:41 UTC (rev 145446)
@@ -52,7 +52,7 @@
};
ShadowRoot::ShadowRoot(Document* document, ShadowRootType type)
- : DocumentFragment(document, CreateShadowRoot)
+ : DocumentFragment(0, CreateShadowRoot)
, TreeScope(this, document)
, m_prev(0)
, m_next(0)
@@ -63,7 +63,6 @@
, m_registeredWithParentShadowRoot(false)
{
ASSERT(document);
- setTreeScope(this);
#if PLATFORM(CHROMIUM)
if (type == ShadowRoot::AuthorShadowRoot) {
@@ -89,6 +88,11 @@
clearRareData();
}
+void ShadowRoot::dispose()
+{
+ removeDetachedChildren();
+}
+
PassRefPtr<Node> ShadowRoot::cloneNode(bool, ExceptionCode& ec)
{
ec = DATA_CLONE_ERR;
Modified: branches/chromium/1410/Source/WebCore/dom/ShadowRoot.h (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/ShadowRoot.h 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/ShadowRoot.h 2013-03-12 01:05:41 UTC (rev 145446)
@@ -100,6 +100,7 @@
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;
Modified: branches/chromium/1410/Source/WebCore/dom/TreeScope.cpp (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/TreeScope.cpp 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/TreeScope.cpp 2013-03-12 01:05:41 UTC (rev 145446)
@@ -59,6 +59,7 @@
struct SameSizeAsTreeScope {
virtual ~SameSizeAsTreeScope();
void* pointers[8];
+ int ints[1];
};
COMPILE_ASSERT(sizeof(TreeScope) == sizeof(SameSizeAsTreeScope), treescope_should_stay_small);
@@ -69,35 +70,47 @@
: 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()
@@ -120,6 +133,9 @@
// 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());
}
@@ -415,4 +431,24 @@
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
Modified: branches/chromium/1410/Source/WebCore/dom/TreeScope.h (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/TreeScope.h 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/TreeScope.h 2013-03-12 01:05:41 UTC (rev 145446)
@@ -92,7 +92,7 @@
// Used by the basic DOM mutation methods (e.g., appendChild()).
void adoptIfNeeded(Node*);
- ContainerNode* rootNode() const { return m_rootNode; }
+ Node* rootNode() const { return m_rootNode; }
IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); }
@@ -104,6 +104,29 @@
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*);
@@ -118,12 +141,26 @@
m_documentScope = document;
}
+ bool hasGuardRefCount() const { return m_guardRefCount; }
+
private:
TreeScope();
- ContainerNode* m_rootNode;
+ virtual void dispose() { }
+
+ int refCount() const;
+#ifndef NDEBUG
+ bool deletionHasBegun();
+ void beginDeletion();
+#else
+ bool deletionHasBegun() { return false; }
+ void beginDeletion() { }
+#endif
+
+ Node* m_rootNode;
Document* m_documentScope;
TreeScope* m_parentTreeScope;
+ int m_guardRefCount;
OwnPtr<DocumentOrderedMap> m_elementsById;
OwnPtr<DocumentOrderedMap> m_imageMapsByName;
Modified: branches/chromium/1410/Source/WebCore/dom/TreeScopeAdopter.cpp (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/TreeScopeAdopter.cpp 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/TreeScopeAdopter.cpp 2013-03-12 01:05:41 UTC (rev 145446)
@@ -40,6 +40,8 @@
{
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
@@ -51,7 +53,7 @@
oldDocument->incDOMTreeVersion();
for (Node* node = root; node; node = NodeTraversal::next(node, root)) {
- node->setTreeScope(m_newScope);
+ updateTreeScope(node);
if (willMoveToNewDocument)
moveNodeToNewDocument(node, oldDocument, newDocument);
@@ -76,6 +78,8 @@
moveTreeToNewDocument(shadow, oldDocument, newDocument);
}
}
+
+ m_oldScope->guardDeref();
}
void TreeScopeAdopter::moveTreeToNewDocument(Node* root, Document* oldDocument, Document* newDocument) const
@@ -99,6 +103,15 @@
}
#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);
@@ -109,7 +122,6 @@
rareData->nodeLists()->adoptDocument(oldDocument, newDocument);
}
- newDocument->guardRef();
if (oldDocument)
oldDocument->moveNodeIteratorsToNewDocument(node, newDocument);
@@ -123,9 +135,6 @@
node->didMoveToNewDocument(oldDocument);
ASSERT(didMoveToNewDocumentWasCalled);
-
- if (oldDocument)
- oldDocument->guardDeref();
}
}
Modified: branches/chromium/1410/Source/WebCore/dom/TreeScopeAdopter.h (145445 => 145446)
--- branches/chromium/1410/Source/WebCore/dom/TreeScopeAdopter.h 2013-03-12 00:53:06 UTC (rev 145445)
+++ branches/chromium/1410/Source/WebCore/dom/TreeScopeAdopter.h 2013-03-12 01:05:41 UTC (rev 145446)
@@ -45,6 +45,7 @@
#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;