Bug 1351535 - Part 7: Add EffectCompositor method to pre-traverse within a specific subtree. r=hiro
☠☠ backed out by 9350287c5078 ☠ ☠
authorCameron McCormack <cam@mcc.id.au>
Tue, 04 Apr 2017 19:12:54 +0800
changeset 351944 c1be168c4c6341d51497de57eda9c8086e576624
parent 351943 b1a425c54b7905e8758e32b73ff62e2d017e44c5
child 351945 bff89114412cf482997864451b08b744e0647be6
push id40349
push usercmccormack@mozilla.com
push dateSat, 08 Apr 2017 14:47:16 +0000
treeherderautoland@0410ff898157 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1351535
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1351535 - Part 7: Add EffectCompositor method to pre-traverse within a specific subtree. r=hiro It's not great that we traverse up the tree looking for the subtree root for each animating element that is in mElementsToRestyle. An alternative could be to traverse the entire subtree and build a hash set of the elements within it, so that each test in the mElementsToRestyle loop can be done quickly. I suspect that most of the time looking up the tree for each animation will be quicker, but it does have worse worst case behavior. MozReview-Commit-ID: FWoQ7fD9YZC
dom/animation/EffectCompositor.cpp
dom/animation/EffectCompositor.h
--- a/dom/animation/EffectCompositor.cpp
+++ b/dom/animation/EffectCompositor.cpp
@@ -958,30 +958,56 @@ EffectCompositor::SetPerformanceWarning(
   for (KeyframeEffectReadOnly* effect : *effects) {
     effect->SetPerformanceWarning(aProperty, aWarning);
   }
 }
 
 bool
 EffectCompositor::PreTraverse()
 {
+  return PreTraverseInSubtree(nullptr);
+}
+
+static bool
+IsFlattenedTreeDescendantOf(nsINode* aPossibleDescendant,
+                            nsINode* aPossibleAncestor)
+{
+  do {
+    if (aPossibleDescendant == aPossibleAncestor) {
+      return true;
+    }
+    aPossibleDescendant = aPossibleDescendant->GetFlattenedTreeParentNode();
+  } while (aPossibleDescendant);
+
+  return false;
+}
+
+bool
+EffectCompositor::PreTraverseInSubtree(Element* aRoot)
+{
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPresContext->RestyleManager()->IsServo());
 
   bool foundElementsNeedingRestyle = false;
   for (auto& elementsToRestyle : mElementsToRestyle) {
     for (auto iter = elementsToRestyle.Iter(); !iter.Done(); iter.Next()) {
       bool postedRestyle = iter.Data();
       // Ignore throttled restyle.
       if (!postedRestyle) {
         continue;
       }
 
       NonOwningAnimationTarget target = iter.Key();
 
+      // Ignore restyles that aren't in the flattened tree subtree rooted at
+      // aRoot.
+      if (aRoot && !IsFlattenedTreeDescendantOf(target.mElement, aRoot)) {
+        continue;
+      }
+
       // We need to post restyle hints even if the target is not in EffectSet to
       // ensure the final restyling for removed animations.
       // We can't call PostRestyleEvent directly here since we are still in the
       // middle of the servo traversal.
       mPresContext->RestyleManager()->AsServo()->
         PostRestyleEventForAnimations(target.mElement, eRestyle_CSSAnimations);
 
       foundElementsNeedingRestyle = true;
--- a/dom/animation/EffectCompositor.h
+++ b/dom/animation/EffectCompositor.h
@@ -244,16 +244,20 @@ public:
   // traversal (e.g. changing member variables) for all elements that we expect
   // to restyle on the next traversal.
   // Returns true if there are elements needing a restyle for animation.
   bool PreTraverse();
 
   // Similar to the above but only for the (pseudo-)element.
   bool PreTraverse(dom::Element* aElement, nsIAtom* aPseudoTagOrNull);
 
+  // Similar to the above but for all elements in the subtree rooted
+  // at aElement.
+  bool PreTraverseInSubtree(dom::Element* aElement);
+
 private:
   ~EffectCompositor() = default;
 
   // Rebuilds the animation rule corresponding to |aCascadeLevel| on the
   // EffectSet associated with the specified (pseudo-)element.
   static void ComposeAnimationRule(dom::Element* aElement,
                                    CSSPseudoElementType aPseudoType,
                                    CascadeLevel aCascadeLevel);