Bug 1367904 - Part 11: stylo: Use ServoStyleContext in ServoStyleSet/ServoRestyleManager; r?bholley draft
authorManish Goregaokar <manishearth@gmail.com>
Thu, 15 Jun 2017 22:49:50 -0700
changeset 607488 20be949ec55606c714803ae098dcff75048b5607
parent 607487 83f5d1487934a17e4c9a35b4229816991a6c0de3
child 607489 a8991c019267deb63ab2aac8678579f1305cdaac
push id67989
push userbmo:manishearth@gmail.com
push dateWed, 12 Jul 2017 08:49:55 +0000
reviewersbholley
bugs1367904
milestone56.0a1
Bug 1367904 - Part 11: stylo: Use ServoStyleContext in ServoStyleSet/ServoRestyleManager; r?bholley MozReview-Commit-ID: JJOBixTSCZq
layout/base/ServoRestyleManager.cpp
layout/base/ServoRestyleManager.h
layout/build/nsLayoutStatics.cpp
layout/generic/nsBlockFrame.cpp
layout/generic/nsFrame.cpp
layout/generic/nsInlineFrame.cpp
layout/style/GeckoStyleContext.cpp
layout/style/GeckoStyleContext.h
layout/style/ServoStyleContext.h
layout/style/ServoStyleSet.cpp
layout/style/ServoStyleSet.h
layout/style/StyleSetHandleInlines.h
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/tables/nsTableFrame.cpp
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -255,17 +255,17 @@ ServoRestyleManager::ClearRestyleStateFr
  *
  * This is currently used to properly compute change hints when the parent
  * element of this node is a display: contents node, and also to avoid computing
  * the style for text children more than once per element.
  */
 struct ServoRestyleManager::TextPostTraversalState
 {
 public:
-  TextPostTraversalState(nsStyleContext& aParentContext,
+  TextPostTraversalState(ServoStyleContext& aParentContext,
                          bool aDisplayContentsParentStyleChanged,
                          ServoRestyleState& aParentRestyleState)
     : mParentContext(aParentContext)
     , mParentRestyleState(aParentRestyleState)
     , mStyle(nullptr)
     , mShouldPostHints(aDisplayContentsParentStyleChanged)
     , mShouldComputeHints(aDisplayContentsParentStyleChanged)
     , mComputedHint(nsChangeHint_Empty)
@@ -289,17 +289,17 @@ public:
   {
     MOZ_ASSERT(aTextFrame);
     MOZ_ASSERT(aNewContext.GetPseudo() == nsCSSAnonBoxes::mozText);
 
     if (MOZ_LIKELY(!mShouldPostHints)) {
       return;
     }
 
-    nsStyleContext* oldContext = aTextFrame->StyleContext();
+    ServoStyleContext* oldContext = aTextFrame->StyleContext()->AsServo();
     MOZ_ASSERT(oldContext->GetPseudo() == nsCSSAnonBoxes::mozText);
 
     // We rely on the fact that all the text children for the same element share
     // style to avoid recomputing style differences for all of them.
     //
     // TODO(emilio): The above may not be true for ::first-{line,letter}, but
     // we'll cross that bridge when we support those in stylo.
     if (mShouldComputeHints) {
@@ -315,17 +315,17 @@ public:
 
     if (mComputedHint) {
       mParentRestyleState.ChangeList().AppendChange(
         aTextFrame, aContent, mComputedHint);
     }
   }
 
 private:
-  nsStyleContext& mParentContext;
+  ServoStyleContext& mParentContext;
   ServoRestyleState& mParentRestyleState;
   RefPtr<nsStyleContext> mStyle;
   bool mShouldPostHints;
   bool mShouldComputeHints;
   nsChangeHint mComputedHint;
 };
 
 // Find the first-letter frame for the given element, if any.  Returns null to
@@ -377,17 +377,17 @@ UpdateBackdropIfNeeded(nsIFrame* aFrame,
     nsPlaceholderFrame::GetRealFrameForPlaceholder(backdropPlaceholder);
   MOZ_ASSERT(backdropFrame->IsBackdropFrame());
   MOZ_ASSERT(backdropFrame->StyleContext()->GetPseudoType() ==
              CSSPseudoElementType::backdrop);
 
   RefPtr<nsStyleContext> newContext =
     aStyleSet.ResolvePseudoElementStyle(aFrame->GetContent()->AsElement(),
                                         CSSPseudoElementType::backdrop,
-                                        aFrame->StyleContext(),
+                                        aFrame->StyleContext()->AsServo(),
                                         /* aPseudoElement = */ nullptr);
 
   // NOTE(emilio): We can't use the changes handled for the owner of the
   // backdrop frame, since it's out of flow, and parented to the viewport frame.
   MOZ_ASSERT(backdropFrame->GetParent()->IsViewportFrame());
   ServoRestyleState state(aStyleSet, aChangeList);
   aFrame->UpdateStyleOfOwnedChildFrame(backdropFrame, newContext, state);
 }
@@ -423,21 +423,20 @@ UpdateFramePseudoElementStyles(nsIFrame*
   }
 
   UpdateBackdropIfNeeded(
     aFrame, aRestyleState.StyleSet(), aRestyleState.ChangeList());
 }
 
 bool
 ServoRestyleManager::ProcessPostTraversal(Element* aElement,
-                                          nsStyleContext* aParentContext,
+                                          ServoStyleContext* aParentContext,
                                           ServoRestyleState& aRestyleState)
 {
   nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(aElement);
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
 
   // NOTE(emilio): This is needed because for table frames the bit is set on the
   // table wrapper (which is the primary frame), not on the table itself.
   const bool isOutOfFlow =
     aElement->GetPrimaryFrame() &&
     aElement->GetPrimaryFrame()->HasAnyStateBits(NS_FRAME_OUT_OF_FLOW);
 
   // Grab the change hint from Servo.
@@ -535,17 +534,17 @@ ServoRestyleManager::ProcessPostTraversa
     MOZ_ASSERT(styleFrame || displayContentsNode);
 
     auto pseudo = aElement->GetPseudoElementType();
     nsIAtom* pseudoTag = pseudo == CSSPseudoElementType::NotPseudo
       ? nullptr : nsCSSPseudoElements::GetPseudoAtom(pseudo);
 
     // XXXManishearth we should just reuse the old one here
     RefPtr<ServoStyleContext> tempContext =
-      Servo_StyleContext_NewContext(currentContext->ComputedValues(), parent,
+      Servo_StyleContext_NewContext(currentContext->ComputedValues(), aParentContext,
                                     PresContext(), pseudo, pseudoTag).Consume();
     newContext = aRestyleState.StyleSet().GetContext(tempContext.forget(), aParentContext,
                                                      pseudoTag, pseudo, aElement);
 
     newContext->ResolveSameStructsAs(PresContext(), oldStyleContext);
 
     // We want to walk all the continuations here, even the ones with different
     // styles.  In practice, the only reason we get continuations with different
@@ -597,17 +596,17 @@ ServoRestyleManager::ProcessPostTraversa
     aElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
   const bool traverseElementChildren =
     aElement->HasDirtyDescendantsForServo() ||
     aElement->HasAnimationOnlyDirtyDescendantsForServo() ||
     descendantsNeedFrames;
   const bool traverseTextChildren = recreateContext || descendantsNeedFrames;
   bool recreatedAnyContext = recreateContext;
   if (traverseElementChildren || traverseTextChildren) {
-    nsStyleContext* upToDateContext =
+    ServoStyleContext* upToDateContext =
       recreateContext ? newContext : oldStyleContext;
 
     StyleChildrenIterator it(aElement);
     TextPostTraversalState textState(*upToDateContext,
                                      displayContentsNode && recreateContext,
                                      childrenRestyleState);
     for (nsIContent* n = it.GetNextChild(); n; n = it.GetNextChild()) {
       if (traverseElementChildren && n->IsElement()) {
--- a/layout/base/ServoRestyleManager.h
+++ b/layout/base/ServoRestyleManager.h
@@ -184,17 +184,17 @@ private:
    * descendants.
    *
    * Returns whether any style did actually change. There may be cases where we
    * didn't need to change any style after all, for example, when a content
    * attribute changes that happens not to have any effect on the style of that
    * element or any descendant or sibling.
    */
   bool ProcessPostTraversal(Element* aElement,
-                            nsStyleContext* aParentContext,
+                            ServoStyleContext* aParentContext,
                             ServoRestyleState& aRestyleState);
 
   struct TextPostTraversalState;
   bool ProcessPostTraversalForText(nsIContent* aTextNode,
                                    TextPostTraversalState& aState);
 
   inline ServoStyleSet* StyleSet() const
   {
--- a/layout/build/nsLayoutStatics.cpp
+++ b/layout/build/nsLayoutStatics.cpp
@@ -291,17 +291,17 @@ nsLayoutStatics::Initialize()
 
   CounterStyleManager::InitializeBuiltinCounterStyles();
 
   IMEStateManager::Init();
 
   ServiceWorkerRegistrar::Initialize();
 
 #ifdef DEBUG
-  nsStyleContext::Initialize();
+  GeckoStyleContext::Initialize();
   mozilla::LayerAnimationInfo::Initialize();
 #endif
 
   MediaDecoder::InitStatics();
 
   PromiseDebugging::Init();
 
   mozilla::dom::WebCryptoThreadPool::Initialize();
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -5637,17 +5637,17 @@ nsBlockFrame::UpdateFirstLetterStyle(Ser
   // nsCSSFrameConstructor::CreateLetterFrame.
   nsIFrame* inFlowFrame = letterFrame;
   if (inFlowFrame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
     inFlowFrame = inFlowFrame->GetPlaceholderFrame();
   }
   nsIFrame* styleParent =
     CorrectStyleParentFrame(inFlowFrame->GetParent(),
                             nsCSSPseudoElements::firstLetter);
-  nsStyleContext* parentStyle = styleParent->StyleContext();
+  ServoStyleContext* parentStyle = styleParent->StyleContext()->AsServo();
   RefPtr<nsStyleContext> firstLetterStyle =
     aRestyleState.StyleSet()
                  .ResolvePseudoElementStyle(mContent->AsElement(),
                                             CSSPseudoElementType::firstLetter,
                                             parentStyle,
                                             nullptr);
   // Note that we don't need to worry about changehints for the continuation
   // styles: those will be handled by the styleParent already.
@@ -5657,17 +5657,17 @@ nsBlockFrame::UpdateFirstLetterStyle(Ser
                                Some(continuationStyle.get()));
 
   // We also want to update the style on the textframe inside the first-letter.
   // We don't need to compute a changehint for this, though, since any changes
   // to it are handled by the first-letter anyway.
   nsIFrame* textFrame = letterFrame->PrincipalChildList().FirstChild();
   RefPtr<nsStyleContext> firstTextStyle =
     aRestyleState.StyleSet().ResolveStyleForText(textFrame->GetContent(),
-                                                 firstLetterStyle);
+                                                 firstLetterStyle->AsServo());
   textFrame->SetStyleContext(firstTextStyle);
 
   // We don't need to update style for textFrame's continuations: it's already
   // set up to inherit from parentStyle, which is what we want.
 }
 
 static nsIFrame*
 FindChildContaining(nsBlockFrame* aFrame, nsIFrame* aFindFrame)
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10220,19 +10220,19 @@ nsIFrame::UpdateStyleOfChildAnonBox(nsIF
   // We could force the caller to pass in the pseudo, since some callers know it
   // statically...  But this API is a bit nicer.
   nsIAtom* pseudo = aChildFrame->StyleContext()->GetPseudo();
   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(pseudo), "Child is not an anon box?");
   MOZ_ASSERT(!nsCSSAnonBoxes::IsNonInheritingAnonBox(pseudo),
              "Why did the caller bother calling us?");
 
   // Anon boxes inherit from their parent; that's us.
-  RefPtr<nsStyleContext> newContext =
+  RefPtr<ServoStyleContext> newContext =
     aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(pseudo,
-                                                                StyleContext());
+                                                                StyleContext()->AsServo());
 
   nsChangeHint childHint =
     UpdateStyleOfOwnedChildFrame(aChildFrame, newContext, aRestyleState);
 
   // Now that we've updated the style on aChildFrame, check whether it itself
   // has anon boxes to deal with.
   ServoRestyleState childrenState(
       *aChildFrame, aRestyleState, childHint, ServoRestyleState::Type::InFlow);
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -1028,21 +1028,21 @@ nsInlineFrame::UpdateStyleOfOwnedAnonBox
              "split should have NS_FRAME_OWNS_ANON_BOXES");
   MOZ_ASSERT(mContent->GetPrimaryFrame() == this,
              "We should be the primary frame for our element");
 
   nsIFrame* blockFrame = GetProperty(nsIFrame::IBSplitSibling());
   MOZ_ASSERT(blockFrame, "Why did we have an IB split?");
 
   // The later inlines need to get our style.
-  nsStyleContext* ourStyle = StyleContext();
+  ServoStyleContext* ourStyle = StyleContext()->AsServo();
 
   // The anonymous block's style inherits from ours, and we already have our new
   // style context.
-  RefPtr<nsStyleContext> newContext =
+  RefPtr<ServoStyleContext> newContext =
     aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(
       nsCSSAnonBoxes::mozBlockInsideInlineWrapper, ourStyle);
 
   // We're guaranteed that newContext only differs from the old style context on
   // the block in things they might inherit from us.  And changehint processing
   // guarantees walking the continuation and ib-sibling chains, so our existing
   // changehint being in aChangeList is good enough.  So we don't need to touch
   // aChangeList at all here.
--- a/layout/style/GeckoStyleContext.cpp
+++ b/layout/style/GeckoStyleContext.cpp
@@ -1,27 +1,41 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #include "mozilla/GeckoStyleContext.h"
 
+#include "CSSVariableImageTable.h"
 #include "nsStyleConsts.h"
 #include "nsStyleStruct.h"
 #include "nsPresContext.h"
 #include "nsRuleNode.h"
 #include "nsStyleContextInlines.h"
 #include "nsIFrame.h"
 #include "nsLayoutUtils.h"
 #include "mozilla/ReflowInput.h"
 #include "RubyUtils.h"
 
 using namespace mozilla;
 
+#ifdef DEBUG
+// Whether to perform expensive assertions in the nsStyleContext destructor.
+static bool sExpensiveStyleStructAssertionsEnabled;
+
+/* static */ void
+GeckoStyleContext::Initialize()
+{
+  Preferences::AddBoolVarCache(
+      &sExpensiveStyleStructAssertionsEnabled,
+      "layout.css.expensive-style-struct-assertions.enabled");
+}
+#endif
+
 GeckoStyleContext::GeckoStyleContext(nsStyleContext* aParent,
                                      nsIAtom* aPseudoTag,
                                      CSSPseudoElementType aPseudoType,
                                      already_AddRefed<nsRuleNode> aRuleNode,
                                      bool aSkipParentDisplayBasedStyleFixup)
   : nsStyleContext(aParent, aPseudoTag, aPseudoType)
   , mCachedResetData(nullptr)
   , mChild(nullptr)
@@ -59,16 +73,54 @@ void*
 GeckoStyleContext::operator new(size_t sz, nsPresContext* aPresContext)
 {
   MOZ_ASSERT(sz == sizeof(GeckoStyleContext));
   // Check the recycle list first.
   return aPresContext->PresShell()->
     AllocateByObjectID(eArenaObjectID_GeckoStyleContext, sz);
 }
 
+GeckoStyleContext::~GeckoStyleContext()
+{
+  nsPresContext *presContext = PresContext();
+#ifdef DEBUG
+  NS_ASSERTION(HasNoChildren(), "destructing context with children");
+  if (sExpensiveStyleStructAssertionsEnabled) {
+    // Assert that the style structs we are about to destroy are not referenced
+    // anywhere else in the style context tree.  These checks are expensive,
+    // which is why they are not enabled by default.
+    GeckoStyleContext* root = this;
+    while (root->GetParent()) {
+      root = root->GetParent();
+    }
+    root->AssertStructsNotUsedElsewhere(this,
+                                        std::numeric_limits<int32_t>::max());
+  } else {
+    // In DEBUG builds when the pref is not enabled, we perform a more limited
+    // check just of the children of this style context.
+    this->AssertStructsNotUsedElsewhere(this, 2);
+  }
+
+  nsStyleSet* geckoStyleSet = presContext->PresShell()->StyleSet()->GetAsGecko();
+  NS_ASSERTION(!geckoStyleSet ||
+               geckoStyleSet->GetRuleTree() == AsGecko()->RuleNode()->RuleTree() ||
+               geckoStyleSet->IsInRuleTreeReconstruct(),
+               "destroying style context from old rule tree too late");
+#endif
+
+  if (mParent) {
+    mParent->AsGecko()->RemoveChild(this);
+  } else {
+    presContext->StyleSet()->RootStyleContextRemoved();
+  }
+
+  // Free up our data structs.
+  DestroyCachedStructs(presContext);
+  CSSVariableImageTable::RemoveAll(this);
+}
 
 void
 GeckoStyleContext::AddChild(GeckoStyleContext* aChild)
 {
   NS_ASSERTION(aChild->mPrevSibling == aChild &&
                aChild->mNextSibling == aChild,
                "child already in a child list");
 
--- a/layout/style/GeckoStyleContext.h
+++ b/layout/style/GeckoStyleContext.h
@@ -26,16 +26,23 @@ public:
   }
 
   void AddChild(GeckoStyleContext* aChild);
   void RemoveChild(GeckoStyleContext* aChild);
 
   void* GetUniqueStyleData(const nsStyleStructID& aSID);
   void* CreateEmptyStyleData(const nsStyleStructID& aSID);
 
+#ifdef DEBUG
+  /**
+   * Initializes a cached pref, which is only used in DEBUG code.
+   */
+  static void Initialize();
+#endif
+
   /**
    * Ensures the same structs are cached on this style context as would be
    * done if we called aOther->CalcDifference(this).
    */
   void EnsureSameStructsCached(nsStyleContext* aOldContext);
 
   /**
    * Sets the NS_STYLE_INELIGIBLE_FOR_SHARING bit on this style context
@@ -129,19 +136,17 @@ public:
     NS_LOG_RELEASE(this, mRefCnt, "nsStyleContext");
     if (mRefCnt == 0) {
       Destroy();
       return;
     }
     return;
   }
 
-  ~GeckoStyleContext() {
-    Destructor();
-  }
+  ~GeckoStyleContext();
 
   /**
    * Swaps owned style struct pointers between this and aNewContext, on
    * the assumption that aNewContext is the new style context for a frame
    * and this is the old one.  aStructs indicates which structs to consider
    * swapping; only those which are owned in both this and aNewContext
    * will be swapped.
    *
--- a/layout/style/ServoStyleContext.h
+++ b/layout/style/ServoStyleContext.h
@@ -30,20 +30,16 @@ public:
   void AddRef() {
     Servo_StyleContext_AddRef(this);
   }
 
   void Release() {
     Servo_StyleContext_Release(this);
   }
 
-  ~ServoStyleContext() {
-    Destructor();
-  }
-
   /**
    * Makes this context match |aOther| in terms of which style structs have
    * been resolved.
    */
   void ResolveSameStructsAs(nsPresContext* aPresContext, ServoStyleContext* aOther) {
     // NB: This function is only called on newly-minted style contexts, but
     // those may already have resolved style structs given the SetStyleBits call
     // in FinishConstruction. So we carefully xor out the bits that are new so
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -165,52 +165,51 @@ ServoStyleSet::BeginUpdate()
 nsresult
 ServoStyleSet::EndUpdate()
 {
   return NS_OK;
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveStyleFor(Element* aElement,
-                               nsStyleContext* aParentContext,
+                               ServoStyleContext* aParentContext,
                                LazyComputeBehavior aMayCompute)
 {
   return GetContext(aElement, aParentContext, nullptr,
                     CSSPseudoElementType::NotPseudo, aMayCompute);
 }
 
 already_AddRefed<ServoStyleContext>
 ServoStyleSet::GetContext(nsIContent* aContent,
-                          nsStyleContext* aParentContext,
+                          ServoStyleContext* aParentContext,
                           nsIAtom* aPseudoTag,
                           CSSPseudoElementType aPseudoType,
                           LazyComputeBehavior aMayCompute)
 {
   MOZ_ASSERT(aContent->IsElement());
   Element* element = aContent->AsElement();
 
   RefPtr<ServoStyleContext> computedValues;
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
   if (aMayCompute == LazyComputeBehavior::Allow) {
     PreTraverseSync();
     RefPtr<ServoStyleContext> tmp =
-      ResolveStyleLazily(element, CSSPseudoElementType::NotPseudo, aPseudoTag, parent);
-      computedValues = GetContext(tmp.forget(), parent, aPseudoTag, aPseudoType,
+      ResolveStyleLazily(element, CSSPseudoElementType::NotPseudo, aPseudoTag, aParentContext);
+      computedValues = GetContext(tmp.forget(), aParentContext, aPseudoTag, aPseudoType,
                                   element);
   } else {
     computedValues = ResolveServoStyle(element);
   }
 
   MOZ_ASSERT(computedValues);
   return computedValues.forget();
 }
 
 already_AddRefed<ServoStyleContext>
 ServoStyleSet::GetContext(already_AddRefed<ServoStyleContext> aComputedValues,
-                          nsStyleContext* aParentContext,
+                          ServoStyleContext* aParentContext,
                           nsIAtom* aPseudoTag,
                           CSSPseudoElementType aPseudoType,
                           Element* aElementForAnimation)
 {
   bool isLink = false;
   bool isVisitedLink = false;
   // If we need visited styles for callers where `aElementForAnimation` is null,
   // we can precompute these and pass them as flags, similar to nsStyleSet.cpp.
@@ -415,47 +414,46 @@ ServoStyleSet::PrepareAndTraverseSubtree
     }
   }
 
   return postTraversalRequired;
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolveStyleForText(nsIContent* aTextNode,
-                                   nsStyleContext* aParentContext)
+                                   ServoStyleContext* aParentContext)
 {
   MOZ_ASSERT(aTextNode && aTextNode->IsNodeOfType(nsINode::eTEXT));
   MOZ_ASSERT(aTextNode->GetParent());
   MOZ_ASSERT(aParentContext);
 
   // Gecko expects text node style contexts to be like elements that match no
   // rules: inherit the inherit structs, reset the reset structs. This is cheap
   // enough to do on the main thread, which means that the parallel style system
   // can avoid worrying about text nodes.
   RefPtr<ServoStyleContext> computedValues =
     Servo_ComputedValues_Inherit(mRawSet.get(),
                                  CSSPseudoElementType::InheritingAnonBox,
                                  nsCSSAnonBoxes::mozText,
-                                 aParentContext->AsServo(),
+                                 aParentContext,
                                  InheritTarget::Text).Consume();
   return GetContext(computedValues.forget(), aParentContext,
                     nsCSSAnonBoxes::mozText,
                     CSSPseudoElementType::InheritingAnonBox,
                     nullptr);
 }
 
 already_AddRefed<nsStyleContext>
-ServoStyleSet::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
+ServoStyleSet::ResolveStyleForFirstLetterContinuation(ServoStyleContext* aParentContext)
 {
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
   RefPtr<ServoStyleContext> computedValues =
     Servo_ComputedValues_Inherit(mRawSet.get(),
                                  CSSPseudoElementType::InheritingAnonBox,
                                  nsCSSAnonBoxes::firstLetterContinuation,
-                                 parent,
+                                 aParentContext,
                                  InheritTarget::FirstLetterContinuation)
                                  .Consume();
   MOZ_ASSERT(computedValues);
 
   return GetContext(computedValues.forget(), aParentContext,
                     nsCSSAnonBoxes::firstLetterContinuation,
                     CSSPseudoElementType::InheritingAnonBox,
                     nullptr);
@@ -487,41 +485,40 @@ ServoStyleSet::ResolveStyleForPlaceholde
                nullptr);
   cache = retval;
   return retval.forget();
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ResolvePseudoElementStyle(Element* aOriginatingElement,
                                          CSSPseudoElementType aType,
-                                         nsStyleContext* aParentContext,
+                                         ServoStyleContext* aParentContext,
                                          Element* aPseudoElement)
 {
   UpdateStylistIfNeeded();
 
   MOZ_ASSERT(aType < CSSPseudoElementType::Count);
 
   RefPtr<ServoStyleContext> computedValues;
 
   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
   if (aPseudoElement) {
     MOZ_ASSERT(aType == aPseudoElement->GetPseudoElementType());
     computedValues = Servo_ResolveStyle(aPseudoElement,
                                         mRawSet.get()).Consume();
   } else {
     const ServoComputedValues* parentStyle =
       aParentContext ? aParentContext->ComputedValues() : nullptr;
-    ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
     computedValues =
       Servo_ResolvePseudoStyle(aOriginatingElement,
                                aType,
                                pseudoTag,
                                /* is_probe = */ false,
                                parentStyle,
-                               parent,
+                               aParentContext,
                                mRawSet.get()).Consume();
   }
 
   MOZ_ASSERT(computedValues);
 
   bool isBeforeOrAfter = aType == CSSPseudoElementType::before ||
                          aType == CSSPseudoElementType::after;
 
@@ -552,29 +549,27 @@ ServoStyleSet::ResolveTransientServoStyl
     StyleRuleInclusion aRuleInclusion)
 {
   PreTraverseSync();
   return ResolveStyleLazily(aElement, aPseudoType, aPseudoTag, nullptr, aRuleInclusion);
 }
 
 already_AddRefed<ServoStyleContext>
 ServoStyleSet::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
-                                                  nsStyleContext* aParentContext)
+                                                  ServoStyleContext* aParentContext)
 {
   MOZ_ASSERT(nsCSSAnonBoxes::IsAnonBox(aPseudoTag) &&
              !nsCSSAnonBoxes::IsNonInheritingAnonBox(aPseudoTag));
 
   UpdateStylistIfNeeded();
 
   bool skipFixup =
     nsCSSAnonBoxes::AnonBoxSkipsParentDisplayBasedStyleFixup(aPseudoTag);
-
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
   RefPtr<ServoStyleContext> computedValues =
-    Servo_ComputedValues_GetForAnonymousBox(parent, CSSPseudoElementType::InheritingAnonBox,
+    Servo_ComputedValues_GetForAnonymousBox(aParentContext, CSSPseudoElementType::InheritingAnonBox,
                                             aPseudoTag, skipFixup,
                                             mRawSet.get()).Consume();
 #ifdef DEBUG
   if (!computedValues) {
     nsString pseudo;
     aPseudoTag->ToString(pseudo);
     NS_ERROR(nsPrintfCString("stylo: could not get anon-box: %s",
              NS_ConvertUTF16toUTF8(pseudo).get()).get());
@@ -829,33 +824,32 @@ ServoStyleSet::AddDocStyleSheet(ServoSty
   }
 
   return NS_OK;
 }
 
 already_AddRefed<nsStyleContext>
 ServoStyleSet::ProbePseudoElementStyle(Element* aOriginatingElement,
                                        CSSPseudoElementType aType,
-                                       nsStyleContext* aParentContext)
+                                       ServoStyleContext* aParentContext)
 {
   UpdateStylistIfNeeded();
 
   // NB: We ignore aParentContext, because in some cases
   // (first-line/first-letter on anonymous box blocks) Gecko passes something
   // nonsensical there.  In all other cases we want to inherit directly from
   // aOriginatingElement's styles anyway.
   MOZ_ASSERT(aType < CSSPseudoElementType::Count);
 
   nsIAtom* pseudoTag = nsCSSPseudoElements::GetPseudoAtom(aType);
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
   RefPtr<ServoStyleContext> computedValues =
     Servo_ResolvePseudoStyle(aOriginatingElement, aType, pseudoTag,
                              /* is_probe = */ true,
                              nullptr,
-                             parent,
+                             aParentContext,
                              mRawSet.get()).Consume();
   if (!computedValues) {
     return nullptr;
   }
 
   // For :before and :after pseudo-elements, having display: none or no
   // 'content' property is equivalent to not having the pseudo-element
   // at all.
@@ -1084,17 +1078,17 @@ ServoStyleSet::GetAnimationValues(
                            aElement,
                            aComputedValues,
                            mRawSet.get(),
                            &aAnimationValues);
 }
 
 already_AddRefed<ServoStyleContext>
 ServoStyleSet::GetBaseContextForElement(dom::Element* aElement,
-                         nsStyleContext* aParentContext,
+                         ServoStyleContext* aParentContext,
                          nsPresContext* aPresContext,
                          nsIAtom* aPseudoTag,
                          CSSPseudoElementType aPseudoType)
 {
   return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
                                                         aElement,
                                                         &Snapshots(),
                                                         aPseudoType).Consume();
--- a/layout/style/ServoStyleSet.h
+++ b/layout/style/ServoStyleSet.h
@@ -128,42 +128,42 @@ public:
   bool GetAuthorStyleDisabled() const;
   nsresult SetAuthorStyleDisabled(bool aStyleDisabled);
 
   void BeginUpdate();
   nsresult EndUpdate();
 
   already_AddRefed<nsStyleContext>
   ResolveStyleFor(dom::Element* aElement,
-                  nsStyleContext* aParentContext,
+                  ServoStyleContext* aParentContext,
                   LazyComputeBehavior aMayCompute);
 
   // Get a style context for a text node (which no rules will match).
   //
   // The returned style context will have nsCSSAnonBoxes::mozText as its pseudo.
   //
   // (Perhaps mozText should go away and we shouldn't even create style
   // contexts for such content nodes, when text-combine-upright is not
   // present.  However, not doing any rule matching for them is a first step.)
   already_AddRefed<nsStyleContext>
   ResolveStyleForText(nsIContent* aTextNode,
-                      nsStyleContext* aParentContext);
+                      ServoStyleContext* aParentContext);
 
   // Get a style context for a first-letter continuation (which no rules will
   // match).
   //
   // The returned style context will have
   // nsCSSAnonBoxes::firstLetterContinuation as its pseudo.
   //
   // (Perhaps nsCSSAnonBoxes::firstLetterContinuation should go away and we
   // shouldn't even create style contexts for such frames.  However, not doing
   // any rule matching for them is a first step.  And right now we do use this
   // style context for some things)
   already_AddRefed<nsStyleContext>
-  ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext);
+  ResolveStyleForFirstLetterContinuation(ServoStyleContext* aParentContext);
 
   // Get a style context for a placeholder frame (which no rules will match).
   //
   // The returned style context will have nsCSSAnonBoxes::oofPlaceholder as
   // its pseudo.
   //
   // (Perhaps nsCSSAnonBoxes::oofPaceholder should go away and we shouldn't even
   // create style contexts for placeholders.  However, not doing any rule
@@ -174,17 +174,17 @@ public:
   // Get a style context for a pseudo-element.  aParentElement must be
   // non-null.  aPseudoID is the CSSPseudoElementType for the
   // pseudo-element.  aPseudoElement must be non-null if the pseudo-element
   // type is one that allows user action pseudo-classes after it or allows
   // style attributes; otherwise, it is ignored.
   already_AddRefed<nsStyleContext>
   ResolvePseudoElementStyle(dom::Element* aOriginatingElement,
                             CSSPseudoElementType aType,
-                            nsStyleContext* aParentContext,
+                            ServoStyleContext* aParentContext,
                             dom::Element* aPseudoElement);
 
   // Resolves style for a (possibly-pseudo) Element without assuming that the
   // style has been resolved, and without worrying about setting the style
   // context up to live in the style context tree (a null parent is used).
   // |aPeudoTag| and |aPseudoType| must match.
   already_AddRefed<nsStyleContext>
   ResolveTransientStyle(dom::Element* aElement,
@@ -202,17 +202,17 @@ public:
                              StyleRuleInclusion aRules =
                                StyleRuleInclusion::All);
 
   // Get a style context for an anonymous box.  aPseudoTag is the pseudo-tag to
   // use and must be non-null.  It must be an anon box, and must be one that
   // inherits style from the given aParentContext.
   already_AddRefed<ServoStyleContext>
   ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
-                                     nsStyleContext* aParentContext);
+                                     ServoStyleContext* aParentContext);
 
   // Get a style context for an anonymous box that does not inherit style from
   // anything.  aPseudoTag is the pseudo-tag to use and must be non-null.  It
   // must be an anon box, and must be a non-inheriting one.
   already_AddRefed<nsStyleContext>
   ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag);
 
   // manage the set of style sheets in the style set
@@ -244,17 +244,17 @@ public:
 
   nsresult RemoveDocStyleSheet(ServoStyleSheet* aSheet);
   nsresult AddDocStyleSheet(ServoStyleSheet* aSheet, nsIDocument* aDocument);
 
   // check whether there is ::before/::after style for an element
   already_AddRefed<nsStyleContext>
   ProbePseudoElementStyle(dom::Element* aOriginatingElement,
                           mozilla::CSSPseudoElementType aType,
-                          nsStyleContext* aParentContext);
+                          ServoStyleContext* aParentContext);
 
   // Test if style is dependent on content state
   nsRestyleHint HasStateDependentStyle(dom::Element* aElement,
                                        EventStates aStateMask);
   nsRestyleHint HasStateDependentStyle(
     dom::Element* aElement, mozilla::CSSPseudoElementType aPseudoType,
     dom::Element* aPseudoElement, EventStates aStateMask);
 
@@ -380,17 +380,17 @@ public:
                      nsTArray<RefPtr<RawServoAnimationValue>>& aAnimationValues);
 
   bool AppendFontFaceRules(nsTArray<nsFontFaceRuleContainer>& aArray);
 
   nsCSSCounterStyleRule* CounterStyleRuleForName(nsIAtom* aName);
 
   already_AddRefed<ServoStyleContext>
   GetBaseContextForElement(dom::Element* aElement,
-                           nsStyleContext* aParentContext,
+                           ServoStyleContext* aParentContext,
                            nsPresContext* aPresContext,
                            nsIAtom* aPseudoTag,
                            CSSPseudoElementType aPseudoType);
 
   /**
    * Resolve style for a given declaration block with/without the parent style.
    * If the parent style is not specified, the document default computed values
    * is used.
@@ -473,23 +473,23 @@ private:
       mSet->RunPostTraversalTasks();
     }
 
   private:
     ServoStyleSet* mSet;
   };
 
   already_AddRefed<ServoStyleContext> GetContext(already_AddRefed<ServoStyleContext>,
-                                                 nsStyleContext* aParentContext,
+                                                 ServoStyleContext* aParentContext,
                                                  nsIAtom* aPseudoTag,
                                                  CSSPseudoElementType aPseudoType,
                                                  dom::Element* aElementForAnimation);
 
   already_AddRefed<ServoStyleContext> GetContext(nsIContent* aContent,
-                                                 nsStyleContext* aParentContext,
+                                                 ServoStyleContext* aParentContext,
                                                  nsIAtom* aPseudoTag,
                                                  CSSPseudoElementType aPseudoType,
                                                  LazyComputeBehavior aMayCompute);
 
   /**
    * Rebuild the style data. This will force a stylesheet flush, and also
    * recompute the default computed styles.
    */
--- a/layout/style/StyleSetHandleInlines.h
+++ b/layout/style/StyleSetHandleInlines.h
@@ -13,16 +13,25 @@
 
 #define FORWARD_CONCRETE(method_, geckoargs_, servoargs_) \
   if (IsGecko()) { \
     return AsGecko()->method_ geckoargs_; \
   } else { \
     return AsServo()->method_ servoargs_; \
   }
 
+#define FORWARD_WITH_PARENT(method_, parent_, args_) \
+  if (IsGecko()) { \
+    nsStyleContext* parent = parent_; \
+    return AsGecko()->method_ args_; \
+  } else { \
+    ServoStyleContext* parent = parent_ ? parent_->AsServo() : nullptr; \
+    return AsServo()->method_ args_; \
+  }
+
 #define FORWARD(method_, args_) FORWARD_CONCRETE(method_, args_, args_)
 
 namespace mozilla {
 
 void
 StyleSetHandle::Ptr::Delete()
 {
   if (mValue) {
@@ -78,67 +87,67 @@ StyleSetHandle::Ptr::EndUpdate()
 }
 
 // resolve a style context
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleFor(dom::Element* aElement,
                                      nsStyleContext* aParentContext,
                                      LazyComputeBehavior aMayCompute)
 {
-  FORWARD(ResolveStyleFor, (aElement, aParentContext, aMayCompute));
+  FORWARD_WITH_PARENT(ResolveStyleFor, aParentContext, (aElement, parent, aMayCompute));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleFor(dom::Element* aElement,
                                      nsStyleContext* aParentContext,
                                      LazyComputeBehavior aMayCompute,
                                      TreeMatchContext* aTreeMatchContext)
 {
   if (IsGecko()) {
     MOZ_ASSERT(aTreeMatchContext);
     return AsGecko()->ResolveStyleFor(aElement, aParentContext, aMayCompute, *aTreeMatchContext);
   } else {
-    return AsServo()->ResolveStyleFor(aElement, aParentContext, aMayCompute);
+    ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+    return AsServo()->ResolveStyleFor(aElement, parent, aMayCompute);
   }
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleForText(nsIContent* aTextNode,
                                          nsStyleContext* aParentContext)
 {
-  FORWARD(ResolveStyleForText, (aTextNode, aParentContext));
+  FORWARD_WITH_PARENT(ResolveStyleForText, aParentContext, (aTextNode, parent));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleForPlaceholder()
 {
   FORWARD(ResolveStyleForPlaceholder, ());
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveStyleForFirstLetterContinuation(nsStyleContext* aParentContext)
 {
-  FORWARD(ResolveStyleForFirstLetterContinuation, (aParentContext));
+  FORWARD_WITH_PARENT(ResolveStyleForFirstLetterContinuation, aParentContext, (parent));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolvePseudoElementStyle(dom::Element* aParentElement,
                                                CSSPseudoElementType aType,
                                                nsStyleContext* aParentContext,
                                                dom::Element* aPseudoElement)
 {
-  FORWARD(ResolvePseudoElementStyle, (aParentElement, aType, aParentContext,
-                                      aPseudoElement));
+  FORWARD_WITH_PARENT(ResolvePseudoElementStyle, aParentContext, (aParentElement, aType, parent, aPseudoElement));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag,
                                                         nsStyleContext* aParentContext)
 {
-  FORWARD(ResolveInheritingAnonymousBoxStyle, (aPseudoTag, aParentContext));
+  FORWARD_WITH_PARENT(ResolveInheritingAnonymousBoxStyle, aParentContext, (aPseudoTag, parent));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ResolveNonInheritingAnonymousBoxStyle(nsIAtom* aPseudoTag)
 {
   FORWARD(ResolveNonInheritingAnonymousBoxStyle, (aPseudoTag));
 }
 
@@ -258,31 +267,32 @@ StyleSetHandle::Ptr::InvalidateStyleForC
 }
 
 // check whether there is ::before/::after style for an element
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ProbePseudoElementStyle(dom::Element* aParentElement,
                                              CSSPseudoElementType aType,
                                              nsStyleContext* aParentContext)
 {
-  FORWARD(ProbePseudoElementStyle, (aParentElement, aType, aParentContext));
+  FORWARD_WITH_PARENT(ProbePseudoElementStyle, aParentContext, (aParentElement, aType, parent));
 }
 
 already_AddRefed<nsStyleContext>
 StyleSetHandle::Ptr::ProbePseudoElementStyle(dom::Element* aParentElement,
                                              CSSPseudoElementType aType,
                                              nsStyleContext* aParentContext,
                                              TreeMatchContext* aTreeMatchContext)
 {
   if (IsGecko()) {
     MOZ_ASSERT(aTreeMatchContext);
     return AsGecko()->ProbePseudoElementStyle(aParentElement, aType, aParentContext,
                                               *aTreeMatchContext);
   }
-  return AsServo()->ProbePseudoElementStyle(aParentElement, aType, aParentContext);
+  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
+  return AsServo()->ProbePseudoElementStyle(aParentElement, aType, parent);
 }
 
 nsRestyleHint
 StyleSetHandle::Ptr::HasStateDependentStyle(dom::Element* aElement,
                                             EventStates aStateMask)
 {
   FORWARD(HasStateDependentStyle, (aElement, aStateMask));
 }
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 /* the interface (to internal code) for retrieving computed style data */
 
 #include "nsStyleContext.h"
-#include "CSSVariableImageTable.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Maybe.h"
 
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
 #include "nsFontMetrics.h"
 #include "nsStyleConsts.h"
 #include "nsStyleStruct.h"
@@ -72,34 +71,46 @@ const uint32_t nsStyleContext::sDependen
 #define STYLE_STRUCT_DEP(dep) NS_STYLE_INHERIT_BIT(dep) |
 #define STYLE_STRUCT_END() 0,
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
 #undef STYLE_STRUCT_DEP
 #undef STYLE_STRUCT_END
 };
 
-// Whether to perform expensive assertions in the nsStyleContext destructor.
-static bool sExpensiveStyleStructAssertionsEnabled;
 #endif
 
 nsStyleContext::nsStyleContext(nsStyleContext* aParent,
                                nsIAtom* aPseudoTag,
                                CSSPseudoElementType aPseudoType)
   : mParent(aParent)
   , mPseudoTag(aPseudoTag)
   , mBits(((uint64_t)aPseudoType) << NS_STYLE_CONTEXT_TYPE_SHIFT)
   , mRefCnt(0)
 #ifdef DEBUG
   , mFrameRefCnt(0)
   , mComputingStruct(nsStyleStructID_None)
 #endif
 {}
 
 void
+nsStyleContext::AddChild(nsStyleContext* aChild)
+{
+  if (auto gecko = GetAsGecko())
+    gecko->AddChild(aChild->AsGecko());
+}
+
+void
+nsStyleContext::RemoveChild(nsStyleContext* aChild)
+{
+  if (auto gecko = GetAsGecko())
+    gecko->RemoveChild(aChild->AsGecko());
+}
+
+void
 nsStyleContext::FinishConstruction()
 {
   // This check has to be done "backward", because if it were written the
   // more natural way it wouldn't fail even when it needed to.
   static_assert((UINT64_MAX >> NS_STYLE_CONTEXT_TYPE_SHIFT) >=
                  static_cast<CSSPseudoElementTypeBase>(
                    CSSPseudoElementType::MAX),
                 "pseudo element bits no longer fit in a uint64_t");
@@ -124,76 +135,16 @@ nsStyleContext::FinishConstruction()
 
   #define eStyleStruct_LastItem (nsStyleStructID_Length - 1)
   static_assert(NS_STYLE_INHERIT_MASK & NS_STYLE_INHERIT_BIT(LastItem),
                 "NS_STYLE_INHERIT_MASK must be bigger, and other bits shifted");
   #undef eStyleStruct_LastItem
 }
 
 void
-nsStyleContext::Destructor()
-{
-  GeckoStyleContext* gecko = GetAsGecko();
-#ifdef DEBUG
-  if (gecko) {
-    NS_ASSERTION(gecko->HasNoChildren(), "destructing context with children");
-    if (sExpensiveStyleStructAssertionsEnabled) {
-      // Assert that the style structs we are about to destroy are not referenced
-      // anywhere else in the style context tree.  These checks are expensive,
-      // which is why they are not enabled by default.
-      GeckoStyleContext* root = gecko;
-      while (root->GetParent()) {
-        root = root->GetParent();
-      }
-      root->AssertStructsNotUsedElsewhere(gecko,
-                                          std::numeric_limits<int32_t>::max());
-    } else {
-      // In DEBUG builds when the pref is not enabled, we perform a more limited
-      // check just of the children of this style context.
-      gecko->AssertStructsNotUsedElsewhere(gecko, 2);
-    }
-  }
-#endif
-
-  nsPresContext *presContext = PresContext();
-  DebugOnly<nsStyleSet*> geckoStyleSet = presContext->PresShell()->StyleSet()->GetAsGecko();
-  NS_ASSERTION(!geckoStyleSet ||
-               geckoStyleSet->GetRuleTree() == AsGecko()->RuleNode()->RuleTree() ||
-               geckoStyleSet->IsInRuleTreeReconstruct(),
-               "destroying style context from old rule tree too late");
-
-  if (mParent) {
-    mParent->RemoveChild(this);
-  } else {
-    presContext->StyleSet()->RootStyleContextRemoved();
-  }
-
-  // Free up our caches.
-  if (gecko) {
-    gecko->DestroyCachedStructs(presContext);
-    // Servo doesn't store things here, and it's not threadsafe
-    CSSVariableImageTable::RemoveAll(this);
-  }
-}
-
-void nsStyleContext::AddChild(nsStyleContext* aChild)
-{
-  if (GeckoStyleContext* gecko = GetAsGecko()) {
-    gecko->AddChild(aChild->AsGecko());
-  }
-}
-
-void nsStyleContext::RemoveChild(nsStyleContext* aChild)
-{
-  if (GeckoStyleContext* gecko = GetAsGecko()) {
-    gecko->RemoveChild(aChild->AsGecko());
-  }
-}
-
-void
 nsStyleContext::MoveTo(nsStyleContext* aNewParent)
 {
   MOZ_ASSERT(aNewParent != mParent);
 
   // This function shouldn't be getting called if the parents have different
   // values for some flags in mBits (unless the flag is also set on this style
   // context) because if that were the case we would need to recompute those
   // bits for |this|.
@@ -765,18 +716,8 @@ nsStyleContext::LookupStruct(const nsACS
     aResult = eStyleStruct_##name_;
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
   else
     return false;
   return true;
 }
 #endif
-
-#ifdef DEBUG
-/* static */ void
-nsStyleContext::Initialize()
-{
-  Preferences::AddBoolVarCache(
-      &sExpensiveStyleStructAssertionsEnabled,
-      "layout.css.expensive-style-struct-assertions.enabled");
-}
-#endif
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -72,22 +72,18 @@ public:
 
   // These two methods are for use by ArenaRefPtr.
   static mozilla::ArenaObjectID ArenaObjectID()
   {
     return mozilla::eArenaObjectID_GeckoStyleContext;
   }
   nsIPresShell* Arena();
 
-#ifdef DEBUG
-  /**
-   * Initializes a cached pref, which is only used in DEBUG code.
-   */
-  static void Initialize();
-#endif
+  void AddChild(nsStyleContext* aChild);
+  void RemoveChild(nsStyleContext* aChild);
 
   inline void AddRef();
   inline void Release();
 
 #ifdef DEBUG
   void FrameAddRef() {
     ++mFrameRefCnt;
   }
@@ -339,33 +335,25 @@ public:
   void List(FILE* out, int32_t aIndent, bool aListDescendants = true);
   static const char* StructName(nsStyleStructID aSID);
   static bool LookupStruct(const nsACString& aName, nsStyleStructID& aResult);
 #endif
 
 protected:
   // protected destructor to discourage deletion outside of Release()
   ~nsStyleContext() {}
-  // Where the actual destructor lives
-  // We use this instead of a real destructor because we need
-  // this to be called *before* the subclass fields are destroyed
-  // by the subclass destructor
-  void Destructor();
+
   // Delegated Helper constructor.
   nsStyleContext(nsStyleContext* aParent,
                  nsIAtom* aPseudoTag,
                  mozilla::CSSPseudoElementType aPseudoType);
 
   // Helper post-contruct hook.
   void FinishConstruction();
 
-  // Only does stuff in Gecko mode
-  void AddChild(nsStyleContext* aChild);
-  void RemoveChild(nsStyleContext* aChild);
-
   void SetStyleBits();
 
   const void* StyleStructFromServoComputedValues(nsStyleStructID aSID) {
     switch (aSID) {
 #define STYLE_STRUCT(name_, checkdata_cb_)                                    \
       case eStyleStruct_##name_:                                              \
         return Servo_GetStyle##name_(ComputedValues());
 #include "nsStyleStructList.h"
--- a/layout/tables/nsTableFrame.cpp
+++ b/layout/tables/nsTableFrame.cpp
@@ -8019,19 +8019,19 @@ nsTableFrame::UpdateStyleOfOwnedAnonBoxe
   nsIFrame* aOwningFrame,
   nsIFrame* aWrapperFrame,
   ServoRestyleState& aRestyleState)
 {
   MOZ_ASSERT(aWrapperFrame->StyleContext()->GetPseudo() ==
                nsCSSAnonBoxes::tableWrapper,
              "What happened to our parent?");
 
-  RefPtr<nsStyleContext> newContext =
+  RefPtr<ServoStyleContext> newContext =
     aRestyleState.StyleSet().ResolveInheritingAnonymousBoxStyle(
-      nsCSSAnonBoxes::tableWrapper, aOwningFrame->StyleContext());
+      nsCSSAnonBoxes::tableWrapper, aOwningFrame->StyleContext()->AsServo());
 
   // Figure out whether we have an actual change.  It's important that we do
   // this, even though all the wrapper's changes are due to properties it
   // inherits from us, because it's possible that no one ever asked us for those
   // style structs and hence changes to them aren't reflected in
   // the handled changes at all.
   //
   // Also note that extensions can add/remove stylesheets that change the styles