Changeset 143840 in webkit
- Timestamp:
- Feb 23, 2013 2:49:49 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 13 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r143838 r143840 1 2013-02-23 Hajime Morrita <morrita@google.com> 2 3 ShadowRoot needs guardRef() and guardDeref() 4 https://bugs.webkit.org/show_bug.cgi?id=109777 5 6 Reviewed by Dimitri Glazkov. 7 8 This change moves m_guardRefCount from Document to TreeScope, 9 which allows ShadowRoot to be guarded by guardRef() mechanism as 10 Document. After r137524, Node referes TreeScope instead of 11 Document. This is natural consequence of the change: It no longer 12 makes sense to guardRef() Document pointer from Node. 13 14 Detail: 15 16 - Document::m_guardRefCount and related funcdtions are moved to TreeScope 17 - Document::removedLastRef is factored out into TreeScope::removedLastRefToScope(), 18 TreeScope::dispose() and Docuent::dispose(). ShadowRoot also got its own dispose() implementation. 19 - Moved guardRef() and guardDeref() calls to TreeScope and Node. 20 Note that there are two "guarded" TreeScope references. One is 21 Node::m_treeScope and another is TreeScope::m_parentTreeScope. 22 The guarded-ref management is now encapsulated in these two classes. 23 24 No new tests. Covered by existing tests. 25 26 * WebCore.exp.in: 27 * dom/Document.cpp: 28 (WebCore::Document::Document): 29 (WebCore::Document::~Document): 30 (WebCore::Document::dispose): Extracted from removedLastRef() 31 * dom/Document.h: 32 (WebCore::Node::isTreeScope): 33 (WebCore::Node::Node): 34 * dom/DocumentFragment.cpp: 35 (WebCore::DocumentFragment::DocumentFragment): Remove ASSERT() and move it to ... 36 (WebCore::DocumentFragment::create): ... here, to allow NULL document from ShadowRoot. 37 * dom/Node.cpp: 38 (WebCore::Node::~Node): 39 (WebCore::Node::removedLastRef): 40 * dom/Node.h: 41 (WebCore::Node::setTreeScope): 42 * dom/ShadowRoot.cpp: 43 (WebCore::ShadowRoot::ShadowRoot): Passed NULL document to superclass. This aligns what Document is doing. 44 (WebCore::ShadowRoot::dispose): Added. 45 * dom/ShadowRoot.h: 46 (ShadowRoot): 47 * dom/TreeScope.cpp: 48 (SameSizeAsTreeScope): 49 (WebCore::TreeScope::TreeScope): 50 (WebCore::TreeScope::~TreeScope): 51 (WebCore::TreeScope::dispose): Added. 52 (WebCore::TreeScope::setParentTreeScope): 53 (WebCore::TreeScope::deletionHasBegun): 54 (WebCore::TreeScope::beginDeletion): 55 (WebCore::TreeScope::refCount): Added. 56 * dom/TreeScope.h: Turned m_rootNode to Node* from ContainerNode* for Node::isTreeScope to be inlined. 57 (WebCore::TreeScope::guardRef): Pulled up from Document. 58 (WebCore::TreeScope::guardDeref): Ditto. 59 (WebCore::TreeScope::hasGuardRefCount): Added to hide m_guardRefCount. 60 (WebCore::TreeScope::deletionHasBegun): Added. 61 (WebCore::TreeScope::beginDeletion): Added. 62 (WebCore::TreeScope::removedLastRefToScope): Pulled up from Document. 63 * dom/TreeScopeAdopter.cpp: 64 (WebCore::TreeScopeAdopter::moveTreeToNewScope): 65 (WebCore::TreeScopeAdopter::moveNodeToNewDocument): 66 1 67 2013-02-23 Alexey Proskuryakov <ap@apple.com> 2 68 -
trunk/Source/WebCore/WebCore.exp.in
r143816 r143840 1414 1414 __ZNK7WebCore4Node13ownerDocumentEv 1415 1415 __ZNK7WebCore4Node14isDescendantOfEPKS0_ 1416 __ZNK7WebCore4Node11isTreeScopeEv1417 1416 __ZNK7WebCore4Node18getSubresourceURLsERN3WTF11ListHashSetINS_4KURLELm256ENS_8KURLHashEEE 1418 1417 __ZNK7WebCore4Node31numberOfScopedHTMLStyleChildrenEv -
trunk/Source/WebCore/dom/Document.cpp
r143806 r143840 414 414 : ContainerNode(0, CreateDocument) 415 415 , TreeScope(this) 416 , m_guardRefCount(0)417 416 , m_styleResolverThrowawayTimer(this, &Document::styleResolverThrowawayTimerFired) 418 417 , m_lastStyleResolverAccessTime(0) … … 486 485 #endif 487 486 { 488 setTreeScope(this);489 490 487 m_printing = false; 491 488 m_paginatedForScreen = false; … … 587 584 ASSERT(!m_styleRecalcTimer.isActive()); 588 585 ASSERT(!m_parentTreeScope); 589 ASSERT(! m_guardRefCount);586 ASSERT(!hasGuardRefCount()); 590 587 591 588 #if ENABLE(TEMPLATE_ELEMENT) … … 654 651 } 655 652 656 void Document::removedLastRef() 657 { 658 ASSERT(!m_deletionHasBegun); 659 if (m_guardRefCount) { 660 // If removing a child removes the last self-only ref, we don't 661 // want the scope to be destructed until after 662 // removeDetachedChildren returns, so we guard ourselves with an 663 // extra self-only ref. 664 guardRef(); 665 666 // We must make sure not to be retaining any of our children through 667 // these extra pointers or we will create a reference cycle. 668 m_docType = 0; 669 m_focusedNode = 0; 670 m_hoverNode = 0; 671 m_activeElement = 0; 672 m_titleElement = 0; 673 m_documentElement = 0; 674 m_contextFeatures = ContextFeatures::defaultSwitch(); 675 m_userActionElements.documentDidRemoveLastRef(); 653 void Document::dispose() 654 { 655 // We must make sure not to be retaining any of our children through 656 // these extra pointers or we will create a reference cycle. 657 m_docType = 0; 658 m_focusedNode = 0; 659 m_hoverNode = 0; 660 m_activeElement = 0; 661 m_titleElement = 0; 662 m_documentElement = 0; 663 m_contextFeatures = ContextFeatures::defaultSwitch(); 664 m_userActionElements.documentDidRemoveLastRef(); 676 665 #if ENABLE(FULLSCREEN_API) 677 678 679 #endif 680 681 682 683 684 685 686 687 688 689 690 666 m_fullScreenElement = 0; 667 m_fullScreenElementStack.clear(); 668 #endif 669 670 detachParser(); 671 672 // removeDetachedChildren() doesn't always unregister IDs, 673 // so tear down scope information upfront to avoid having stale references in the map. 674 destroyTreeScopeData(); 675 removeDetachedChildren(); 676 677 m_markers->detach(); 678 679 m_cssCanvasElements.clear(); 691 680 692 681 #if ENABLE(REQUEST_ANIMATION_FRAME) 693 // FIXME: consider using ActiveDOMObject. 694 if (m_scriptedAnimationController) 695 m_scriptedAnimationController->clearDocumentPointer(); 696 m_scriptedAnimationController.clear(); 697 #endif 698 699 #ifndef NDEBUG 700 m_inRemovedLastRefFunction = false; 701 #endif 702 703 guardDeref(); 704 } else { 705 #ifndef NDEBUG 706 m_deletionHasBegun = true; 707 #endif 708 delete this; 709 } 682 // FIXME: consider using ActiveDOMObject. 683 if (m_scriptedAnimationController) 684 m_scriptedAnimationController->clearDocumentPointer(); 685 m_scriptedAnimationController.clear(); 686 #endif 710 687 } 711 688 -
trunk/Source/WebCore/dom/Document.h
r142977 r143840 230 230 using ContainerNode::deref; 231 231 232 // Nodes belonging to this document hold guard references -233 // these are enough to keep the document from being destroyed, but234 // not enough to keep it from removing its children. This allows a235 // node that outlives its document to still have a valid document236 // pointer without introducing reference cycles.237 void guardRef()238 {239 ASSERT(!m_deletionHasBegun);240 ++m_guardRefCount;241 }242 243 void guardDeref()244 {245 ASSERT(!m_deletionHasBegun);246 --m_guardRefCount;247 if (!m_guardRefCount && !refCount()) {248 #ifndef NDEBUG249 m_deletionHasBegun = true;250 #endif251 delete this;252 }253 }254 255 232 Element* getElementById(const AtomicString& id) const; 256 233 … … 1218 1195 friend class IgnoreDestructiveWriteCountIncrementer; 1219 1196 1220 v oid removedLastRef();1221 1197 virtual void dispose() OVERRIDE; 1198 1222 1199 void detachParser(); 1223 1200 … … 1286 1263 void addListenerType(ListenerType listenerType) { m_listenerTypes |= listenerType; } 1287 1264 void addMutationEventListenerTypeIfEnabled(ListenerType); 1288 1289 int m_guardRefCount;1290 1265 1291 1266 void styleResolverThrowawayTimerFired(Timer<Document>*); … … 1604 1579 , m_next(0) 1605 1580 { 1606 if (document) 1607 document->guardRef(); 1608 else 1581 if (!m_treeScope) 1609 1582 m_treeScope = TreeScope::noDocumentInstance(); 1583 m_treeScope->guardRef(); 1610 1584 1611 1585 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) -
trunk/Source/WebCore/dom/DocumentFragment.cpp
r140399 r143840 35 35 : ContainerNode(document, constructionType) 36 36 { 37 ASSERT(document);38 37 } 39 38 40 39 PassRefPtr<DocumentFragment> DocumentFragment::create(Document* document) 41 40 { 41 ASSERT(document); 42 42 return adoptRef(new DocumentFragment(document, Node::CreateDocumentFragment)); 43 43 } -
trunk/Source/WebCore/dom/Node.cpp
r143239 r143840 443 443 m_next->setPreviousSibling(0); 444 444 445 if (doc) 446 doc->guardDeref(); 445 m_treeScope->guardDeref(); 447 446 448 447 InspectorCounters::decrementCounter(InspectorCounters::NodeCounter); … … 891 890 892 891 return true; 893 }894 895 bool Node::isTreeScope() const896 {897 return treeScope()->rootNode() == this;898 892 } 899 893 … … 2562 2556 #endif 2563 2557 2558 // This is here for inlining 2559 inline void TreeScope::removedLastRefToScope() 2560 { 2561 ASSERT(!deletionHasBegun()); 2562 if (m_guardRefCount) { 2563 // If removing a child removes the last self-only ref, we don't 2564 // want the scope to be destructed until after 2565 // removeDetachedChildren returns, so we guard ourselves with an 2566 // extra self-only ref. 2567 guardRef(); 2568 dispose(); 2569 #ifndef NDEBUG 2570 // We need to do this right now since guardDeref() can delete this. 2571 rootNode()->m_inRemovedLastRefFunction = false; 2572 #endif 2573 guardDeref(); 2574 } else { 2575 #ifndef NDEBUG 2576 rootNode()->m_inRemovedLastRefFunction = false; 2577 beginDeletion(); 2578 #endif 2579 delete this; 2580 } 2581 } 2582 2564 2583 // It's important not to inline removedLastRef, because we don't want to inline the code to 2565 2584 // delete a Node at each deref call site. … … 2569 2588 // faster for non-Document nodes, and because the call to removedLastRef that is inlined 2570 2589 // at all deref call sites is smaller if it's a non-virtual function. 2571 if (is DocumentNode()) {2572 static_cast<Document*>(this)->removedLastRef();2590 if (isTreeScope()) { 2591 treeScope()->removedLastRefToScope(); 2573 2592 return; 2574 2593 } 2594 2575 2595 #ifndef NDEBUG 2576 2596 m_deletionHasBegun = true; -
trunk/Source/WebCore/dom/Node.h
r143089 r143840 249 249 250 250 bool isDocumentNode() const; 251 bool isTreeScope() const ;251 bool isTreeScope() const { return treeScope()->rootNode() == this; } 252 252 bool isDocumentFragment() const { return getFlag(IsDocumentFragmentFlag); } 253 253 bool isShadowRoot() const { return isDocumentFragment() && isTreeScope(); } -
trunk/Source/WebCore/dom/ShadowRoot.cpp
r143089 r143840 53 53 54 54 ShadowRoot::ShadowRoot(Document* document, ShadowRootType type) 55 : DocumentFragment( document, CreateShadowRoot)55 : DocumentFragment(0, CreateShadowRoot) 56 56 , TreeScope(this, document) 57 57 , m_prev(0) … … 64 64 { 65 65 ASSERT(document); 66 setTreeScope(this);67 66 68 67 #if PLATFORM(CHROMIUM) … … 88 87 if (hasRareData()) 89 88 clearRareData(); 89 } 90 91 void ShadowRoot::dispose() 92 { 93 removeDetachedChildren(); 90 94 } 91 95 -
trunk/Source/WebCore/dom/ShadowRoot.h
r141524 r143840 101 101 virtual ~ShadowRoot(); 102 102 103 virtual void dispose() OVERRIDE; 103 104 virtual bool childTypeAllowed(NodeType) const OVERRIDE; 104 105 virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE; -
trunk/Source/WebCore/dom/TreeScope.cpp
r143422 r143840 60 60 virtual ~SameSizeAsTreeScope(); 61 61 void* pointers[8]; 62 int ints[1]; 62 63 }; 63 64 … … 70 71 , m_documentScope(document) 71 72 , m_parentTreeScope(document) 73 , m_guardRefCount(0) 72 74 , m_idTargetObserverRegistry(IdTargetObserverRegistry::create()) 73 75 { … … 75 77 ASSERT(document); 76 78 ASSERT(rootNode != document); 79 m_parentTreeScope->guardRef(); 80 m_rootNode->setTreeScope(this); 77 81 } 78 82 … … 81 85 , m_documentScope(document) 82 86 , m_parentTreeScope(0) 87 , m_guardRefCount(0) 83 88 , m_idTargetObserverRegistry(IdTargetObserverRegistry::create()) 84 89 { 85 90 ASSERT(document); 91 m_rootNode->setTreeScope(this); 86 92 } 87 93 … … 90 96 , m_documentScope(0) 91 97 , m_parentTreeScope(0) 98 , m_guardRefCount(0) 92 99 { 93 100 } … … 95 102 TreeScope::~TreeScope() 96 103 { 104 ASSERT(!m_guardRefCount); 105 m_rootNode->setTreeScope(noDocumentInstance()); 106 97 107 if (m_selection) { 98 108 m_selection->clearTreeScope(); 99 109 m_selection = 0; 100 110 } 111 112 if (m_parentTreeScope) 113 m_parentTreeScope->guardDeref(); 101 114 } 102 115 … … 121 134 ASSERT(newParentScope); 122 135 136 newParentScope->guardRef(); 137 if (m_parentTreeScope) 138 m_parentTreeScope->guardDeref(); 123 139 m_parentTreeScope = newParentScope; 124 140 setDocumentScope(newParentScope->documentScope()); … … 416 432 } 417 433 434 #ifndef NDEBUG 435 bool TreeScope::deletionHasBegun() 436 { 437 return rootNode() && rootNode()->m_deletionHasBegun; 438 } 439 440 void TreeScope::beginDeletion() 441 { 442 ASSERT(this != noDocumentInstance()); 443 rootNode()->m_deletionHasBegun = true; 444 } 445 #endif 446 447 int TreeScope::refCount() const 448 { 449 if (Node* root = rootNode()) 450 return root->refCount(); 451 return 0; 452 } 453 418 454 } // namespace WebCore -
trunk/Source/WebCore/dom/TreeScope.h
r138735 r143840 93 93 void adoptIfNeeded(Node*); 94 94 95 ContainerNode* rootNode() const { return m_rootNode; }95 Node* rootNode() const { return m_rootNode; } 96 96 97 97 IdTargetObserverRegistry& idTargetObserverRegistry() const { return *m_idTargetObserverRegistry.get(); } … … 104 104 return &instance; 105 105 } 106 107 // Nodes belonging to this scope hold guard references - 108 // these are enough to keep the scope from being destroyed, but 109 // not enough to keep it from removing its children. This allows a 110 // node that outlives its scope to still have a valid document 111 // pointer without introducing reference cycles. 112 void guardRef() 113 { 114 ASSERT(!deletionHasBegun()); 115 ++m_guardRefCount; 116 } 117 118 void guardDeref() 119 { 120 ASSERT(!deletionHasBegun()); 121 --m_guardRefCount; 122 if (!m_guardRefCount && !refCount() && this != noDocumentInstance()) { 123 beginDeletion(); 124 delete this; 125 } 126 } 127 128 void removedLastRefToScope(); 106 129 107 130 protected: … … 119 142 } 120 143 144 bool hasGuardRefCount() const { return m_guardRefCount; } 145 121 146 private: 122 147 TreeScope(); 123 148 124 ContainerNode* m_rootNode; 149 virtual void dispose() { } 150 151 int refCount() const; 152 #ifndef NDEBUG 153 bool deletionHasBegun(); 154 void beginDeletion(); 155 #else 156 bool deletionHasBegun() { return false; } 157 void beginDeletion() { } 158 #endif 159 160 Node* m_rootNode; 125 161 Document* m_documentScope; 126 162 TreeScope* m_parentTreeScope; 163 int m_guardRefCount; 127 164 128 165 OwnPtr<DocumentOrderedMap> m_elementsById; -
trunk/Source/WebCore/dom/TreeScopeAdopter.cpp
r140103 r143840 41 41 ASSERT(needsScopeChange()); 42 42 43 m_oldScope->guardRef(); 44 43 45 // If an element is moved from a document and then eventually back again the collection cache for 44 46 // that element may contain stale data as changes made to it will have updated the DOMTreeVersion … … 52 54 53 55 for (Node* node = root; node; node = NodeTraversal::next(node, root)) { 54 node->setTreeScope(m_newScope);56 updateTreeScope(node); 55 57 56 58 if (willMoveToNewDocument) … … 77 79 } 78 80 } 81 82 m_oldScope->guardDeref(); 79 83 } 80 84 … … 100 104 #endif 101 105 106 inline void TreeScopeAdopter::updateTreeScope(Node* node) const 107 { 108 ASSERT(!node->isTreeScope()); 109 ASSERT(node->treeScope() == m_oldScope); 110 m_newScope->guardRef(); 111 m_oldScope->guardDeref(); 112 node->setTreeScope(m_newScope); 113 } 114 102 115 inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDocument, Document* newDocument) const 103 116 { … … 110 123 } 111 124 112 newDocument->guardRef();113 125 if (oldDocument) 114 126 oldDocument->moveNodeIteratorsToNewDocument(node, newDocument); … … 124 136 node->didMoveToNewDocument(oldDocument); 125 137 ASSERT(didMoveToNewDocumentWasCalled); 126 127 if (oldDocument)128 oldDocument->guardDeref();129 138 } 130 139 -
trunk/Source/WebCore/dom/TreeScopeAdopter.h
r127300 r143840 46 46 47 47 private: 48 void updateTreeScope(Node*) const; 48 49 void moveTreeToNewScope(Node*) const; 49 50 void moveTreeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
Note: See TracChangeset
for help on using the changeset viewer.