Source/WebCore/ChangeLog

 12012-11-01 Elliott Sprehn <esprehn@chromium.org>
 2
 3 Replace NodeRareData hash map with a union on m_renderer
 4 https://bugs.webkit.org/show_bug.cgi?id=100057
 5
 6 Reviewed by Eric Seidel.
 7
 8 Use a union on Node::m_renderer between NodeRareData* and RenderObject*. This removes
 9 the overhead of accessing rare data and the memory from the map. We now get the 5%
 10 performance increase observed in Bug 90059 but when accessing node lists on any node.
 11
 12 By removing the overhead of rareData() this patch addresses the performance issues
 13 raised in Bugs 73853, 87034 and 89635.
 14
 15 This is also a 15% improvement on Parser/textarea-parsing.html
 16
 17 I ran Parser/html5-full-render.html and there was no performance regression after
 18 tuning Text::recalcTextStyle and the refactor that was done in r132684.
 19
 20 No new tests, this is just a refactor.
 21
 22 * dom/Document.cpp:
 23 (WebCore::Document::Document):
 24 * dom/Document.h:
 25 (WebCore::Node::Node):
 26 * dom/Element.cpp:
 27 (WebCore::Element::elementRareData):
 28 * dom/Node.cpp:
 29 (WebCore::Node::rareData):
 30 (WebCore::Node::ensureRareData):
 31 (WebCore::Node::clearRareData):
 32 (WebCore::Node::renderBox):
 33 (WebCore::Node::renderBoxModelObject):
 34 (WebCore::Node::reportMemoryUsage):
 35 * dom/Node.h:
 36 (NodeRareDataBase):
 37 Base class for NodeRareData that knows about the renderer so we can
 38 inline the accesses in Node.h
 39 (WebCore::NodeRareDataBase::renderer):
 40 (WebCore::NodeRareDataBase::setRenderer):
 41 (WebCore::NodeRareDataBase::~NodeRareDataBase):
 42 (WebCore::NodeRareDataBase::NodeRareDataBase):
 43 (WebCore):
 44 (WebCore::Node::renderer):
 45 (WebCore::Node::setRenderer):
 46 (Node):
 47 * dom/NodeRareData.h:
 48 * dom/NodeRenderStyle.h:
 49 (WebCore::Node::renderStyle):
 50 * dom/Text.cpp:
 51 (WebCore::Text::recalcTextStyle):
 52 This method appears very hot in html5-full-render.html and accessing the
 53 renderer 4 times caused a 2% performance regression with this patch. I
 54 reduced it to 1 access and there's no longer any performance regression.
 55
1562012-11-01 Alexandru Chiculita <achicu@adobe.com>
257
358 [CSS Shaders] Move MeshBoxType out of CustomFilterOperation

Source/WebCore/dom/Document.cpp

@@Document::Document(Frame* frame, const KURL& url, bool isXHTML, bool isHTML)
479479 , m_isViewSource(false)
480480 , m_sawElementsInKnownNamespaces(false)
481481 , m_isSrcdocDocument(false)
482  , m_documentRareData(0)
483482 , m_eventQueue(DocumentEventQueue::create(this))
484483 , m_weakReference(DocumentWeakReference::create(this))
485484 , m_idAttributeName(idAttr)

@@void Document::pageSizeAndMarginsInPixels(int pageIndex, IntSize& pageSize, int&
20302029 marginLeft = style->marginLeft().isAuto() ? marginLeft : intValueForLength(style->marginLeft(), width, view);
20312030}
20322031
2033 void Document::setDocumentRareData(NodeRareData* rareData)
2034 {
2035  m_documentRareData = rareData;
2036 }
2037 
20382032void Document::setIsViewSource(bool isViewSource)
20392033{
20402034 m_isViewSource = isViewSource;

Source/WebCore/dom/Document.h

@@class MouseEventWithHitTestResults;
116116class NamedFlowCollection;
117117class NodeFilter;
118118class NodeIterator;
119 class NodeRareData;
120119class Page;
121120class PlatformMouseEvent;
122121class ProcessingInstruction;

@@public:
467466
468467 bool isSrcdocDocument() const { return m_isSrcdocDocument; }
469468
470  NodeRareData* documentRareData() const { return m_documentRareData; };
471  void setDocumentRareData(NodeRareData*);
472 
473469 StyleResolver* styleResolverIfExists() const { return m_styleResolver.get(); }
474470
475471 bool isViewSource() const { return m_isViewSource; }

@@private:
14341430 bool m_sawElementsInKnownNamespaces;
14351431 bool m_isSrcdocDocument;
14361432
1437  NodeRareData* m_documentRareData;
1438 
14391433 RefPtr<DocumentEventQueue> m_eventQueue;
14401434
14411435 RefPtr<DocumentWeakReference> m_weakReference;

@@inline Node::Node(Document* document, ConstructionType type)
15351529 , m_document(document)
15361530 , m_previous(0)
15371531 , m_next(0)
1538  , m_renderer(0)
15391532{
15401533 if (document)
15411534 document->guardRef();

Source/WebCore/dom/Element.cpp

@@Element::~Element()
154154inline ElementRareData* Element::elementRareData() const
155155{
156156 ASSERT(hasRareData());
157  return static_cast<ElementRareData*>(NodeRareData::rareDataFromMap(this));
 157 return static_cast<ElementRareData*>(rareData());
158158}
159 
 159
160160inline ElementRareData* Element::ensureElementRareData()
161161{
162162 return static_cast<ElementRareData*>(ensureRareData());

Source/WebCore/dom/Node.cpp

@@TreeScope* Node::treeScope() const
470470NodeRareData* Node::rareData() const
471471{
472472 ASSERT(hasRareData());
473  NodeRareData* data = isDocumentNode() ? static_cast<const Document*>(this)->documentRareData() : NodeRareData::rareDataFromMap(this);
474  ASSERT(data);
475  return data;
 473 return static_cast<NodeRareData*>(m_data.m_rareData);
476474}
477475
478476NodeRareData* Node::ensureRareData()

@@NodeRareData* Node::ensureRareData()
481479 return rareData();
482480
483481 NodeRareData* data = createRareData().leakPtr();
484  if (isDocumentNode()) {
485  // Fast path for a Document. A Document knows a pointer to NodeRareData.
486  ASSERT(!static_cast<Document*>(this)->documentRareData());
487  static_cast<Document*>(this)->setDocumentRareData(data);
488  } else {
489  ASSERT(!NodeRareData::rareDataMap().contains(this));
490  NodeRareData::rareDataMap().set(this, data);
491  }
 482 ASSERT(data);
 483 data->setRenderer(m_data.m_renderer);
 484 m_data.m_rareData = data;
492485 setFlag(HasRareDataFlag);
493486 return data;
494487}
495 
 488
496489OwnPtr<NodeRareData> Node::createRareData()
497490{
498491 return adoptPtr(new NodeRareData);

@@void Node::clearRareData()
506499 ASSERT(!transientMutationObserverRegistry() || transientMutationObserverRegistry()->isEmpty());
507500#endif
508501
509  if (isDocumentNode()) {
510  Document* document = static_cast<Document*>(this);
511  NodeRareData* data = document->documentRareData();
512  ASSERT(data);
513  delete data;
514  document->setDocumentRareData(0);
515  } else {
516  NodeRareData::NodeRareDataMap& dataMap = NodeRareData::rareDataMap();
517  NodeRareData::NodeRareDataMap::iterator it = dataMap.find(this);
518  ASSERT(it != dataMap.end());
519  delete it->value;
520  dataMap.remove(it);
521  }
 502 RenderObject* renderer = m_data.m_rareData->renderer();
 503 delete m_data.m_rareData;
 504 m_data.m_renderer = renderer;
522505 clearFlag(HasRareDataFlag);
523506}
524507

@@bool Node::shouldUseInputMethod()
796779
797780RenderBox* Node::renderBox() const
798781{
799  return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0;
 782 RenderObject* renderer = this->renderer();
 783 return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
800784}
801785
802786RenderBoxModelObject* Node::renderBoxModelObject() const
803787{
804  return m_renderer && m_renderer->isBoxModelObject() ? toRenderBoxModelObject(m_renderer) : 0;
 788 RenderObject* renderer = this->renderer();
 789 return renderer && renderer->isBoxModelObject() ? toRenderBoxModelObject(renderer) : 0;
805790}
806791
807792LayoutRect Node::boundingBox() const

@@void Node::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
28282813 info.addMember(m_document);
28292814 info.addMember(m_next);
28302815 info.addMember(m_previous);
2831  if (m_renderer)
2832  info.addMember(m_renderer->style());
 2816 if (RenderObject* renderer = this->renderer())
 2817 info.addMember(renderer->style());
28332818}
28342819
28352820void Node::textRects(Vector<IntRect>& rects) const

Source/WebCore/dom/Node.h

@@enum StyleChangeType {
111111 SyntheticStyleChange = 3 << nodeStyleChangeShift
112112};
113113
 114class NodeRareDataBase {
 115public:
 116 RenderObject* renderer() const { return m_renderer; }
 117 void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
 118 virtual ~NodeRareDataBase() { }
 119protected:
 120 NodeRareDataBase() { }
 121private:
 122 RenderObject* m_renderer;
 123};
 124
114125class Node : public EventTarget, public ScriptWrappable, public TreeShared<Node, ContainerNode> {
115126 friend class Document;
116127 friend class TreeScope;

@@public:
503514 // -----------------------------------------------------------------------------
504515 // Integration with rendering tree
505516
506  RenderObject* renderer() const { return m_renderer; }
507  void setRenderer(RenderObject* renderer) { m_renderer = renderer; }
508 
 517 // As renderer() includes a branch you should avoid calling it repeatedly in hot code paths.
 518 RenderObject* renderer() const { return hasRareData() ? m_data.m_rareData->renderer() : m_data.m_renderer; };
 519 void setRenderer(RenderObject* renderer)
 520 {
 521 if (hasRareData())
 522 m_data.m_rareData->setRenderer(renderer);
 523 else
 524 m_data.m_renderer = renderer;
 525 }
 526
509527 // Use these two methods with caution.
510528 RenderBox* renderBox() const;
511529 RenderBoxModelObject* renderBoxModelObject() const;

@@private:
815833 Document* m_document;
816834 Node* m_previous;
817835 Node* m_next;
818  RenderObject* m_renderer;
 836 // When a node has rare data we move the renderer into the rare data.
 837 union DataUnion {
 838 DataUnion() : m_renderer(0) { }
 839 RenderObject* m_renderer;
 840 NodeRareDataBase* m_rareData;
 841 } m_data;
819842
820843public:
821844 bool isStyleAttributeValid() const { return getFlag(IsStyleAttributeValidFlag); }

Source/WebCore/dom/NodeRareData.h

@@private:
176176 TagNodeListCacheNS m_tagNodeListCacheNS;
177177};
178178
179 class NodeRareData {
 179class NodeRareData : public NodeRareDataBase {
180180 WTF_MAKE_NONCOPYABLE(NodeRareData); WTF_MAKE_FAST_ALLOCATED;
181181public:
182182 NodeRareData()

@@public:
198198 {
199199 }
200200
201  typedef HashMap<const Node*, NodeRareData*> NodeRareDataMap;
202 
203  static NodeRareDataMap& rareDataMap()
204  {
205  static NodeRareDataMap* dataMap = new NodeRareDataMap;
206  return *dataMap;
207  }
208 
209  static NodeRareData* rareDataFromMap(const Node* node)
210  {
211  return rareDataMap().get(node);
212  }
213 
214201 TreeScope* treeScope() const { return m_treeScope; }
215202 void setTreeScope(TreeScope* treeScope) { m_treeScope = treeScope; }
216203

Source/WebCore/dom/NodeRenderStyle.h

@@inline RenderStyle* Node::renderStyle() const
3535{
3636 // Using a ternary here confuses the Solaris Studio 12/12.1/12.2 compilers:
3737 // Bug is CR 6569194, "Problem with question operator binding in inline function"
38  if (m_renderer)
39  return m_renderer->style();
 38 if (RenderObject* renderer = this->renderer())
 39 return renderer->style();
4040 return nonRendererStyle();
4141}
4242

Source/WebCore/dom/Text.cpp

@@void Text::recalcTextStyle(StyleChange change)
256256 if (hasCustomCallbacks())
257257 willRecalcTextStyle(change);
258258
259  if (change != NoChange && parentNode() && parentNode()->renderer()) {
260  if (renderer())
261  renderer()->setStyle(parentNode()->renderer()->style());
262  }
 259 RenderObject* renderer = this->renderer();
 260
 261 // The only time we have a renderer and our parent doesn't is if our parent
 262 // is a shadow root.
 263 if (change != NoChange && renderer && !parentNode()->isShadowRoot())
 264 renderer->setStyle(parentNode()->renderer()->style());
 265
263266 if (needsStyleRecalc()) {
264  if (renderer()) {
265  if (renderer()->isText())
266  toRenderText(renderer())->setText(dataImpl());
 267 if (renderer) {
 268 if (renderer->isText())
 269 toRenderText(renderer)->setText(dataImpl());
267270 } else
268271 reattach();
269272 }