Source/WebCore/ChangeLog

 12012-06-12 Hajime Morrita <morrita@chromium.org>
 2
 3 [Refactoring] Replace Node's Document pointer with a TreeScope pointer.
 4 https://bugs.webkit.org/show_bug.cgi?id=59816
 5
 6 Now Node::document() return m_treeScope->rootTreeScope() instead of Node::m_document.
 7 Each node in shadow tree is no longer need its NodeRareData instance to point the ShadowRoot.
 8
 9 - Node: Replaced Node::m_docuent with Node::m_treeScope. setDocument() is gone.
 10 - NodeRareData: Removed m_treeScope
 11 - TreeScope: Added m_rootTreeScope to make Node::document() fast.
 12
 13 Reviewed by NOBODY (OOPS!).
 14
 15 No new tests. No behavioral change.
 16
 17 * dom/Document.cpp:
 18 (WebCore::Document::Document):
 19 (WebCore::Document::~Document):
 20 (WebCore::Document::suggestedMIMEType):
 21 * dom/Document.h:
 22 (WebCore::Node::isDocumentNode):
 23 (WebCore::Node::document):
 24 (WebCore::Node::documentInternal):
 25 (WebCore::Node::Node):
 26 (WebCore::TreeScope::isDocumentScope):
 27 * dom/Node.cpp:
 28 (WebCore::Node::~Node):
 29 (WebCore::Node::isInShadowTree):
 30 * dom/Node.h:
 31 (WebCore::Node::treeScope):
 32 (WebCore::Node::inDocument):
 33 (WebCore::Node::setTreeScope):
 34 * dom/NodeRareData.h:
 35 (WebCore::NodeRareData::NodeRareData):
 36 * dom/ShadowRoot.cpp:
 37 (WebCore::ShadowRoot::ShadowRoot):
 38 * dom/TreeScope.cpp: Added m_docuent which points the root Document object of the scope tree.
 39 (WebCore::TreeScope::TreeScope):
 40 (WebCore::TreeScope::~TreeScope):
 41 (WebCore::TreeScope::setDocument):
 42 (WebCore::TreeScope::setParentTreeScope):
 43 * dom/TreeScope.h:
 44 (WebCore::TreeScope::document):
 45 * dom/TreeScopeAdopter.cpp:
 46 (WebCore::TreeScopeAdopter::moveTreeToNewScope):
 47 (WebCore::TreeScopeAdopter::moveNodeToNewDocument):
 48 (WebCore::TreeScopeAdopter::moveNodeListCaches): Extracted.
 49 * dom/TreeScopeAdopter.h:
 50
1512012-06-12 Wei James <james.wei@intel.com>
252
353 webcore should depend on webcore_arm_neon for only arm target_arch

Source/WebCore/dom/Document.cpp

@@uint64_t Document::s_globalTreeVersion = 0;
426426
427427Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
428428 : ContainerNode(0, CreateDocument)
429  , TreeScope(this)
 429 , TreeScope(this, this)
430430 , m_guardRefCount(0)
431431 , m_compatibilityMode(NoQuirksMode)
432432 , m_compatibilityModeLocked(false)

@@Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
496496 , m_didDispatchViewportPropertiesChanged(false)
497497#endif
498498{
499  m_document = this;
500 
501499 m_pageGroupUserSheetCacheValid = false;
502500
503501 m_printing = false;

@@Document::~Document()
601599 // if the DocumentParser outlives the Document it won't cause badness.
602600 ASSERT(!m_parser || m_parser->refCount() == 1);
603601 detachParser();
604  m_document = 0;
605 
606602 m_renderArena.clear();
607603
608604 clearAXObjectCache();

@@void Document::setContent(const String& content)
13351331
13361332String Document::suggestedMIMEType() const
13371333{
1338  if (m_document->isXHTMLDocument())
 1334 if (isXHTMLDocument())
13391335 return "application/xhtml+xml";
1340  if (m_document->isSVGDocument())
 1336 if (isSVGDocument())
13411337 return "image/svg+xml";
1342  if (m_document->xmlStandalone())
 1338 if (xmlStandalone())
13431339 return "text/xml";
1344  if (m_document->isHTMLDocument())
 1340 if (isHTMLDocument())
13451341 return "text/html";
13461342
13471343 if (DocumentLoader* documentLoader = loader())

Source/WebCore/dom/Document.h

@@private:
14901490
14911491// Put these methods here, because they require the Document definition, but we really want to inline them.
14921492
1493 inline bool Node::isDocumentNode() const
1494 {
1495  return this == m_document;
1496 }
1497 
14981493inline Node::Node(Document* document, ConstructionType type)
14991494 : m_nodeFlags(type)
1500  , m_document(document)
 1495 , m_treeScope(document)
15011496 , m_previous(0)
15021497 , m_next(0)
15031498 , m_renderer(0)

@@inline Node::Node(Document* document, ConstructionType type)
15121507
15131508Node* eventTargetNodeForDocument(Document*);
15141509
 1510inline Document* Node::document() const
 1511{
 1512 ASSERT(this);
 1513 // FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor
 1514 // due to the virtual function call to nodeType().
 1515 ASSERT(m_treeScope->rootDocument() || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument()));
 1516 return m_treeScope->rootDocument();
 1517}
 1518
 1519inline bool Node::isTreeScope() const
 1520{
 1521 // FIXME: This should be replaced with IsTreeScope flag once we introduce it in NodeFlags.
 1522 return this == m_treeScope->rootNode();
 1523}
 1524
 1525inline bool Node::isDocumentNode() const
 1526{
 1527 return this == m_treeScope->rootDocument();
 1528}
 1529
15151530} // namespace WebCore
15161531
15171532#endif // Document_h

Source/WebCore/dom/DocumentFragment.cpp

@@namespace WebCore {
3535DocumentFragment::DocumentFragment(Document* document, ConstructionType constructionType)
3636 : ContainerNode(document, constructionType)
3737{
38  ASSERT(document);
3938}
4039
4140PassRefPtr<DocumentFragment> DocumentFragment::create(Document* document)
4241{
 42 ASSERT(document);
4343 return adoptRef(new DocumentFragment(document));
4444}
4545

Source/WebCore/dom/DocumentType.cpp

@@DocumentType::DocumentType(Document* document, const String& name, const String&
3434 , m_publicId(publicId)
3535 , m_systemId(systemId)
3636{
 37 if (!treeScope())
 38 setOrphanTreeScope();
3739}
3840
3941KURL DocumentType::baseURI() const

@@void DocumentType::removedFrom(ContainerNode* insertionPoint)
8082 Node::removedFrom(insertionPoint);
8183}
8284
 85void Node::setOrphanTreeScope()
 86{
 87 ASSERT(!m_treeScope && nodeType() == DOCUMENT_TYPE_NODE);
 88 m_treeScope = TreeScope::orphanInstance();
 89}
 90
8391}

Source/WebCore/dom/Node.cpp

@@Node::~Node()
406406 if (renderer())
407407 detach();
408408
409  Document* doc = m_document;
 409 Document* doc = treeScope() ? document() : 0;
410410 if (AXObjectCache::accessibilityEnabled() && doc && doc->axObjectCacheExists())
411411 doc->axObjectCache()->removeNodeForUse(this);
412412

@@Node::~Node()
421421 InspectorCounters::decrementCounter(InspectorCounters::NodeCounter);
422422}
423423
424 void Node::setDocument(Document* document)
425 {
426  ASSERT(!inDocument() || m_document == document);
427  if (inDocument() || m_document == document)
428  return;
429 
430  m_document = document;
431 }
432 
433 NodeRareData* Node::setTreeScope(TreeScope* scope)
434 {
435  if (!scope) {
436  if (hasRareData()) {
437  NodeRareData* data = rareData();
438  data->setTreeScope(0);
439  return data;
440  }
441 
442  return 0;
443  }
444 
445  NodeRareData* data = ensureRareData();
446  data->setTreeScope(scope);
447  return data;
448 }
449 
450 TreeScope* Node::treeScope() const
451 {
452  // FIXME: Using m_document directly is not good -> see comment with document() in the header file.
453  if (!hasRareData())
454  return m_document;
455  TreeScope* scope = rareData()->treeScope();
456  return scope ? scope : m_document;
457 }
458 
459424NodeRareData* Node::rareData() const
460425{
461426 ASSERT(hasRareData());

@@OwnPtr<NodeRareData> Node::createRareData()
482447void Node::clearRareData()
483448{
484449 ASSERT(hasRareData());
485  if (treeScope() && rareData()->nodeLists())
 450 if (rareData()->nodeLists())
486451 treeScope()->removeNodeListCache();
487452
488453#if ENABLE(MUTATION_OBSERVERS)

@@ContainerNode* Node::nonShadowBoundaryParentNode() const
15311496
15321497bool Node::isInShadowTree() const
15331498{
1534  return treeScope() != document();
 1499 return !treeScope()->isDocumentScope();
15351500}
15361501
15371502Element* Node::parentOrHostElement() const

Source/WebCore/dom/Node.h

@@public:
217217 virtual bool isFrameOwnerElement() const { return false; }
218218 bool isDocumentNode() const;
219219 bool isShadowRoot() const { return getFlag(IsShadowRootFlag); }
 220 bool isTreeScope() const;
220221 bool inNamedFlow() const { return getFlag(InNamedFlowFlag); }
221222 bool hasAttrList() const { return getFlag(HasAttrListFlag); }
222223 bool hasCustomCallbacks() const { return getFlag(HasCustomCallbacksFlag); }

@@public:
405406
406407 // Returns the document associated with this node. This method never returns NULL, except in the case
407408 // of a DocumentType node that is not used with any Document yet. A Document node returns itself.
408  Document* document() const
409  {
410  ASSERT(this);
411  // FIXME: below ASSERT is useful, but prevents the use of document() in the constructor or destructor
412  // due to the virtual function call to nodeType().
413  ASSERT(m_document || (nodeType() == DOCUMENT_TYPE_NODE && !inDocument()));
414  return m_document;
415  }
 409 Document* document() const;
416410
417  TreeScope* treeScope() const;
 411 TreeScope* treeScope() const { return m_treeScope; }
418412
419413 // Returns true if this node is associated with a document and is in its associated document's
420414 // node tree, false otherwise.
421  bool inDocument() const
422  {
423  ASSERT(m_document || !getFlag(InDocumentFlag));
 415 bool inDocument() const
 416 {
 417 ASSERT(m_treeScope || !getFlag(InDocumentFlag));
424418 return getFlag(InDocumentFlag);
425419 }
426420

@@protected:
740734
741735 void setHasCustomCallbacks() { setFlag(true, HasCustomCallbacksFlag); }
742736
 737 void setOrphanTreeScope();
743738private:
 739
744740 friend class TreeShared<Node, ContainerNode>;
745741
746742 void removedLastRef();
747743
748744 // These API should be only used for a tree scope migration.
749  // setTreeScope() returns NodeRareData to save extra nodeRareData() invocations on the caller site.
750  NodeRareData* setTreeScope(TreeScope*);
751745 void setDocument(Document*);
 746 void setTreeScope(TreeScope* scope) { m_treeScope = scope; }
752747
753748 enum EditableLevel { Editable, RichlyEditable };
754749 bool rendererIsEditable(EditableLevel) const;

@@private:
792787#endif
793788
794789 mutable uint32_t m_nodeFlags;
795  Document* m_document;
 790 TreeScope* m_treeScope;
796791 Node* m_previous;
797792 Node* m_next;
798793 RenderObject* m_renderer;

Source/WebCore/dom/NodeRareData.h

@@namespace WebCore {
4646
4747class LabelsNodeList;
4848class RadioNodeList;
49 class TreeScope;
5049
5150struct NodeListsNodeData {
5251 WTF_MAKE_NONCOPYABLE(NodeListsNodeData); WTF_MAKE_FAST_ALLOCATED;

@@class NodeRareData {
9493 WTF_MAKE_NONCOPYABLE(NodeRareData); WTF_MAKE_FAST_ALLOCATED;
9594public:
9695 NodeRareData()
97  : m_treeScope(0)
98  , m_childNodeList(0)
 96 : m_childNodeList(0)
9997 , m_tabIndex(0)
10098 , m_tabIndexWasSetExplicitly(false)
10199 , m_isFocused(false)

@@public:
123121 return rareDataMap().get(node);
124122 }
125123
126  TreeScope* treeScope() const { return m_treeScope; }
127  void setTreeScope(TreeScope* treeScope) { m_treeScope = treeScope; }
128 
129124 void clearNodeLists() { m_nodeLists.clear(); }
130125 void setNodeLists(PassOwnPtr<NodeListsNodeData> lists) { m_nodeLists = lists; }
131126 NodeListsNodeData* nodeLists() const { return m_nodeLists.get(); }

@@protected:
264259private:
265260 void createNodeLists(Node*);
266261
267  TreeScope* m_treeScope;
268262 OwnPtr<NodeListsNodeData> m_nodeLists;
269263 ChildNodeList* m_childNodeList;
270264 OwnPtr<EventTargetData> m_eventTargetData;

Source/WebCore/dom/ShadowRoot.cpp

4545namespace WebCore {
4646
4747ShadowRoot::ShadowRoot(Document* document)
48  : DocumentFragment(document, CreateShadowRoot)
49  , TreeScope(this)
 48 : DocumentFragment(0, CreateShadowRoot)
 49 , TreeScope(this, document)
5050 , m_prev(0)
5151 , m_next(0)
5252 , m_applyAuthorStyles(false)

@@ShadowRoot::ShadowRoot(Document* document)
5757
5858 // Assume document as parent scope.
5959 setParentTreeScope(document);
60  // Shadow tree scopes have the scope pointer point to themselves.
61  // This way, direct children will receive the correct scope pointer.
62  ensureRareData()->setTreeScope(this);
 60 rootDocument()->guardRef();
6361}
6462
6563ShadowRoot::~ShadowRoot()

@@ShadowRoot::~ShadowRoot()
7169 // as well as Node. See a comment on TreeScope.h for the reason.
7270 if (hasRareData())
7371 clearRareData();
 72 rootDocument()->guardDeref();
7473}
7574
7675static bool allowsAuthorShadowRoot(Element* element)

Source/WebCore/dom/TreeScope.cpp

@@namespace WebCore {
4949
5050using namespace HTMLNames;
5151
52 TreeScope::TreeScope(ContainerNode* rootNode)
 52TreeScope::TreeScope(ContainerNode* rootNode, Document* document)
5353 : m_rootNode(rootNode)
54  , m_parentTreeScope(0)
 54 , m_parentTreeScope(rootNode == document ? 0 : document)
 55 , m_rootDocument(document)
5556 , m_numNodeListCaches(0)
5657{
5758 ASSERT(rootNode);
 59 // TreeScope-mixed objects need to control guard-ref count by
 60 // itself instead of delegating it to Node constructor/destructor
 61 // because the TreeScope object, which holds the Document reference,
 62 // is not available at that timing.
 63 ASSERT(!rootNode->treeScope());
 64 rootNode->setTreeScope(this);
 65}
 66
 67TreeScope::TreeScope()
 68 : m_rootNode(0)
 69 , m_parentTreeScope(0)
 70 , m_rootDocument(0)
 71 , m_numNodeListCaches(0)
 72{
5873}
5974
6075TreeScope::~TreeScope()
6176{
 77 ASSERT(m_rootNode || this == orphanInstance());
 78 if (m_rootNode) {
 79 ASSERT(m_rootNode->treeScope() == this);
 80 m_rootNode->setTreeScope(0);
 81 }
 82
6283 if (m_selection) {
6384 m_selection->clearTreeScope();
6485 m_selection = 0;

@@void TreeScope::destroyTreeScopeData()
7495void TreeScope::setParentTreeScope(TreeScope* newParentScope)
7596{
7697 // A document node cannot be re-parented.
77  ASSERT(!rootNode()->isDocumentNode());
 98 ASSERT(!isDocumentScope() && !isOrphan());
7899 // Every scope other than document needs a parent scope.
79100 ASSERT(newParentScope);
80101
81102 m_parentTreeScope = newParentScope;
 103 m_rootDocument = newParentScope->rootDocument();
82104}
83105
84106Element* TreeScope::getElementById(const AtomicString& elementId) const

@@HTMLMapElement* TreeScope::getImageMap(const String& url) const
133155 return 0;
134156 size_t hashPos = url.find('#');
135157 String name = (hashPos == notFound ? url : url.substring(hashPos + 1)).impl();
136  if (rootNode()->document()->isHTMLDocument())
 158 if (rootDocument()->isHTMLDocument())
137159 return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByLowercasedMapName(AtomicString(name.lower()).impl(), this));
138160 return static_cast<HTMLMapElement*>(m_imageMapsByName.getElementByMapName(AtomicString(name).impl(), this));
139161}

@@Element* TreeScope::findAnchor(const String& name)
172194 for (Node* node = rootNode(); node; node = node->traverseNextNode()) {
173195 if (node->hasTagName(aTag)) {
174196 HTMLAnchorElement* anchor = static_cast<HTMLAnchorElement*>(node);
175  if (rootNode()->document()->inQuirksMode()) {
 197 if (rootDocument()->inQuirksMode()) {
176198 // Quirks mode, case insensitive comparison of names.
177199 if (equalIgnoringCase(anchor->name(), name))
178200 return anchor;

@@void TreeScope::adoptIfNeeded(Node* node)
202224 ASSERT(node);
203225 ASSERT(!node->isDocumentNode());
204226 ASSERT(!node->m_deletionHasBegun);
 227 ASSERT(!isOrphan());
205228 TreeScopeAdopter adopter(node, this);
206229 if (adopter.needsScopeChange())
207230 adopter.execute();

@@static Node* focusedFrameOwnerElement(Frame* focusedFrame, Frame* currentFrame)
218241
219242Node* TreeScope::focusedNode()
220243{
 244 ASSERT(!isOrphan());
 245
221246 Document* document = rootNode()->document();
222247 Node* node = document->focusedNode();
223248 if (!node && document->page())

@@TreeScope* commonTreeScope(Node* nodeA, Node* nodeB)
270295 return treeScopesA[indexA] == treeScopesB[indexB] ? treeScopesA[indexA] : 0;
271296}
272297
 298TreeScope* TreeScope::orphanInstance()
 299{
 300 DEFINE_STATIC_LOCAL(TreeScope, instance, ());
 301 return &instance;
 302}
 303
273304} // namespace WebCore
274305

Source/WebCore/dom/TreeScope.h

@@namespace WebCore {
3434
3535class ContainerNode;
3636class DOMSelection;
 37class Document;
3738class Element;
3839class HTMLMapElement;
3940class Node;

@@class TreeScope {
4546 friend class Document;
4647
4748public:
 49 static TreeScope* orphanInstance();
 50
4851 TreeScope* parentTreeScope() const { return m_parentTreeScope; }
4952 void setParentTreeScope(TreeScope*);
 53 Document* rootDocument() const { return m_rootDocument; }
 54 ContainerNode* rootNode() const { return m_rootNode; }
 55 bool isDocumentScope() const;
5056
5157 Node* focusedNode();
5258 Element* getElementById(const AtomicString&) const;

@@public:
8086 // Used by the basic DOM mutation methods (e.g., appendChild()).
8187 void adoptIfNeeded(Node*);
8288
83  ContainerNode* rootNode() const { return m_rootNode; }
84 
8589protected:
86  TreeScope(ContainerNode*);
 90 TreeScope(ContainerNode*, Document*);
8791 virtual ~TreeScope();
8892
8993 void destroyTreeScopeData();
 94 bool isOrphan() const { return this == orphanInstance(); }
9095
9196private:
 97 TreeScope();
 98
9299 ContainerNode* m_rootNode;
93100 TreeScope* m_parentTreeScope;
 101 // m_rootDocument is a cache and should be synced with m_parentTreeScope->rootDocument()
 102 // except m_parentTreeScope is null, which means this is a root scope.
 103 Document* m_rootDocument;
94104
95105 DocumentOrderedMap m_elementsById;
96106 DocumentOrderedMap m_imageMapsByName;

@@inline bool TreeScope::containsMultipleElementsWithId(const AtomicString& id) co
113123
114124TreeScope* commonTreeScope(Node*, Node*);
115125
 126inline bool TreeScope::isDocumentScope() const
 127{
 128 return !m_parentTreeScope;
 129}
 130
116131} // namespace WebCore
117132
118133#endif // TreeScope_h

Source/WebCore/dom/TreeScopeAdopter.cpp

@@void TreeScopeAdopter::moveTreeToNewScope(Node* root) const
4545 // that element may contain stale data as changes made to it will have updated the DOMTreeVersion
4646 // of the document it was moved to. By increasing the DOMTreeVersion of the donating document here
4747 // we ensure that the collection cache will be invalidated as needed when the element is moved back.
48  Document* oldDocument = m_oldScope ? m_oldScope->rootNode()->document() : 0;
49  Document* newDocument = m_newScope->rootNode()->document();
 48 Document* oldDocument = m_oldScope->rootDocument();
 49 Document* newDocument = m_newScope->rootDocument();
5050 bool willMoveToNewDocument = oldDocument != newDocument;
5151 if (oldDocument && willMoveToNewDocument)
5252 oldDocument->incDOMTreeVersion();
5353
5454 for (Node* node = root; node; node = node->traverseNextNode(root)) {
55  NodeRareData* rareData = node->setTreeScope(newDocument == m_newScope ? 0 : m_newScope);
56  if (rareData && rareData->nodeLists()) {
57  rareData->nodeLists()->invalidateCaches();
58  if (m_oldScope)
59  m_oldScope->removeNodeListCache();
60  m_newScope->addNodeListCache();
61  }
62 
 55 node->setTreeScope(m_newScope);
 56 moveNodeListCaches(node);
6357 if (willMoveToNewDocument)
6458 moveNodeToNewDocument(node, oldDocument, newDocument);
6559

@@inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDoc
10094 if (oldDocument)
10195 oldDocument->moveNodeIteratorsToNewDocument(node, newDocument);
10296
103  node->setDocument(newDocument);
104 
10597#ifndef NDEBUG
10698 didMoveToNewDocumentWasCalled = false;
10799 oldDocumentDidMoveToNewDocumentWasCalledWith = oldDocument;

@@inline void TreeScopeAdopter::moveNodeToNewDocument(Node* node, Document* oldDoc
114106 oldDocument->guardDeref();
115107}
116108
 109inline void TreeScopeAdopter::moveNodeListCaches(Node* node) const
 110{
 111 if (!node->hasRareData())
 112 return;
 113 NodeRareData* rareData = node->rareData();
 114 if (!rareData->nodeLists())
 115 return;
 116 rareData->nodeLists()->invalidateCaches();
 117 m_oldScope->removeNodeListCache();
 118 m_newScope->addNodeListCache();
 119}
 120
117121}

Source/WebCore/dom/TreeScopeAdopter.h

@@public:
4444
4545private:
4646 void moveTreeToNewScope(Node*) const;
 47 void moveNodeListCaches(Node*) const;
4748 void moveTreeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
4849 void moveNodeToNewDocument(Node*, Document* oldDocument, Document* newDocument) const;
4950

Source/WebCore/editing/MoveSelectionCommand.cpp

2626#include "config.h"
2727#include "MoveSelectionCommand.h"
2828
 29#include "Document.h"
2930#include "DocumentFragment.h"
3031#include "ReplaceSelectionCommand.h"
3132

Source/WebCore/editing/RemoveNodeCommand.cpp

2626#include "config.h"
2727#include "RemoveNodeCommand.h"
2828
 29#include "Document.h"
2930#include "Node.h"
3031#include <wtf/Assertions.h>
3132

Source/WebCore/editing/RemoveNodePreservingChildrenCommand.cpp

2626#include "config.h"
2727#include "RemoveNodePreservingChildrenCommand.h"
2828
 29#include "Document.h"
2930#include "Node.h"
3031#include <wtf/Assertions.h>
3132