Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: Source/core/dom/ContainerNode.h

Issue 15871005: Avoid N^2 walk placing renderers when building the render tree (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Adding a mitigation for the perf regression to Element::recalcStyle. Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « Source/core/css/resolver/StyleResolverState.cpp ('k') | Source/core/dom/ContainerNode.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) 3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2001 Dirk Mueller (mueller@kde.org) 4 * (C) 2001 Dirk Mueller (mueller@kde.org)
5 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved. 5 * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 Apple Inc. All rights reserved.
6 * 6 *
7 * This library is free software; you can redistribute it and/or 7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public 8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version. 10 * version 2 of the License, or (at your option) any later version.
(...skipping 18 matching lines...) Expand all
29 29
30 #include <wtf/OwnPtr.h> 30 #include <wtf/OwnPtr.h>
31 #include <wtf/Vector.h> 31 #include <wtf/Vector.h>
32 32
33 namespace WebCore { 33 namespace WebCore {
34 34
35 class FloatPoint; 35 class FloatPoint;
36 class HTMLCollection; 36 class HTMLCollection;
37 37
38 typedef void (*NodeCallback)(Node*); 38 typedef void (*NodeCallback)(Node*);
39 typedef void (*ElementCallback)(Element*);
39 40
40 namespace Private { 41 namespace Private {
41 template<class GenericNode, class GenericNodeContainer> 42 template<class GenericNode, class GenericNodeContainer>
42 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge nericNodeContainer*); 43 void addChildNodesToDeletionQueue(GenericNode*& head, GenericNode*& tail, Ge nericNodeContainer*);
43 }; 44 };
44 45
45 class NoEventDispatchAssertion { 46 class NoEventDispatchAssertion {
46 public: 47 public:
47 NoEventDispatchAssertion() 48 NoEventDispatchAssertion()
48 { 49 {
(...skipping 24 matching lines...) Expand all
73 #endif 74 #endif
74 75
75 private: 76 private:
76 #ifndef NDEBUG 77 #ifndef NDEBUG
77 static unsigned s_count; 78 static unsigned s_count;
78 #endif 79 #endif
79 }; 80 };
80 81
81 class ContainerNode : public Node { 82 class ContainerNode : public Node {
82 friend class PostAttachCallbackDisabler; 83 friend class PostAttachCallbackDisabler;
84 friend class InsertionCallbackDeferer;
83 public: 85 public:
84 virtual ~ContainerNode(); 86 virtual ~ContainerNode();
85 87
86 Node* firstChild() const { return m_firstChild; } 88 Node* firstChild() const { return m_firstChild; }
87 Node* lastChild() const { return m_lastChild; } 89 Node* lastChild() const { return m_lastChild; }
88 bool hasChildNodes() const { return m_firstChild; } 90 bool hasChildNodes() const { return m_firstChild; }
89 91
90 // ParentNode interface API 92 // ParentNode interface API
91 PassRefPtr<HTMLCollection> children(); 93 PassRefPtr<HTMLCollection> children();
92 Element* firstElementChild() const; 94 Element* firstElementChild() const;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 // Notifies the node that it's list of children have changed (either by addi ng or removing child nodes), or a child 128 // Notifies the node that it's list of children have changed (either by addi ng or removing child nodes), or a child
127 // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE ha s changed its value. 129 // node that is of the type CDATA_SECTION_NODE, TEXT_NODE or COMMENT_NODE ha s changed its value.
128 virtual void childrenChanged(bool createdByParser = false, Node* beforeChang e = 0, Node* afterChange = 0, int childCountDelta = 0); 130 virtual void childrenChanged(bool createdByParser = false, Node* beforeChang e = 0, Node* afterChange = 0, int childCountDelta = 0);
129 131
130 void disconnectDescendantFrames(); 132 void disconnectDescendantFrames();
131 133
132 virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const { return true; } 134 virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const { return true; }
133 135
134 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE; 136 virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
135 137
138 static void queueInsertionCallback(ElementCallback, Element*);
136 protected: 139 protected:
137 ContainerNode(TreeScope*, ConstructionType = CreateContainer); 140 ContainerNode(TreeScope*, ConstructionType = CreateContainer);
138 141
142 static bool insertionCallbacksAreSuspended();
139 static void queuePostAttachCallback(NodeCallback, Node*); 143 static void queuePostAttachCallback(NodeCallback, Node*);
140 static bool postAttachCallbacksAreSuspended(); 144 static bool postAttachCallbacksAreSuspended();
141 145
142 template<class GenericNode, class GenericNodeContainer> 146 template<class GenericNode, class GenericNodeContainer>
143 friend void appendChildToContainer(GenericNode* child, GenericNodeContainer* ); 147 friend void appendChildToContainer(GenericNode* child, GenericNodeContainer* );
144 148
145 template<class GenericNode, class GenericNodeContainer> 149 template<class GenericNode, class GenericNodeContainer>
146 friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, Generi cNode*& tail, GenericNodeContainer*); 150 friend void Private::addChildNodesToDeletionQueue(GenericNode*& head, Generi cNode*& tail, GenericNodeContainer*);
147 151
148 void removeDetachedChildren(); 152 void removeDetachedChildren();
149 void setFirstChild(Node* child) { m_firstChild = child; } 153 void setFirstChild(Node* child) { m_firstChild = child; }
150 void setLastChild(Node* child) { m_lastChild = child; } 154 void setLastChild(Node* child) { m_lastChild = child; }
151 155
152 private: 156 private:
153 void removeBetween(Node* previousChild, Node* nextChild, Node* oldChild); 157 void removeBetween(Node* previousChild, Node* nextChild, Node* oldChild);
154 void insertBeforeCommon(Node* nextChild, Node* oldChild); 158 void insertBeforeCommon(Node* nextChild, Node* oldChild);
155 159
156 void attachChildren(const AttachContext& = AttachContext()); 160 void attachChildren(const AttachContext& = AttachContext());
157 void detachChildren(const AttachContext& = AttachContext()); 161 void detachChildren(const AttachContext& = AttachContext());
158 162
159 static void dispatchPostAttachCallbacks(); 163 static void dispatchPostAttachCallbacks();
160 164
161 void suspendPostAttachCallbacks(); 165 void suspendPostAttachCallbacks();
162 void resumePostAttachCallbacks(); 166 void resumePostAttachCallbacks();
163 167
168 static void dispatchInsertionCallbacks();
169
170 static void suspendInsertionCallbacks();
171 static void resumeInsertionCallbacks();
172
164 bool getUpperLeftCorner(FloatPoint&) const; 173 bool getUpperLeftCorner(FloatPoint&) const;
165 bool getLowerRightCorner(FloatPoint&) const; 174 bool getLowerRightCorner(FloatPoint&) const;
166 175
167 Node* m_firstChild; 176 Node* m_firstChild;
168 Node* m_lastChild; 177 Node* m_lastChild;
169 }; 178 };
170 179
171 #ifndef NDEBUG 180 #ifndef NDEBUG
172 bool childAttachedAllowedWhenAttachingChildren(ContainerNode*); 181 bool childAttachedAllowedWhenAttachingChildren(ContainerNode*);
173 #endif 182 #endif
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 ASSERT(!nodes.size()); 272 ASSERT(!nodes.size());
264 for (Node* child = node->firstChild(); child; child = child->nextSibling()) 273 for (Node* child = node->firstChild(); child; child = child->nextSibling())
265 nodes.append(child); 274 nodes.append(child);
266 } 275 }
267 276
268 class ChildNodesLazySnapshot { 277 class ChildNodesLazySnapshot {
269 WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot); 278 WTF_MAKE_NONCOPYABLE(ChildNodesLazySnapshot);
270 WTF_MAKE_FAST_ALLOCATED; 279 WTF_MAKE_FAST_ALLOCATED;
271 public: 280 public:
272 explicit ChildNodesLazySnapshot(Node* parentNode) 281 explicit ChildNodesLazySnapshot(Node* parentNode)
273 : m_currentNode(parentNode->firstChild()) 282 : m_currentNode(parentNode->lastChild())
274 , m_currentIndex(0) 283 , m_currentIndex(0)
275 { 284 {
276 m_nextSnapshot = latestSnapshot; 285 m_nextSnapshot = latestSnapshot;
277 latestSnapshot = this; 286 latestSnapshot = this;
278 } 287 }
279 288
280 ~ChildNodesLazySnapshot() 289 ~ChildNodesLazySnapshot()
281 { 290 {
282 latestSnapshot = m_nextSnapshot; 291 latestSnapshot = m_nextSnapshot;
283 } 292 }
284 293
285 // Returns 0 if there is no next Node. 294 // Returns 0 if there is no previous Node.
286 PassRefPtr<Node> nextNode() 295 PassRefPtr<Node> previousNode()
287 { 296 {
288 if (LIKELY(!hasSnapshot())) { 297 if (LIKELY(!hasSnapshot())) {
289 RefPtr<Node> node = m_currentNode; 298 RefPtr<Node> node = m_currentNode;
290 if (node) 299 if (node)
291 m_currentNode = node->nextSibling(); 300 m_currentNode = node->previousSibling();
292 return node.release(); 301 return node.release();
293 } 302 }
294 Vector<RefPtr<Node> >& nodeVector = *m_childNodes; 303 Vector<RefPtr<Node> >& nodeVector = *m_childNodes;
295 if (m_currentIndex >= nodeVector.size()) 304 if (m_currentIndex >= nodeVector.size())
296 return 0; 305 return 0;
297 return nodeVector[m_currentIndex++]; 306 return nodeVector[m_currentIndex++];
298 } 307 }
299 308
300 void takeSnapshot() 309 void takeSnapshot()
301 { 310 {
302 if (hasSnapshot()) 311 if (hasSnapshot())
303 return; 312 return;
304 m_childNodes = adoptPtr(new Vector<RefPtr<Node> >()); 313 m_childNodes = adoptPtr(new Vector<RefPtr<Node> >());
305 Node* node = m_currentNode.get(); 314 Node* node = m_currentNode.get();
306 while (node) { 315 while (node) {
307 m_childNodes->append(node); 316 m_childNodes->append(node);
308 node = node->nextSibling(); 317 node = node->previousSibling();
309 } 318 }
310 } 319 }
311 320
312 ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; } 321 ChildNodesLazySnapshot* nextSnapshot() { return m_nextSnapshot; }
313 bool hasSnapshot() { return !!m_childNodes.get(); } 322 bool hasSnapshot() { return !!m_childNodes.get(); }
314 323
315 static void takeChildNodesLazySnapshot() 324 static void takeChildNodesLazySnapshot()
316 { 325 {
317 ChildNodesLazySnapshot* snapshot = latestSnapshot; 326 ChildNodesLazySnapshot* snapshot = latestSnapshot;
318 while (snapshot && !snapshot->hasSnapshot()) { 327 while (snapshot && !snapshot->hasSnapshot()) {
319 snapshot->takeSnapshot(); 328 snapshot->takeSnapshot();
320 snapshot = snapshot->nextSnapshot(); 329 snapshot = snapshot->nextSnapshot();
321 } 330 }
322 } 331 }
323 332
324 private: 333 private:
325 static ChildNodesLazySnapshot* latestSnapshot; 334 static ChildNodesLazySnapshot* latestSnapshot;
326 335
327 RefPtr<Node> m_currentNode; 336 RefPtr<Node> m_currentNode;
328 unsigned m_currentIndex; 337 unsigned m_currentIndex;
329 OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated. 338 OwnPtr<Vector<RefPtr<Node> > > m_childNodes; // Lazily instantiated.
330 ChildNodesLazySnapshot* m_nextSnapshot; 339 ChildNodesLazySnapshot* m_nextSnapshot;
331 }; 340 };
332 341
342 // Used to ensure Radio Buttons resolve their checked state in document
343 // order when a subtree of them is inserted. This is necessary because
344 // we resolve style in reverse document order.
345 class InsertionCallbackDeferer {
346 public:
347 InsertionCallbackDeferer()
348 {
349 ContainerNode::suspendInsertionCallbacks();
350 }
351
352 ~InsertionCallbackDeferer()
353 {
354 ContainerNode::resumeInsertionCallbacks();
355 }
356 };
357
333 class PostAttachCallbackDisabler { 358 class PostAttachCallbackDisabler {
334 public: 359 public:
335 PostAttachCallbackDisabler(ContainerNode* node) 360 PostAttachCallbackDisabler(ContainerNode* node)
336 : m_node(node) 361 : m_node(node)
337 { 362 {
338 ASSERT(m_node); 363 ASSERT(m_node);
339 m_node->suspendPostAttachCallbacks(); 364 m_node->suspendPostAttachCallbacks();
340 } 365 }
341 366
342 ~PostAttachCallbackDisabler() 367 ~PostAttachCallbackDisabler()
343 { 368 {
344 m_node->resumePostAttachCallbacks(); 369 m_node->resumePostAttachCallbacks();
345 } 370 }
346 371
347 private: 372 private:
348 ContainerNode* m_node; 373 ContainerNode* m_node;
349 }; 374 };
350 375
351 } // namespace WebCore 376 } // namespace WebCore
352 377
353 #endif // ContainerNode_h 378 #endif // ContainerNode_h
OLDNEW
« no previous file with comments | « Source/core/css/resolver/StyleResolverState.cpp ('k') | Source/core/dom/ContainerNode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698