Bug 1372318. Add a way to compute a changehint based on two stylo ComputedValues structs. r=bholley draft
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 12 Jun 2017 16:06:02 -0400
changeset 592845 9ee4416974369cd43425ec2f5f242d1e2ecce71e
parent 591631 646b691852bd9bf6d50e2ca2b14daa85a7f8ecdb
child 632940 5b2e63445fd6e6bb144b5fc1bbd5ed785a16e078
push id63513
push userbzbarsky@mozilla.com
push dateMon, 12 Jun 2017 20:06:47 +0000
reviewersbholley
bugs1372318
milestone55.0a1
Bug 1372318. Add a way to compute a changehint based on two stylo ComputedValues structs. r=bholley This does not update the generated bindings; I figure we can do that whenever we actually add a servo-side consumer if it hasn't ridden along with some other bindings change first. MozReview-Commit-ID: 6hfjHfvMBSI
layout/style/ServoBindings.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -374,16 +374,34 @@ Gecko_CalcStyleDifference(nsStyleContext
     aOldStyleContext->CalcStyleDifference(aComputedValues,
                                           &equalStructs,
                                           &samePointerStructs);
   *aAnyStyleChanged = equalStructs != NS_STYLE_INHERIT_MASK;
   return result;
 }
 
 nsChangeHint
+Gecko_CalcComputedValuesDifference(ServoComputedValuesBorrowed aOldComputedValues,
+                                   ServoComputedValuesBorrowed aNewComputedValues,
+                                   bool* aAnyStyleChanged)
+{
+  MOZ_ASSERT(aOldComputedValues);
+  MOZ_ASSERT(aNewComputedValues);
+
+  uint32_t equalStructs, samePointerStructs;
+  nsChangeHint result =
+    nsStyleContext::CalcStyleDifference(aOldComputedValues,
+                                        aNewComputedValues,
+                                        &equalStructs,
+                                        &samePointerStructs);
+  *aAnyStyleChanged = equalStructs != NS_STYLE_INHERIT_MASK;
+  return result;
+}
+
+nsChangeHint
 Gecko_HintsHandledForDescendants(nsChangeHint aHint)
 {
   return aHint & ~NS_HintsNotHandledForDescendantsIn(aHint);
 }
 
 const ServoElementSnapshot*
 Gecko_GetElementSnapshot(const ServoElementSnapshotTable* aTable,
                          const Element* aElement)
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -984,28 +984,31 @@ nsStyleContext::ApplyStyleFixups(bool aS
     }
   }
 
   // Compute User Interface style, to trigger loads of cursors
   StyleUserInterface();
 #undef GET_UNIQUE_STYLE_DATA
 }
 
-template<class StyleContextLike>
-nsChangeHint
-nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
+template<class StyleContextLike1, class StyleContextLike2>
+/* static */ nsChangeHint
+nsStyleContext::CalcStyleDifferenceInternal(StyleContextLike1* aOldContext,
+                                            StyleContextLike2* aNewContext,
                                             uint32_t* aEqualStructs,
                                             uint32_t* aSamePointerStructs)
 {
   PROFILER_LABEL("nsStyleContext", "CalcStyleDifference",
     js::ProfileEntry::Category::CSS);
 
   static_assert(nsStyleStructID_Length <= 32,
                 "aEqualStructs is not big enough");
 
+  MOZ_ASSERT(aOldContext, "What are we doing here?");
+
   *aEqualStructs = 0;
 
   nsChangeHint hint = nsChangeHint(0);
   NS_ENSURE_TRUE(aNewContext, hint);
   // We must always ensure that we populate the structs on the new style
   // context that are filled in on the old context, so that if we get
   // two style changes in succession, the second of which causes a real
   // style change, the PeekStyleData doesn't return null (implying that
@@ -1014,17 +1017,17 @@ nsStyleContext::CalcStyleDifferenceInter
   // we could later get a small change in one of those structs that we
   // don't want to miss.
 
   DebugOnly<uint32_t> structsFound = 0;
 
   // FIXME(heycam): We should just do the comparison in
   // nsStyleVariables::CalcDifference, returning NeutralChange if there are
   // any Variables differences.
-  const nsStyleVariables* thisVariables = PeekStyleVariables();
+  const nsStyleVariables* thisVariables = aOldContext->PeekStyleVariables();
   if (thisVariables) {
     structsFound |= NS_STYLE_INHERIT_BIT(Variables);
     const nsStyleVariables* otherVariables = aNewContext->StyleVariables();
     if (thisVariables->mVariables == otherVariables->mVariables) {
       *aEqualStructs |= NS_STYLE_INHERIT_BIT(Variables);
     }
   } else {
     *aEqualStructs |= NS_STYLE_INHERIT_BIT(Variables);
@@ -1032,28 +1035,30 @@ nsStyleContext::CalcStyleDifferenceInter
 
   DebugOnly<int> styleStructCount = 1;  // count Variables already
 
   // Servo's optimization to stop the cascade when there are no style changes
   // that children need to be recascade for relies on comparing all of the
   // structs, not just those that are returned from PeekStyleData, although
   // if PeekStyleData does return null we still don't want to accumulate
   // any change hints for those structs.
-  bool checkUnrequestedServoStructs = mSource.IsServoComputedValues();
+  bool checkUnrequestedServoStructs =
+    aOldContext->StyleSource().IsServoComputedValues();
 
 #define DO_STRUCT_DIFFERENCE(struct_)                                         \
   PR_BEGIN_MACRO                                                              \
-    const nsStyle##struct_* this##struct_ = PeekStyle##struct_();             \
+    const nsStyle##struct_* this##struct_ = aOldContext->PeekStyle##struct_();\
     bool unrequestedStruct;                                                   \
     if (this##struct_) {                                                      \
       unrequestedStruct = false;                                              \
       structsFound |= NS_STYLE_INHERIT_BIT(struct_);                          \
     } else if (checkUnrequestedServoStructs) {                                \
       this##struct_ =                                                         \
-        Servo_GetStyle##struct_(mSource.AsServoComputedValues());             \
+        Servo_GetStyle##struct_(                                              \
+          aOldContext->StyleSource().AsServoComputedValues());                \
       unrequestedStruct = true;                                               \
     } else {                                                                  \
       unrequestedStruct = false;                                              \
     }                                                                         \
     if (this##struct_) {                                                      \
       const nsStyle##struct_* other##struct_ = aNewContext->Style##struct_(); \
       if (this##struct_ == other##struct_) {                                  \
         /* The very same struct, so we know that there will be no */          \
@@ -1089,17 +1094,17 @@ nsStyleContext::CalcStyleDifferenceInter
   DO_STRUCT_DIFFERENCE(TableBorder);
   DO_STRUCT_DIFFERENCE(Table);
   DO_STRUCT_DIFFERENCE(UIReset);
   DO_STRUCT_DIFFERENCE(Text);
   DO_STRUCT_DIFFERENCE(List);
   DO_STRUCT_DIFFERENCE(SVGReset);
   DO_STRUCT_DIFFERENCE(SVG);
 #undef EXTRA_DIFF_ARGS
-#define EXTRA_DIFF_ARGS , PeekStyleVisibility()
+#define EXTRA_DIFF_ARGS , aOldContext->PeekStyleVisibility()
   DO_STRUCT_DIFFERENCE(Position);
 #undef EXTRA_DIFF_ARGS
 #define EXTRA_DIFF_ARGS /* nothing */
   DO_STRUCT_DIFFERENCE(Font);
   DO_STRUCT_DIFFERENCE(Margin);
   DO_STRUCT_DIFFERENCE(Padding);
   DO_STRUCT_DIFFERENCE(Border);
   DO_STRUCT_DIFFERENCE(TextReset);
@@ -1111,17 +1116,17 @@ nsStyleContext::CalcStyleDifferenceInter
 #undef DO_STRUCT_DIFFERENCE
 
   MOZ_ASSERT(styleStructCount == nsStyleStructID_Length,
              "missing a call to DO_STRUCT_DIFFERENCE");
 
 #ifdef DEBUG
   #define STYLE_STRUCT(name_, callback_)                                      \
     MOZ_ASSERT(!!(structsFound & NS_STYLE_INHERIT_BIT(name_)) ==              \
-               !!PeekStyle##name_(),                                          \
+               !!aOldContext->PeekStyle##name_(),                             \
                "PeekStyleData results must not change in the middle of "      \
                "difference calculation.");
   #include "nsStyleStructList.h"
   #undef STYLE_STRUCT
 #endif
 
   // We check for struct pointer equality here rather than as part of the
   // DO_STRUCT_DIFFERENCE calls, since those calls can result in structs
@@ -1130,17 +1135,17 @@ nsStyleContext::CalcStyleDifferenceInter
   // happen when the nsRuleNode::ComputeXXXData method looks up another
   // struct.)  This is important for callers in RestyleManager that
   // need to know the equality or not of the final set of cached struct
   // pointers.
   *aSamePointerStructs = 0;
 
 #define STYLE_STRUCT(name_, callback_)                                        \
   {                                                                           \
-    const nsStyle##name_* data = PeekStyle##name_();                          \
+    const nsStyle##name_* data = aOldContext->PeekStyle##name_();             \
     if (!data || data == aNewContext->Style##name_()) {                       \
       *aSamePointerStructs |= NS_STYLE_INHERIT_BIT(name_);                    \
     }                                                                         \
   }
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 
   // Note that we do not check whether this->RelevantLinkVisited() !=
@@ -1154,17 +1159,17 @@ nsStyleContext::CalcStyleDifferenceInter
   // the page to measure.
   // However, we do need to compute the larger of the changes that can
   // happen depending on whether the link is visited or unvisited, since
   // doing only the one that's currently appropriate would expose which
   // links are in history to easy performance measurement.  Therefore,
   // here, we add nsChangeHint_RepaintFrame hints (the maximum for
   // things that can depend on :visited) for the properties on which we
   // call GetVisitedDependentColor.
-  nsStyleContext *thisVis = GetStyleIfVisited(),
+  nsStyleContext *thisVis = aOldContext->GetStyleIfVisited(),
                 *otherVis = aNewContext->GetStyleIfVisited();
   if (!thisVis != !otherVis) {
     // One style context has a style-if-visited and the other doesn't.
     // Presume a difference.
     hint |= nsChangeHint_RepaintFrame;
   } else if (thisVis && !NS_IsHintSubset(nsChangeHint_RepaintFrame, hint)) {
     // Bug 1364484: Update comments here and potentially remove the assertion
     // below once we return a non-null visited context in CalcStyleDifference
@@ -1179,17 +1184,17 @@ nsStyleContext::CalcStyleDifferenceInter
 
     // NB: Calling Peek on |this|, not |thisVis|, since callers may look
     // at a struct on |this| without looking at the same struct on
     // |thisVis| (including this function if we skip one of these checks
     // due to change being true already or due to the old style context
     // not having a style-if-visited), but not the other way around.
 #define STYLE_FIELD(name_) thisVisStruct->name_ != otherVisStruct->name_
 #define STYLE_STRUCT(name_, fields_)                                    \
-    if (!change && PeekStyle##name_()) {                                \
+    if (!change && aOldContext->PeekStyle##name_()) {                   \
       const nsStyle##name_* thisVisStruct = thisVis->Style##name_();    \
       const nsStyle##name_* otherVisStruct = otherVis->Style##name_();  \
       if (MOZ_FOR_EACH_SEPARATED(STYLE_FIELD, (||), (), fields_)) {     \
         change = true;                                                  \
       }                                                                 \
     }
 #include "nsCSSVisitedDependentPropList.h"
 #undef STYLE_STRUCT
@@ -1209,20 +1214,22 @@ nsStyleContext::CalcStyleDifferenceInter
 
     // This depends on data in nsStyleDisplay, nsStyleEffects and
     // nsStyleSVGReset, so we do it here.
 
     // Note that it's perhaps good for this test to be last because it
     // doesn't use Peek* functions to get the structs on the old
     // context.  But this isn't a big concern because these struct
     // getters should be called during frame construction anyway.
-    if (ThreadsafeStyleDisplay()->IsAbsPosContainingBlockForAppropriateFrame(this) ==
+    if (aOldContext->ThreadsafeStyleDisplay()->
+          IsAbsPosContainingBlockForAppropriateFrame(aOldContext) ==
         aNewContext->ThreadsafeStyleDisplay()->
           IsAbsPosContainingBlockForAppropriateFrame(aNewContext) &&
-        ThreadsafeStyleDisplay()->IsFixedPosContainingBlockForAppropriateFrame(this) ==
+        aOldContext->ThreadsafeStyleDisplay()->
+          IsFixedPosContainingBlockForAppropriateFrame(aOldContext) ==
         aNewContext->ThreadsafeStyleDisplay()->
           IsFixedPosContainingBlockForAppropriateFrame(aNewContext)) {
       // While some styles that cause the frame to be a containing block
       // has changed, the overall result hasn't.
       hint &= ~nsChangeHint_UpdateContainingBlock;
     }
   }
 
@@ -1231,17 +1238,18 @@ nsStyleContext::CalcStyleDifferenceInter
   return hint & ~nsChangeHint_NeutralChange;
 }
 
 nsChangeHint
 nsStyleContext::CalcStyleDifference(nsStyleContext* aNewContext,
                                     uint32_t* aEqualStructs,
                                     uint32_t* aSamePointerStructs)
 {
-  return CalcStyleDifferenceInternal(aNewContext,
+  return CalcStyleDifferenceInternal(this,
+                                     aNewContext,
                                      aEqualStructs,
                                      aSamePointerStructs);
 }
 
 class MOZ_STACK_CLASS FakeStyleContext
 {
 public:
   explicit FakeStyleContext(const ServoComputedValues* aComputedValues)
@@ -1261,31 +1269,49 @@ public:
   }
 
   #define STYLE_STRUCT(name_, checkdata_cb_)                                  \
   const nsStyle##name_ * Style##name_() {                                     \
     return Servo_GetStyle##name_(mComputedValues);                            \
   }                                                                           \
   const nsStyle##name_ * ThreadsafeStyle##name_() {                           \
     return Servo_GetStyle##name_(mComputedValues);                            \
+  }                                                                           \
+  const nsStyle##name_ * PeekStyle##name_() {                                 \
+    return Servo_GetStyle##name_(mComputedValues);                            \
   }
   #include "nsStyleStructList.h"
   #undef STYLE_STRUCT
 
 private:
   const ServoComputedValues* MOZ_NON_OWNING_REF mComputedValues;
 };
 
 nsChangeHint
 nsStyleContext::CalcStyleDifference(const ServoComputedValues* aNewComputedValues,
                                     uint32_t* aEqualStructs,
                                     uint32_t* aSamePointerStructs)
 {
   FakeStyleContext newContext(aNewComputedValues);
-  return CalcStyleDifferenceInternal(&newContext,
+  return CalcStyleDifferenceInternal(this,
+                                     &newContext,
+                                     aEqualStructs,
+                                     aSamePointerStructs);
+}
+
+/* static */ nsChangeHint
+nsStyleContext::CalcStyleDifference(const ServoComputedValues* aOldComputedValues,
+                                    const ServoComputedValues* aNewComputedValues,
+                                    uint32_t* aEqualStructs,
+                                    uint32_t* aSamePointerStructs)
+{
+  FakeStyleContext oldContext(aOldComputedValues);
+  FakeStyleContext newContext(aNewComputedValues);
+  return CalcStyleDifferenceInternal(&oldContext,
+                                     &newContext,
                                      aEqualStructs,
                                      aSamePointerStructs);
 }
 
 void
 nsStyleContext::EnsureSameStructsCached(nsStyleContext* aOldContext)
 {
   // NOTE(emilio): We could do better here for stylo, where we only call
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -416,19 +416,30 @@ public:
   /**
    * Like the above, but allows comparing ServoComputedValues instead of needing
    * a full-fledged style context.
    */
   nsChangeHint CalcStyleDifference(const ServoComputedValues* aNewComputedValues,
                                    uint32_t* aEqualStructs,
                                    uint32_t* aSamePointerStructs);
 
+  /**
+   * Like the above, but compares two ServoComputedValues to each other.
+   */
+  static nsChangeHint CalcStyleDifference(
+    const ServoComputedValues* aOldComputedValues,
+    const ServoComputedValues* aNewComputedValues,
+    uint32_t* aEqualStructs,
+    uint32_t* aSamePointerStructs);
+
 private:
-  template<class StyleContextLike>
-  nsChangeHint CalcStyleDifferenceInternal(StyleContextLike* aNewContext,
+  template<class StyleContextLike1, class StyleContextLike2>
+  static
+  nsChangeHint CalcStyleDifferenceInternal(StyleContextLike1* aOldContext,
+                                           StyleContextLike2* aNewContext,
                                            uint32_t* aEqualStructs,
                                            uint32_t* aSamePointerStructs);
 
 public:
   /**
    * Ensures the same structs are cached on this style context as would be
    * done if we called aOther->CalcDifference(this).
    */