Bug 1202512 - Part 1: Add Element flags to record whether an eRestyle_SomeDescendants restyle is pending for it. r=bzbarsky
authorCameron McCormack <cam@mcc.id.au>
Sat, 12 Sep 2015 19:08:10 +1000
changeset 294760 dc09037597461b7550f6ddc7359af6a9b80b9ed3
parent 294711 3f4912c6cf479fba90859f6cb9be99c8fd702819
child 294761 9a682ef7ea95814fc7f5781593d346931807c5da
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1202512
milestone43.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 1202512 - Part 1: Add Element flags to record whether an eRestyle_SomeDescendants restyle is pending for it. r=bzbarsky
dom/base/Element.h
layout/base/RestyleManager.cpp
layout/base/RestyleTracker.cpp
layout/base/RestyleTracker.h
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -84,28 +84,37 @@ enum {
   // it was).
   ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE =  ELEMENT_FLAG_BIT(2),
 
   // Set if the element is a potential animation-only restyle root (that
   // is, has an animation-only style change pending _and_ that style
   // change will attempt to restyle descendants).
   ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT = ELEMENT_FLAG_BIT(3),
 
-  // All of those bits together, for convenience.
-  ELEMENT_ALL_RESTYLE_FLAGS = ELEMENT_HAS_PENDING_RESTYLE |
-                              ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
-                              ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE |
-                              ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT,
+  // Set if this element has a pending restyle with an eRestyle_SomeDescendants
+  // restyle hint.
+  ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR = ELEMENT_FLAG_BIT(4),
 
   // Just the HAS_PENDING bits, for convenience
-  ELEMENT_PENDING_RESTYLE_FLAGS = ELEMENT_HAS_PENDING_RESTYLE |
-                                  ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE,
+  ELEMENT_PENDING_RESTYLE_FLAGS =
+    ELEMENT_HAS_PENDING_RESTYLE |
+    ELEMENT_HAS_PENDING_ANIMATION_ONLY_RESTYLE,
+
+  // Just the IS_POTENTIAL bits, for convenience
+  ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS =
+    ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
+    ELEMENT_IS_POTENTIAL_ANIMATION_ONLY_RESTYLE_ROOT,
+
+  // All of the restyle bits together, for convenience.
+  ELEMENT_ALL_RESTYLE_FLAGS = ELEMENT_PENDING_RESTYLE_FLAGS |
+                              ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS |
+                              ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR,
 
   // Remaining bits are for subclasses
-  ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 4
+  ELEMENT_TYPE_SPECIFIC_BITS_OFFSET = NODE_TYPE_SPECIFIC_BITS_OFFSET + 5
 };
 
 #undef ELEMENT_FLAG_BIT
 
 // Make sure we have space for our bits
 ASSERT_NODE_FLAGS_SPACE(ELEMENT_TYPE_SPECIFIC_BITS_OFFSET);
 
 namespace mozilla {
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -86,17 +86,18 @@ RestyleManager::RestyleManager(nsPresCon
   , mHoverGeneration(0)
   , mRebuildAllExtraHint(nsChangeHint(0))
   , mRebuildAllRestyleHint(nsRestyleHint(0))
   , mLastUpdateForThrottledAnimations(aPresContext->RefreshDriver()->
                                         MostRecentRefresh())
   , mAnimationGeneration(0)
   , mReframingStyleContexts(nullptr)
   , mPendingRestyles(ELEMENT_HAS_PENDING_RESTYLE |
-                     ELEMENT_IS_POTENTIAL_RESTYLE_ROOT)
+                     ELEMENT_IS_POTENTIAL_RESTYLE_ROOT |
+                     ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR)
 #ifdef DEBUG
   , mIsProcessingRestyles(false)
 #endif
 #ifdef RESTYLE_LOGGING
   , mLoggingDepth(0)
 #endif
 {
   mPendingRestyles.Init(this);
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -133,17 +133,18 @@ CollectRestyles(nsISupports* aElement,
                // to the roots list because we had the bits will be
                // completely restyled in a moment.
                (aData->mChangeHint & nsChangeHint_ReconstructFrame),
                "Why did this not get handled while processing mRestyleRoots?");
 
   // Unset the restyle bits now, so if they get readded later as we
   // process we won't clobber that adding of the bit.
   element->UnsetFlags(collector->tracker->RestyleBit() |
-                      collector->tracker->RootBit());
+                      collector->tracker->RootBit() |
+                      collector->tracker->ConditionalDescendantsBit());
 
   RestyleEnumerateData** restyleArrayPtr = collector->restyleArrayPtr;
   RestyleEnumerateData* currentRestyle = *restyleArrayPtr;
   currentRestyle->mElement = element;
   currentRestyle->mRestyleHint = aData->mRestyleHint;
   currentRestyle->mChangeHint = aData->mChangeHint;
   // We can move aData since we'll be clearing mPendingRestyles after
   // we finish enumerating it.
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -235,20 +235,20 @@ public:
   {
     NS_PRECONDITION((mRestyleBits & ~ELEMENT_ALL_RESTYLE_FLAGS) == 0,
                     "Why do we have these bits set?");
     NS_PRECONDITION((mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS) != 0,
                     "Must have a restyle flag");
     NS_PRECONDITION((mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS) !=
                       ELEMENT_PENDING_RESTYLE_FLAGS,
                     "Shouldn't have both restyle flags set");
-    NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) != 0,
+    NS_PRECONDITION((mRestyleBits & ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS) != 0,
                     "Must have root flag");
-    NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) !=
-                    (ELEMENT_ALL_RESTYLE_FLAGS & ~ELEMENT_PENDING_RESTYLE_FLAGS),
+    NS_PRECONDITION((mRestyleBits & ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS) !=
+                    ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS,
                     "Shouldn't have both root flags");
   }
 
   void Init(RestyleManager* aRestyleManager) {
     mRestyleManager = aRestyleManager;
   }
 
   uint32_t Count() const {
@@ -279,17 +279,23 @@ public:
 
   // Return our ELEMENT_HAS_PENDING_(ANIMATION_)RESTYLE bit
   uint32_t RestyleBit() const {
     return mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS;
   }
 
   // Return our ELEMENT_IS_POTENTIAL_(ANIMATION_)RESTYLE_ROOT bit
   Element::FlagsType RootBit() const {
-    return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
+    return mRestyleBits & ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS;
+  }
+
+  // Return our ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR bit if present,
+  // or 0 if it is not.
+  Element::FlagsType ConditionalDescendantsBit() const {
+    return mRestyleBits & ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR;
   }
 
   struct Hints {
     nsRestyleHint mRestyleHint;        // What we want to restyle
     nsChangeHint mChangeHint;          // The minimal change hint for "self"
     RestyleHintData mRestyleHintData;  // Data associated with mRestyleHint
   };
 
@@ -385,18 +391,19 @@ private:
   inline void ProcessOneRestyle(Element* aElement,
                                 nsRestyleHint aRestyleHint,
                                 nsChangeHint aChangeHint,
                                 const RestyleHintData& aRestyleHintData);
 
   typedef nsClassHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
   typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
   // Our restyle bits.  These will be a subset of ELEMENT_ALL_RESTYLE_FLAGS, and
-  // will include one flag from ELEMENT_PENDING_RESTYLE_FLAGS and one flag
-  // that's not in ELEMENT_PENDING_RESTYLE_FLAGS.
+  // will include one flag from ELEMENT_PENDING_RESTYLE_FLAGS, one flag
+  // from ELEMENT_POTENTIAL_RESTYLE_ROOT_FLAGS, and might also include
+  // ELEMENT_IS_CONDITIONAL_RESTYLE_ANCESTOR.
   Element::FlagsType mRestyleBits;
   RestyleManager* mRestyleManager; // Owns us
   // A hashtable that maps elements to pointers to RestyleData structs.  The
   // values only make sense if the element's current document is our
   // document and it has our RestyleBit() flag set.  In particular,
   // said bit might not be set if the element had a restyle posted and
   // then was moved around in the DOM.
   PendingRestyleTable mPendingRestyles;
@@ -434,16 +441,23 @@ RestyleTracker::AddPendingRestyleToTable
   // relevant anymore (if the flag is not set).
   if (aElement->HasFlag(RestyleBit())) {
     mPendingRestyles.Get(aElement, &existingData);
   } else {
     aElement->SetFlags(RestyleBit());
     existingData = nullptr;
   }
 
+  if (aRestyleHint & eRestyle_SomeDescendants) {
+    NS_ASSERTION(ConditionalDescendantsBit(),
+                 "why are we getting eRestyle_SomeDescendants in an "
+                 "animation-only restyle?");
+    aElement->SetFlags(ConditionalDescendantsBit());
+  }
+
   if (!existingData) {
     RestyleData* rd =
       new RestyleData(aRestyleHint, aMinChangeHint, aRestyleHintData);
 #if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
     if (profiler_feature_active("restyle")) {
       rd->mBacktrace.reset(profiler_get_backtrace());
     }
 #endif