Changeset 144735 in webkit
- Timestamp:
- Mar 5, 2013 12:08:15 AM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 14 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r144732 r144735 1 2013-03-05 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/Element.cpp: 43 (WebCore::Element::ensureAttr): This has been wrong and is fixed in this revision since the incorrectness is unveiled by this change. 44 * dom/ShadowRoot.cpp: 45 (WebCore::ShadowRoot::ShadowRoot): Passed NULL document to superclass. This aligns what Document is doing. 46 (WebCore::ShadowRoot::dispose): Added. 47 * dom/ShadowRoot.h: 48 (ShadowRoot): 49 * dom/TreeScope.cpp: 50 (SameSizeAsTreeScope): 51 (WebCore::TreeScope::TreeScope): 52 (WebCore::TreeScope::~TreeScope): 53 (WebCore::TreeScope::dispose): Added. 54 (WebCore::TreeScope::setParentTreeScope): 55 (WebCore::TreeScope::deletionHasBegun): 56 (WebCore::TreeScope::beginDeletion): 57 (WebCore::TreeScope::refCount): Added. 58 * dom/TreeScope.h: Turned m_rootNode to Node* from ContainerNode* for Node::isTreeScope to be inlined. 59 (WebCore::TreeScope::guardRef): Pulled up from Document. 60 (WebCore::TreeScope::guardDeref): Ditto. 61 (WebCore::TreeScope::hasGuardRefCount): Added to hide m_guardRefCount. 62 (WebCore::TreeScope::deletionHasBegun): Added. 63 (WebCore::TreeScope::beginDeletion): Added. 64 (WebCore::TreeScope::removedLastRefToScope): Pulled up from Document. 65 * dom/TreeScopeAdopter.cpp: 66 (WebCore::TreeScopeAdopter::moveTreeToNewScope): 67 (WebCore::TreeScopeAdopter::moveNodeToNewDocument): 68 1 69 2013-03-04 Uday Kiran <udaykiran@motorola.com> 2 70 -
trunk/Source/WebCore/WebCore.exp.in
r144696 r144735 1424 1424 __ZNK7WebCore4Node13ownerDocumentEv 1425 1425 __ZNK7WebCore4Node14isDescendantOfEPKS0_ 1426 __ZNK7WebCore4Node11isTreeScopeEv1427 1426 __ZNK7WebCore4Node18getSubresourceURLsERN3WTF11ListHashSetINS_4KURLELm256ENS_8KURLHashEEE 1428 1427 __ZNK7WebCore4Node31numberOfScopedHTMLStyleChildrenEv -
trunk/Source/WebCore/dom/Document.cpp
r144696 r144735 418 418 : ContainerNode(0, CreateDocument) 419 419 , TreeScope(this) 420 , m_guardRefCount(0)421 420 , m_styleResolverThrowawayTimer(this, &Document::styleResolverThrowawayTimerFired) 422 421 , m_lastStyleResolverAccessTime(0) … … 490 489 #endif 491 490 { 492 setTreeScope(this);493 494 491 m_printing = false; 495 492 m_paginatedForScreen = false; … … 591 588 ASSERT(!m_styleRecalcTimer.isActive()); 592 589 ASSERT(!m_parentTreeScope); 593 ASSERT(! m_guardRefCount);590 ASSERT(!hasGuardRefCount()); 594 591 595 592 #if ENABLE(TEMPLATE_ELEMENT) … … 658 655 } 659 656 660 void Document:: removedLastRef()657 void Document::dispose() 661 658 { 662 659 ASSERT(!m_deletionHasBegun); 663 if (m_guardRefCount) { 664 // If removing a child removes the last self-only ref, we don't 665 // want the scope to be destructed until after 666 // removeDetachedChildren returns, so we guard ourselves with an 667 // extra self-only ref. 668 guardRef(); 669 670 // We must make sure not to be retaining any of our children through 671 // these extra pointers or we will create a reference cycle. 672 m_docType = 0; 673 m_focusedNode = 0; 674 m_hoverNode = 0; 675 m_activeElement = 0; 676 m_titleElement = 0; 677 m_documentElement = 0; 678 m_contextFeatures = ContextFeatures::defaultSwitch(); 679 m_userActionElements.documentDidRemoveLastRef(); 660 // We must make sure not to be retaining any of our children through 661 // these extra pointers or we will create a reference cycle. 662 m_docType = 0; 663 m_focusedNode = 0; 664 m_hoverNode = 0; 665 m_activeElement = 0; 666 m_titleElement = 0; 667 m_documentElement = 0; 668 m_contextFeatures = ContextFeatures::defaultSwitch(); 669 m_userActionElements.documentDidRemoveLastRef(); 680 670 #if ENABLE(FULLSCREEN_API) 681 682 683 #endif 684 685 671 m_fullScreenElement = 0; 672 m_fullScreenElementStack.clear(); 673 #endif 674 675 detachParser(); 686 676 687 677 #if ENABLE(CUSTOM_ELEMENTS) 688 689 #endif 690 691 692 693 694 695 696 697 698 678 m_registry.clear(); 679 #endif 680 681 // removeDetachedChildren() doesn't always unregister IDs, 682 // so tear down scope information upfront to avoid having stale references in the map. 683 destroyTreeScopeData(); 684 removeDetachedChildren(); 685 686 m_markers->detach(); 687 688 m_cssCanvasElements.clear(); 699 689 700 690 #if ENABLE(REQUEST_ANIMATION_FRAME) 701 // FIXME: consider using ActiveDOMObject. 702 if (m_scriptedAnimationController) 703 m_scriptedAnimationController->clearDocumentPointer(); 704 m_scriptedAnimationController.clear(); 705 #endif 706 707 #ifndef NDEBUG 708 m_inRemovedLastRefFunction = false; 709 #endif 710 711 guardDeref(); 712 } else { 713 #ifndef NDEBUG 714 m_deletionHasBegun = true; 715 #endif 716 delete this; 717 } 691 // FIXME: consider using ActiveDOMObject. 692 if (m_scriptedAnimationController) 693 m_scriptedAnimationController->clearDocumentPointer(); 694 m_scriptedAnimationController.clear(); 695 #endif 718 696 } 719 697 -
trunk/Source/WebCore/dom/Document.h
r144696 r144735 232 232 using ContainerNode::deref; 233 233 234 // Nodes belonging to this document hold guard references -235 // these are enough to keep the document from being destroyed, but236 // not enough to keep it from removing its children. This allows a237 // node that outlives its document to still have a valid document238 // pointer without introducing reference cycles.239 void guardRef()240 {241 ASSERT(!m_deletionHasBegun);242 ++m_guardRefCount;243 }244 245 void guardDeref()246 {247 ASSERT(!m_deletionHasBegun);248 --m_guardRefCount;249 if (!m_guardRefCount && !refCount()) {250 #ifndef NDEBUG251 m_deletionHasBegun = true;252 #endif253 delete this;254 }255 }256 257 234 Element* getElementById(const AtomicString& id) const; 258 235 … … 1227 1204 friend class IgnoreDestructiveWriteCountIncrementer; 1228 1205 1229 v oid removedLastRef();1230 1206 virtual void dispose() OVERRIDE; 1207 1231 1208 void detachParser(); 1232 1209 … … 1295 1272 void addListenerType(ListenerType listenerType) { m_listenerTypes |= listenerType; } 1296 1273 void addMutationEventListenerTypeIfEnabled(ListenerType); 1297 1298 int m_guardRefCount;1299 1274 1300 1275 void styleResolverThrowawayTimerFired(Timer<Document>*); … … 1617 1592 , m_next(0) 1618 1593 { 1619 if (document) 1620 document->guardRef(); 1621 else 1594 if (!m_treeScope) 1622 1595 m_treeScope = TreeScope::noDocumentInstance(); 1596 m_treeScope->guardRef(); 1623 1597 1624 1598 #if !defined(NDEBUG) || (defined(DUMP_NODE_STATISTICS) && DUMP_NODE_STATISTICS) -
trunk/Source/WebCore/dom/DocumentFragment.cpp
r143940 r144735 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/Element.cpp
r144702 r144735 2754 2754 if (!attrNode) { 2755 2755 attrNode = Attr::create(this, name); 2756 treeScope()->adoptIfNeeded(attrNode.get()); 2756 2757 attrNodeList->append(attrNode); 2757 2758 } -
trunk/Source/WebCore/dom/Node.cpp
r144526 r144735 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 … … 2568 2562 #endif 2569 2563 2564 // This is here for inlining 2565 inline void TreeScope::removedLastRefToScope() 2566 { 2567 ASSERT(!deletionHasBegun()); 2568 if (m_guardRefCount) { 2569 // If removing a child removes the last self-only ref, we don't 2570 // want the scope to be destructed until after 2571 // removeDetachedChildren returns, so we guard ourselves with an 2572 // extra self-only ref. 2573 guardRef(); 2574 dispose(); 2575 #ifndef NDEBUG 2576 // We need to do this right now since guardDeref() can delete this. 2577 rootNode()->m_inRemovedLastRefFunction = false; 2578 #endif 2579 guardDeref(); 2580 } else { 2581 #ifndef NDEBUG 2582 rootNode()->m_inRemovedLastRefFunction = false; 2583 beginDeletion(); 2584 #endif 2585 delete this; 2586 } 2587 } 2588 2570 2589 // It's important not to inline removedLastRef, because we don't want to inline the code to 2571 2590 // delete a Node at each deref call site. … … 2575 2594 // faster for non-Document nodes, and because the call to removedLastRef that is inlined 2576 2595 // at all deref call sites is smaller if it's a non-virtual function. 2577 if (is DocumentNode()) {2578 static_cast<Document*>(this)->removedLastRef();2596 if (isTreeScope()) { 2597 treeScope()->removedLastRefToScope(); 2579 2598 return; 2580 2599 } 2600 2581 2601 #ifndef NDEBUG 2582 2602 m_deletionHasBegun = true; -
trunk/Source/WebCore/dom/Node.h
r143940 r144735 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
r143940 r144735 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
r143940 r144735 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
r143940 r144735 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
r143940 r144735 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
r143940 r144735 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
r143940 r144735 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.