Title: [143498] trunk/Source/WebCore
Revision
143498
Author
fmal...@chromium.org
Date
2013-02-20 13:43:29 -0800 (Wed, 20 Feb 2013)

Log Message

[SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
https://bugs.webkit.org/show_bug.cgi?id=97905

Reviewed by Dirk Schulze.

Rebuilding the shadow and instance trees of dependent use nodes recursively can be
extremely inefficient with non-trivial dependency graphs (the trees are not constructed
in topological order).

To avoid redundant buildShadowAndInstanceTree() invokations, separate the invalidation
phase from the actual tree (re)building phase, and only descend into the dependency DAG
during the invalidation phase (recursion also stops at nodes that have been previously
invalidated).

No new tests: functional coverage provided by existing tests, perfomance tracked by
PerformanceTests/SVG/SvgNestedUse.html.

* svg/SVGUseElement.cpp:
(WebCore::SVGUseElement::buildPendingResource):
(WebCore::SVGUseElement::buildShadowAndInstanceTree):
(WebCore::SVGUseElement::invalidateShadowTree):
(WebCore):
(WebCore::SVGUseElement::invalidateDependentShadowTrees):
* svg/SVGUseElement.h:
(SVGUseElement):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (143497 => 143498)


--- trunk/Source/WebCore/ChangeLog	2013-02-20 21:34:19 UTC (rev 143497)
+++ trunk/Source/WebCore/ChangeLog	2013-02-20 21:43:29 UTC (rev 143498)
@@ -1,3 +1,31 @@
+2013-02-20  Florin Malita  <fmal...@chromium.org>
+
+        [SVG] Update of element referenced by multiple 'use' nodes is absurdly slow
+        https://bugs.webkit.org/show_bug.cgi?id=97905
+
+        Reviewed by Dirk Schulze.
+
+        Rebuilding the shadow and instance trees of dependent use nodes recursively can be
+        extremely inefficient with non-trivial dependency graphs (the trees are not constructed
+        in topological order).
+
+        To avoid redundant buildShadowAndInstanceTree() invokations, separate the invalidation
+        phase from the actual tree (re)building phase, and only descend into the dependency DAG
+        during the invalidation phase (recursion also stops at nodes that have been previously
+        invalidated).
+
+        No new tests: functional coverage provided by existing tests, perfomance tracked by
+        PerformanceTests/SVG/SvgNestedUse.html.
+
+        * svg/SVGUseElement.cpp:
+        (WebCore::SVGUseElement::buildPendingResource):
+        (WebCore::SVGUseElement::buildShadowAndInstanceTree):
+        (WebCore::SVGUseElement::invalidateShadowTree):
+        (WebCore):
+        (WebCore::SVGUseElement::invalidateDependentShadowTrees):
+        * svg/SVGUseElement.h:
+        (SVGUseElement):
+
 2013-02-20  Tim Horton  <timothy_hor...@apple.com>
 
         RenderLayerBacking should initialize TiledBacking's isInWindow state with Page's isInWindow, not isOnscreen

Modified: trunk/Source/WebCore/svg/SVGUseElement.cpp (143497 => 143498)


--- trunk/Source/WebCore/svg/SVGUseElement.cpp	2013-02-20 21:34:19 UTC (rev 143497)
+++ trunk/Source/WebCore/svg/SVGUseElement.cpp	2013-02-20 21:43:29 UTC (rev 143498)
@@ -409,10 +409,10 @@
 
 void SVGUseElement::buildPendingResource()
 {
-    if (!referencedDocument())
+    if (!referencedDocument() || isInShadowTree())
         return;
     clearResourceReferences();
-    if (!inDocument() || isInShadowTree())
+    if (!inDocument())
         return;
 
     String id;
@@ -430,8 +430,11 @@
         return;
     }
 
-    if (target->isSVGElement())
+    if (target->isSVGElement()) {
         buildShadowAndInstanceTree(static_cast<SVGElement*>(target));
+        invalidateDependentShadowTrees();
+    }
+
     ASSERT(!m_needsShadowTreeRecreation);
 }
 
@@ -517,10 +520,6 @@
     // Update relative length information.
     updateRelativeLengthsInformation();
 
-    // Rebuild all dependent use elements.
-    ASSERT(document());
-    document()->accessSVGExtensions()->rebuildAllElementReferencesForTarget(this);
-
     // Eventually dump instance tree
 #ifdef DUMP_INSTANCE_TREE
     String text;
@@ -906,8 +905,22 @@
         return;
     m_needsShadowTreeRecreation = true;
     setNeedsStyleRecalc();
+    invalidateDependentShadowTrees();
 }
 
+void SVGUseElement::invalidateDependentShadowTrees()
+{
+    // Recursively invalidate dependent <use> shadow trees
+    const HashSet<SVGElementInstance*>& instances = instancesForElement();
+    const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
+    for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
+        if (SVGUseElement* element = (*it)->correspondingUseElement()) {
+            ASSERT(element->inDocument());
+            element->invalidateShadowTree();
+        }
+    }
+}
+
 void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
 {
     ASSERT(from);

Modified: trunk/Source/WebCore/svg/SVGUseElement.h (143497 => 143498)


--- trunk/Source/WebCore/svg/SVGUseElement.h	2013-02-20 21:34:19 UTC (rev 143497)
+++ trunk/Source/WebCore/svg/SVGUseElement.h	2013-02-20 21:43:29 UTC (rev 143498)
@@ -50,6 +50,7 @@
     SVGElementInstance* animatedInstanceRoot() const;
     SVGElementInstance* instanceForShadowTreeElement(Node*) const;
     void invalidateShadowTree();
+    void invalidateDependentShadowTrees();
 
     RenderObject* rendererClipChild() const;
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to