Bug 897763 - Take into account nsChangeHint_{NeedReflow,ClearAncestorIntrinsics} never being inherited for difference calculations on certain style structs. r=dbaron
authorCameron McCormack <cam@mcc.id.au>
Fri, 03 Jan 2014 13:39:54 +1100
changeset 162013 e6b308fc9b66373cf6495505780e96d916d962e8
parent 162012 0208d8f09898e4824355c6a8845b3a9fbf8b18e7
child 162014 567977c0c7da732975a91ddf50904c72b8a591dc
push id38059
push usercmccormack@mozilla.com
push dateFri, 03 Jan 2014 02:40:17 +0000
treeherdermozilla-inbound@e6b308fc9b66 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs897763
milestone29.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 897763 - Take into account nsChangeHint_{NeedReflow,ClearAncestorIntrinsics} never being inherited for difference calculations on certain style structs. r=dbaron
layout/build/nsLayoutModule.cpp
layout/generic/crashtests/crashtests.list
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleStruct.h
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -428,16 +428,20 @@ Initialize()
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     observerService->AddObserver(observer, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   } else {
     NS_WARNING("Could not get an observer service.  We will leak on shutdown.");
   }
 
+#ifdef DEBUG
+  nsStyleContext::AssertStyleStructMaxDifferenceValid();
+#endif
+
   return NS_OK;
 }
 
 // Shutdown this module, releasing all of the module resources
 
 // static
 void
 Shutdown()
--- a/layout/generic/crashtests/crashtests.list
+++ b/layout/generic/crashtests/crashtests.list
@@ -395,17 +395,17 @@ load 547843-1.xhtml
 load 551635-1.html
 load 553504-1.xhtml
 load 564368-1.xhtml
 load 564968.xhtml
 load 570160.html
 load 570289-1.html
 load 571618-1.svg
 asserts(1) load 571975-1.html # bug 574889
-asserts(1) load 571995.xhtml # 761848
+load 571995.xhtml
 load 574958.xhtml
 asserts(0-4) load 578977.html # bug 757305
 load 580504-1.xhtml
 load 585598-1.xhtml
 asserts(0-11) load 586806-1.html # Bug 439258
 load 586806-2.html
 load 586806-3.html
 load 586973-1.html
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -455,18 +455,21 @@ nsStyleContext::CalcStyleDifference(nsSt
   DebugOnly<int> styleStructCount = 1;  // count Variables already
 
 #define DO_STRUCT_DIFFERENCE(struct_)                                         \
   PR_BEGIN_MACRO                                                              \
     const nsStyle##struct_* this##struct_ = PeekStyle##struct_();             \
     if (this##struct_) {                                                      \
       const nsStyle##struct_* other##struct_ = aOther->Style##struct_();      \
       nsChangeHint maxDifference = nsStyle##struct_::MaxDifference();         \
+      nsChangeHint maxDifferenceNeverInherited =                              \
+        nsStyle##struct_::MaxDifferenceNeverInherited();                      \
       if ((compare ||                                                         \
-           (maxDifference & aParentHintsNotHandledForDescendants)) &&         \
+           (NS_SubtractHint(maxDifference, maxDifferenceNeverInherited) &     \
+            aParentHintsNotHandledForDescendants)) &&                         \
           !NS_IsHintSubset(maxDifference, hint) &&                            \
           this##struct_ != other##struct_) {                                  \
         NS_ASSERTION(NS_IsHintSubset(                                         \
              this##struct_->CalcDifference(*other##struct_),                  \
              nsStyle##struct_::MaxDifference()),                              \
              "CalcDifference() returned bigger hint than MaxDifference()");   \
         NS_UpdateHint(hint, this##struct_->CalcDifference(*other##struct_));  \
       }                                                                       \
@@ -859,8 +862,20 @@ nsStyleContext::FreeAllocations(nsPresCo
 {
   nsIPresShell *shell = aPresContext->PresShell();
 
   for (AllocationHeader *alloc = mAllocations, *next; alloc; alloc = next) {
     next = alloc->mNext;
     shell->FreeMisc(alloc->mSize, alloc);
   }
 }
+
+#ifdef DEBUG
+/* static */ void
+nsStyleContext::AssertStyleStructMaxDifferenceValid()
+{
+#define STYLE_STRUCT(name, checkdata_cb)                                     \
+    MOZ_ASSERT(NS_IsHintSubset(nsStyle##name::MaxDifferenceNeverInherited(), \
+                               nsStyle##name::MaxDifference()));
+#include "nsStyleStructList.h"
+#undef STYLE_STRUCT
+}
+#endif
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -335,16 +335,17 @@ public:
    */
   void StartBackgroundImageLoads() {
     // Just get our background struct; that should do the trick
     StyleBackground();
   }
 
 #ifdef DEBUG
   void List(FILE* out, int32_t aIndent);
+  static void AssertStyleStructMaxDifferenceValid();
 #endif
 
 protected:
   void AddChild(nsStyleContext* aChild);
   void RemoveChild(nsStyleContext* aChild);
 
   void ApplyStyleFixups(bool aSkipFlexItemStyleFixup);
 
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -74,16 +74,22 @@ public:
   ~nsStyleFont(void) {
     MOZ_COUNT_DTOR(nsStyleFont);
   }
 
   nsChangeHint CalcDifference(const nsStyleFont& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
   static nsChangeHint CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2);
 
   static nscoord ZoomText(nsPresContext* aPresContext, nscoord aSize);
   static nscoord UnZoomText(nsPresContext* aPresContext, nscoord aSize);
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
   void Destroy(nsPresContext* aContext);
 
@@ -300,16 +306,21 @@ struct nsStyleColor {
   ~nsStyleColor(void) {
     MOZ_COUNT_DTOR(nsStyleColor);
   }
 
   nsChangeHint CalcDifference(const nsStyleColor& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_VISUAL;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics at all.
+    return nsChangeHint(0);
+  }
 
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
     return aContext->AllocateFromShell(sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleColor();
     aContext->FreeToShell(sizeof(nsStyleColor), this);
   }
@@ -328,16 +339,21 @@ struct nsStyleBackground {
     return aContext->AllocateFromShell(sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBackground& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics at all.
+    return nsChangeHint(0);
+  }
 
   struct Position;
   friend struct Position;
   struct Position {
     typedef nsStyleCoord::Calc PositionCoord;
     PositionCoord mXPosition, mYPosition;
 
     // Initialize nothing
@@ -556,16 +572,21 @@ struct nsStyleMargin {
 
   void RecalcData();
   nsChangeHint CalcDifference(const nsStyleMargin& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
                            NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
                                           nsChangeHint_NeedDirtyReflow));
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
+    // nsChangeHint_NeedReflow as inherited hints.
+    return nsChangeHint(0);
+  }
 
   nsStyleSides  mMargin;          // [reset] coord, percent, calc, auto
 
   bool IsWidthDependent() const { return !mHasCachedMargin; }
   bool GetMargin(nsMargin& aMargin) const
   {
     if (mHasCachedMargin) {
       aMargin = mCachedMargin;
@@ -591,16 +612,21 @@ struct nsStylePadding {
   void Destroy(nsPresContext* aContext);
 
   void RecalcData();
   nsChangeHint CalcDifference(const nsStylePadding& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
                            nsChangeHint_ClearDescendantIntrinsics);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference can return nsChangeHint_ClearAncestorIntrinsics as an
+    // inherited hint.
+    return nsChangeHint(0);
+  }
 
   nsStyleSides  mPadding;         // [reset] coord, percent, calc
 
   bool IsWidthDependent() const { return !mHasCachedPadding; }
   bool GetPadding(nsMargin& aPadding) const
   {
     if (mHasCachedPadding) {
       aPadding = mCachedPadding;
@@ -768,16 +794,22 @@ struct nsStyleBorder {
   void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBorder& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_CombineHint(NS_STYLE_HINT_REFLOW,
                           nsChangeHint_BorderStyleNoneChange);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   void EnsureBorderColors() {
     if (!mBorderColors) {
       mBorderColors = new nsBorderColors*[4];
       if (mBorderColors)
         for (int32_t i = 0; i < 4; i++)
           mBorderColors[i] = nullptr;
     }
@@ -990,16 +1022,22 @@ struct nsStyleOutline {
   }
 
   void RecalcData(nsPresContext* aContext);
   nsChangeHint CalcDifference(const nsStyleOutline& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_CombineHint(nsChangeHint_AllReflowHints,
                           nsChangeHint_RepaintFrame);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   nsStyleCorners  mOutlineRadius; // [reset] coord, percent, calc
 
   // Note that this is a specified value.  You can get the actual values
   // with GetOutlineWidth.  You cannot get the computed value directly.
   nsStyleCoord  mOutlineWidth;    // [reset] coord, enum (see nsStyleConsts.h)
   nscoord       mOutlineOffset;   // [reset]
 
@@ -1075,16 +1113,22 @@ struct nsStyleList {
     this->~nsStyleList();
     aContext->FreeToShell(sizeof(nsStyleList), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleList& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   imgRequestProxy* GetListStyleImage() const { return mListStyleImage; }
   void SetListStyleImage(imgRequestProxy* aReq)
   {
     if (mListStyleImage)
       mListStyleImage->UnlockImage();
     mListStyleImage = aReq;
     if (mListStyleImage)
@@ -1114,16 +1158,21 @@ struct nsStylePosition {
   }
 
   nsChangeHint CalcDifference(const nsStylePosition& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_CombineHint(NS_STYLE_HINT_REFLOW,
                           nsChangeHint(nsChangeHint_RecomputePosition |
                                        nsChangeHint_UpdateOverflow));
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
+    // nsChangeHint_NeedReflow as inherited hints.
+    return nsChangeHint(0);
+  }
 
   nsStyleSides  mOffset;                // [reset] coord, percent, calc, auto
   nsStyleCoord  mWidth;                 // [reset] coord, percent, enum, calc, auto
   nsStyleCoord  mMinWidth;              // [reset] coord, percent, enum, calc
   nsStyleCoord  mMaxWidth;              // [reset] coord, percent, enum, calc, none
   nsStyleCoord  mHeight;                // [reset] coord, percent, calc, auto
   nsStyleCoord  mMinHeight;             // [reset] coord, percent, calc
   nsStyleCoord  mMaxHeight;             // [reset] coord, percent, calc, none
@@ -1279,16 +1328,22 @@ struct nsStyleTextReset {
     mTextDecorationStyle &= ~BORDER_COLOR_SPECIAL;
     mTextDecorationStyle |= BORDER_COLOR_FOREGROUND;
   }
 
   nsChangeHint CalcDifference(const nsStyleTextReset& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   nsStyleCoord  mVerticalAlign;         // [reset] coord, percent, calc, enum (see nsStyleConsts.h)
   nsStyleTextOverflow mTextOverflow;    // [reset] enum, string
 
   uint8_t mTextDecorationLine;          // [reset] see nsStyleConsts.h
   uint8_t mUnicodeBidi;                 // [reset] see nsStyleConsts.h
 protected:
   uint8_t mTextDecorationStyle;         // [reset] see nsStyleConsts.h
@@ -1308,16 +1363,22 @@ struct nsStyleText {
     this->~nsStyleText();
     aContext->FreeToShell(sizeof(nsStyleText), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleText& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   uint8_t mTextAlign;                   // [inherited] see nsStyleConsts.h
   uint8_t mTextAlignLast;               // [inherited] see nsStyleConsts.h
   bool mTextAlignTrue : 1;              // [inherited] see nsStyleConsts.h
   bool mTextAlignLastTrue : 1;          // [inherited] see nsStyleConsts.h
   uint8_t mTextTransform;               // [inherited] see nsStyleConsts.h
   uint8_t mWhiteSpace;                  // [inherited] see nsStyleConsts.h
   uint8_t mWordBreak;                   // [inherited] see nsStyleConsts.h
@@ -1483,16 +1544,22 @@ struct nsStyleVisibility {
     this->~nsStyleVisibility();
     aContext->FreeToShell(sizeof(nsStyleVisibility), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   nsStyleImageOrientation mImageOrientation;  // [inherited]
   uint8_t mDirection;                  // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
   uint8_t mVisible;                    // [inherited]
   uint8_t mPointerEvents;              // [inherited] see nsStyleConsts.h
   uint8_t mWritingMode;                // [inherited] see nsStyleConsts.h
 
   bool IsVisible() const {
@@ -1690,16 +1757,21 @@ struct nsStyleDisplay {
   static nsChangeHint MaxDifference() {
     // All the parts of FRAMECHANGE are present in CalcDifference.
     return nsChangeHint(NS_STYLE_HINT_FRAMECHANGE |
                         nsChangeHint_UpdateOpacityLayer |
                         nsChangeHint_UpdateTransformLayer |
                         nsChangeHint_UpdateOverflow |
                         nsChangeHint_AddOrRemoveTransform);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference can return both nsChangeHint_ClearAncestorIntrinsics and
+    // nsChangeHint_NeedReflow as inherited hints.
+    return nsChangeHint(0);
+  }
 
   // We guarantee that if mBinding is non-null, so are mBinding->GetURI() and
   // mBinding->mOriginPrincipal.
   nsRefPtr<mozilla::css::URLValue> mBinding;    // [reset]
   nsRect  mClip;                // [reset] offsets from upper-left border edge
   float   mOpacity;             // [reset]
   uint8_t mDisplay;             // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
   uint8_t mOriginalDisplay;     // [reset] saved mDisplay for position:absolute/fixed
@@ -1859,16 +1931,22 @@ struct nsStyleTable {
     this->~nsStyleTable();
     aContext->FreeToShell(sizeof(nsStyleTable), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleTable& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   uint8_t       mLayoutStrategy;// [reset] see nsStyleConsts.h NS_STYLE_TABLE_LAYOUT_*
   uint8_t       mFrame;         // [reset] see nsStyleConsts.h NS_STYLE_TABLE_FRAME_*
   uint8_t       mRules;         // [reset] see nsStyleConsts.h NS_STYLE_TABLE_RULES_*
   int32_t       mSpan;          // [reset] the number of columns spanned by a colgroup or col
 };
 
 struct nsStyleTableBorder {
@@ -1883,16 +1961,22 @@ struct nsStyleTableBorder {
     this->~nsStyleTableBorder();
     aContext->FreeToShell(sizeof(nsStyleTableBorder), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleTableBorder& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   nscoord       mBorderSpacingX;// [inherited]
   nscoord       mBorderSpacingY;// [inherited]
   uint8_t       mBorderCollapse;// [inherited]
   uint8_t       mCaptionSide;   // [inherited]
   uint8_t       mEmptyCells;    // [inherited]
 };
 
@@ -1973,16 +2057,22 @@ struct nsStyleQuotes {
 
   void SetInitial();
   void CopyFrom(const nsStyleQuotes& aSource);
 
   nsChangeHint CalcDifference(const nsStyleQuotes& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   uint32_t  QuotesCount(void) const { return mQuotesCount; } // [inherited]
 
   const nsString* OpenQuoteAt(uint32_t aIndex) const
   {
     NS_ASSERTION(aIndex < mQuotesCount, "out of range");
     return mQuotes + (aIndex * 2);
   }
@@ -2040,16 +2130,22 @@ struct nsStyleContent {
     return aContext->AllocateFromShell(sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleContent& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   uint32_t  ContentCount(void) const  { return mContentCount; } // [reset]
 
   const nsStyleContentData& ContentAt(uint32_t aIndex) const {
     NS_ASSERTION(aIndex < mContentCount, "out of range");
     return mContents[aIndex];
   }
 
@@ -2144,16 +2240,22 @@ struct nsStyleUIReset {
     this->~nsStyleUIReset();
     aContext->FreeToShell(sizeof(nsStyleUIReset), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleUIReset& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   uint8_t   mUserSelect;      // [reset] (selection-style)
   uint8_t   mForceBrokenImageIcon; // [reset]  (0 if not forcing, otherwise forcing)
   uint8_t   mIMEMode;         // [reset]
   uint8_t   mWindowShadow;    // [reset]
 };
 
 struct nsCursorImage {
@@ -2197,16 +2299,22 @@ struct nsStyleUserInterface {
     this->~nsStyleUserInterface();
     aContext->FreeToShell(sizeof(nsStyleUserInterface), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleUserInterface& aOther) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint(nsChangeHint_UpdateCursor | NS_STYLE_HINT_FRAMECHANGE);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   uint8_t   mUserInput;       // [inherited]
   uint8_t   mUserModify;      // [inherited] (modify-content)
   uint8_t   mUserFocus;       // [inherited] (auto-select)
 
   uint8_t   mCursor;          // [inherited] See nsStyleConsts.h
 
   uint32_t mCursorArrayLength;
@@ -2232,16 +2340,22 @@ struct nsStyleXUL {
     this->~nsStyleXUL();
     aContext->FreeToShell(sizeof(nsStyleXUL), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleXUL& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   float         mBoxFlex;               // [reset] see nsStyleConsts.h
   uint32_t      mBoxOrdinal;            // [reset] see nsStyleConsts.h
   uint8_t       mBoxAlign;              // [reset] see nsStyleConsts.h
   uint8_t       mBoxDirection;          // [reset] see nsStyleConsts.h
   uint8_t       mBoxOrient;             // [reset] see nsStyleConsts.h
   uint8_t       mBoxPack;               // [reset] see nsStyleConsts.h
   bool          mStretchStack;          // [reset] see nsStyleConsts.h
@@ -2259,16 +2373,22 @@ struct nsStyleColumn {
     this->~nsStyleColumn();
     aContext->FreeToShell(sizeof(nsStyleColumn), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleColumn& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_FRAMECHANGE;
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   /**
    * This is the maximum number of columns we can process. It's used in both
    * nsColumnSetFrame and nsRuleNode.
    */
   static const uint32_t kMaxColumnCount;
 
   uint32_t     mColumnCount; // [reset] see nsStyleConsts.h
@@ -2344,16 +2464,21 @@ struct nsStyleSVG {
   }
 
   nsChangeHint CalcDifference(const nsStyleSVG& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_CombineHint(NS_CombineHint(nsChangeHint_UpdateEffects,
              NS_CombineHint(nsChangeHint_NeedReflow, nsChangeHint_NeedDirtyReflow)), // XXX remove nsChangeHint_NeedDirtyReflow: bug 876085
                                          nsChangeHint_RepaintFrame);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow as an inherited hint
+    // and never returns nsChangeHint_ClearAncestorIntrinsics at all.
+    return nsChangeHint_NeedReflow;
+  }
 
   nsStyleSVGPaint  mFill;             // [inherited]
   nsStyleSVGPaint  mStroke;           // [inherited]
   nsCOMPtr<nsIURI> mMarkerEnd;        // [inherited]
   nsCOMPtr<nsIURI> mMarkerMid;        // [inherited]
   nsCOMPtr<nsIURI> mMarkerStart;      // [inherited]
   nsStyleCoord    *mStrokeDasharray;  // [inherited] coord, percent, factor
 
@@ -2472,16 +2597,22 @@ struct nsStyleSVGReset {
     aContext->FreeToShell(sizeof(nsStyleSVGReset), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const;
   static nsChangeHint MaxDifference() {
     return NS_CombineHint(nsChangeHint_UpdateEffects,
             NS_CombineHint(nsChangeHint_UpdateOverflow, NS_STYLE_HINT_REFLOW));
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics as inherited hints.
+    return NS_CombineHint(nsChangeHint_NeedReflow,
+                          nsChangeHint_ClearAncestorIntrinsics);
+  }
 
   // The backend only supports one SVG reference right now.
   // Eventually, it will support multiple chained SVG reference filters and CSS
   // filter functions.
   nsIURI* SingleFilter() const {
     return (mFilters.Length() == 1 &&
             mFilters[0].GetType() == NS_STYLE_FILTER_URL) ?
             mFilters[0].GetURL() : nullptr;
@@ -2514,13 +2645,18 @@ struct nsStyleVariables {
     this->~nsStyleVariables();
     aContext->FreeToShell(sizeof(nsStyleVariables), this);
   }
 
   nsChangeHint CalcDifference(const nsStyleVariables& aOther) const;
   static nsChangeHint MaxDifference() {
     return nsChangeHint(0);
   }
+  static nsChangeHint MaxDifferenceNeverInherited() {
+    // CalcDifference never returns nsChangeHint_NeedReflow or
+    // nsChangeHint_ClearAncestorIntrinsics at all.
+    return nsChangeHint(0);
+  }
 
   mozilla::CSSVariableValues mVariables;
 };
 
 #endif /* nsStyleStruct_h___ */