Bug 1367904 - Part 11: stylo: Use ServoStyleContext in ServoStyleSet/ServoRestyleManager; r=bholley
authorManish Goregaokar <manishearth@gmail.com>
Mon, 17 Jul 2017 11:42:04 -0700
changeset 418018 4d5e5d40c7ee04bba9fc8b96322a9aa10c220107
parent 418017 914f8a42fa695f14a4c610297ad55580364c4a45
child 418019 c55df972f7c3ee0ec11e4b2841e20b7d0b1a0fd8
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1367904
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 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
@@ -266,17 +266,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)
@@ -300,17 +300,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) {
@@ -326,17 +326,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
@@ -388,17 +388,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);
 }
@@ -450,22 +450,21 @@ NeedsToTraverseElementChildren(const Ele
            aParent.HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
   }
   return false;
 }
 
 bool
 ServoRestyleManager::ProcessPostTraversal(
   Element* aElement,
-  nsStyleContext* aParentContext,
+  ServoStyleContext* aParentContext,
   ServoRestyleState& aRestyleState,
   TraversalRestyleBehavior aRestyleBehavior)
 {
   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.
@@ -556,17 +555,17 @@ ServoRestyleManager::ProcessPostTraversa
     MOZ_ASSERT(oldStyleContext->ComputedValues() != currentContext->ComputedValues());
 
     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
@@ -619,17 +618,17 @@ ServoRestyleManager::ProcessPostTraversa
   const bool descendantsNeedFrames =
     aElement->HasFlag(NODE_DESCENDANTS_NEED_FRAMES);
   const bool forThrottledAnimationFlush =
     aRestyleBehavior == TraversalRestyleBehavior::ForThrottledAnimationFlush;
   const bool traverseTextChildren =
     wasRestyled || (!forThrottledAnimationFlush && descendantsNeedFrames);
   bool recreatedAnyContext = wasRestyled;
   if (traverseElementChildren || traverseTextChildren) {
-    nsStyleContext* upToDateContext =
+    ServoStyleContext* upToDateContext =
       wasRestyled ? newContext : oldStyleContext;
 
     StyleChildrenIterator it(aElement);
     TextPostTraversalState textState(*upToDateContext,
                                      displayContentsNode && wasRestyled,
                                      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,
                             TraversalRestyleBehavior aRestyleBehavior);
 
   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
@@ -5645,17 +5645,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.
@@ -5665,17 +5665,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)
@@ -62,16 +76,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, const ServoStyleContext* aOther) {
     // Only resolve structs that are not already resolved in this struct.
     uint64_t ourBits = mBits & NS_STYLE_INHERIT_MASK;
     uint64_t otherBits = aOther->mBits & NS_STYLE_INHERIT_MASK;
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -167,52 +167,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.
@@ -437,47 +436,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);
@@ -509,41 +507,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;
 
@@ -573,26 +570,25 @@ 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();
 
-  ServoStyleContext* parent = aParentContext ? aParentContext->AsServo() : nullptr;
   RefPtr<ServoStyleContext> computedValues =
-    Servo_ComputedValues_GetForAnonymousBox(parent, CSSPseudoElementType::InheritingAnonBox,
+    Servo_ComputedValues_GetForAnonymousBox(aParentContext, CSSPseudoElementType::InheritingAnonBox,
                                             aPseudoTag,
                                             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());
@@ -847,33 +843,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.
@@ -1104,17 +1099,17 @@ ServoStyleSet::GetAnimationValues(
                            aComputedValues,
                            mRawSet.get(),
                            &aAnimationValues);
 }
 
 already_AddRefed<ServoStyleContext>
 ServoStyleSet::GetBaseContextForElement(
   Element* aElement,
-  nsStyleContext* aParentContext,
+  ServoStyleContext* aParentContext,
   nsPresContext* aPresContext,
   nsIAtom* aPseudoTag,
   CSSPseudoElementType aPseudoType,
   const ServoStyleContext* aStyle)
 {
   return Servo_StyleSet_GetBaseComputedValuesForElement(mRawSet.get(),
                                                         aElement,
                                                         aStyle,
--- 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,
                            const ServoStyleContext* aStyle);
 
   /**
    * Resolve style for a given declaration block with/without the parent style.
    * If the parent style is not specified, the document default computed values
@@ -474,23 +474,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,33 +71,45 @@ 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)
 #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");
@@ -123,76 +134,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|.
@@ -784,18 +735,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
@@ -8040,19 +8040,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