Bug 1356103 - Part 3: Make it easy to access the ServoStyleSet currently in traversal. r=bholley draft
authorCameron McCormack <cam@mcc.id.au>
Sun, 30 Apr 2017 14:41:11 +0800
changeset 572575 5d58bfbab0ad0d11c5bfc500e46bc0307beb98a4
parent 572427 ec12098f89788478de5327d40345d2733747ac48
child 572576 e4c231fa09ec1eb15db9b4a8b40385bb6971d3f2
push id57115
push userbmo:cam@mcc.id.au
push dateThu, 04 May 2017 10:01:25 +0000
reviewersbholley
bugs1356103
milestone55.0a1
Bug 1356103 - Part 3: Make it easy to access the ServoStyleSet currently in traversal. r=bholley In a later patch, we'll want to queue up some tasks to run when the Servo traversal is one, and the ServoStyleSet seems like the natural place to store those tasks. We could probably find the ServoStyleSet by chasing a bunch of pointers from the task-adding call sites, but it seems simpler just to make it available directly. MozReview-Commit-ID: AJoFZEoNaGm
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -290,18 +290,17 @@ ServoStyleSet::PrepareAndTraverseSubtree
                                          TraversalRestyleBehavior
                                            aRestyleBehavior)
 {
   // Get the Document's root element to ensure that the cache is valid before
   // calling into the (potentially-parallel) Servo traversal, where a cache hit
   // is necessary to avoid a data race when updating the cache.
   mozilla::Unused << aRoot->OwnerDoc()->GetRootElement();
 
-  MOZ_ASSERT(!sInServoTraversal);
-  sInServoTraversal = true;
+  AutoSetInServoTraversal guard(this);
 
   bool isInitial = !aRoot->HasServoData();
   bool forReconstruct =
     aRestyleBehavior == TraversalRestyleBehavior::ForReconstruct;
   bool postTraversalRequired =
     Servo_TraverseSubtree(aRoot, mRawSet.get(), aRootBehavior, aRestyleBehavior);
   MOZ_ASSERT_IF(isInitial || forReconstruct, !postTraversalRequired);
 
@@ -333,17 +332,16 @@ ServoStyleSet::PrepareAndTraverseSubtree
         MOZ_ASSERT(!postTraversalRequired);
         ServoRestyleManager::ClearRestyleStateFromSubtree(root);
       } else {
         postTraversalRequired = true;
       }
     }
   }
 
-  sInServoTraversal = false;
   return postTraversalRequired;
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveStyleFor(Element* aElement,
                                nsStyleContext* aParentContext,
                                LazyComputeBehavior aMayCompute,
                                TreeMatchContext& aTreeMatchContext)
@@ -978,18 +976,18 @@ ServoStyleSet::ClearNonInheritingStyleCo
     ptr = nullptr;
   }
 }
 
 already_AddRefed<ServoComputedValues>
 ServoStyleSet::ResolveStyleLazily(Element* aElement, nsIAtom* aPseudoTag)
 {
   mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoTag);
-  MOZ_ASSERT(!sInServoTraversal);
-  sInServoTraversal = true;
+
+  AutoSetInServoTraversal guard(this);
 
   /**
    * NB: This is needed because we process animations and transitions on the
    * pseudo-elements themselves, not on the parent's EagerPseudoStyles.
    *
    * That means that that style doesn't account for animations, and we can't do
    * that easily from the traversal without doing wasted work.
    *
@@ -1018,18 +1016,16 @@ ServoStyleSet::ResolveStyleLazily(Elemen
 
   if (mPresContext->EffectCompositor()->PreTraverse(aElement, aPseudoTag)) {
     computedValues =
       Servo_ResolveStyleLazily(elementForStyleResolution,
                                pseudoTagForStyleResolution,
                                mRawSet.get()).Consume();
   }
 
-  sInServoTraversal = false;
-
   return computedValues.forget();
 }
 
 bool
 ServoStyleSet::AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray)
 {
   Servo_StyleSet_GetFontFaceRules(mRawSet.get(), &aArray);
   return true;
@@ -1105,9 +1101,9 @@ ServoStyleSet::RemoveSheetOfType(SheetTy
       uint32_t uniqueID = mEntries[aType][i].uniqueID;
       mEntries[aType].RemoveElementAt(i);
       return uniqueID;
     }
   }
   return 0;
 }
 
-bool ServoStyleSet::sInServoTraversal = false;
+ServoStyleSet* ServoStyleSet::sInServoTraversal = nullptr;
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -80,16 +80,21 @@ public:
     // maintain this static boolean. However, the danger is that those callers
     // are generally unprepared to deal with non-Servo-but-also-non-main-thread
     // callers, and are likely to take the main-thread codepath if this function
     // returns false. So we assert against other non-main-thread callers here.
     MOZ_ASSERT(sInServoTraversal || NS_IsMainThread());
     return sInServoTraversal;
   }
 
+  static ServoStyleSet* Current()
+  {
+    return sInServoTraversal;
+  }
+
   ServoStyleSet();
   ~ServoStyleSet();
 
   void Init(nsPresContext* aPresContext);
   void BeginShutdown();
   void Shutdown();
 
   size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
@@ -304,16 +309,33 @@ public:
   ResolveForDeclarations(ServoComputedValuesBorrowedOrNull aParentOrNull,
                          RawServoDeclarationBlockBorrowed aDeclarations);
 
   already_AddRefed<RawServoAnimationValue>
   ComputeAnimationValue(RawServoDeclarationBlock* aDeclaration,
                         const ServoComputedValuesWithParent& aComputedValues);
 
 private:
+  class MOZ_STACK_CLASS AutoSetInServoTraversal
+  {
+  public:
+    explicit AutoSetInServoTraversal(ServoStyleSet* aSet)
+    {
+      MOZ_ASSERT(!sInServoTraversal);
+      MOZ_ASSERT(aSet);
+      sInServoTraversal = aSet;
+    }
+
+    ~AutoSetInServoTraversal()
+    {
+      MOZ_ASSERT(sInServoTraversal);
+      sInServoTraversal = nullptr;
+    }
+  };
+
   already_AddRefed<nsStyleContext> GetContext(already_AddRefed<ServoComputedValues>,
                                               nsStyleContext* aParentContext,
                                               nsIAtom* aPseudoTag,
                                               CSSPseudoElementType aPseudoType,
                                               dom::Element* aElementForAnimation);
 
   already_AddRefed<nsStyleContext> GetContext(nsIContent* aContent,
                                               nsStyleContext* aParentContext,
@@ -394,14 +416,14 @@ private:
   bool mAuthorStyleDisabled;
 
   // Stores pointers to our cached style contexts for non-inheriting anonymous
   // boxes.
   EnumeratedArray<nsCSSAnonBoxes::NonInheriting,
                   nsCSSAnonBoxes::NonInheriting::_Count,
                   RefPtr<nsStyleContext>> mNonInheritingStyleContexts;
 
-  static bool sInServoTraversal;
+  static ServoStyleSet* sInServoTraversal;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ServoStyleSet_h