Bug 1395351: Use the parallel traversal flag more often. r?bholley draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Fri, 01 Sep 2017 19:28:57 +0200
changeset 657643 99058669514143979dc0e200a1b6226320582395
parent 657642 6535d852a23138393a4b6203001fd5abb948e407
child 657644 88d886eb0e661daa941434ff5e872e59d4b6ed75
push id77581
push userbmo:emilio@crisal.io
push dateFri, 01 Sep 2017 18:40:22 +0000
reviewersbholley
bugs1395351
milestone57.0a1
Bug 1395351: Use the parallel traversal flag more often. r?bholley MozReview-Commit-ID: JF6i0HDniR2
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -869,92 +869,88 @@ ServoStyleSet::HasStateDependentStyle(do
                                       dom::Element* aPseudoElement,
                                       EventStates aStateMask)
 {
   NS_WARNING("stylo: HasStateDependentStyle always returns zero!");
   return nsRestyleHint(0);
 }
 
 bool
-ServoStyleSet::StyleDocument(ServoTraversalFlags aBaseFlags)
+ServoStyleSet::StyleDocument(ServoTraversalFlags aFlags)
 {
   nsIDocument* doc = mPresContext->Document();
   if (!doc->GetServoRestyleRoot()) {
     return false;
   }
 
-  PreTraverse(aBaseFlags);
+  PreTraverse(aFlags);
   AutoPrepareTraversal guard(this);
   const SnapshotTable& snapshots = Snapshots();
 
   // Restyle the document from the root element and each of the document level
   // NAC subtree roots.
   bool postTraversalRequired = false;
 
   Element* rootElement = doc->GetRootElement();
   MOZ_ASSERT_IF(rootElement, rootElement->HasServoData());
 
+  if (ShouldTraverseInParallel()) {
+    aFlags |= ServoTraversalFlags::ParallelTraversal;
+  }
+
   // Do the first traversal.
   DocumentStyleRootIterator iter(doc->GetServoRestyleRoot());
   while (Element* root = iter.GetNextStyleRoot()) {
     MOZ_ASSERT(MayTraverseFrom(const_cast<Element*>(root)));
 
     // If there were text nodes inserted into the document (but not elements),
     // there may be lazy frame construction to do even if no styling is required.
     postTraversalRequired |= root->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
 
-    // Allow the parallel traversal, unless we're traversing traversing one of
-    // the native anonymous document style roots, which are tiny and not worth
-    // parallelizing over.
-    //
-    // We only allow the parallel traversal in active (foreground) tabs.
-    auto flags = aBaseFlags;
-    if (!root->IsInNativeAnonymousSubtree() && mPresContext->PresShell()->IsActive()) {
-      flags |= ServoTraversalFlags::ParallelTraversal;
-    }
-
-    bool required = Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, flags);
+    bool required = Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
     postTraversalRequired |= required;
   }
 
   // If there are still animation restyles needed, trigger a second traversal to
   // update CSS animations or transitions' styles.
   //
   // Note that we need to check the style root again, because doing another
   // PreTraverse on the EffectCompositor might alter the style root. But we
   // don't need to worry about NAC, since document-level NAC shouldn't have
   // animations.
   //
   // We don't need to do this for SMIL since SMIL only updates its animation
   // values once at the begin of a tick. As a result, even if the previous
   // traversal caused, for example, the font-size to change, the SMIL style
   // won't be updated until the next tick anyway.
-  if (mPresContext->EffectCompositor()->PreTraverse(aBaseFlags)) {
+  if (mPresContext->EffectCompositor()->PreTraverse(aFlags)) {
     nsINode* styleRoot = doc->GetServoRestyleRoot();
     Element* root = styleRoot->IsElement() ? styleRoot->AsElement() : rootElement;
 
-    auto flags = aBaseFlags | ServoTraversalFlags::ParallelTraversal;
-
-    bool required = Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, flags);
+    bool required = Servo_TraverseSubtree(root, mRawSet.get(), &snapshots, aFlags);
     postTraversalRequired |= required;
   }
 
   return postTraversalRequired;
 }
 
 void
 ServoStyleSet::StyleNewSubtree(Element* aRoot)
 {
   MOZ_ASSERT(!aRoot->HasServoData(), "Should have called StyleNewChildren");
   PreTraverseSync();
   AutoPrepareTraversal guard(this);
 
   // Do the traversal. The snapshots will not be used.
   const SnapshotTable& snapshots = Snapshots();
   auto flags = ServoTraversalFlags::Empty;
+  if (ShouldTraverseInParallel()) {
+    flags |= ServoTraversalFlags::ParallelTraversal;
+  }
+
   DebugOnly<bool> postTraversalRequired =
     Servo_TraverseSubtree(aRoot, mRawSet.get(), &snapshots, flags);
   MOZ_ASSERT(!postTraversalRequired);
 
   // Annoyingly, the newly-styled content may have animations that need
   // starting, which requires traversing them again. Mark the elements
   // that need animation processing, then do a forgetful traversal to
   // update the styles and clear the animation bits.
@@ -999,23 +995,17 @@ ServoStyleSet::StyleNewChildren(Element*
   //     traversal, which is buggy.
 
   // Set ourselves up to find the children by marking the parent as having
   // dirty descendants.
   bool hadDirtyDescendants = aParent->HasDirtyDescendantsForServo();
   aParent->SetHasDirtyDescendantsForServo();
 
   auto flags = ServoTraversalFlags::UnstyledOnly;
-
-  // If there is an XBL binding on the root element, we do the initial document
-  // styling with this API. Not clear how common that is, but we allow parallel
-  // traversals in this case to preserve the old behavior (where Servo would
-  // use the parallel traversal i.f.f. the traversal root was the document root).
-  if (aParent == aParent->OwnerDoc()->GetRootElement() &&
-      mPresContext->PresShell()->IsActive()) {
+  if (ShouldTraverseInParallel()) {
     flags |= ServoTraversalFlags::ParallelTraversal;
   }
 
   // Do the traversal. The snapshots will be ignored.
   const SnapshotTable& snapshots = Snapshots();
   Servo_TraverseSubtree(aParent, mRawSet.get(), &snapshots, flags);
 
   // Restore the old state of the dirty descendants bit.
@@ -1410,16 +1400,22 @@ ServoStyleSet::MayTraverseFrom(Element* 
 
   if (!parent->HasServoData()) {
     return false;
   }
 
   return !Servo_Element_IsDisplayNone(parent);
 }
 
+bool
+ServoStyleSet::ShouldTraverseInParallel() const
+{
+  return mPresContext->PresShell()->IsActive();
+}
+
 void
 ServoStyleSet::PrependSheetOfType(SheetType aType,
                                   ServoStyleSheet* aSheet)
 {
   aSheet->AddStyleSet(this);
   mSheets[aType].InsertElementAt(0, aSheet);
 }
 
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -469,16 +469,18 @@ public:
                        ServoStyleContext* aNewParentIgnoringFirstLine,
                        ServoStyleContext* aNewLayoutParent,
                        Element* aElement);
 
 private:
   friend class AutoSetInServoTraversal;
   friend class AutoPrepareTraversal;
 
+  bool ShouldTraverseInParallel() const;
+
   /**
    * Gets the pending snapshots to handle from the restyle manager.
    */
   const SnapshotTable& Snapshots();
 
   bool IsMaster() const { return mKind == Kind::Master; }
   bool IsForXBL() const { return mKind == Kind::ForXBL; }