Backed out 13 changesets (bug 1180118) for crashes on a CLOSED TREE
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 04 Aug 2015 12:20:20 +0200
changeset 287754 01576b408ea703f6abba09d8e38628723df18c75
parent 287753 538add9f7b34bad3d58a885e4ea1cdd197989bd4
child 287755 458994e3fcc9929233dfd4dfa5b1f244e2c8c732
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1180118
milestone42.0a1
backs outc65d298d7cfa96fab2fd77a009a49dc6f7513fdc
7c5ebadc3fc9d0e584731784d04c311fda1d7ccc
91a3e220538892313cc5648dd6ed03948ec11b94
15ad6049b940ffe57b13941bfed374155528eb32
9b41cd9f2bc5822f27f287f515d8fd16a4d3af6e
37493f6eef20c1dbf6d6c042a609474e93e1d996
b7ec8d4d2d7ec81147f6c37d536693a722c8f10b
cfeeae42d514010575d03a9a767fa98640ec0f34
9bcc3233f3c8f847e37aa465d9f541776db6f8da
b99c358a6fea8ee0949f3d5f877e1d88d308aaf0
4a7b7998035393642b06092c233100a4c3ebfbab
20984dfa43025254ccbebaf2f17fa1496660ef0b
ef165b896cf48ae389ffb947c7887dda8c75f002
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
Backed out 13 changesets (bug 1180118) for crashes on a CLOSED TREE Backed out changeset c65d298d7cfa (bug 1180118) Backed out changeset 7c5ebadc3fc9 (bug 1180118) Backed out changeset 91a3e2205388 (bug 1180118) Backed out changeset 15ad6049b940 (bug 1180118) Backed out changeset 9b41cd9f2bc5 (bug 1180118) Backed out changeset 37493f6eef20 (bug 1180118) Backed out changeset b7ec8d4d2d7e (bug 1180118) Backed out changeset cfeeae42d514 (bug 1180118) Backed out changeset 9bcc3233f3c8 (bug 1180118) Backed out changeset b99c358a6fea (bug 1180118) Backed out changeset 4a7b79980353 (bug 1180118) Backed out changeset 20984dfa4302 (bug 1180118) Backed out changeset ef165b896cf4 (bug 1180118)
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
layout/base/RestyleTracker.cpp
layout/base/RestyleTracker.h
layout/base/nsChangeHint.h
layout/style/AnimationCommon.cpp
layout/style/AnimationCommon.h
layout/style/CSSStyleSheet.cpp
layout/style/SVGAttrAnimationRuleProcessor.cpp
layout/style/SVGAttrAnimationRuleProcessor.h
layout/style/StyleRule.cpp
layout/style/StyleRule.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRuleProcessor.h
layout/style/nsHTMLCSSStyleSheet.cpp
layout/style/nsHTMLCSSStyleSheet.h
layout/style/nsHTMLStyleSheet.cpp
layout/style/nsHTMLStyleSheet.h
layout/style/nsIStyleRuleProcessor.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -36,18 +36,16 @@
 #include "nsIRootBox.h"
 #include "nsIDOMMutationEvent.h"
 #include "nsContentUtils.h"
 #include "nsIFrameInlines.h"
 #include "ActiveLayerTracker.h"
 #include "nsDisplayList.h"
 #include "RestyleTrackerInlines.h"
 #include "nsSMILAnimationController.h"
-#include "nsCSSRuleProcessor.h"
-#include "ChildIterator.h"
 
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
 namespace mozilla {
 
 using namespace layers;
@@ -58,25 +56,16 @@ using namespace layers;
 #ifdef RESTYLE_LOGGING
 static nsCString
 FrameTagToString(const nsIFrame* aFrame)
 {
   nsCString result;
   aFrame->ListTag(result);
   return result;
 }
-
-static nsCString
-ElementTagToString(dom::Element* aElement)
-{
-  nsCString result;
-  nsDependentAtomString buf(aElement->NodeInfo()->NameAtom());
-  result.AppendPrintf("(%s@%p)", NS_ConvertUTF16toUTF8(buf).get(), aElement);
-  return result;
-}
 #endif
 
 RestyleManager::RestyleManager(nsPresContext* aPresContext)
   : mPresContext(aPresContext)
   , mDoRebuildAllStyleData(false)
   , mInRebuildAllStyleData(false)
   , mObservingRefreshDriver(false)
   , mInStyleRefresh(false)
@@ -987,22 +976,21 @@ RestyleManager::ProcessRestyledFrames(ns
 #endif
   }
 
   aChangeList.Clear();
   return NS_OK;
 }
 
 void
-RestyleManager::RestyleElement(Element*               aElement,
-                               nsIFrame*              aPrimaryFrame,
-                               nsChangeHint           aMinHint,
-                               RestyleTracker&        aRestyleTracker,
-                               nsRestyleHint          aRestyleHint,
-                               const RestyleHintData& aRestyleHintData)
+RestyleManager::RestyleElement(Element*        aElement,
+                               nsIFrame*       aPrimaryFrame,
+                               nsChangeHint    aMinHint,
+                               RestyleTracker& aRestyleTracker,
+                               nsRestyleHint   aRestyleHint)
 {
   MOZ_ASSERT(mReframingStyleContexts, "should have rsc");
   NS_ASSERTION(aPrimaryFrame == aElement->GetPrimaryFrame(),
                "frame/content mismatch");
   if (aPrimaryFrame && aPrimaryFrame->GetContent() != aElement) {
     // XXXbz this is due to image maps messing with the primary frame pointer
     // of <area>s.  See bug 135040.  We can remove this block once that's fixed.
     aPrimaryFrame = nullptr;
@@ -1017,49 +1005,45 @@ RestyleManager::RestyleElement(Element* 
     nsStyleContext *oldContext = aPrimaryFrame->StyleContext();
     if (!oldContext->GetParent()) { // check that we're the root element
       nsRefPtr<nsStyleContext> newContext = mPresContext->StyleSet()->
         ResolveStyleFor(aElement, nullptr /* == oldContext->GetParent() */);
       if (oldContext->StyleFont()->mFont.size !=
           newContext->StyleFont()->mFont.size) {
         // The basis for 'rem' units has changed.
         mRebuildAllRestyleHint |= aRestyleHint;
-        if (aRestyleHint & eRestyle_SomeDescendants) {
-          mRebuildAllRestyleHint |= eRestyle_Subtree;
-        }
         NS_UpdateHint(mRebuildAllExtraHint, aMinHint);
         StartRebuildAllStyleData(aRestyleTracker);
         return;
       }
     }
   }
 
   if (aMinHint & nsChangeHint_ReconstructFrame) {
     FrameConstructor()->RecreateFramesForContent(aElement, false,
       nsCSSFrameConstructor::REMOVE_FOR_RECONSTRUCTION, nullptr);
   } else if (aPrimaryFrame) {
     ComputeAndProcessStyleChange(aPrimaryFrame, aMinHint, aRestyleTracker,
-                                 aRestyleHint, aRestyleHintData);
+                                 aRestyleHint);
   } else if (aRestyleHint & ~eRestyle_LaterSiblings) {
     // We're restyling an element with no frame, so we should try to
     // make one if its new style says it should have one.  But in order
     // to try to honor the restyle hint (which we'd like to do so that,
     // for example, an animation-only style flush doesn't flush other
     // buffered style changes), we only do this if the restyle hint says
     // we have *some* restyling for this frame.  This means we'll
     // potentially get ahead of ourselves in that case, but not as much
     // as we would if we didn't check the restyle hint.
     nsStyleContext* newContext =
       FrameConstructor()->MaybeRecreateFramesForElement(aElement);
     if (newContext &&
         newContext->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_CONTENTS) {
       // Style change for a display:contents node that did not recreate frames.
       ComputeAndProcessStyleChange(newContext, aElement, aMinHint,
-                                   aRestyleTracker, aRestyleHint,
-                                   aRestyleHintData);
+                                   aRestyleTracker, aRestyleHint);
     }
   }
 }
 
 RestyleManager::ReframingStyleContexts::ReframingStyleContexts(
                                           RestyleManager* aRestyleManager)
   : mRestyleManager(aRestyleManager)
   , mRestorePointer(mRestyleManager->mReframingStyleContexts)
@@ -1174,25 +1158,23 @@ RestyleManager::ContentStateChanged(nsIC
 // Forwarded nsIMutationObserver method, to handle restyling.
 void
 RestyleManager::AttributeWillChange(Element* aElement,
                                     int32_t aNameSpaceID,
                                     nsIAtom* aAttribute,
                                     int32_t aModType,
                                     const nsAttrValue* aNewValue)
 {
-  RestyleHintData rsdata;
   nsRestyleHint rshint =
     mPresContext->StyleSet()->HasAttributeDependentStyle(aElement,
                                                          aAttribute,
                                                          aModType,
                                                          false,
-                                                         aNewValue,
-                                                         rsdata);
-  PostRestyleEvent(aElement, rshint, NS_STYLE_HINT_NONE, &rsdata);
+                                                         aNewValue);
+  PostRestyleEvent(aElement, rshint, NS_STYLE_HINT_NONE);
 }
 
 // Forwarded nsIMutationObserver method, to handle restyling (and
 // passing the notification to the frame).
 void
 RestyleManager::AttributeChanged(Element* aElement,
                                  int32_t aNameSpaceID,
                                  nsIAtom* aAttribute,
@@ -1265,25 +1247,24 @@ RestyleManager::AttributeChanged(Element
     // XXXwaterson should probably check for IB split siblings
     // here, and propagate the AttributeChanged notification to
     // them, as well. Currently, inline frames don't do anything on
     // this notification, so it's not that big a deal.
   }
 
   // See if we can optimize away the style re-resolution -- must be called after
   // the frame's AttributeChanged() in case it does something that affects the style
-  RestyleHintData rsdata;
   nsRestyleHint rshint =
     mPresContext->StyleSet()->HasAttributeDependentStyle(aElement,
                                                          aAttribute,
                                                          aModType,
                                                          true,
-                                                         aOldValue,
-                                                         rsdata);
-  PostRestyleEvent(aElement, rshint, hint, &rsdata);
+                                                         aOldValue);
+
+  PostRestyleEvent(aElement, rshint, hint);
 }
 
 /* static */ uint64_t
 RestyleManager::GetMaxAnimationGenerationForFrame(nsIFrame* aFrame)
 {
   nsIContent* content = aFrame->GetContent();
   if (!content || !content->IsElement()) {
     return 0;
@@ -1570,19 +1551,16 @@ RestyleManager::RestyleForRemove(Element
 
 void
 RestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint,
                                     nsRestyleHint aRestyleHint)
 {
   NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
                "Should not reconstruct the root of the frame tree.  "
                "Use ReconstructDocElementHierarchy instead.");
-  MOZ_ASSERT(!(aRestyleHint & ~(eRestyle_Subtree | eRestyle_ForceDescendants)),
-             "the only bits allowed in aRestyleHint are eRestyle_Subtree and "
-             "eRestyle_ForceDescendants");
 
   NS_UpdateHint(mRebuildAllExtraHint, aExtraHint);
   mRebuildAllRestyleHint |= aRestyleHint;
 
   // Processing the style changes could cause a flush that propagates to
   // the parent frame and thus destroys the pres shell, so we must hold
   // a reference.
   nsCOMPtr<nsIPresShell> presShell = mPresContext->GetPresShell();
@@ -1654,18 +1632,17 @@ RestyleManager::StartRebuildAllStyleData
   // root frame.  We can't do this with a change hint, since we can't
   // post a change hint for the root frame.
   // Note that we can ignore the return value of ComputeStyleChangeFor
   // because we never need to reframe the root frame.
   // XXX Does it matter that we're passing aExtraHint to the real root
   // frame and not the root node's primary frame?  (We could do
   // roughly what we do for aRestyleHint above.)
   ComputeAndProcessStyleChange(rootFrame,
-                               changeHint, aRestyleTracker, restyleHint,
-                               RestyleHintData());
+                               changeHint, aRestyleTracker, restyleHint);
 }
 
 void
 RestyleManager::FinishRebuildAllStyleData()
 {
   MOZ_ASSERT(mInRebuildAllStyleData, "bad caller");
 
   // Tell the style set it's safe to destroy the old rule tree.  We
@@ -1837,31 +1814,29 @@ RestyleManager::UpdateOnlyAnimationStyle
   ProcessRestyles(tracker);
 
   transitionManager->SetInAnimationOnlyStyleUpdate(false);
 }
 
 void
 RestyleManager::PostRestyleEvent(Element* aElement,
                                  nsRestyleHint aRestyleHint,
-                                 nsChangeHint aMinChangeHint,
-                                 const RestyleHintData* aRestyleHintData)
+                                 nsChangeHint aMinChangeHint)
 {
   if (MOZ_UNLIKELY(!mPresContext) ||
       MOZ_UNLIKELY(mPresContext->PresShell()->IsDestroying())) {
     return;
   }
 
   if (aRestyleHint == 0 && !aMinChangeHint) {
     // Nothing to do here
     return;
   }
 
-  mPendingRestyles.AddPendingRestyle(aElement, aRestyleHint, aMinChangeHint,
-                                     aRestyleHintData);
+  mPendingRestyles.AddPendingRestyle(aElement, aRestyleHint, aMinChangeHint);
 
   // Set mHavePendingNonAnimationRestyles for any restyle that could
   // possibly contain non-animation styles (i.e., those that require us
   // to do an animation-only style flush before processing style changes
   // to ensure correct initialization of CSS transitions).
   if (aRestyleHint & ~eRestyle_AllHintsWithAnimations) {
     mHavePendingNonAnimationRestyles = true;
   }
@@ -1890,19 +1865,16 @@ RestyleManager::PostRestyleEventInternal
 
 void
 RestyleManager::PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
                                              nsRestyleHint aRestyleHint)
 {
   NS_ASSERTION(!(aExtraHint & nsChangeHint_ReconstructFrame),
                "Should not reconstruct the root of the frame tree.  "
                "Use ReconstructDocElementHierarchy instead.");
-  MOZ_ASSERT(!(aRestyleHint & eRestyle_SomeDescendants),
-             "PostRebuildAllStyleDataEvent does not handle "
-             "eRestyle_SomeDescendants");
 
   mDoRebuildAllStyleData = true;
   NS_UpdateHint(mRebuildAllExtraHint, aExtraHint);
   mRebuildAllRestyleHint |= aRestyleHint;
 
   // Get a restyle event posted if necessary
   PostRestyleEventInternal(false);
 }
@@ -2490,18 +2462,16 @@ RestyleManager::ReparentStyleContext(nsI
   return NS_OK;
 }
 
 ElementRestyler::ElementRestyler(nsPresContext* aPresContext,
                                  nsIFrame* aFrame,
                                  nsStyleChangeList* aChangeList,
                                  nsChangeHint aHintsHandledByAncestors,
                                  RestyleTracker& aRestyleTracker,
-                                 nsTArray<nsCSSSelector*>&
-                                   aSelectorsForDescendants,
                                  TreeMatchContext& aTreeMatchContext,
                                  nsTArray<nsIContent*>&
                                    aVisibleKidsOfHiddenElement,
                                  nsTArray<ContextToClear>& aContextsToClear,
                                  nsTArray<nsRefPtr<nsStyleContext>>&
                                    aSwappedStructOwners)
   : mPresContext(aPresContext)
   , mFrame(aFrame)
@@ -2510,17 +2480,16 @@ ElementRestyler::ElementRestyler(nsPresC
     // comment above assertion at start of ElementRestyler::Restyle.)
   , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
   , mChangeList(aChangeList)
   , mHintsHandled(NS_SubtractHint(aHintsHandledByAncestors,
                   NS_HintsNotHandledForDescendantsIn(aHintsHandledByAncestors)))
   , mParentFrameHintsNotHandledForDescendants(nsChangeHint(0))
   , mHintsNotHandledForDescendants(nsChangeHint(0))
   , mRestyleTracker(aRestyleTracker)
-  , mSelectorsForDescendants(aSelectorsForDescendants)
   , mTreeMatchContext(aTreeMatchContext)
   , mResolvedChild(nullptr)
   , mContextsToClear(aContextsToClear)
   , mSwappedStructOwners(aSwappedStructOwners)
 #ifdef ACCESSIBILITY
   , mDesiredA11yNotifications(eSendAllNotifications)
   , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
   , mOurA11yNotification(eDontNotify)
@@ -2543,17 +2512,16 @@ ElementRestyler::ElementRestyler(const E
   , mContent(mFrame->GetContent() ? mFrame->GetContent() : mParentContent)
   , mChangeList(aParentRestyler.mChangeList)
   , mHintsHandled(NS_SubtractHint(aParentRestyler.mHintsHandled,
                   NS_HintsNotHandledForDescendantsIn(aParentRestyler.mHintsHandled)))
   , mParentFrameHintsNotHandledForDescendants(
       aParentRestyler.mHintsNotHandledForDescendants)
   , mHintsNotHandledForDescendants(nsChangeHint(0))
   , mRestyleTracker(aParentRestyler.mRestyleTracker)
-  , mSelectorsForDescendants(aParentRestyler.mSelectorsForDescendants)
   , mTreeMatchContext(aParentRestyler.mTreeMatchContext)
   , mResolvedChild(nullptr)
   , mContextsToClear(aParentRestyler.mContextsToClear)
   , mSwappedStructOwners(aParentRestyler.mSwappedStructOwners)
 #ifdef ACCESSIBILITY
   , mDesiredA11yNotifications(aParentRestyler.mKidsDesiredA11yNotifications)
   , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
   , mOurA11yNotification(eDontNotify)
@@ -2590,17 +2558,16 @@ ElementRestyler::ElementRestyler(ParentC
   , mChangeList(aParentRestyler.mChangeList)
   , mHintsHandled(NS_SubtractHint(aParentRestyler.mHintsHandled,
                   NS_HintsNotHandledForDescendantsIn(aParentRestyler.mHintsHandled)))
   , mParentFrameHintsNotHandledForDescendants(
       // assume the worst
       nsChangeHint_Hints_NotHandledForDescendants)
   , mHintsNotHandledForDescendants(nsChangeHint(0))
   , mRestyleTracker(aParentRestyler.mRestyleTracker)
-  , mSelectorsForDescendants(aParentRestyler.mSelectorsForDescendants)
   , mTreeMatchContext(aParentRestyler.mTreeMatchContext)
   , mResolvedChild(nullptr)
   , mContextsToClear(aParentRestyler.mContextsToClear)
   , mSwappedStructOwners(aParentRestyler.mSwappedStructOwners)
 #ifdef ACCESSIBILITY
   , mDesiredA11yNotifications(aParentRestyler.mDesiredA11yNotifications)
   , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
   , mOurA11yNotification(eDontNotify)
@@ -2612,34 +2579,32 @@ ElementRestyler::ElementRestyler(ParentC
 {
 }
 
 ElementRestyler::ElementRestyler(nsPresContext* aPresContext,
                                  nsIContent* aContent,
                                  nsStyleChangeList* aChangeList,
                                  nsChangeHint aHintsHandledByAncestors,
                                  RestyleTracker& aRestyleTracker,
-                                 nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
                                  TreeMatchContext& aTreeMatchContext,
                                  nsTArray<nsIContent*>&
                                    aVisibleKidsOfHiddenElement,
                                  nsTArray<ContextToClear>& aContextsToClear,
                                  nsTArray<nsRefPtr<nsStyleContext>>&
                                    aSwappedStructOwners)
   : mPresContext(aPresContext)
   , mFrame(nullptr)
   , mParentContent(nullptr)
   , mContent(aContent)
   , mChangeList(aChangeList)
   , mHintsHandled(NS_SubtractHint(aHintsHandledByAncestors,
                   NS_HintsNotHandledForDescendantsIn(aHintsHandledByAncestors)))
   , mParentFrameHintsNotHandledForDescendants(nsChangeHint(0))
   , mHintsNotHandledForDescendants(nsChangeHint(0))
   , mRestyleTracker(aRestyleTracker)
-  , mSelectorsForDescendants(aSelectorsForDescendants)
   , mTreeMatchContext(aTreeMatchContext)
   , mResolvedChild(nullptr)
   , mContextsToClear(aContextsToClear)
   , mSwappedStructOwners(aSwappedStructOwners)
 #ifdef ACCESSIBILITY
   , mDesiredA11yNotifications(eSendAllNotifications)
   , mKidsDesiredA11yNotifications(mDesiredA11yNotifications)
   , mOurA11yNotification(eDontNotify)
@@ -2729,101 +2694,16 @@ ElementRestyler::CaptureChange(nsStyleCo
     }
   }
   NS_UpdateHint(mHintsNotHandledForDescendants,
                 NS_HintsNotHandledForDescendantsIn(ourChange));
   LOG_RESTYLE("mHintsNotHandledForDescendants = %s",
               RestyleManager::ChangeHintToString(mHintsNotHandledForDescendants).get());
 }
 
-class MOZ_STACK_CLASS AutoSelectorArrayTruncater final
-{
-public:
-  explicit AutoSelectorArrayTruncater(nsTArray<nsCSSSelector*>& aSelectorsForDescendants)
-    : mSelectorsForDescendants(aSelectorsForDescendants)
-    , mOriginalLength(aSelectorsForDescendants.Length())
-  {
-  }
-
-  ~AutoSelectorArrayTruncater()
-  {
-    mSelectorsForDescendants.TruncateLength(mOriginalLength);
-  }
-
-private:
-  nsTArray<nsCSSSelector*>& mSelectorsForDescendants;
-  size_t mOriginalLength;
-};
-
-/**
- * Called when we are stopping a restyle with eRestyle_SomeDescendants, to
- * search for descendants that match any of the selectors in
- * mSelectorsForDescendants.  If the element does match one of the selectors,
- * we cause it to be restyled with eRestyle_Self.
- *
- * We traverse down the flattened tree unless we find an element that
- * (a) already has a pending restyle, or (b) does not have a pending restyle
- * but does match one of the selectors in mSelectorsForDescendants.  For (a),
- * we add the current mSelectorsForDescendants into the existing restyle data,
- * and for (b) we add a new pending restyle with that array.  So in both
- * cases, when we come to restyling this element back up in
- * ProcessPendingRestyles, we will again find the eRestyle_SomeDescendants
- * hint and its selectors array.
- *
- * This ensures that we don't visit descendant elements and check them
- * against mSelectorsForDescendants more than once.
- */
-void
-ElementRestyler::AddPendingRestylesForDescendantsMatchingSelectors(
-    Element* aElement,
-    Element* aRestyleRoot)
-{
-  LOG_RESTYLE("considering element %s for eRestyle_SomeDescendants",
-              ElementTagToString(aElement).get());
-  LOG_RESTYLE_INDENT();
-
-  if (aElement->HasFlag(mRestyleTracker.RootBit())) {
-    aRestyleRoot = aElement;
-  }
-
-  if (mRestyleTracker.HasRestyleData(aElement)) {
-    nsRestyleHint rshint = eRestyle_SomeDescendants;
-    if (SelectorMatchesForRestyle(aElement)) {
-      LOG_RESTYLE("element has existing restyle data and matches a selector");
-      rshint |= eRestyle_Self;
-    } else {
-      LOG_RESTYLE("element has existing restyle data but doesn't match selectors");
-    }
-    RestyleHintData data;
-    data.mSelectorsForDescendants = mSelectorsForDescendants;
-    mRestyleTracker.AddPendingRestyle(aElement, rshint, nsChangeHint(0), &data,
-                                      Some(aRestyleRoot));
-    return;
-  }
-
-  if (SelectorMatchesForRestyle(aElement)) {
-    LOG_RESTYLE("element has no restyle data but matches a selector");
-    RestyleHintData data;
-    data.mSelectorsForDescendants = mSelectorsForDescendants;
-    mRestyleTracker.AddPendingRestyle(aElement,
-                                      eRestyle_Self | eRestyle_SomeDescendants,
-                                      nsChangeHint(0), &data,
-                                      Some(aRestyleRoot));
-    return;
-  }
-
-  FlattenedChildIterator it(aElement);
-  for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
-    if (n->IsElement()) {
-      AddPendingRestylesForDescendantsMatchingSelectors(n->AsElement(),
-                                                        aRestyleRoot);
-    }
-  }
-}
-
 /**
  * Recompute style for mFrame (which should not have a prev continuation
  * with the same style), all of its next continuations with the same
  * style, and all ib-split siblings of the same type (either block or
  * inline, skipping the intermediates of the other type) and accumulate
  * changes into mChangeList given that mHintsHandled is already accumulated
  * for an ancestor.
  * mParentContent is the content node used to resolve the parent style
@@ -2850,26 +2730,23 @@ ElementRestyler::Restyle(nsRestyleHint a
                "should not be trying to restyle this frame separately");
 
   MOZ_ASSERT(!(aRestyleHint & eRestyle_LaterSiblings),
              "eRestyle_LaterSiblings must not be part of aRestyleHint");
 
   AutoDisplayContentsAncestorPusher adcp(mTreeMatchContext, mFrame->PresContext(),
       mFrame->GetContent() ? mFrame->GetContent()->GetParent() : nullptr);
 
-  AutoSelectorArrayTruncater asat(mSelectorsForDescendants);
-
   // List of descendant elements of mContent we know we will eventually need to
   // restyle.  Before we return from this function, we call
   // RestyleTracker::AddRestyleRootsIfAwaitingRestyle to ensure they get
   // restyled in RestyleTracker::DoProcessRestyles.
   nsTArray<nsRefPtr<Element>> descendants;
 
   nsRestyleHint hintToRestore = nsRestyleHint(0);
-  RestyleHintData hintDataToRestore;
   if (mContent && mContent->IsElement() &&
       // If we're resolving from the root of the frame tree (which
       // we do when mDoRebuildAllStyleData), we need to avoid getting the
       // root's restyle data until we get to its primary frame, since
       // it's the primary frame that has the styles for the root element
       // (rather than the ancestors of the primary frame whose mContent
       // is the root node but which have different styles).  If we use
       // up the hint for one of the ancestors that we hit first, then
@@ -2881,31 +2758,27 @@ ElementRestyler::Restyle(nsRestyleHint a
       // for the inner frame.
       mContent->GetPrimaryFrame() == mFrame) {
     mContent->OwnerDoc()->FlushPendingLinkUpdates();
     nsAutoPtr<RestyleTracker::RestyleData> restyleData;
     if (mRestyleTracker.GetRestyleData(mContent->AsElement(), restyleData)) {
       if (NS_UpdateHint(mHintsHandled, restyleData->mChangeHint)) {
         mChangeList->AppendChange(mFrame, mContent, restyleData->mChangeHint);
       }
-      mSelectorsForDescendants.AppendElements(
-          restyleData->mRestyleHintData.mSelectorsForDescendants);
       hintToRestore = restyleData->mRestyleHint;
-      hintDataToRestore = Move(restyleData->mRestyleHintData);
       aRestyleHint = nsRestyleHint(aRestyleHint | restyleData->mRestyleHint);
       descendants.SwapElements(restyleData->mDescendants);
     }
   }
 
   // If we are restyling this frame with eRestyle_Self or weaker hints,
   // we restyle children with nsRestyleHint(0).  But we pass the
   // eRestyle_ForceDescendants flag down too.
   nsRestyleHint childRestyleHint =
-    nsRestyleHint(aRestyleHint & (eRestyle_SomeDescendants |
-                                  eRestyle_Subtree |
+    nsRestyleHint(aRestyleHint & (eRestyle_Subtree |
                                   eRestyle_ForceDescendants));
 
   nsRefPtr<nsStyleContext> oldContext = mFrame->StyleContext();
 
   // TEMPORARY (until bug 918064):  Call RestyleSelf for each
   // continuation or block-in-inline sibling.
 
   // We must make a single decision on how to process this frame and
@@ -2998,41 +2871,16 @@ ElementRestyler::Restyle(nsRestyleHint a
     // Send the accessibility notifications that RestyleChildren otherwise
     // would have sent.
     if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
       InitializeAccessibilityNotifications(mFrame->StyleContext());
       SendAccessibilityNotifications();
     }
 
     mRestyleTracker.AddRestyleRootsIfAwaitingRestyle(descendants);
-
-    if (mContent->IsElement()) {
-      if ((aRestyleHint & eRestyle_SomeDescendants) &&
-          !mSelectorsForDescendants.IsEmpty()) {
-        Element* element = mContent->AsElement();
-        LOG_RESTYLE("traversing descendants of element %s to propagate "
-                    "eRestyle_SomeDescendants for these %d selectors:",
-                    ElementTagToString(element).get(),
-                    int(mSelectorsForDescendants.Length()));
-        LOG_RESTYLE_INDENT();
-#ifdef RESTYLE_LOGGING
-        for (nsCSSSelector* sel : mSelectorsForDescendants) {
-          LOG_RESTYLE("%s", sel->RestrictedSelectorToString().get());
-        }
-#endif
-        Element* restyleRoot = mRestyleTracker.FindClosestRestyleRoot(element);
-        FlattenedChildIterator it(element);
-        for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
-          if (n->IsElement()) {
-            AddPendingRestylesForDescendantsMatchingSelectors(n->AsElement(),
-                                                              restyleRoot);
-          }
-        }
-      }
-    }
     return;
   }
 
   if (!swappedStructs) {
     // If we swapped any structs from the old context, then we need to keep
     // it alive until after the RestyleChildren call so that we can fix up
     // its descendants' cached structs.
     oldContext = nullptr;
@@ -3224,54 +3072,16 @@ ElementRestyler::ComputeRestyleResultFro
     LOG_RESTYLE_CONTINUE("NS_STYLE_IN_DISPLAY_NONE_SUBTREE differs between old"
                          " and new style contexts");
     return eRestyleResult_Continue;
   }
 
   return eRestyleResult_Stop;
 }
 
-bool
-ElementRestyler::SelectorMatchesForRestyle(Element* aElement)
-{
-  if (!aElement) {
-    return false;
-  }
-  for (nsCSSSelector* selector : mSelectorsForDescendants) {
-    if (nsCSSRuleProcessor::RestrictedSelectorMatches(aElement, selector,
-                                                      mTreeMatchContext)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool
-ElementRestyler::MustRestyleSelf(nsRestyleHint aRestyleHint,
-                                 Element* aElement)
-{
-  return (aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) ||
-         ((aRestyleHint & eRestyle_SomeDescendants) &&
-          SelectorMatchesForRestyle(aElement));
-}
-
-bool
-ElementRestyler::CanReparentStyleContext(nsRestyleHint aRestyleHint)
-{
-  // If we had any restyle hints other than the ones listed below,
-  // which don't control whether the current frame/element needs
-  // a new style context by looking up a new rule node, or if
-  // we are reconstructing the entire rule tree, then we can't
-  // use ReparentStyleContext.
-  return !(aRestyleHint & ~(eRestyle_Force |
-                            eRestyle_ForceDescendants |
-                            eRestyle_SomeDescendants)) &&
-         !mPresContext->StyleSet()->IsInRuleTreeReconstruct();
-}
-
 ElementRestyler::RestyleResult
 ElementRestyler::RestyleSelf(nsIFrame* aSelf,
                              nsRestyleHint aRestyleHint,
                              uint32_t* aSwappedStructs)
 {
   MOZ_ASSERT(!(aRestyleHint & eRestyle_LaterSiblings),
              "eRestyle_LaterSiblings must not be part of aRestyleHint");
 
@@ -3285,17 +3095,17 @@ ElementRestyler::RestyleSelf(nsIFrame* a
 
   LOG_RESTYLE("RestyleSelf %s, aRestyleHint = %s",
               FrameTagToString(aSelf).get(),
               RestyleManager::RestyleHintToString(aRestyleHint).get());
   LOG_RESTYLE_INDENT();
 
   RestyleResult result;
 
-  if (aRestyleHint & ~eRestyle_SomeDescendants) {
+  if (aRestyleHint) {
     result = eRestyleResult_Continue;
   } else {
     result = ComputeRestyleResultFromFrame(aSelf);
   }
 
   nsChangeHint assumeDifferenceHint = NS_STYLE_HINT_NONE;
   nsRefPtr<nsStyleContext> oldContext = aSelf->StyleContext();
   nsStyleSet* styleSet = mPresContext->StyleSet();
@@ -3370,100 +3180,99 @@ ElementRestyler::RestyleSelf(nsIFrame* a
     LOG_RESTYLE("using previous continuation's context");
     newContext = prevContinuationContext;
   }
   else if (pseudoTag == nsCSSAnonBoxes::mozNonElement) {
     NS_ASSERTION(aSelf->GetContent(),
                  "non pseudo-element frame without content node");
     newContext = styleSet->ResolveStyleForNonElement(parentContext);
   }
+  else if (!(aRestyleHint & (eRestyle_Self | eRestyle_Subtree))) {
+    Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
+    if (!(aRestyleHint & ~(eRestyle_Force | eRestyle_ForceDescendants)) &&
+        !styleSet->IsInRuleTreeReconstruct()) {
+      LOG_RESTYLE("reparenting style context");
+      newContext =
+        styleSet->ReparentStyleContext(oldContext, parentContext, element);
+    } else {
+      // Use ResolveStyleWithReplacement either for actual replacements
+      // or, with no replacements, as a substitute for
+      // ReparentStyleContext that rebuilds the path in the rule tree
+      // rather than reusing the rule node, as we need to do during a
+      // rule tree reconstruct.
+      Element* pseudoElement = PseudoElementForStyleContext(aSelf, pseudoType);
+      MOZ_ASSERT(!element || element != pseudoElement,
+                 "pseudo-element for selector matching should be "
+                 "the anonymous content node that we create, "
+                 "not the real element");
+      LOG_RESTYLE("resolving style with replacement");
+      newContext =
+        styleSet->ResolveStyleWithReplacement(element, pseudoElement,
+                                              parentContext, oldContext,
+                                              aRestyleHint);
+    }
+  } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
+    newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
+                                                    parentContext);
+  }
   else {
     Element* element = ElementForStyleContext(mParentContent, aSelf, pseudoType);
-    if (!MustRestyleSelf(aRestyleHint, element)) {
-      if (CanReparentStyleContext(aRestyleHint)) {
-        LOG_RESTYLE("reparenting style context");
-        newContext =
-          styleSet->ReparentStyleContext(oldContext, parentContext, element);
+    if (pseudoTag) {
+      if (pseudoTag == nsCSSPseudoElements::before ||
+          pseudoTag == nsCSSPseudoElements::after) {
+        // XXX what other pseudos do we need to treat like this?
+        newContext = styleSet->ProbePseudoElementStyle(element,
+                                                       pseudoType,
+                                                       parentContext,
+                                                       mTreeMatchContext);
+        if (!newContext) {
+          // This pseudo should no longer exist; gotta reframe
+          NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
+          mChangeList->AppendChange(aSelf, element,
+                                    nsChangeHint_ReconstructFrame);
+          // We're reframing anyway; just keep the same context
+          newContext = oldContext;
+#ifdef DEBUG
+          // oldContext's parent might have had its style structs swapped out
+          // with parentContext, so to avoid any assertions that might
+          // otherwise trigger in oldContext's parent's destructor, we set a
+          // flag on oldContext to skip it and its descendants in
+          // nsStyleContext::AssertStructsNotUsedElsewhere.
+          if (oldContext->GetParent() != parentContext) {
+            oldContext->AddStyleBit(NS_STYLE_IS_GOING_AWAY);
+          }
+#endif
+        }
       } else {
-        // Use ResolveStyleWithReplacement either for actual replacements
-        // or, with no replacements, as a substitute for
-        // ReparentStyleContext that rebuilds the path in the rule tree
-        // rather than reusing the rule node, as we need to do during a
-        // rule tree reconstruct.
-        Element* pseudoElement = PseudoElementForStyleContext(aSelf, pseudoType);
-        MOZ_ASSERT(!element || element != pseudoElement,
+        // Don't expect XUL tree stuff here, since it needs a comparator and
+        // all.
+        NS_ASSERTION(pseudoType <
+                       nsCSSPseudoElements::ePseudo_PseudoElementCount,
+                     "Unexpected pseudo type");
+        Element* pseudoElement =
+          PseudoElementForStyleContext(aSelf, pseudoType);
+        MOZ_ASSERT(element != pseudoElement,
                    "pseudo-element for selector matching should be "
                    "the anonymous content node that we create, "
                    "not the real element");
-        LOG_RESTYLE("resolving style with replacement");
-        nsRestyleHint rshint = aRestyleHint & ~eRestyle_SomeDescendants;
-        newContext =
-          styleSet->ResolveStyleWithReplacement(element, pseudoElement,
-                                                parentContext, oldContext,
-                                                rshint);
-      }
-    } else if (pseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
-      newContext = styleSet->ResolveAnonymousBoxStyle(pseudoTag,
-                                                      parentContext);
-    }
-    else {
-      if (pseudoTag) {
-        if (pseudoTag == nsCSSPseudoElements::before ||
-            pseudoTag == nsCSSPseudoElements::after) {
-          // XXX what other pseudos do we need to treat like this?
-          newContext = styleSet->ProbePseudoElementStyle(element,
+        newContext = styleSet->ResolvePseudoElementStyle(element,
                                                          pseudoType,
                                                          parentContext,
-                                                         mTreeMatchContext);
-          if (!newContext) {
-            // This pseudo should no longer exist; gotta reframe
-            NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-            mChangeList->AppendChange(aSelf, element,
-                                      nsChangeHint_ReconstructFrame);
-            // We're reframing anyway; just keep the same context
-            newContext = oldContext;
-#ifdef DEBUG
-            // oldContext's parent might have had its style structs swapped out
-            // with parentContext, so to avoid any assertions that might
-            // otherwise trigger in oldContext's parent's destructor, we set a
-            // flag on oldContext to skip it and its descendants in
-            // nsStyleContext::AssertStructsNotUsedElsewhere.
-            if (oldContext->GetParent() != parentContext) {
-              oldContext->AddStyleBit(NS_STYLE_IS_GOING_AWAY);
-            }
-#endif
-          }
-        } else {
-          // Don't expect XUL tree stuff here, since it needs a comparator and
-          // all.
-          NS_ASSERTION(pseudoType <
-                         nsCSSPseudoElements::ePseudo_PseudoElementCount,
-                       "Unexpected pseudo type");
-          Element* pseudoElement =
-            PseudoElementForStyleContext(aSelf, pseudoType);
-          MOZ_ASSERT(element != pseudoElement,
-                     "pseudo-element for selector matching should be "
-                     "the anonymous content node that we create, "
-                     "not the real element");
-          newContext = styleSet->ResolvePseudoElementStyle(element,
-                                                           pseudoType,
-                                                           parentContext,
-                                                           pseudoElement);
-        }
+                                                         pseudoElement);
       }
-      else {
-        NS_ASSERTION(aSelf->GetContent(),
-                     "non pseudo-element frame without content node");
-        // Skip parent display based style fixup for anonymous subtrees:
-        TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper
-          parentDisplayBasedFixupSkipper(mTreeMatchContext,
-                                 element->IsRootOfNativeAnonymousSubtree());
-        newContext = styleSet->ResolveStyleFor(element, parentContext,
-                                               mTreeMatchContext);
-      }
+    }
+    else {
+      NS_ASSERTION(aSelf->GetContent(),
+                   "non pseudo-element frame without content node");
+      // Skip parent display based style fixup for anonymous subtrees:
+      TreeMatchContext::AutoParentDisplayBasedStyleFixupSkipper
+        parentDisplayBasedFixupSkipper(mTreeMatchContext,
+                               element->IsRootOfNativeAnonymousSubtree());
+      newContext = styleSet->ResolveStyleFor(element, parentContext,
+                                             mTreeMatchContext);
     }
   }
 
   MOZ_ASSERT(newContext);
 
   if (!parentContext) {
     if (oldContext->RuleNode() == newContext->RuleNode() &&
         oldContext->IsLinkContext() == newContext->IsLinkContext() &&
@@ -3643,37 +3452,37 @@ ElementRestyler::RestyleSelf(nsIFrame* a
     LOG_RESTYLE_INDENT();
     nsRefPtr<nsStyleContext> newExtraContext;
     nsIAtom* const extraPseudoTag = oldExtraContext->GetPseudo();
     const nsCSSPseudoElements::Type extraPseudoType =
       oldExtraContext->GetPseudoType();
     NS_ASSERTION(extraPseudoTag &&
                  extraPseudoTag != nsCSSAnonBoxes::mozNonElement,
                  "extra style context is not pseudo element");
-    Element* element = extraPseudoType != nsCSSPseudoElements::ePseudo_AnonBox
-                         ? mContent->AsElement() : nullptr;
-    if (!MustRestyleSelf(aRestyleHint, element)) {
-      if (CanReparentStyleContext(aRestyleHint)) {
-        newExtraContext =
-          styleSet->ReparentStyleContext(oldExtraContext, newContext, element);
-      } else {
+    if (!(aRestyleHint & (eRestyle_Self | eRestyle_Subtree))) {
+      Element* element = extraPseudoType != nsCSSPseudoElements::ePseudo_AnonBox
+                           ? mContent->AsElement() : nullptr;
+      if (styleSet->IsInRuleTreeReconstruct()) {
         // Use ResolveStyleWithReplacement as a substitute for
         // ReparentStyleContext that rebuilds the path in the rule tree
         // rather than reusing the rule node, as we need to do during a
         // rule tree reconstruct.
         Element* pseudoElement =
           PseudoElementForStyleContext(aSelf, extraPseudoType);
         MOZ_ASSERT(!element || element != pseudoElement,
                    "pseudo-element for selector matching should be "
                    "the anonymous content node that we create, "
                    "not the real element");
         newExtraContext =
           styleSet->ResolveStyleWithReplacement(element, pseudoElement,
                                                 newContext, oldExtraContext,
                                                 nsRestyleHint(0));
+      } else {
+        newExtraContext =
+          styleSet->ReparentStyleContext(oldExtraContext, newContext, element);
       }
     } else if (extraPseudoType == nsCSSPseudoElements::ePseudo_AnonBox) {
       newExtraContext = styleSet->ResolveAnonymousBoxStyle(extraPseudoTag,
                                                            newContext);
     } else {
       // Don't expect XUL tree stuff here, since it needs a comparator and
       // all.
       NS_ASSERTION(extraPseudoType <
@@ -3772,22 +3581,21 @@ ElementRestyler::RestyleChildren(nsResty
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame) &&
       mightReframePseudos) {
     MaybeReframeForAfterPseudo(lastContinuation);
   }
 }
 
 void
 ElementRestyler::RestyleChildrenOfDisplayContentsElement(
-  nsIFrame*              aParentFrame,
-  nsStyleContext*        aNewContext,
-  nsChangeHint           aMinHint,
-  RestyleTracker&        aRestyleTracker,
-  nsRestyleHint          aRestyleHint,
-  const RestyleHintData& aRestyleHintData)
+  nsIFrame*       aParentFrame,
+  nsStyleContext* aNewContext,
+  nsChangeHint    aMinHint,
+  RestyleTracker& aRestyleTracker,
+  nsRestyleHint   aRestyleHint)
 {
   MOZ_ASSERT(!(mHintsHandled & nsChangeHint_ReconstructFrame), "why call me?");
 
   const bool mightReframePseudos = aRestyleHint & eRestyle_Subtree;
   DoRestyleUndisplayedDescendants(nsRestyleHint(0), mContent, aNewContext);
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame) && mightReframePseudos) {
     MaybeReframeForBeforePseudo(aParentFrame, nullptr, mContent, aNewContext);
   }
@@ -3806,35 +3614,34 @@ ElementRestyler::RestyleChildrenOfDispla
     for ( ; !lists.IsDone(); lists.Next()) {
       nsFrameList::Enumerator childFrames(lists.CurrentList());
       for (; !childFrames.AtEnd(); childFrames.Next()) {
         nsIFrame* f = childFrames.get();
         if (nsContentUtils::ContentIsDescendantOf(f->GetContent(), mContent) &&
             !f->GetPrevContinuation()) {
           if (!(f->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
             ComputeStyleChangeFor(f, mChangeList, aMinHint, aRestyleTracker,
-                                  aRestyleHint, aRestyleHintData,
-                                  mContextsToClear, mSwappedStructOwners);
+                                  aRestyleHint, mContextsToClear,
+                                  mSwappedStructOwners);
           }
         }
       }
     }
   }
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
     SendAccessibilityNotifications();
   }
 }
 
 void
 ElementRestyler::ComputeStyleChangeFor(nsIFrame*          aFrame,
                                        nsStyleChangeList* aChangeList,
                                        nsChangeHint       aMinChange,
                                        RestyleTracker&    aRestyleTracker,
                                        nsRestyleHint      aRestyleHint,
-                                       const RestyleHintData& aRestyleHintData,
                                        nsTArray<ContextToClear>&
                                          aContextsToClear,
                                        nsTArray<nsRefPtr<nsStyleContext>>&
                                          aSwappedStructOwners)
 {
   nsIContent* content = aFrame->GetContent();
   nsAutoCString idStr;
   if (profiler_is_active() && content) {
@@ -3872,34 +3679,30 @@ ElementRestyler::ComputeStyleChangeFor(n
   FramePropertyTable* propTable = presContext->PropertyTable();
 
   TreeMatchContext treeMatchContext(true,
                                     nsRuleWalker::eRelevantLinkUnvisited,
                                     presContext->Document());
   Element* parent =
     content ? content->GetParentElementCrossingShadowRoot() : nullptr;
   treeMatchContext.InitAncestors(parent);
-  nsTArray<nsCSSSelector*> selectorsForDescendants;
-  selectorsForDescendants.AppendElements(
-      aRestyleHintData.mSelectorsForDescendants);
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
   for (nsIFrame* ibSibling = aFrame; ibSibling;
        ibSibling = GetNextBlockInInlineSibling(propTable, ibSibling)) {
     // Outer loop over ib-split siblings
     for (nsIFrame* cont = ibSibling; cont; cont = cont->GetNextContinuation()) {
       if (GetPrevContinuationWithSameStyle(cont)) {
         // We already handled this element when dealing with its earlier
         // continuation.
         continue;
       }
 
       // Inner loop over next-in-flows of the current frame
       ElementRestyler restyler(presContext, cont, aChangeList,
                                aMinChange, aRestyleTracker,
-                               selectorsForDescendants,
                                treeMatchContext,
                                visibleKidsOfHiddenElement,
                                aContextsToClear, aSwappedStructOwners);
 
       restyler.Restyle(aRestyleHint);
 
       if (restyler.HintsHandledForFrame() & nsChangeHint_ReconstructFrame) {
         // If it's going to cause a framechange, then don't bother
@@ -3988,35 +3791,31 @@ ElementRestyler::RestyleUndisplayedNodes
     Element* element = undisplayed->mContent->AsElement();
     if (mRestyleTracker.GetRestyleData(element,
                                        undisplayedRestyleData)) {
       thisChildHint =
         nsRestyleHint(thisChildHint | undisplayedRestyleData->mRestyleHint);
     }
     nsRefPtr<nsStyleContext> undisplayedContext;
     nsStyleSet* styleSet = mPresContext->StyleSet();
-    if (MustRestyleSelf(thisChildHint, element)) {
+    if (thisChildHint & (eRestyle_Self | eRestyle_Subtree)) {
       undisplayedContext =
         styleSet->ResolveStyleFor(element, aParentContext, mTreeMatchContext);
     } else if (thisChildHint ||
                styleSet->IsInRuleTreeReconstruct()) {
-      // XXX Should the above condition ignore eRestyle_Force(Descendants)
-      // like the corresponding check in RestyleSelf?
-
       // Use ResolveStyleWithReplacement either for actual
       // replacements, or as a substitute for ReparentStyleContext
       // that rebuilds the path in the rule tree rather than reusing
       // the rule node, as we need to do during a rule tree
       // reconstruct.
-      nsRestyleHint rshint = thisChildHint & ~eRestyle_SomeDescendants;
       undisplayedContext =
         styleSet->ResolveStyleWithReplacement(element, nullptr,
                                               aParentContext,
                                               undisplayed->mStyle,
-                                              rshint);
+                                              thisChildHint);
     } else {
       undisplayedContext =
         styleSet->ReparentStyleContext(undisplayed->mStyle,
                                        aParentContext,
                                        element);
     }
     const nsStyleDisplay* display = undisplayedContext->StyleDisplay();
     if (display->mDisplay != aDisplay) {
@@ -4286,75 +4085,69 @@ ClearCachedInheritedStyleDataOnDescendan
       entry.mStyleContext->ClearCachedInheritedStyleDataOnDescendants(
           entry.mStructs);
     }
     entry.mStyleContext = nullptr;
   }
 }
 
 void
-RestyleManager::ComputeAndProcessStyleChange(nsIFrame*              aFrame,
-                                             nsChangeHint           aMinChange,
-                                             RestyleTracker&        aRestyleTracker,
-                                             nsRestyleHint          aRestyleHint,
-                                             const RestyleHintData& aRestyleHintData)
+RestyleManager::ComputeAndProcessStyleChange(nsIFrame*          aFrame,
+                                             nsChangeHint       aMinChange,
+                                             RestyleTracker&    aRestyleTracker,
+                                             nsRestyleHint      aRestyleHint)
 {
   MOZ_ASSERT(mReframingStyleContexts, "should have rsc");
   nsStyleChangeList changeList;
   nsTArray<ElementRestyler::ContextToClear> contextsToClear;
 
   // swappedStructOwners needs to be kept alive until after
   // ProcessRestyledFrames and ClearCachedInheritedStyleDataOnDescendants
   // calls; see comment in ElementRestyler::Restyle.
   nsTArray<nsRefPtr<nsStyleContext>> swappedStructOwners;
   ElementRestyler::ComputeStyleChangeFor(aFrame, &changeList, aMinChange,
                                          aRestyleTracker, aRestyleHint,
-                                         aRestyleHintData,
                                          contextsToClear, swappedStructOwners);
   ProcessRestyledFrames(changeList);
   ClearCachedInheritedStyleDataOnDescendants(contextsToClear);
 }
 
 void
-RestyleManager::ComputeAndProcessStyleChange(nsStyleContext*        aNewContext,
-                                             Element*               aElement,
-                                             nsChangeHint           aMinChange,
-                                             RestyleTracker&        aRestyleTracker,
-                                             nsRestyleHint          aRestyleHint,
-                                             const RestyleHintData& aRestyleHintData)
+RestyleManager::ComputeAndProcessStyleChange(nsStyleContext*    aNewContext,
+                                             Element*           aElement,
+                                             nsChangeHint       aMinChange,
+                                             RestyleTracker&    aRestyleTracker,
+                                             nsRestyleHint      aRestyleHint)
 {
   MOZ_ASSERT(mReframingStyleContexts, "should have rsc");
   MOZ_ASSERT(aNewContext->StyleDisplay()->mDisplay == NS_STYLE_DISPLAY_CONTENTS);
   nsIFrame* frame = GetNearestAncestorFrame(aElement);
   MOZ_ASSERT(frame, "display:contents node in map although it's a "
                     "display:none descendant?");
   TreeMatchContext treeMatchContext(true,
                                     nsRuleWalker::eRelevantLinkUnvisited,
                                     frame->PresContext()->Document());
   nsIContent* parent = aElement->GetParent();
   Element* parentElement =
     parent && parent->IsElement() ? parent->AsElement() : nullptr;
   treeMatchContext.InitAncestors(parentElement);
-
-  nsTArray<nsCSSSelector*> selectorsForDescendants;
   nsTArray<nsIContent*> visibleKidsOfHiddenElement;
   nsTArray<ElementRestyler::ContextToClear> contextsToClear;
 
   // swappedStructOwners needs to be kept alive until after
   // ProcessRestyledFrames and ClearCachedInheritedStyleDataOnDescendants
   // calls; see comment in ElementRestyler::Restyle.
   nsTArray<nsRefPtr<nsStyleContext>> swappedStructOwners;
   nsStyleChangeList changeList;
   ElementRestyler r(frame->PresContext(), aElement, &changeList, aMinChange,
-                    aRestyleTracker, selectorsForDescendants, treeMatchContext,
+                    aRestyleTracker, treeMatchContext,
                     visibleKidsOfHiddenElement, contextsToClear,
                     swappedStructOwners);
   r.RestyleChildrenOfDisplayContentsElement(frame, aNewContext, aMinChange,
-                                            aRestyleTracker,
-                                            aRestyleHint, aRestyleHintData);
+                                            aRestyleTracker, aRestyleHint);
   ProcessRestyledFrames(changeList);
   ClearCachedInheritedStyleDataOnDescendants(contextsToClear);
 }
 
 AutoDisplayContentsAncestorPusher::AutoDisplayContentsAncestorPusher(
   TreeMatchContext& aTreeMatchContext, nsPresContext* aPresContext,
   nsIContent* aParent)
   : mTreeMatchContext(aTreeMatchContext)
@@ -4425,21 +4218,19 @@ RestyleManager::StructsToLog()
 }
 #endif
 
 /* static */ nsCString
 RestyleManager::RestyleHintToString(nsRestyleHint aHint)
 {
   nsCString result;
   bool any = false;
-  const char* names[] = {
-    "Self", "SomeDescendants", "Subtree", "LaterSiblings", "CSSTransitions",
-    "CSSAnimations", "SVGAttrAnimations", "StyleAttribute",
-    "StyleAttribute_Animations", "Force", "ForceDescendants"
-  };
+  const char* names[] = { "Self", "Subtree", "LaterSiblings", "CSSTransitions",
+                          "CSSAnimations", "SVGAttrAnimations", "StyleAttribute",
+                          "StyleAttribute_Animations", "Force", "ForceDescendants" };
   uint32_t hint = aHint & ((1 << ArrayLength(names)) - 1);
   uint32_t rest = aHint & ~((1 << ArrayLength(names)) - 1);
   for (uint32_t i = 0; i < ArrayLength(names); i++) {
     if (hint & (1 << i)) {
       if (any) {
         result.AppendLiteral(" | ");
       }
       result.AppendPrintf("eRestyle_%s", names[i]);
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -122,34 +122,28 @@ public:
    * aFrame must be changed to the new parent before this function is called;
    * the new parent style context will be automatically computed based on the
    * new position in the frame tree.
    *
    * @param aFrame the root of the subtree to reparent.  Must not be null.
    */
   nsresult ReparentStyleContext(nsIFrame* aFrame);
 
-  void ClearSelectors() {
-    mPendingRestyles.ClearSelectors();
-  }
-
 private:
   // Used when restyling an element with a frame.
-  void ComputeAndProcessStyleChange(nsIFrame*              aFrame,
-                                    nsChangeHint           aMinChange,
-                                    RestyleTracker&        aRestyleTracker,
-                                    nsRestyleHint          aRestyleHint,
-                                    const RestyleHintData& aRestyleHintData);
+  void ComputeAndProcessStyleChange(nsIFrame*       aFrame,
+                                    nsChangeHint    aMinChange,
+                                    RestyleTracker& aRestyleTracker,
+                                    nsRestyleHint   aRestyleHint);
   // Used when restyling a display:contents element.
-  void ComputeAndProcessStyleChange(nsStyleContext*        aNewContext,
-                                    Element*               aElement,
-                                    nsChangeHint           aMinChange,
-                                    RestyleTracker&        aRestyleTracker,
-                                    nsRestyleHint          aRestyleHint,
-                                    const RestyleHintData& aRestyleHintData);
+  void ComputeAndProcessStyleChange(nsStyleContext* aNewContext,
+                                    Element*        aElement,
+                                    nsChangeHint    aMinChange,
+                                    RestyleTracker& aRestyleTracker,
+                                    nsRestyleHint   aRestyleHint);
 
 public:
 
 #ifdef DEBUG
   /**
    * DEBUG ONLY method to verify integrity of style tree versus frame tree
    */
   void DebugVerifyStyleTree(nsIFrame* aFrame);
@@ -336,22 +330,20 @@ public:
   /**
    * Notify the frame constructor that an element needs to have its
    * style recomputed.
    * @param aElement: The element to be restyled.
    * @param aRestyleHint: Which nodes need to have selector matching run
    *                      on them.
    * @param aMinChangeHint: A minimum change hint for aContent and its
    *                        descendants.
-   * @param aRestyleHintData: Additional data to go with aRestyleHint.
    */
   void PostRestyleEvent(Element* aElement,
                         nsRestyleHint aRestyleHint,
-                        nsChangeHint aMinChangeHint,
-                        const RestyleHintData* aRestyleHintData = nullptr);
+                        nsChangeHint aMinChangeHint);
 
   void PostRestyleEventForLazyConstruction()
   {
     PostRestyleEventInternal(true);
   }
 
   void FlushOverflowChangedTracker()
   {
@@ -426,18 +418,17 @@ public:
 
 private:
   /* aMinHint is the minimal change that should be made to the element */
   // XXXbz do we really need the aPrimaryFrame argument here?
   void RestyleElement(Element*        aElement,
                       nsIFrame*       aPrimaryFrame,
                       nsChangeHint    aMinHint,
                       RestyleTracker& aRestyleTracker,
-                      nsRestyleHint   aRestyleHint,
-                      const RestyleHintData& aRestyleHintData);
+                      nsRestyleHint   aRestyleHint);
 
   void StartRebuildAllStyleData(RestyleTracker& aRestyleTracker);
   void FinishRebuildAllStyleData();
 
   void StyleChangeReflow(nsIFrame* aFrame, nsChangeHint aHint);
 
   // Recursively add all the given frame and all children to the tracker.
   void AddSubtreeToOverflowTracker(nsIFrame* aFrame);
@@ -518,17 +509,16 @@ public:
   };
 
   // Construct for the root of the subtree that we're restyling.
   ElementRestyler(nsPresContext* aPresContext,
                   nsIFrame* aFrame,
                   nsStyleChangeList* aChangeList,
                   nsChangeHint aHintsHandledByAncestors,
                   RestyleTracker& aRestyleTracker,
-                  nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
                   TreeMatchContext& aTreeMatchContext,
                   nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
                   nsTArray<ContextToClear>& aContextsToClear,
                   nsTArray<nsRefPtr<nsStyleContext>>& aSwappedStructOwners);
 
   // Construct for an element whose parent is being restyled.
   enum ConstructorFlags {
     FOR_OUT_OF_FLOW_CHILD = 1<<0
@@ -549,17 +539,16 @@ public:
                   nsIFrame* aFrame);
 
   // For restyling undisplayed content only (mFrame==null).
   ElementRestyler(nsPresContext* aPresContext,
                   nsIContent* aContent,
                   nsStyleChangeList* aChangeList,
                   nsChangeHint aHintsHandledByAncestors,
                   RestyleTracker& aRestyleTracker,
-                  nsTArray<nsCSSSelector*>& aSelectorsForDescendants,
                   TreeMatchContext& aTreeMatchContext,
                   nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement,
                   nsTArray<ContextToClear>& aContextsToClear,
                   nsTArray<nsRefPtr<nsStyleContext>>& aSwappedStructOwners);
 
   /**
    * Restyle our frame's element and its subtree.
    *
@@ -583,30 +572,27 @@ public:
   /**
    * Called from RestyleManager::ComputeAndProcessStyleChange to restyle
    * children of a display:contents element.
    */
   void RestyleChildrenOfDisplayContentsElement(nsIFrame*       aParentFrame,
                                                nsStyleContext* aNewContext,
                                                nsChangeHint    aMinHint,
                                                RestyleTracker& aRestyleTracker,
-                                               nsRestyleHint   aRestyleHint,
-                                               const RestyleHintData&
-                                                 aRestyleHintData);
+                                               nsRestyleHint   aRestyleHint);
 
   /**
    * Re-resolve the style contexts for a frame tree, building aChangeList
    * based on the resulting style changes, plus aMinChange applied to aFrame.
    */
   static void ComputeStyleChangeFor(nsIFrame*          aFrame,
                                     nsStyleChangeList* aChangeList,
                                     nsChangeHint       aMinChange,
                                     RestyleTracker&    aRestyleTracker,
                                     nsRestyleHint      aRestyleHint,
-                                    const RestyleHintData& aRestyleHintData,
                                     nsTArray<ContextToClear>& aContextsToClear,
                                     nsTArray<nsRefPtr<nsStyleContext>>&
                                       aSwappedStructOwners);
 
 #ifdef RESTYLE_LOGGING
   bool ShouldLogRestyle() {
     return RestyleManager::ShouldLogRestyle(mPresContext);
   }
@@ -640,41 +626,16 @@ private:
   /**
    * Restyle the children of this frame (and, in turn, their children).
    *
    * Second half of Restyle().
    */
   void RestyleChildren(nsRestyleHint aChildRestyleHint);
 
   /**
-   * Returns true iff a selector in mSelectorsForDescendants matches aElement.
-   * This is called when processing a eRestyle_SomeDescendants restyle hint.
-   */
-  bool SelectorMatchesForRestyle(Element* aElement);
-
-  /**
-   * Returns true iff aRestyleHint indicates that we should be restyling.
-   * Specifically, this will return true when eRestyle_Self or
-   * eRestyle_Subtree is present, or if eRestyle_SomeDescendants is
-   * present and the specified element matches one of the selectors in
-   * mSelectorsForDescendants.
-   */
-  bool MustRestyleSelf(nsRestyleHint aRestyleHint, Element* aElement);
-
-  /**
-   * Returns true iff aRestyleHint indicates that we can call
-   * ReparentStyleContext rather than any other restyling method of
-   * nsStyleSet that looks up a new rule node, and if we are
-   * not in the process of reconstructing the whole rule tree.
-   * This is used to check whether it is appropriate to call
-   * ReparentStyleContext.
-   */
-  bool CanReparentStyleContext(nsRestyleHint aRestyleHint);
-
-  /**
    * Helpers for Restyle().
    */
   void AddLayerChangesForAnimation();
 
   /**
    * Helpers for RestyleSelf().
    */
   void CaptureChange(nsStyleContext* aOldContext,
@@ -724,19 +685,16 @@ private:
   };
 
   enum A11yNotificationType {
     eDontNotify,
     eNotifyShown,
     eNotifyHidden
   };
 
-  void AddPendingRestylesForDescendantsMatchingSelectors(Element* aElement,
-                                                         Element* aRestyleRoot);
-
 #ifdef RESTYLE_LOGGING
   int32_t& LoggingDepth() { return mLoggingDepth; }
 #endif
 
 #ifdef DEBUG
   static nsCString RestyleResultToString(RestyleResult aRestyleResult);
 #endif
 
@@ -754,17 +712,16 @@ private:
   // the end of Restyle it is those handled for this frame as well).  We
   // need to generate a new change list entry for the frame when its
   // style comparision returns a hint other than one of these hints.
   nsChangeHint mHintsHandled;
   // See nsStyleContext::CalcStyleDifference
   nsChangeHint mParentFrameHintsNotHandledForDescendants;
   nsChangeHint mHintsNotHandledForDescendants;
   RestyleTracker& mRestyleTracker;
-  nsTArray<nsCSSSelector*>& mSelectorsForDescendants;
   TreeMatchContext& mTreeMatchContext;
   nsIFrame* mResolvedChild; // child that provides our parent style context
   // Array of style context subtrees in which we need to clear out cached
   // structs at the end of the restyle (after change hints have been
   // processed).
   nsTArray<ContextToClear>& mContextsToClear;
   // Style contexts that had old structs swapped into it and which should
   // stay alive until the end of the restyle.  (See comment in
--- a/layout/base/RestyleTracker.cpp
+++ b/layout/base/RestyleTracker.cpp
@@ -164,19 +164,16 @@ CollectRestyles(nsISupports* aElement,
   element->UnsetFlags(collector->tracker->RestyleBit() |
                       collector->tracker->RootBit());
 
   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.
-  currentRestyle->mRestyleHintData = Move(aData->mRestyleHintData);
 #if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
   currentRestyle->mBacktrace = Move(aData->mBacktrace);
 #endif
 
 #ifdef RESTYLE_LOGGING
   collector->count++;
 #endif
 
@@ -184,18 +181,17 @@ CollectRestyles(nsISupports* aElement,
   *restyleArrayPtr = currentRestyle + 1;
 
   return PL_DHASH_NEXT;
 }
 
 inline void
 RestyleTracker::ProcessOneRestyle(Element* aElement,
                                   nsRestyleHint aRestyleHint,
-                                  nsChangeHint aChangeHint,
-                                  const RestyleHintData& aRestyleHintData)
+                                  nsChangeHint aChangeHint)
 {
   NS_PRECONDITION((aRestyleHint & eRestyle_LaterSiblings) == 0,
                   "Someone should have handled this before calling us");
   NS_PRECONDITION(Document(), "Must have a document");
   NS_PRECONDITION(aElement->GetCrossShadowCurrentDoc() == Document(),
                   "Element has unexpected document");
 
   LOG_RESTYLE("aRestyleHint = %s, aChangeHint = %s",
@@ -210,17 +206,17 @@ RestyleTracker::ProcessOneRestyle(Elemen
         RestyleManager::StructsToLog() != 0) {
       LOG_RESTYLE("style context tree before restyle:");
       LOG_RESTYLE_INDENT();
       primaryFrame->StyleContext()->LogStyleContextTree(
           LoggingDepth(), RestyleManager::StructsToLog());
     }
 #endif
     mRestyleManager->RestyleElement(aElement, primaryFrame, aChangeHint,
-                                    *this, aRestyleHint, aRestyleHintData);
+                                    *this, aRestyleHint);
   } else if (aChangeHint &&
              (primaryFrame ||
               (aChangeHint & nsChangeHint_ReconstructFrame))) {
     // Don't need to recompute style; just apply the hint
     nsStyleChangeList changeList;
     changeList.AppendChange(primaryFrame, aElement, aChangeHint);
     mRestyleManager->ProcessRestyledFrames(changeList);
   }
@@ -366,18 +362,17 @@ RestyleTracker::DoProcessRestyles()
         }
 
 #if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
         Maybe<GeckoProfilerTracingRAII> profilerRAII;
         if (profiler_feature_active("restyle")) {
           profilerRAII.emplace("Paint", "Styles", Move(data->mBacktrace));
         }
 #endif
-        ProcessOneRestyle(element, data->mRestyleHint, data->mChangeHint,
-                          data->mRestyleHintData);
+        ProcessOneRestyle(element, data->mRestyleHint, data->mChangeHint);
         AddRestyleRootsIfAwaitingRestyle(data->mDescendants);
 
         if (isTimelineRecording) {
           mozilla::UniquePtr<TimelineMarker> marker =
             MakeUnique<RestyleTimelineMarker>(docShell,
                                               TRACING_INTERVAL_END,
                                               data->mRestyleHint);
           TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
@@ -427,34 +422,30 @@ RestyleTracker::DoProcessRestyles()
               MakeUnique<RestyleTimelineMarker>(docShell,
                                                 TRACING_INTERVAL_START,
                                                 currentRestyle->mRestyleHint);
             TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
           }
 
           ProcessOneRestyle(currentRestyle->mElement,
                             currentRestyle->mRestyleHint,
-                            currentRestyle->mChangeHint,
-                            currentRestyle->mRestyleHintData);
+                            currentRestyle->mChangeHint);
 
           if (isTimelineRecording) {
             mozilla::UniquePtr<TimelineMarker> marker =
               MakeUnique<RestyleTimelineMarker>(docShell,
                                                 TRACING_INTERVAL_END,
                                                 currentRestyle->mRestyleHint);
             TimelineConsumers::AddMarkerForDocShell(docShell, Move(marker));
           }
         }
       }
     }
   }
 
-  // mPendingRestyles is now empty.
-  mHaveSelectors = false;
-
   mRestyleManager->EndProcessingRestyles();
 }
 
 bool
 RestyleTracker::GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData)
 {
   NS_PRECONDITION(aElement->GetCrossShadowCurrentDoc() == Document(),
                   "Unexpected document; this will lead to incorrect behavior!");
@@ -510,28 +501,9 @@ RestyleTracker::AddRestyleRootsIfAwaitin
   for (size_t i = 0; i < aElements.Length(); i++) {
     Element* element = aElements[i];
     if (element->HasFlag(RestyleBit())) {
       mRestyleRoots.AppendElement(element);
     }
   }
 }
 
-void
-RestyleTracker::ClearSelectors()
-{
-  if (!mHaveSelectors) {
-    return;
-  }
-  for (auto it = mPendingRestyles.Iter(); !it.Done(); it.Next()) {
-    RestyleData* data = it.Data();
-    if (data->mRestyleHint & eRestyle_SomeDescendants) {
-      data->mRestyleHint =
-        (data->mRestyleHint & ~eRestyle_SomeDescendants) | eRestyle_Subtree;
-      data->mRestyleHintData.mSelectorsForDescendants.Clear();
-    } else {
-      MOZ_ASSERT(data->mRestyleHintData.mSelectorsForDescendants.IsEmpty());
-    }
-  }
-  mHaveSelectors = false;
-}
-
 } // namespace mozilla
--- a/layout/base/RestyleTracker.h
+++ b/layout/base/RestyleTracker.h
@@ -12,17 +12,16 @@
 #define mozilla_RestyleTracker_h
 
 #include "mozilla/dom/Element.h"
 #include "nsClassHashtable.h"
 #include "nsContainerFrame.h"
 #include "mozilla/SplayTree.h"
 #include "mozilla/RestyleLogging.h"
 #include "GeckoProfiler.h"
-#include "mozilla/Maybe.h"
 
 #if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
 #include "ProfilerBacktrace.h"
 #endif
 
 namespace mozilla {
 
 class RestyleManager;
@@ -226,17 +225,16 @@ class RestyleTracker {
 public:
   typedef mozilla::dom::Element Element;
 
   friend class ElementRestyler; // for AddPendingRestyleToTable
 
   explicit RestyleTracker(Element::FlagsType aRestyleBits)
     : mRestyleBits(aRestyleBits)
     , mHaveLaterSiblingRestyles(false)
-    , mHaveSelectors(false)
   {
     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");
@@ -253,29 +251,19 @@ public:
 
   uint32_t Count() const {
     return mPendingRestyles.Count();
   }
 
   /**
    * Add a restyle for the given element to the tracker.  Returns true
    * if the element already had eRestyle_LaterSiblings set on it.
-   *
-   * aRestyleRoot is the closest restyle root for aElement.  If the caller
-   * does not know what the closest restyle root is, Nothing should be
-   * passed.  A Some(nullptr) restyle root can be passed if there is no
-   * ancestor element that is a restyle root.
    */
   bool AddPendingRestyle(Element* aElement, nsRestyleHint aRestyleHint,
-                         nsChangeHint aMinChangeHint,
-                         const RestyleHintData* aRestyleHintData = nullptr,
-                         mozilla::Maybe<Element*> aRestyleRoot =
-                           mozilla::Nothing());
-
-  Element* FindClosestRestyleRoot(Element* aElement);
+                         nsChangeHint aMinChangeHint);
 
   /**
    * Process the restyles we've been tracking.
    */
   void DoProcessRestyles();
 
   // Return our ELEMENT_HAS_PENDING_(ANIMATION_)RESTYLE bit
   uint32_t RestyleBit() const {
@@ -283,34 +271,29 @@ public:
   }
 
   // Return our ELEMENT_IS_POTENTIAL_(ANIMATION_)RESTYLE_ROOT bit
   Element::FlagsType RootBit() const {
     return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
   }
 
   struct Hints {
-    nsRestyleHint mRestyleHint;        // What we want to restyle
-    nsChangeHint mChangeHint;          // The minimal change hint for "self"
-    RestyleHintData mRestyleHintData;  // Data associated with mRestyleHint
+    nsRestyleHint mRestyleHint;       // What we want to restyle
+    nsChangeHint mChangeHint;         // The minimal change hint for "self"
   };
 
   struct RestyleData : Hints {
     RestyleData() {
       mRestyleHint = nsRestyleHint(0);
       mChangeHint = NS_STYLE_HINT_NONE;
     }
 
-    RestyleData(nsRestyleHint aRestyleHint, nsChangeHint aChangeHint,
-                const RestyleHintData* aRestyleHintData) {
+    RestyleData(nsRestyleHint aRestyleHint, nsChangeHint aChangeHint) {
       mRestyleHint = aRestyleHint;
       mChangeHint = aChangeHint;
-      if (aRestyleHintData) {
-        mRestyleHintData = *aRestyleHintData;
-      }
     }
 
     // Descendant elements we must check that we ended up restyling, ordered
     // with the same invariant as mRestyleRoots.  The elements here are those
     // that we called AddPendingRestyle for and found the element this is
     // the RestyleData for as its nearest restyle root.
     nsTArray<nsRefPtr<Element>> mDescendants;
 #if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
@@ -326,71 +309,53 @@ public:
    * eRestyle_LaterSiblings hint in it.
    *
    * The return value indicates whether any restyle data was found for
    * the element.  aData is set to nullptr iff false is returned.
    */
   bool GetRestyleData(Element* aElement, nsAutoPtr<RestyleData>& aData);
 
   /**
-   * Returns whether there is a RestyleData entry in mPendingRestyles
-   * for the given element.
-   */
-  bool HasRestyleData(Element* aElement) {
-    return mPendingRestyles.Contains(aElement);
-  }
-
-  /**
    * For each element in aElements, appends it to mRestyleRoots if it
    * has its restyle bit set.  This is used to ensure we restyle elements
    * that we did not add as restyle roots initially (due to there being
    * an ancestor with the restyle root bit set), but which we might
    * not have got around to restyling due to the restyle process
    * terminating early with eRestyleResult_Stop (see ElementRestyler::Restyle).
    *
    * This function must be called with elements in order such that
    * appending them to mRestyleRoots maintains its ordering invariant that
    * ancestors appear after descendants.
    */
   void AddRestyleRootsIfAwaitingRestyle(
                                   const nsTArray<nsRefPtr<Element>>& aElements);
 
   /**
-   * Converts any eRestyle_SomeDescendants restyle hints in the pending restyle
-   * table into eRestyle_Subtree hints and clears out the associated arrays of
-   * nsCSSSelector pointers.  This is called in response to a style sheet change
-   * that might have cause an nsCSSSelector to be destroyed.
-   */
-  void ClearSelectors();
-
-  /**
    * The document we're associated with.
    */
   inline nsIDocument* Document() const;
 
 #ifdef RESTYLE_LOGGING
   // Defined in RestyleTrackerInlines.h.
   inline bool ShouldLogRestyle();
   inline int32_t& LoggingDepth();
 #endif
 
 private:
   bool AddPendingRestyleToTable(Element* aElement, nsRestyleHint aRestyleHint,
-                                nsChangeHint aMinChangeHint,
-                                const RestyleHintData* aRestyleHintData = nullptr);
+                                nsChangeHint aMinChangeHint);
 
   /**
    * Handle a single mPendingRestyles entry.  aRestyleHint must not
    * include eRestyle_LaterSiblings; that needs to be dealt with
    * before calling this function.
    */
   inline void ProcessOneRestyle(Element* aElement,
                                 nsRestyleHint aRestyleHint,
-                                nsChangeHint aChangeHint,
-                                const RestyleHintData& aRestyleHintData);
+                                nsChangeHint aChangeHint);
 
   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.
   Element::FlagsType mRestyleBits;
   RestyleManager* mRestyleManager; // Owns us
@@ -406,118 +371,91 @@ private:
   // We maintain this invariant by checking whether an element has an
   // ancestor with the restyle root bit set before appending it to the
   // array.
   RestyleRootArray mRestyleRoots;
   // True if we have some entries with the eRestyle_LaterSiblings
   // flag.  We need this to avoid enumerating the hashtable looking
   // for such entries when we can't possibly have any.
   bool mHaveLaterSiblingRestyles;
-  // True if we have some entries with selectors in the restyle hint data.
-  // We use this to skip iterating over mPendingRestyles in ClearSelectors.
-  bool mHaveSelectors;
 };
 
 inline bool
 RestyleTracker::AddPendingRestyleToTable(Element* aElement,
                                          nsRestyleHint aRestyleHint,
-                                         nsChangeHint aMinChangeHint,
-                                         const RestyleHintData* aRestyleHintData)
+                                         nsChangeHint aMinChangeHint)
 {
   RestyleData* existingData;
 
-  if (aRestyleHintData &&
-      !aRestyleHintData->mSelectorsForDescendants.IsEmpty()) {
-    mHaveSelectors = true;
-  }
-
   // Check the RestyleBit() flag before doing the hashtable Get, since
   // it's possible that the data in the hashtable isn't actually
   // relevant anymore (if the flag is not set).
   if (aElement->HasFlag(RestyleBit())) {
     mPendingRestyles.Get(aElement, &existingData);
   } else {
     aElement->SetFlags(RestyleBit());
     existingData = nullptr;
   }
 
   if (!existingData) {
-    RestyleData* rd =
-      new RestyleData(aRestyleHint, aMinChangeHint, aRestyleHintData);
+    RestyleData* rd = new RestyleData(aRestyleHint, aMinChangeHint);
 #if defined(MOZ_ENABLE_PROFILER_SPS) && !defined(MOZILLA_XPCOMRT_API)
     if (profiler_feature_active("restyle")) {
       rd->mBacktrace.reset(profiler_get_backtrace());
     }
 #endif
     mPendingRestyles.Put(aElement, rd);
     return false;
   }
 
   bool hadRestyleLaterSiblings =
     (existingData->mRestyleHint & eRestyle_LaterSiblings) != 0;
   existingData->mRestyleHint =
     nsRestyleHint(existingData->mRestyleHint | aRestyleHint);
   NS_UpdateHint(existingData->mChangeHint, aMinChangeHint);
-  if (aRestyleHintData) {
-    existingData->mRestyleHintData.mSelectorsForDescendants
-      .AppendElements(aRestyleHintData->mSelectorsForDescendants);
-  }
 
   return hadRestyleLaterSiblings;
 }
 
-inline mozilla::dom::Element*
-RestyleTracker::FindClosestRestyleRoot(Element* aElement)
-{
-  Element* cur = aElement;
-  while (!cur->HasFlag(RootBit())) {
-    nsIContent* parent = cur->GetFlattenedTreeParent();
-    // Stop if we have no parent or the parent is not an element or
-    // we're part of the viewport scrollbars (because those are not
-    // frametree descendants of the primary frame of the root
-    // element).
-    // XXXbz maybe the primary frame of the root should be the root scrollframe?
-    if (!parent || !parent->IsElement() ||
-        // If we've hit the root via a native anonymous kid and that
-        // this native anonymous kid is not obviously a descendant
-        // of the root's primary frame, assume we're under the root
-        // scrollbars.  Since those don't get reresolved when
-        // reresolving the root, we need to make sure to add the
-        // element to mRestyleRoots.
-        (cur->IsInNativeAnonymousSubtree() && !parent->GetParent() &&
-         cur->GetPrimaryFrame() &&
-         cur->GetPrimaryFrame()->GetParent() != parent->GetPrimaryFrame())) {
-      return nullptr;
-    }
-    cur = parent->AsElement();
-  }
-  return cur;
-}
-
 inline bool
 RestyleTracker::AddPendingRestyle(Element* aElement,
                                   nsRestyleHint aRestyleHint,
-                                  nsChangeHint aMinChangeHint,
-                                  const RestyleHintData* aRestyleHintData,
-                                  mozilla::Maybe<Element*> aRestyleRoot)
+                                  nsChangeHint aMinChangeHint)
 {
   bool hadRestyleLaterSiblings =
-    AddPendingRestyleToTable(aElement, aRestyleHint, aMinChangeHint,
-                             aRestyleHintData);
+    AddPendingRestyleToTable(aElement, aRestyleHint, aMinChangeHint);
 
   // We can only treat this element as a restyle root if we would
   // actually restyle its descendants (so either call
   // ReResolveStyleContext on it or just reframe it).
   if ((aRestyleHint & ~eRestyle_LaterSiblings) ||
       (aMinChangeHint & nsChangeHint_ReconstructFrame)) {
-    Element* cur =
-      aRestyleRoot ? *aRestyleRoot : FindClosestRestyleRoot(aElement);
-    if (!cur) {
-      mRestyleRoots.AppendElement(aElement);
-      cur = aElement;
+    Element* cur = aElement;
+    while (!cur->HasFlag(RootBit())) {
+      nsIContent* parent = cur->GetFlattenedTreeParent();
+      // Stop if we have no parent or the parent is not an element or
+      // we're part of the viewport scrollbars (because those are not
+      // frametree descendants of the primary frame of the root
+      // element).
+      // XXXbz maybe the primary frame of the root should be the root scrollframe?
+      if (!parent || !parent->IsElement() ||
+          // If we've hit the root via a native anonymous kid and that
+          // this native anonymous kid is not obviously a descendant
+          // of the root's primary frame, assume we're under the root
+          // scrollbars.  Since those don't get reresolved when
+          // reresolving the root, we need to make sure to add the
+          // element to mRestyleRoots.
+          (cur->IsInNativeAnonymousSubtree() && !parent->GetParent() &&
+           cur->GetPrimaryFrame() &&
+           cur->GetPrimaryFrame()->GetParent() != parent->GetPrimaryFrame())) {
+        mRestyleRoots.AppendElement(aElement);
+        cur = aElement;
+        break;
+      }
+      cur = parent->AsElement();
     }
     // At this point some ancestor of aElement (possibly aElement
     // itself) is in mRestyleRoots.  Set the root bit on aElement, to
     // speed up searching for an existing root on its descendants.
     aElement->SetFlags(RootBit());
     if (cur != aElement) {
       // We are already going to restyle cur, one of aElement's ancestors,
       // but we might not end up restyling all the way down to aElement.
--- a/layout/base/nsChangeHint.h
+++ b/layout/base/nsChangeHint.h
@@ -3,21 +3,18 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* constants for what needs to be recomputed in response to style changes */
 
 #ifndef nsChangeHint_h___
 #define nsChangeHint_h___
 
+#include "nsDebug.h"
 #include "mozilla/Types.h"
-#include "nsDebug.h"
-#include "nsTArray.h"
-
-struct nsCSSSelector;
 
 // Defines for various style related constants
 
 enum nsChangeHint {
   // change was visual only (e.g., COLOR=)
   // Invalidates all descendant frames (including following
   // placeholders to out-of-flow frames).
   nsChangeHint_RepaintFrame = 0x01,
@@ -375,76 +372,72 @@ inline nsChangeHint NS_HintsNotHandledFo
  */
 enum nsRestyleHint {
   // Rerun selector matching on the element.  If a new style context
   // results, update the style contexts of descendants.  (Irrelevant if
   // eRestyle_Subtree is also set, since that implies a superset of the
   // work.)
   eRestyle_Self = (1<<0),
 
-  // Rerun selector matching on descendants of the element that match
-  // a given selector.
-  eRestyle_SomeDescendants = (1<<1),
-
   // Rerun selector matching on the element and all of its descendants.
   // (Implies eRestyle_ForceDescendants, which ensures that we continue
   // the restyling process for all descendants, but doesn't cause
   // selector matching.)
-  eRestyle_Subtree = (1<<2),
+  eRestyle_Subtree = (1<<1),
 
   // Rerun selector matching on all later siblings of the element and
   // all of their descendants.
-  eRestyle_LaterSiblings = (1<<3),
+  eRestyle_LaterSiblings = (1<<2),
 
   // Replace the style data coming from CSS transitions without updating
   // any other style data.  If a new style context results, update style
   // contexts on the descendants.  (Irrelevant if eRestyle_Self or
   // eRestyle_Subtree is also set, since those imply a superset of the
   // work.)
-  eRestyle_CSSTransitions = (1<<4),
+  eRestyle_CSSTransitions = (1<<3),
 
   // Replace the style data coming from CSS animations without updating
   // any other style data.  If a new style context results, update style
   // contexts on the descendants.  (Irrelevant if eRestyle_Self or
   // eRestyle_Subtree is also set, since those imply a superset of the
   // work.)
-  eRestyle_CSSAnimations = (1<<5),
+  eRestyle_CSSAnimations = (1<<4),
 
   // Replace the style data coming from SVG animations (SMIL Animations)
   // without updating any other style data.  If a new style context
   // results, update style contexts on the descendants.  (Irrelevant if
   // eRestyle_Self or eRestyle_Subtree is also set, since those imply a
   // superset of the work.)
-  eRestyle_SVGAttrAnimations = (1<<6),
+  eRestyle_SVGAttrAnimations = (1<<5),
 
   // Replace the style data coming from inline style without updating
   // any other style data.  If a new style context results, update style
   // contexts on the descendants.  (Irrelevant if eRestyle_Self or
   // eRestyle_Subtree is also set, since those imply a superset of the
   // work.)  Supported only for element style contexts and not for
   // pseudo-elements or anonymous boxes, on which it converts to
   // eRestyle_Self.
   // If the change is for the advance of a declarative animation, use
   // the value below instead.
-  eRestyle_StyleAttribute = (1<<7),
+  eRestyle_StyleAttribute = (1<<6),
 
   // Same as eRestyle_StyleAttribute, but for when the change results
   // from the advance of a declarative animation.
-  eRestyle_StyleAttribute_Animations = (1<<8),
+  eRestyle_StyleAttribute_Animations = (1<<7),
 
   // Continue the restyling process to the current frame's children even
   // if this frame's restyling resulted in no style changes.
-  eRestyle_Force = (1<<9),
+  eRestyle_Force = (1<<8),
 
   // Continue the restyling process to all of the current frame's
   // descendants, even if any frame's restyling resulted in no style
   // changes.  (Implies eRestyle_Force.)  Note that this is weaker than
   // eRestyle_Subtree, which makes us rerun selector matching on all
   // descendants rather than just continuing the restyling process.
-  eRestyle_ForceDescendants = (1<<10),
+  eRestyle_ForceDescendants = (1<<9),
 
   // Useful unions:
   eRestyle_AllHintsWithAnimations = eRestyle_CSSTransitions |
                                     eRestyle_CSSAnimations |
                                     eRestyle_SVGAttrAnimations |
                                     eRestyle_StyleAttribute_Animations,
 };
 
@@ -485,24 +478,9 @@ inline nsRestyleHint operator^(nsRestyle
                        nsRestyleHint_size_t(aRight));
 }
 
 inline nsRestyleHint operator^=(nsRestyleHint& aLeft, nsRestyleHint aRight)
 {
   return aLeft = aLeft ^ aRight;
 }
 
-namespace mozilla {
-
-/**
- * Additional data used in conjunction with an nsRestyleHint to control the
- * restyle process.
- */
-struct RestyleHintData
-{
-  // When eRestyle_SomeDescendants is used, this array contains the selectors
-  // that identify which descendants will be restyled.
-  nsTArray<nsCSSSelector*> mSelectorsForDescendants;
-};
-
-} // namespace mozilla
-
 #endif /* nsChangeHint_h___ */
--- a/layout/style/AnimationCommon.cpp
+++ b/layout/style/AnimationCommon.cpp
@@ -205,19 +205,17 @@ CommonAnimationManager::HasStateDependen
 
 bool
 CommonAnimationManager::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
 {
   return false;
 }
 
 nsRestyleHint
-CommonAnimationManager::HasAttributeDependentStyle(
-    AttributeRuleProcessorData* aData,
-    RestyleHintData& aRestyleHintDataResult)
+CommonAnimationManager::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
 {
   return nsRestyleHint(0);
 }
 
 /* virtual */ bool
 CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
 {
   return false;
--- a/layout/style/AnimationCommon.h
+++ b/layout/style/AnimationCommon.h
@@ -47,18 +47,17 @@ public:
   // nsISupports
   NS_DECL_ISUPPORTS
 
   // nsIStyleRuleProcessor (parts)
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override;
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint
-    HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
-                               RestyleHintData& aRestyleHintDataResult) override;
+    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override;
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
   virtual void RulesMatching(ElementRuleProcessorData* aData) override;
   virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override;
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData) override;
 #endif
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
--- a/layout/style/CSSStyleSheet.cpp
+++ b/layout/style/CSSStyleSheet.cpp
@@ -1704,25 +1704,16 @@ CSSStyleSheet::List(FILE* out, int32_t a
   fprintf_stderr(out, "%s", "Rules in source order:\n");
   ListRules(mInner->mOrderedRules, out, aIndent);
 }
 #endif
 
 void 
 CSSStyleSheet::ClearRuleCascades()
 {
-  // We might be in ClearRuleCascades because we had a modification
-  // to the sheet that resulted in an nsCSSSelector being destroyed.
-  // Tell the RestyleManager for each document we're used in
-  // so that they can drop any nsCSSSelector pointers (used for
-  // eRestyle_SomeDescendants) in their mPendingRestyles.
-  for (nsStyleSet* styleSet : mStyleSets) {
-    styleSet->ClearSelectors();
-  }
-
   bool removedSheetFromRuleProcessorCache = false;
   if (mRuleProcessors) {
     nsCSSRuleProcessor **iter = mRuleProcessors->Elements(),
                        **end = iter + mRuleProcessors->Length();
     for(; iter != end; ++iter) {
       if (!removedSheetFromRuleProcessorCache && (*iter)->IsShared()) {
         // Since the sheet has been modified, we need to remove all
         // RuleProcessorCache entries that contain this sheet, as the
--- a/layout/style/SVGAttrAnimationRuleProcessor.cpp
+++ b/layout/style/SVGAttrAnimationRuleProcessor.cpp
@@ -57,19 +57,17 @@ SVGAttrAnimationRuleProcessor::HasStateD
 
 /* virtual */ bool
 SVGAttrAnimationRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
 {
   return false;
 }
 
 /* virtual */ nsRestyleHint
-SVGAttrAnimationRuleProcessor::HasAttributeDependentStyle(
-    AttributeRuleProcessorData* aData,
-    RestyleHintData& aRestyleHintDataResult)
+SVGAttrAnimationRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
 {
   return nsRestyleHint(0);
 }
 
 /* virtual */ bool
 SVGAttrAnimationRuleProcessor::MediumFeaturesChanged(nsPresContext* aPresContext)
 {
   return false;
--- a/layout/style/SVGAttrAnimationRuleProcessor.h
+++ b/layout/style/SVGAttrAnimationRuleProcessor.h
@@ -39,18 +39,17 @@ public:
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData) override;
 #endif
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override;
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint
-    HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
-                               RestyleHintData& aRestyleHintDataResult) override;
+    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override;
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const MOZ_MUST_OVERRIDE override;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const MOZ_MUST_OVERRIDE override;
 
   size_t DOMSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -554,17 +554,17 @@ nsCSSSelector::ToString(nsAString& aStri
     stack.AppendElement(s);
   }
 
   while (!stack.IsEmpty()) {
     uint32_t index = stack.Length() - 1;
     const nsCSSSelector *s = stack.ElementAt(index);
     stack.RemoveElementAt(index);
 
-    s->AppendToStringWithoutCombinators(aString, aSheet, false);
+    s->AppendToStringWithoutCombinators(aString, aSheet);
 
     // Append the combinator, if needed.
     if (!stack.IsEmpty()) {
       const nsCSSSelector *next = stack.ElementAt(index - 1);
       char16_t oper = s->mOperator;
       if (next->IsPseudoElement()) {
         NS_ASSERTION(oper == char16_t(':'),
                      "improperly chained pseudo element");
@@ -578,122 +578,50 @@ nsCSSSelector::ToString(nsAString& aStri
           aString.Append(char16_t(' '));
         }
       }
     }
   }
 }
 
 void
-nsCSSSelector::AppendToStringWithoutCombinators(
-    nsAString& aString,
-    CSSStyleSheet* aSheet,
-    bool aUseStandardNamespacePrefixes) const
+nsCSSSelector::AppendToStringWithoutCombinators
+                   (nsAString& aString, CSSStyleSheet* aSheet) const
 {
-  AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, false,
-                                              aUseStandardNamespacePrefixes);
+  AppendToStringWithoutCombinatorsOrNegations(aString, aSheet, false);
 
   for (const nsCSSSelector* negation = mNegations; negation;
        negation = negation->mNegations) {
     aString.AppendLiteral(":not(");
-    negation->AppendToStringWithoutCombinatorsOrNegations(
-        aString, aSheet, true, aUseStandardNamespacePrefixes);
+    negation->AppendToStringWithoutCombinatorsOrNegations(aString, aSheet,
+                                                          true);
     aString.Append(char16_t(')'));
   }
 }
 
-#ifdef DEBUG
-nsCString
-nsCSSSelector::RestrictedSelectorToString() const
-{
-  MOZ_ASSERT(IsRestrictedSelector());
-
-  nsString result;
-  AppendToStringWithoutCombinators(result, nullptr, true);
-  return NS_ConvertUTF16toUTF8(result);
-}
-
-static bool
-AppendStandardNamespacePrefixToString(nsAString& aString, int32_t aNameSpace)
-{
-  if (aNameSpace == kNameSpaceID_Unknown) {
-    // Wildcard namespace; no prefix to write.
-    return false;
-  }
-  switch (aNameSpace) {
-    case kNameSpaceID_None:
-      break;
-    case kNameSpaceID_XML:
-      aString.AppendLiteral("xml");
-      break;
-    case kNameSpaceID_XHTML:
-      aString.AppendLiteral("html");
-      break;
-    case kNameSpaceID_XLink:
-      aString.AppendLiteral("xlink");
-      break;
-    case kNameSpaceID_XSLT:
-      aString.AppendLiteral("xsl");
-      break;
-    case kNameSpaceID_XBL:
-      aString.AppendLiteral("xbl");
-      break;
-    case kNameSpaceID_MathML:
-      aString.AppendLiteral("math");
-      break;
-    case kNameSpaceID_RDF:
-      aString.AppendLiteral("rdf");
-      break;
-    case kNameSpaceID_XUL:
-      aString.AppendLiteral("xul");
-      break;
-    case kNameSpaceID_SVG:
-      aString.AppendLiteral("svg");
-      break;
-    default:
-      aString.AppendLiteral("ns");
-      aString.AppendInt(aNameSpace);
-      break;
-  }
-  return true;
-}
-#endif
-
 void
 nsCSSSelector::AppendToStringWithoutCombinatorsOrNegations
                    (nsAString& aString, CSSStyleSheet* aSheet,
-                   bool aIsNegated,
-                   bool aUseStandardNamespacePrefixes) const
+                   bool aIsNegated) const
 {
   nsAutoString temp;
   bool isPseudoElement = IsPseudoElement();
 
   // For non-pseudo-element selectors or for lone pseudo-elements, deal with
   // namespace prefixes.
   bool wroteNamespace = false;
   if (!isPseudoElement || !mNext) {
     // append the namespace prefix if needed
     nsXMLNameSpaceMap *sheetNS = aSheet ? aSheet->GetNameSpaceMap() : nullptr;
 
     // sheetNS is non-null if and only if we had an @namespace rule.  If it's
     // null, that means that the only namespaces we could have are the
     // wildcard namespace (which can be implicit in this case) and the "none"
     // namespace, which then needs to be explicitly specified.
-    if (aUseStandardNamespacePrefixes) {
-#ifdef DEBUG
-      // We have no sheet to look up prefix information from.  This is
-      // only for debugging, so use some "standard" prefixes that
-      // are recognizable.
-      wroteNamespace =
-        AppendStandardNamespacePrefixToString(aString, mNameSpace);
-      if (wroteNamespace) {
-        aString.Append(char16_t('|'));
-      }
-#endif
-    } else if (!sheetNS) {
+    if (!sheetNS) {
       NS_ASSERTION(mNameSpace == kNameSpaceID_Unknown ||
                    mNameSpace == kNameSpaceID_None,
                    "How did we get this namespace?");
       if (mNameSpace == kNameSpaceID_None) {
         aString.Append(char16_t('|'));
         wroteNamespace = true;
       }
     } else if (sheetNS->FindNameSpaceID(nullptr) == mNameSpace) {
@@ -807,22 +735,17 @@ nsCSSSelector::AppendToStringWithoutComb
     nsAttrSelector* list = mAttrList;
     while (list != nullptr) {
       aString.Append(char16_t('['));
       // Append the namespace prefix
       if (list->mNameSpace == kNameSpaceID_Unknown) {
         aString.Append(char16_t('*'));
         aString.Append(char16_t('|'));
       } else if (list->mNameSpace != kNameSpaceID_None) {
-        if (aUseStandardNamespacePrefixes) {
-#ifdef DEBUG
-          AppendStandardNamespacePrefixToString(aString, list->mNameSpace);
-          aString.Append(char16_t('|'));
-#endif
-        } else if (aSheet) {
+        if (aSheet) {
           nsXMLNameSpaceMap *sheetNS = aSheet->GetNameSpaceMap();
           nsIAtom *prefixAtom = sheetNS->FindPrefix(list->mNameSpace);
           // Default namespaces don't apply to attribute selectors, so
           // we must have a useful prefix.
           NS_ASSERTION(prefixAtom,
                        "How did we end up with a namespace if the prefix "
                        "is unknown?");
           nsAutoString prefix;
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -154,37 +154,26 @@ public:
   }
 
   // Calculate the specificity of this selector (not including its mNext!).
   int32_t CalcWeight() const;
 
   void ToString(nsAString& aString, mozilla::CSSStyleSheet* aSheet,
                 bool aAppend = false) const;
 
-  bool IsRestrictedSelector() const {
-    return PseudoType() == nsCSSPseudoElements::ePseudo_NotPseudoElement;
-  }
-
-#ifdef DEBUG
-  nsCString RestrictedSelectorToString() const;
-#endif
-
 private:
   void AddPseudoClassInternal(nsPseudoClassList *aPseudoClass);
   nsCSSSelector* Clone(bool aDeepNext, bool aDeepNegations) const;
 
-  void AppendToStringWithoutCombinators(
-      nsAString& aString,
-      mozilla::CSSStyleSheet* aSheet,
-      bool aUseStandardNamespacePrefixes) const;
-  void AppendToStringWithoutCombinatorsOrNegations(
-      nsAString& aString,
-      mozilla::CSSStyleSheet* aSheet,
-      bool aIsNegated,
-      bool aUseStandardNamespacePrefixes) const;
+  void AppendToStringWithoutCombinators(nsAString& aString,
+                                        mozilla::CSSStyleSheet* aSheet) const;
+  void AppendToStringWithoutCombinatorsOrNegations(nsAString& aString,
+                                                   mozilla::CSSStyleSheet* aSheet,
+                                                   bool aIsNegated)
+                                                        const;
   // Returns true if this selector can have a namespace specified (which
   // happens if and only if the default namespace would apply to this
   // selector).
   bool CanBeNamespaced(bool aIsNegated) const;
   // Calculate the specificity of this selector (not including its mNext
   // or its mNegations).
   int32_t CalcWeightWithoutNegations() const;
 
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -778,49 +778,22 @@ RuleHash::SizeOfExcludingThis(MallocSize
 size_t
 RuleHash::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
 
 //--------------------------------
 
-/**
- * A struct that stores an nsCSSSelector pointer along side a pointer to
- * the rightmost nsCSSSelector in the selector.  For example, for
- *
- *   .main p > span
- *
- * if mSelector points to the |p| nsCSSSelector, mRightmostSelector would
- * point to the |span| nsCSSSelector.
- *
- * Both mSelector and mRightmostSelector are always top-level selectors,
- * i.e. they aren't selectors within a :not() or :-moz-any().
- */
-struct SelectorPair
-{
-  SelectorPair(nsCSSSelector* aSelector, nsCSSSelector* aRightmostSelector)
-    : mSelector(aSelector), mRightmostSelector(aRightmostSelector)
-  {
-    MOZ_ASSERT(aSelector);
-    MOZ_ASSERT(mRightmostSelector);
-  }
-  SelectorPair(const SelectorPair& aOther)
-    : mSelector(aOther.mSelector)
-    , mRightmostSelector(aOther.mRightmostSelector) {}
-  nsCSSSelector* const mSelector;
-  nsCSSSelector* const mRightmostSelector;
-};
-
 // A hash table mapping atoms to lists of selectors
 struct AtomSelectorEntry : public PLDHashEntryHdr {
   nsIAtom *mAtom;
   // Auto length 2, because a decent fraction of these arrays ends up
   // with 2 elements, and each entry is cheap.
-  nsAutoTArray<SelectorPair, 2> mSelectors;
+  nsAutoTArray<nsCSSSelector*, 2> mSelectors;
 };
 
 static void
 AtomSelector_ClearEntry(PLDHashTable *table, PLDHashEntryHdr *hdr)
 {
   (static_cast<AtomSelectorEntry*>(hdr))->~AtomSelectorEntry();
 }
 
@@ -933,17 +906,17 @@ struct RuleCascadeData {
   nsTArray<nsCSSPageRule*> mPageRules;
   nsTArray<nsCSSCounterStyleRule*> mCounterStyleRules;
 
   nsDataHashtable<nsStringHashKey, nsCSSKeyframesRule*> mKeyframesRuleTable;
   nsDataHashtable<nsStringHashKey, nsCSSCounterStyleRule*> mCounterStyleRuleTable;
 
   // Looks up or creates the appropriate list in |mAttributeSelectors|.
   // Returns null only on allocation failure.
-  nsTArray<SelectorPair>* AttributeListFor(nsIAtom* aAttribute);
+  nsTArray<nsCSSSelector*>* AttributeListFor(nsIAtom* aAttribute);
 
   nsMediaQueryResultCacheKey mCacheKey;
   RuleCascadeData*  mNext; // for a different medium
 
   const bool mQuirksMode;
 };
 
 static size_t
@@ -997,17 +970,17 @@ RuleCascadeData::SizeOfIncludingThis(Mal
     // since otherwise aKey would be a copy of the string key and we would not
     // be measuring the right object here.
     n += iter.Key().SizeOfExcludingThisIfUnshared(aMallocSizeOf);
   }
 
   return n;
 }
 
-nsTArray<SelectorPair>*
+nsTArray<nsCSSSelector*>*
 RuleCascadeData::AttributeListFor(nsIAtom* aAttribute)
 {
   AtomSelectorEntry *entry =
     static_cast<AtomSelectorEntry*>
                (PL_DHashTableAdd(&mAttributeSelectors, aAttribute, fallible));
   if (!entry)
     return nullptr;
   return &entry->mSelectors;
@@ -2315,73 +2288,16 @@ static bool SelectorMatches(Element* aEl
       result = result || dependence;
     }
   }
   return result;
 }
 
 #undef STATE_CHECK
 
-#ifdef DEBUG
-static bool
-HasPseudoClassSelectorArgsWithCombinators(nsCSSSelector* aSelector)
-{
-  for (nsPseudoClassList* p = aSelector->mPseudoClassList; p; p = p->mNext) {
-    if (nsCSSPseudoClasses::HasSelectorListArg(p->mType)) {
-      for (nsCSSSelectorList* l = p->u.mSelectors; l; l = l->mNext) {
-        if (l->mSelectors->mNext) {
-          return true;
-        }
-      }
-    }
-  }
-  for (nsCSSSelector* n = aSelector->mNegations; n; n = n->mNegations) {
-    if (n->mNext) {
-      return true;
-    }
-  }
-  return false;
-}
-#endif
-
-/* static */ bool
-nsCSSRuleProcessor::RestrictedSelectorMatches(
-    Element* aElement,
-    nsCSSSelector* aSelector,
-    TreeMatchContext& aTreeMatchContext)
-{
-  MOZ_ASSERT(aSelector->IsRestrictedSelector(),
-             "aSelector must not have a pseudo-element");
-
-  NS_WARN_IF_FALSE(!HasPseudoClassSelectorArgsWithCombinators(aSelector),
-                   "processing eRestyle_SomeDescendants can be slow if "
-                   "pseudo-classes with selector arguments can now have "
-                   "combinators in them");
-
-  // We match aSelector as if :visited and :link both match visited and
-  // unvisited links.
-
-  NodeMatchContext nodeContext(EventStates(),
-                               nsCSSRuleProcessor::IsLink(aElement));
-  if (nodeContext.mIsRelevantLink) {
-    aTreeMatchContext.SetHaveRelevantLink();
-  }
-  aTreeMatchContext.ResetForUnvisitedMatching();
-  bool matches = SelectorMatches(aElement, aSelector, nodeContext,
-                                 aTreeMatchContext, SelectorMatchesFlags::NONE);
-  if (nodeContext.mIsRelevantLink) {
-    aTreeMatchContext.ResetForVisitedMatching();
-    if (SelectorMatches(aElement, aSelector, nodeContext, aTreeMatchContext,
-                        SelectorMatchesFlags::NONE)) {
-      matches = true;
-    }
-  }
-  return matches;
-}
-
 // Right now, there are four operators:
 //   ' ', the descendant combinator, is greedy
 //   '~', the indirect adjacent sibling combinator, is greedy
 //   '+' and '>', the direct adjacent sibling and child combinators, are not
 #define NS_IS_GREEDY_OPERATOR(ch) \
   ((ch) == char16_t(' ') || (ch) == char16_t('~'))
 
 static bool SelectorMatchesTree(Element* aPrevElement,
@@ -2776,153 +2692,68 @@ bool
 nsCSSRuleProcessor::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
 {
   RuleCascadeData* cascade = GetRuleCascade(aData->mPresContext);
 
   return cascade && cascade->mSelectorDocumentStates.HasAtLeastOneOfStates(aData->mStateMask);
 }
 
 struct AttributeEnumData {
-  AttributeEnumData(AttributeRuleProcessorData *aData,
-                    RestyleHintData& aRestyleHintData)
-    : data(aData), change(nsRestyleHint(0)), hintData(aRestyleHintData) {}
+  explicit AttributeEnumData(AttributeRuleProcessorData *aData)
+    : data(aData), change(nsRestyleHint(0)) {}
 
   AttributeRuleProcessorData *data;
   nsRestyleHint change;
-  RestyleHintData& hintData;
 };
 
 
-static inline nsRestyleHint
-RestyleHintForSelectorWithAttributeChange(nsRestyleHint aCurrentHint,
-                                          nsCSSSelector* aSelector,
-                                          nsCSSSelector* aRightmostSelector)
-{
-  MOZ_ASSERT(aSelector);
-
-  char16_t oper = aSelector->mOperator;
-
-  if (oper == char16_t('+') || oper == char16_t('~')) {
-    return eRestyle_LaterSiblings;
-  }
-
-  if (oper == char16_t(':')) {
-    return eRestyle_Subtree;
-  }
-
-  if (oper != char16_t(0)) {
-    // Check whether the selector is in a form that supports
-    // eRestyle_SomeDescendants.  If it isn't, return eRestyle_Subtree.
-
-    if (aCurrentHint & eRestyle_Subtree) {
-      // No point checking, since we'll end up restyling the whole
-      // subtree anyway.
-      return eRestyle_Subtree;
-    }
-
-    if (!aRightmostSelector) {
-      // aSelector wasn't a top-level selector, which means we were inside
-      // a :not() or :-moz-any().  We don't support that.
-      return eRestyle_Subtree;
-    }
-
-    MOZ_ASSERT(aSelector != aRightmostSelector,
-               "if aSelector == aRightmostSelector then we should have "
-               "no operator");
-
-    // Check that aRightmostSelector can be passed to RestrictedSelectorMatches.
-    if (!aRightmostSelector->IsRestrictedSelector()) {
-      return eRestyle_Subtree;
-    }
-
-    // We also don't support pseudo-elements on any of the selectors
-    // between aRightmostSelector and aSelector.
-    // XXX Can we lift this restriction, so that we don't have to loop
-    // over all the selectors?
-    for (nsCSSSelector* sel = aRightmostSelector->mNext;
-         sel != aSelector;
-         sel = sel->mNext) {
-      MOZ_ASSERT(sel, "aSelector must be reachable from aRightmostSelector");
-      if (sel->PseudoType() != nsCSSPseudoElements::ePseudo_NotPseudoElement) {
-        return eRestyle_Subtree;
-      }
-    }
-
-    return eRestyle_SomeDescendants;
-  }
-
-  return eRestyle_Self;
-}
-
 static void
-AttributeEnumFunc(nsCSSSelector* aSelector,
-                  nsCSSSelector* aRightmostSelector,
-                  AttributeEnumData* aData)
+AttributeEnumFunc(nsCSSSelector* aSelector, AttributeEnumData* aData)
 {
   AttributeRuleProcessorData *data = aData->data;
 
   if (!data->mTreeMatchContext.SetStyleScopeForSelectorMatching(data->mElement,
                                                                 data->mScope)) {
     // The selector is for a rule in a scoped style sheet, and the subject
     // of the selector matching is not in its scope.
     return;
   }
 
-  nsRestyleHint possibleChange =
-    RestyleHintForSelectorWithAttributeChange(aData->change,
-                                              aSelector, aRightmostSelector);
-
-  // If, ignoring eRestyle_SomeDescendants, enumData->change already includes
-  // all the bits of possibleChange, don't bother calling SelectorMatches, since
-  // even if it returns false enumData->change won't change.  If possibleChange
-  // has eRestyle_SomeDescendants, we need to call SelectorMatches(Tree)
-  // regardless as it might give us new selectors to append to
-  // mSelectorsForDescendants.
+  nsRestyleHint possibleChange = RestyleHintForOp(aSelector->mOperator);
+
+  // If enumData->change already includes all the bits of possibleChange, don't
+  // bother calling SelectorMatches, since even if it returns false
+  // enumData->change won't change.
   NodeMatchContext nodeContext(EventStates(), false);
-  if (((possibleChange & (~(aData->change) | eRestyle_SomeDescendants))) &&
+  if ((possibleChange & ~(aData->change)) &&
       SelectorMatches(data->mElement, aSelector, nodeContext,
                       data->mTreeMatchContext, SelectorMatchesFlags::UNKNOWN) &&
       SelectorMatchesTree(data->mElement, aSelector->mNext,
                           data->mTreeMatchContext, false)) {
     aData->change = nsRestyleHint(aData->change | possibleChange);
-    if (possibleChange & eRestyle_SomeDescendants) {
-      aData->hintData.mSelectorsForDescendants.AppendElement(aRightmostSelector);
-    }
-  }
-}
-
-static MOZ_ALWAYS_INLINE void
-EnumerateSelectors(nsTArray<SelectorPair>& aSelectors, AttributeEnumData* aData)
-{
-  SelectorPair *iter = aSelectors.Elements(),
-               *end = iter + aSelectors.Length();
-  for (; iter != end; ++iter) {
-    AttributeEnumFunc(iter->mSelector, iter->mRightmostSelector, aData);
   }
 }
 
 static MOZ_ALWAYS_INLINE void
 EnumerateSelectors(nsTArray<nsCSSSelector*>& aSelectors, AttributeEnumData* aData)
 {
   nsCSSSelector **iter = aSelectors.Elements(),
                 **end = iter + aSelectors.Length();
   for (; iter != end; ++iter) {
-    AttributeEnumFunc(*iter, nullptr, aData);
+    AttributeEnumFunc(*iter, aData);
   }
 }
 
 nsRestyleHint
-nsCSSRuleProcessor::HasAttributeDependentStyle(
-    AttributeRuleProcessorData* aData,
-    RestyleHintData& aRestyleHintDataResult)
+nsCSSRuleProcessor::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
 {
   //  We could try making use of aData->mModType, but :not rules make it a bit
   //  of a pain to do so...  So just ignore it for now.
 
-  AttributeEnumData data(aData, aRestyleHintDataResult);
+  AttributeEnumData data(aData);
 
   // Don't do our special handling of certain attributes if the attr
   // hasn't changed yet.
   if (aData->mAttrHasChanged) {
     // check for the lwtheme and lwthemetextcolor attribute on root XUL elements
     if ((aData->mAttribute == nsGkAtoms::lwtheme ||
          aData->mAttribute == nsGkAtoms::lwthemetextcolor) &&
         aData->mElement->GetNameSpaceID() == kNameSpaceID_XUL &&
@@ -3234,19 +3065,17 @@ EventStates ComputeSelectorStateDependen
   return states;
 }
 
 static bool
 AddSelector(RuleCascadeData* aCascade,
             // The part between combinators at the top level of the selector
             nsCSSSelector* aSelectorInTopLevel,
             // The part we should look through (might be in :not or :-moz-any())
-            nsCSSSelector* aSelectorPart,
-            // The right-most selector at the top level
-            nsCSSSelector* aRightmostSelector)
+            nsCSSSelector* aSelectorPart)
 {
   // It's worth noting that this loop over negations isn't quite
   // optimal for two reasons.  One, we could add something to one of
   // these lists twice, which means we'll check it twice, but I don't
   // think that's worth worrying about.   (We do the same for multiple
   // attribute selectors on the same attribute.)  Two, we don't really
   // need to check negations past the first in the current
   // implementation (and they're rare as well), but that might change
@@ -3261,23 +3090,22 @@ AddSelector(RuleCascadeData* aCascade,
           aCascade->mSelectorDocumentStates |= NS_DOCUMENT_STATE_RTL_LOCALE;
           break;
         }
         case nsCSSPseudoClasses::ePseudoClass_mozWindowInactive: {
           aCascade->mSelectorDocumentStates |= NS_DOCUMENT_STATE_WINDOW_INACTIVE;
           break;
         }
         case nsCSSPseudoClasses::ePseudoClass_mozTableBorderNonzero: {
-          nsTArray<SelectorPair> *array =
+          nsTArray<nsCSSSelector*> *array =
             aCascade->AttributeListFor(nsGkAtoms::border);
           if (!array) {
             return false;
           }
-          array->AppendElement(SelectorPair(aSelectorInTopLevel,
-                                            aRightmostSelector));
+          array->AppendElement(aSelectorInTopLevel);
           break;
         }
         default: {
           break;
         }
       }
     }
 
@@ -3291,68 +3119,63 @@ AddSelector(RuleCascadeData* aCascade,
 
     // Build mIDSelectors
     if (negation == aSelectorInTopLevel) {
       for (nsAtomList* curID = negation->mIDList; curID;
            curID = curID->mNext) {
         AtomSelectorEntry *entry = static_cast<AtomSelectorEntry*>
           (PL_DHashTableAdd(&aCascade->mIdSelectors, curID->mAtom, fallible));
         if (entry) {
-          entry->mSelectors.AppendElement(SelectorPair(aSelectorInTopLevel,
-                                                       aRightmostSelector));
+          entry->mSelectors.AppendElement(aSelectorInTopLevel);
         }
       }
     } else if (negation->mIDList) {
       aCascade->mPossiblyNegatedIDSelectors.AppendElement(aSelectorInTopLevel);
     }
 
     // Build mClassSelectors
     if (negation == aSelectorInTopLevel) {
       for (nsAtomList* curClass = negation->mClassList; curClass;
            curClass = curClass->mNext) {
         AtomSelectorEntry *entry = static_cast<AtomSelectorEntry*>
           (PL_DHashTableAdd(&aCascade->mClassSelectors, curClass->mAtom,
                             fallible));
         if (entry) {
-          entry->mSelectors.AppendElement(SelectorPair(aSelectorInTopLevel,
-                                                       aRightmostSelector));
+          entry->mSelectors.AppendElement(aSelectorInTopLevel);
         }
       }
     } else if (negation->mClassList) {
       aCascade->mPossiblyNegatedClassSelectors.AppendElement(aSelectorInTopLevel);
     }
 
     // Build mAttributeSelectors.
     for (nsAttrSelector *attr = negation->mAttrList; attr;
          attr = attr->mNext) {
-      nsTArray<SelectorPair> *array =
+      nsTArray<nsCSSSelector*> *array =
         aCascade->AttributeListFor(attr->mCasedAttr);
       if (!array) {
         return false;
       }
-      array->AppendElement(SelectorPair(aSelectorInTopLevel,
-                                        aRightmostSelector));
+      array->AppendElement(aSelectorInTopLevel);
       if (attr->mLowercaseAttr != attr->mCasedAttr) {
         array = aCascade->AttributeListFor(attr->mLowercaseAttr);
         if (!array) {
           return false;
         }
-        array->AppendElement(SelectorPair(aSelectorInTopLevel,
-                                          aRightmostSelector));
+        array->AppendElement(aSelectorInTopLevel);
       }
     }
 
     // Recur through any :-moz-any selectors
     for (nsPseudoClassList* pseudoClass = negation->mPseudoClassList;
          pseudoClass; pseudoClass = pseudoClass->mNext) {
       if (pseudoClass->mType == nsCSSPseudoClasses::ePseudoClass_any) {
         for (nsCSSSelectorList *l = pseudoClass->u.mSelectors; l; l = l->mNext) {
           nsCSSSelector *s = l->mSelectors;
-          if (!AddSelector(aCascade, aSelectorInTopLevel, s,
-                           aRightmostSelector)) {
+          if (!AddSelector(aCascade, aSelectorInTopLevel, s)) {
             return false;
           }
         }
       }
     }
   }
 
   return true;
@@ -3423,17 +3246,17 @@ AddRule(RuleSelectorPair* aRuleInfo, Rul
         // selector's mNext (i.e. the thing that matches against the element),
         // but we want to make sure that selectors for any other kinds of
         // pseudo-elements don't end up in the hashtables.  In particular, tree
         // pseudos store strange things in mPseudoClassList that we don't want
         // to try to match elements against.
         continue;
       }
     }
-    if (!AddSelector(cascade, selector, selector, aRuleInfo->mSelector)) {
+    if (!AddSelector(cascade, selector, selector)) {
       return false;
     }
   }
 
   return true;
 }
 
 struct PerWeightDataListItem : public RuleSelectorPair {
--- a/layout/style/nsCSSRuleProcessor.h
+++ b/layout/style/nsCSSRuleProcessor.h
@@ -107,31 +107,16 @@ public:
              nsRuleWalker::VisitedHandlingType aVisitedHandling,
              bool aIsRelevantLink);
 
   /*
    * Helper to test whether a node is a link
    */
   static bool IsLink(mozilla::dom::Element* aElement);
 
-  /**
-   * Returns true if the given aElement matches aSelector.
-   * Like nsCSSRuleProcessor.cpp's SelectorMatches (and unlike
-   * SelectorMatchesTree), this does not check an entire selector list
-   * separated by combinators.
-   *
-   * :visited and :link will match both visited and non-visited links,
-   * as if aTreeMatchContext->mVisitedHandling were eLinksVisitedOrUnvisited.
-   *
-   * aSelector is restricted to not containing pseudo-elements.
-   */
-  static bool RestrictedSelectorMatches(mozilla::dom::Element* aElement,
-                                        nsCSSSelector* aSelector,
-                                        TreeMatchContext& aTreeMatchContext);
-
   // nsIStyleRuleProcessor
   virtual void RulesMatching(ElementRuleProcessorData* aData) override;
 
   virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override;
 
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
 
 #ifdef MOZ_XUL
@@ -139,19 +124,17 @@ public:
 #endif
 
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override;
 
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
 
   virtual nsRestyleHint
-    HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
-                               mozilla::RestyleHintData& aRestyleHintDataResult)
-                                 override;
+    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override;
 
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
 
   /**
    * If this rule processor currently has a substantive media query
    * result cache key, return a copy of it.
    */
   mozilla::UniquePtr<nsMediaQueryResultCacheKey> CloneMQCacheKey();
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -139,19 +139,17 @@ nsHTMLCSSStyleSheet::HasStateDependentSt
 /* virtual */ bool
 nsHTMLCSSStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
 {
   return false;
 }
 
 // Test if style is dependent on attribute
 /* virtual */ nsRestyleHint
-nsHTMLCSSStyleSheet::HasAttributeDependentStyle(
-    AttributeRuleProcessorData* aData,
-    RestyleHintData& aRestyleHintDataResult)
+nsHTMLCSSStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
 {
   // Perhaps should check that it's XUL, SVG, (or HTML) namespace, but
   // it doesn't really matter.
   if (aData->mAttrHasChanged && aData->mAttribute == nsGkAtoms::style) {
     return eRestyle_StyleAttribute;
   }
 
   return nsRestyleHint(0);
--- a/layout/style/nsHTMLCSSStyleSheet.h
+++ b/layout/style/nsHTMLCSSStyleSheet.h
@@ -38,18 +38,17 @@ public:
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData) override;
 #endif
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override;
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint
-    HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
-                               mozilla::RestyleHintData& aRestyleHintDataResult) override;
+    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override;
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const MOZ_MUST_OVERRIDE override;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const MOZ_MUST_OVERRIDE override;
 
   // Variants of RulesMatching method above that is specific to this
   // rule processor.
--- a/layout/style/nsHTMLStyleSheet.cpp
+++ b/layout/style/nsHTMLStyleSheet.cpp
@@ -330,19 +330,17 @@ nsHTMLStyleSheet::HasStateDependentStyle
 
 /* virtual */ bool
 nsHTMLStyleSheet::HasDocumentStateDependentStyle(StateRuleProcessorData* aData)
 {
   return false;
 }
 
 /* virtual */ nsRestyleHint
-nsHTMLStyleSheet::HasAttributeDependentStyle(
-    AttributeRuleProcessorData* aData,
-    RestyleHintData& aRestyleHintDataResult)
+nsHTMLStyleSheet::HasAttributeDependentStyle(AttributeRuleProcessorData* aData)
 {
   // Do nothing on before-change checks
   if (!aData->mAttrHasChanged) {
     return nsRestyleHint(0);
   }
 
   // Note: no need to worry about whether some states changed with this
   // attribute here, because we handle that under HasStateDependentStyle() as
--- a/layout/style/nsHTMLStyleSheet.h
+++ b/layout/style/nsHTMLStyleSheet.h
@@ -40,18 +40,17 @@ public:
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
 #ifdef MOZ_XUL
   virtual void RulesMatching(XULTreeRuleProcessorData* aData) override;
 #endif
   virtual nsRestyleHint HasStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint HasStateDependentStyle(PseudoElementStateRuleProcessorData* aData) override;
   virtual bool HasDocumentStateDependentStyle(StateRuleProcessorData* aData) override;
   virtual nsRestyleHint
-    HasAttributeDependentStyle(AttributeRuleProcessorData* aData,
-                               mozilla::RestyleHintData& aRestyleHintDataResult) override;
+    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) override;
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) override;
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const MOZ_MUST_OVERRIDE override;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf)
     const MOZ_MUST_OVERRIDE override;
   size_t DOMSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
   void Reset();
--- a/layout/style/nsIStyleRuleProcessor.h
+++ b/layout/style/nsIStyleRuleProcessor.h
@@ -110,19 +110,18 @@ public:
    * implementation to decide how to split the bits up amongst the two
    * return values.  For example, it could return the bits needed by
    * rules that might stop matching the node from the first call and
    * the bits needed by rules that might have started matching the
    * node from the second call.  This test is used for optimization
    * only, and may err on the side of reporting more dependencies than
    * really exist.
    */
-  virtual nsRestyleHint HasAttributeDependentStyle(
-      AttributeRuleProcessorData* aData,
-      mozilla::RestyleHintData& aRestyleHintDataResult) = 0;
+  virtual nsRestyleHint
+    HasAttributeDependentStyle(AttributeRuleProcessorData* aData) = 0;
 
   /**
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether this rule
    * processor's rules have changed (e.g., because of media queries).
    */
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) = 0;
 
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -380,24 +380,16 @@ SortStyleSheetsByScope(nsTArray<CSSStyle
   for (uint32_t i = 0; i < n; i++) {
     aSheets[i] = sheets[i].mSheet;
   }
 }
 
 nsresult
 nsStyleSet::GatherRuleProcessors(sheetType aType)
 {
-  // We might be in GatherRuleProcessors because we are dropping a sheet,
-  // resulting in an nsCSSSelector being destroyed.  Tell the
-  // RestyleManager for each document we're used in so that they can
-  // drop any nsCSSSelector pointers (used for eRestyle_SomeDescendants)
-  // in their mPendingRestyles.
-  if (IsCSSSheetType(aType)) {
-    ClearSelectors();
-  }
   nsCOMPtr<nsIStyleRuleProcessor> oldRuleProcessor(mRuleProcessors[aType]);
   nsTArray<nsCOMPtr<nsIStyleRuleProcessor>> oldScopedDocRuleProcessors;
   if (aType == eAgentSheet || aType == eUserSheet) {
     // drop reference to cached rule processor
     nsCSSRuleProcessor* rp =
       static_cast<nsCSSRuleProcessor*>(mRuleProcessors[aType].get());
     if (rp) {
       MOZ_ASSERT(rp->IsShared());
@@ -2380,51 +2372,42 @@ struct MOZ_STACK_CLASS AttributeData : p
   AttributeData(nsPresContext* aPresContext,
                 Element* aElement, nsIAtom* aAttribute, int32_t aModType,
                 bool aAttrHasChanged, const nsAttrValue* aOtherValue,
                 TreeMatchContext& aTreeMatchContext)
     : AttributeRuleProcessorData(aPresContext, aElement, aAttribute, aModType,
                                  aAttrHasChanged, aOtherValue, aTreeMatchContext),
       mHint(nsRestyleHint(0))
   {}
-  nsRestyleHint mHint;
-  RestyleHintData mHintData;
+  nsRestyleHint   mHint;
 };
 
 static bool
 SheetHasAttributeStyle(nsIStyleRuleProcessor* aProcessor, void *aData)
 {
   AttributeData* data = (AttributeData*)aData;
-  nsRestyleHint hint =
-    aProcessor->HasAttributeDependentStyle(data, data->mHintData);
+  nsRestyleHint hint = aProcessor->HasAttributeDependentStyle(data);
   data->mHint = nsRestyleHint(data->mHint | hint);
   return true; // continue
 }
 
 // Test if style is dependent on content state
 nsRestyleHint
 nsStyleSet::HasAttributeDependentStyle(Element*       aElement,
                                        nsIAtom*       aAttribute,
                                        int32_t        aModType,
                                        bool           aAttrHasChanged,
-                                       const nsAttrValue* aOtherValue,
-                                       mozilla::RestyleHintData&
-                                         aRestyleHintDataResult)
+                                       const nsAttrValue* aOtherValue)
 {
   TreeMatchContext treeContext(false, nsRuleWalker::eLinksVisitedOrUnvisited,
                                aElement->OwnerDoc());
   InitStyleScopes(treeContext, aElement);
   AttributeData data(PresContext(), aElement, aAttribute,
                      aModType, aAttrHasChanged, aOtherValue, treeContext);
   WalkRuleProcessors(SheetHasAttributeStyle, &data, false);
-  if (!(data.mHint & eRestyle_Subtree)) {
-    // No point keeping the list of selectors around if we are going to
-    // restyle the whole subtree unconditionally.
-    aRestyleHintDataResult = Move(data.mHintData);
-  }
   return data.mHint;
 }
 
 bool
 nsStyleSet::MediumFeaturesChanged()
 {
   NS_ASSERTION(mBatching == 0, "rule processors out of date");
 
@@ -2501,14 +2484,8 @@ nsStyleSet::HasRuleProcessorUsedByMultip
   MOZ_ASSERT(size_t(aSheetType) < ArrayLength(mRuleProcessors));
   if (!IsCSSSheetType(aSheetType) || !mRuleProcessors[aSheetType]) {
     return false;
   }
   nsCSSRuleProcessor* rp =
     static_cast<nsCSSRuleProcessor*>(mRuleProcessors[aSheetType].get());
   return rp->IsUsedByMultipleStyleSets();
 }
-
-void
-nsStyleSet::ClearSelectors()
-{
-  PresContext()->RestyleManager()->ClearSelectors();
-}
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -281,19 +281,17 @@ class nsStyleSet final
                                        mozilla::dom::Element* aPseudoElement,
                                        mozilla::EventStates aStateMask);
 
   // Test if style is dependent on the presence of an attribute.
   nsRestyleHint HasAttributeDependentStyle(mozilla::dom::Element* aElement,
                                            nsIAtom*       aAttribute,
                                            int32_t        aModType,
                                            bool           aAttrHasChanged,
-                                           const nsAttrValue* aOtherValue,
-                                           mozilla::RestyleHintData&
-                                             aRestyleHintDataResult);
+                                           const nsAttrValue* aOtherValue);
 
   /*
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether style rules
    * may have changed as a result.
    */
   bool MediumFeaturesChanged();
 
@@ -394,20 +392,16 @@ class nsStyleSet final
   void SetNeedsRestyleAfterEnsureUniqueInner() {
     mNeedsRestyleAfterEnsureUniqueInner = true;
   }
 
   nsIStyleRule* InitialStyleRule();
 
   bool HasRuleProcessorUsedByMultipleStyleSets(sheetType aSheetType);
 
-  // Tells the RestyleManager for the document using this style set
-  // to drop any nsCSSSelector pointers it has.
-  void ClearSelectors();
-
  private:
   nsStyleSet(const nsStyleSet& aCopy) = delete;
   nsStyleSet& operator=(const nsStyleSet& aCopy) = delete;
 
   // Run mark-and-sweep GC on mRuleTree and mOldRuleTrees, based on mRoots.
   void GCRuleTrees();
 
   // Update the rule processor list after a change to the style sheet list.