Back out a0488e9c0024..5ebcedea1fa5 (bug 1288302 and bug 1310463) for Talos RSS regressions.
authorCameron McCormack <cam@mcc.id.au>
Tue, 01 Nov 2016 08:42:49 +0800
changeset 320342 7fd0f297a13d6a939ae317144d4e862f0bdc381b
parent 318623 5ebcedea1fa53f37b402de7f7118e8f1a9d54acb
child 320343 aba9bfae0d98e344149e370b7b2d13fcbaa6b546
push id83365
push usercmccormack@mozilla.com
push dateTue, 01 Nov 2016 00:53:23 +0000
treeherdermozilla-inbound@aba9bfae0d98 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1288302, 1310463
milestone52.0a1
backs outa0488e9c00247c438cd5de57f83b4ef28747d402
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
Back out a0488e9c0024..5ebcedea1fa5 (bug 1288302 and bug 1310463) for Talos RSS regressions. MozReview-Commit-ID: JB5uwDeO0We
layout/base/nsCSSRendering.cpp
layout/base/nsDisplayList.cpp
layout/generic/nsFrame.cpp
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/nsCSSValue.cpp
layout/style/nsCSSValue.h
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleContext.cpp
layout/style/nsStyleContext.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/layout/base/nsCSSRendering.cpp
+++ b/layout/base/nsCSSRendering.cpp
@@ -662,27 +662,36 @@ nsCSSRendering::PaintBorder(nsPresContex
   // same amount of time whether or not it's true.
   if (!styleIfVisited) {
     return PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
                                       aDirtyRect, aBorderArea, *styleBorder,
                                       aStyleContext, aFlags, aSkipSides);
   }
 
   nsStyleBorder newStyleBorder(*styleBorder);
+  // We could do something fancy to avoid the TrackImage/UntrackImage
+  // work, but it doesn't seem worth it.  (We need to call TrackImage
+  // since we're not going through nsRuleNode::ComputeBorderData.)
+  newStyleBorder.TrackImage(aPresContext);
 
   NS_FOR_CSS_SIDES(side) {
     nscolor color = aStyleContext->GetVisitedDependentColor(
       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color)[side]);
     newStyleBorder.mBorderColor[side] = StyleComplexColor::FromColor(color);
   }
   DrawResult result =
     PaintBorderWithStyleBorder(aPresContext, aRenderingContext, aForFrame,
                                aDirtyRect, aBorderArea, newStyleBorder,
                                aStyleContext, aFlags, aSkipSides);
 
+  // We could do something fancy to avoid the TrackImage/UntrackImage
+  // work, but it doesn't seem worth it.  (We need to call UntrackImage
+  // since we're not going through nsStyleBorder::Destroy.)
+  newStyleBorder.UntrackImage(aPresContext);
+
   return result;
 }
 
 DrawResult
 nsCSSRendering::PaintBorderWithStyleBorder(nsPresContext* aPresContext,
                                            nsRenderingContext& aRenderingContext,
                                            nsIFrame* aForFrame,
                                            const nsRect& aDirtyRect,
@@ -5018,31 +5027,26 @@ ShouldTreatAsCompleteDueToSyncDecode(con
   if (!(aFlags & nsImageRenderer::FLAG_SYNC_DECODE_IMAGES)) {
     return false;
   }
 
   if (aImage->GetType() != eStyleImageType_Image) {
     return false;
   }
 
-  imgRequestProxy* req = aImage->GetImageData();
-  if (!req) {
-    return false;
-  }
-
   uint32_t status = 0;
-  if (NS_FAILED(req->GetImageStatus(&status))) {
+  if (NS_FAILED(aImage->GetImageData()->GetImageStatus(&status))) {
     return false;
   }
 
   if (status & imgIRequest::STATUS_ERROR) {
     // The image is "complete" since it's a corrupt image. If we created an
     // imgIContainer at all, return true.
     nsCOMPtr<imgIContainer> image;
-    req->GetImage(getter_AddRefs(image));
+    aImage->GetImageData()->GetImage(getter_AddRefs(image));
     return bool(image);
   }
 
   if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
     // We must have loaded all of the image's data and the size must be
     // available, or else sync decoding won't be able to decode the image.
     return false;
   }
@@ -5069,19 +5073,18 @@ nsImageRenderer::PrepareImage()
     if (!mImage->IsComplete() &&
         !ShouldTreatAsCompleteDueToSyncDecode(mImage, mFlags)) {
       mPrepareResult = DrawResult::NOT_READY;
       return false;
     }
   }
 
   switch (mType) {
-    case eStyleImageType_Image: {
-      MOZ_ASSERT(mImage->GetImageData(),
-                 "must have image data, since we checked IsEmpty above");
+    case eStyleImageType_Image:
+    {
       nsCOMPtr<imgIContainer> srcImage;
       DebugOnly<nsresult> rv =
         mImage->GetImageData()->GetImage(getter_AddRefs(srcImage));
       MOZ_ASSERT(NS_SUCCEEDED(rv) && srcImage,
                  "If GetImage() is failing, mImage->IsComplete() "
                  "should have returned false");
 
       if (!mImage->GetCropRect()) {
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2859,19 +2859,17 @@ nsDisplayBackgroundImage::ShouldCreateOw
   }
 
   if (nsLayoutUtils::AnimatedImageLayersEnabled() && mBackgroundStyle) {
     const nsStyleImageLayers::Layer &layer = mBackgroundStyle->mImage.mLayers[mLayer];
     const nsStyleImage* image = &layer.mImage;
     if (image->GetType() == eStyleImageType_Image) {
       imgIRequest* imgreq = image->GetImageData();
       nsCOMPtr<imgIContainer> image;
-      if (imgreq &&
-          NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) &&
-          image) {
+      if (NS_SUCCEEDED(imgreq->GetImage(getter_AddRefs(image))) && image) {
         bool animated = false;
         if (NS_SUCCEEDED(image->GetAnimated(&animated)) && animated) {
           return WHENEVER_POSSIBLE;
         }
       }
     }
   }
 
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -787,36 +787,33 @@ AddAndRemoveImageAssociations(nsFrame* a
       if (i >= aNewLayers->mImageCount ||
           !aOldLayers->mLayers[i].mImage.ImageDataEquals(
             aNewLayers->mLayers[i].mImage)) {
         const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage;
         if (oldImage.GetType() != eStyleImageType_Image) {
           continue;
         }
 
-        if (imgRequestProxy* req = oldImage.GetImageData()) {
-          imageLoader->DisassociateRequestFromFrame(req, aFrame);
-        }
+        imageLoader->DisassociateRequestFromFrame(oldImage.GetImageData(),
+                                                   aFrame);
       }
     }
   }
 
   NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) {
     // If there is an image in newBG that's not in oldBG, add it.
     if (!aOldLayers || i >= aOldLayers->mImageCount ||
         !aNewLayers->mLayers[i].mImage.ImageDataEquals(
           aOldLayers->mLayers[i].mImage)) {
       const nsStyleImage& newImage = aNewLayers->mLayers[i].mImage;
       if (newImage.GetType() != eStyleImageType_Image) {
         continue;
       }
 
-      if (imgRequestProxy* req = newImage.GetImageData()) {
-        imageLoader->AssociateRequestToFrame(req, aFrame);
-      }
+      imageLoader->AssociateRequestToFrame(newImage.GetImageData(), aFrame);
     }
   }
 }
 
 // Subclass hook for style post processing
 /* virtual */ void
 nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
@@ -4298,21 +4295,17 @@ nsIFrame::ContentOffsets nsFrame::CalcCo
 
 void
 nsIFrame::AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext)
 {
   if (aImage.GetType() != eStyleImageType_Image) {
     return;
   }
 
-  imgRequestProxy* req = aImage.GetImageData();
-  if (!req) {
-    return;
-  }
-
+  imgIRequest *req = aImage.GetImageData();
   mozilla::css::ImageLoader* loader =
     aPresContext->Document()->StyleImageLoader();
 
   // If this fails there's not much we can do ...
   loader->AssociateRequestToFrame(req, this);
 }
 
 nsresult
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -729,55 +729,16 @@ Gecko_SetNullImageValue(nsStyleImage* aI
 
 void
 Gecko_SetGradientImageValue(nsStyleImage* aImage, nsStyleGradient* aGradient)
 {
   MOZ_ASSERT(aImage);
   aImage->SetGradientData(aGradient);
 }
 
-static already_AddRefed<nsStyleImageRequest>
-CreateStyleImageRequest(nsStyleImageRequest::Mode aModeFlags,
-                        const uint8_t* aURLString, uint32_t aURLStringLength,
-                        ThreadSafeURIHolder* aBaseURI,
-                        ThreadSafeURIHolder* aReferrer,
-                        ThreadSafePrincipalHolder* aPrincipal)
-{
-  MOZ_ASSERT(aURLString);
-  MOZ_ASSERT(aBaseURI);
-  MOZ_ASSERT(aReferrer);
-  MOZ_ASSERT(aPrincipal);
-
-  nsString url;
-  nsDependentCSubstring urlString(reinterpret_cast<const char*>(aURLString),
-                                  aURLStringLength);
-  AppendUTF8toUTF16(urlString, url);
-  RefPtr<nsStringBuffer> urlBuffer = nsCSSValue::BufferFromString(url);
-
-  RefPtr<nsStyleImageRequest> req =
-    new nsStyleImageRequest(aModeFlags, urlBuffer, do_AddRef(aBaseURI),
-                            do_AddRef(aReferrer), do_AddRef(aPrincipal));
-  return req.forget();
-}
-
-void
-Gecko_SetUrlImageValue(nsStyleImage* aImage,
-                       const uint8_t* aURLString, uint32_t aURLStringLength,
-                       ThreadSafeURIHolder* aBaseURI,
-                       ThreadSafeURIHolder* aReferrer,
-                       ThreadSafePrincipalHolder* aPrincipal)
-{
-  RefPtr<nsStyleImageRequest> req =
-    CreateStyleImageRequest(nsStyleImageRequest::Mode::Track |
-                            nsStyleImageRequest::Mode::Lock,
-                            aURLString, aURLStringLength,
-                            aBaseURI, aReferrer, aPrincipal);
-  aImage->SetImageRequest(req.forget());
-}
-
 void
 Gecko_CopyImageValueFrom(nsStyleImage* aImage, const nsStyleImage* aOther)
 {
   MOZ_ASSERT(aImage);
   MOZ_ASSERT(aOther);
 
   *aImage = *aOther;
 }
@@ -810,42 +771,16 @@ Gecko_CreateGradient(uint8_t aShape,
   for (uint32_t i = 0; i < aStopCount; i++) {
     result->mStops.AppendElement(dummyStop);
   }
 
   return result;
 }
 
 void
-Gecko_SetListStyleImageNone(nsStyleList* aList)
-{
-  aList->mListStyleImage = nullptr;
-}
-
-void
-Gecko_SetListStyleImage(nsStyleList* aList,
-                        const uint8_t* aURLString, uint32_t aURLStringLength,
-                        ThreadSafeURIHolder* aBaseURI,
-                        ThreadSafeURIHolder* aReferrer,
-                        ThreadSafePrincipalHolder* aPrincipal)
-{
-  aList->mListStyleImage =
-    CreateStyleImageRequest(nsStyleImageRequest::Mode::Track |
-                            nsStyleImageRequest::Mode::Lock,
-                            aURLString, aURLStringLength,
-                            aBaseURI, aReferrer, aPrincipal);
-}
-
-void
-Gecko_CopyListStyleImageFrom(nsStyleList* aList, const nsStyleList* aSource)
-{
-  aList->mListStyleImage = aSource->mListStyleImage;
-}
-
-void
 Gecko_EnsureTArrayCapacity(void* aArray, size_t aCapacity, size_t aElemSize)
 {
   auto base =
     reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
                                    nsTArray_CopyWithMemutils>*>(aArray);
 
   base->EnsureCapacity<nsTArrayInfallibleAllocator>(aCapacity, aElemSize);
 }
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -151,20 +151,16 @@ DECL_BORROWED_MUT_REF_TYPE_FOR(StyleChil
 #define NS_IMPL_HOLDER_FFI_REFCOUNTING(class_, name_)                         \
   void Gecko_AddRef##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr)  \
   { NS_ADDREF(aPtr); }                                                        \
   void Gecko_Release##name_##ArbitraryThread(ThreadSafe##name_##Holder* aPtr) \
   { NS_RELEASE(aPtr); }                                                       \
 
 extern "C" {
 
-// Object refcounting.
-NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
-NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
-
 // DOM Traversal.
 uint32_t Gecko_ChildrenCount(RawGeckoNodeBorrowed node);
 bool Gecko_NodeIsElement(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetParentNode(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetFirstChild(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetLastChild(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetPrevSibling(RawGeckoNodeBorrowed node);
 RawGeckoNodeBorrowedOrNull Gecko_GetNextSibling(RawGeckoNodeBorrowed node);
@@ -245,41 +241,30 @@ void Gecko_FontFamilyList_AppendNamed(Fo
 void Gecko_FontFamilyList_AppendGeneric(FontFamilyList* list, FontFamilyType familyType);
 void Gecko_CopyFontFamilyFrom(nsFont* dst, const nsFont* src);
 
 // Counter style.
 void Gecko_SetListStyleType(nsStyleList* style_struct, uint32_t type);
 void Gecko_CopyListStyleTypeFrom(nsStyleList* dst, const nsStyleList* src);
 
 // background-image style.
-// TODO: support element() and -moz-image()
+// TODO: support url() values (and maybe element() too?).
 void Gecko_SetNullImageValue(nsStyleImage* image);
 void Gecko_SetGradientImageValue(nsStyleImage* image, nsStyleGradient* gradient);
-void Gecko_SetUrlImageValue(nsStyleImage* image,
-                            const uint8_t* url_bytes,
-                            uint32_t url_length,
-                            ThreadSafeURIHolder* base_uri,
-                            ThreadSafeURIHolder* referrer,
-                            ThreadSafePrincipalHolder* principal);
 void Gecko_CopyImageValueFrom(nsStyleImage* image, const nsStyleImage* other);
 
 nsStyleGradient* Gecko_CreateGradient(uint8_t shape,
                                       uint8_t size,
                                       bool repeating,
                                       bool legacy_syntax,
                                       uint32_t stops);
 
-// list-style-image style.
-void Gecko_SetListStyleImageNone(nsStyleList* style_struct);
-void Gecko_SetListStyleImage(nsStyleList* style_struct,
-                             const uint8_t* string_bytes, uint32_t string_length,
-                             ThreadSafeURIHolder* base_uri,
-                             ThreadSafeURIHolder* referrer,
-                             ThreadSafePrincipalHolder* principal);
-void Gecko_CopyListStyleImageFrom(nsStyleList* dest, const nsStyleList* src);
+// Object refcounting.
+NS_DECL_HOLDER_FFI_REFCOUNTING(nsIPrincipal, Principal)
+NS_DECL_HOLDER_FFI_REFCOUNTING(nsIURI, URI)
 
 // Display style.
 void Gecko_SetMozBinding(nsStyleDisplay* style_struct,
                          const uint8_t* string_bytes, uint32_t string_length,
                          ThreadSafeURIHolder* base_uri,
                          ThreadSafeURIHolder* referrer,
                          ThreadSafePrincipalHolder* principal);
 void Gecko_CopyMozBindingFrom(nsStyleDisplay* des, const nsStyleDisplay* src);
--- a/layout/style/nsCSSValue.cpp
+++ b/layout/style/nsCSSValue.cpp
@@ -20,17 +20,16 @@
 #include "nsIDocument.h"
 #include "nsIPrincipal.h"
 #include "nsCSSProps.h"
 #include "nsNetUtil.h"
 #include "nsPresContext.h"
 #include "nsStyleUtil.h"
 #include "nsDeviceContext.h"
 #include "nsStyleSet.h"
-#include "nsContentUtils.h"
 
 using namespace mozilla;
 
 static bool
 IsLocalRefURL(nsStringBuffer* aString)
 {
   // Find the first non-"C0 controls + space" character.
   char16_t* current = static_cast<char16_t*>(aString->Data());
@@ -361,27 +360,16 @@ nsCSSValue::GetAngleValueInDegrees() con
 }
 
 imgRequestProxy* nsCSSValue::GetImageValue(nsIDocument* aDocument) const
 {
   MOZ_ASSERT(mUnit == eCSSUnit_Image, "not an Image value");
   return mValue.mImage->mRequests.GetWeak(aDocument);
 }
 
-already_AddRefed<imgRequestProxy>
-nsCSSValue::GetPossiblyStaticImageValue(nsIDocument* aDocument,
-                                        nsPresContext* aPresContext) const
-{
-  imgRequestProxy* req = GetImageValue(aDocument);
-  if (aPresContext->IsDynamic()) {
-    return do_AddRef(req);
-  }
-  return nsContentUtils::GetStaticRequest(req);
-}
-
 nscoord nsCSSValue::GetFixedLength(nsPresContext* aPresContext) const
 {
   MOZ_ASSERT(mUnit == eCSSUnit_PhysicalMillimeter,
              "not a fixed length unit");
 
   float inches = mValue.mFloat / MM_PER_INCH_FLOAT;
   return NSToCoordFloorClamped(inches *
     float(aPresContext->DeviceContext()->AppUnitsPerPhysicalInch()));
@@ -2874,53 +2862,32 @@ css::ImageValue::ImageValue(nsIURI* aURI
                             nsIPrincipal* aOriginPrincipal,
                             nsIDocument* aDocument)
   : URLValueData(do_AddRef(new PtrHolder<nsIURI>(aURI)),
                  aString,
                  do_AddRef(new PtrHolder<nsIURI>(aBaseURI, false)),
                  do_AddRef(new PtrHolder<nsIURI>(aReferrer)),
                  do_AddRef(new PtrHolder<nsIPrincipal>(aOriginPrincipal)))
 {
-  Initialize(aDocument);
-}
-
-css::ImageValue::ImageValue(
-    nsStringBuffer* aString,
-    already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-    already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-    already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPrincipal)
-  : URLValueData(aString, Move(aBaseURI), Move(aReferrer),
-                 Move(aOriginPrincipal))
-{
-}
-
-void
-css::ImageValue::Initialize(nsIDocument* aDocument)
-{
   MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!mInitialized);
 
   // NB: If aDocument is not the original document, we may not be able to load
   // images from aDocument.  Instead we do the image load from the original doc
   // and clone it to aDocument.
   nsIDocument* loadingDoc = aDocument->GetOriginalDocument();
   if (!loadingDoc) {
     loadingDoc = aDocument;
   }
 
-  loadingDoc->StyleImageLoader()->LoadImage(GetURI(), mOriginPrincipal,
-                                            mReferrer, this);
+  loadingDoc->StyleImageLoader()->LoadImage(aURI, aOriginPrincipal, aReferrer,
+                                            this);
 
   if (loadingDoc != aDocument) {
     aDocument->StyleImageLoader()->MaybeRegisterCSSImage(this);
   }
-
-#ifdef DEBUG
-  mInitialized = true;
-#endif
 }
 
 css::ImageValue::~ImageValue()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
     nsIDocument* doc = iter.Key();
--- a/layout/style/nsCSSValue.h
+++ b/layout/style/nsCSSValue.h
@@ -203,42 +203,28 @@ struct ImageValue final : public URLValu
   // this header is included all over.
   // aString must not be null.
   //
   // This constructor is only safe to call from the main thread.
   ImageValue(nsIURI* aURI, nsStringBuffer* aString, nsIURI* aBaseURI,
              nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal,
              nsIDocument* aDocument);
 
-  // This constructor is safe to call from any thread, but Initialize
-  // must be called later for the object to be useful.
-  ImageValue(nsStringBuffer* aString,
-             already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-             already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-             already_AddRefed<PtrHolder<nsIPrincipal>> aOriginPrincipal);
-
   ImageValue(const ImageValue&) = delete;
   ImageValue& operator=(const ImageValue&) = delete;
 
-  void Initialize(nsIDocument* aDocument);
-
   // XXXheycam We should have our own SizeOfIncludingThis method.
 
 protected:
   ~ImageValue();
 
 public:
   // Inherit Equals from URLValueData
 
   nsRefPtrHashtable<nsPtrHashKey<nsIDocument>, imgRequestProxy> mRequests;
-
-private:
-#ifdef DEBUG
-  bool mInitialized = false;
-#endif
 };
 
 struct GridNamedArea {
   nsString mName;
   uint32_t mColumnStart;
   uint32_t mColumnEnd;
   uint32_t mRowStart;
   uint32_t mRowEnd;
@@ -864,21 +850,16 @@ public:
                             mValue.mImage->mString);
   }
 
   // Not making this inline because that would force us to include
   // imgIRequest.h, which leads to REQUIRES hell, since this header is included
   // all over.
   imgRequestProxy* GetImageValue(nsIDocument* aDocument) const;
 
-  // Like GetImageValue, but additionally will pass the imgRequestProxy
-  // through nsContentUtils::GetStaticRequest if aPresContent is static.
-  already_AddRefed<imgRequestProxy> GetPossiblyStaticImageValue(
-      nsIDocument* aDocument, nsPresContext* aPresContext) const;
-
   nscoord GetFixedLength(nsPresContext* aPresContext) const;
   nscoord GetPixelLength() const;
 
   nsCSSValueFloatColor* GetFloatColorValue() const
   {
     MOZ_ASSERT(IsFloatColorUnit(), "not a float color value");
     return mValue.mFloatColor;
   }
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -2077,25 +2077,17 @@ nsComputedDOMStyle::GetImageRectString(n
 
 void
 nsComputedDOMStyle::SetValueToStyleImage(const nsStyleImage& aStyleImage,
                                          nsROCSSPrimitiveValue* aValue)
 {
   switch (aStyleImage.GetType()) {
     case eStyleImageType_Image:
     {
-      imgIRequest* req = aStyleImage.GetImageData();
-      if (!req) {
-        // XXXheycam If we had some problem resolving the imgRequestProxy,
-        // maybe we should just use the URL stored in the nsStyleImage's
-        // mImageValue?  (Similarly in DoGetListStyleImage.)
-        aValue->SetIdent(eCSSKeyword_none);
-        break;
-      }
-
+      imgIRequest *req = aStyleImage.GetImageData();
       nsCOMPtr<nsIURI> uri;
       req->GetURI(getter_AddRefs(uri));
 
       const UniquePtr<nsStyleSides>& cropRect = aStyleImage.GetCropRect();
       if (cropRect) {
         nsAutoString imageRectString;
         GetImageRectString(uri, *cropRect, imageRectString);
         aValue->SetString(imageRectString);
@@ -3498,26 +3490,23 @@ nsComputedDOMStyle::DoGetZIndex()
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetListStyleImage()
 {
   RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
 
   const nsStyleList* list = StyleList();
 
-  // XXXheycam As in SetValueToStyleImage, we might want to use the
-  // URL stored in the nsStyleImageRequest's mImageValue if we
-  // failed to resolve the imgRequestProxy.
-
-  imgRequestProxy* image = list->GetListStyleImage();
-  if (!image) {
+  if (!list->GetListStyleImage()) {
     val->SetIdent(eCSSKeyword_none);
   } else {
     nsCOMPtr<nsIURI> uri;
-    image->GetURI(getter_AddRefs(uri));
+    if (list->GetListStyleImage()) {
+      list->GetListStyleImage()->GetURI(getter_AddRefs(uri));
+    }
     val->SetURI(uri);
   }
 
   return val.forget();
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetListStylePosition()
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -123,40 +123,23 @@ GetImageRequest(nsPresContext* aPresCont
 // showing the first frame, without animation) will be created.
 // (The expectation is then that aCallback will set the resulting
 // imgRequestProxy in a style struct somewhere.)
 static void
 SetImageRequest(function<void(imgRequestProxy*)> aCallback,
                 nsPresContext* aPresContext,
                 const nsCSSValue& aValue)
 {
-  RefPtr<imgRequestProxy> req =
-    aValue.GetPossiblyStaticImageValue(aPresContext->Document(),
-                                       aPresContext);
-  aCallback(req);
-}
-
-static void
-SetStyleImageRequest(function<void(nsStyleImageRequest*)> aCallback,
-                     nsPresContext* aPresContext,
-                     const nsCSSValue& aValue,
-                     nsStyleImageRequest::Mode aModeFlags =
-                       nsStyleImageRequest::Mode::Track |
-                       nsStyleImageRequest::Mode::Lock)
-{
-  SetImageRequest([&](imgRequestProxy* aProxy) {
-    RefPtr<nsStyleImageRequest> request;
-    if (aProxy) {
-      css::ImageValue* imageValue = aValue.GetImageStructValue();
-      ImageTracker* imageTracker = aPresContext->Document()->ImageTracker();
-      request =
-        new nsStyleImageRequest(aModeFlags, aProxy, imageValue, imageTracker);
-    }
-    aCallback(request);
-  }, aPresContext, aValue);
+  imgRequestProxy* req = GetImageRequest(aPresContext, aValue);
+  if (aPresContext->IsDynamic()) {
+    aCallback(req);
+  } else {
+    RefPtr<imgRequestProxy> staticReq = nsContentUtils::GetStaticRequest(req);
+    aCallback(staticReq);
+  }
 }
 
 template<typename ReferenceBox>
 static void
 SetStyleShapeSourceToCSSValue(StyleShapeSource<ReferenceBox>* aShapeSource,
                               const nsCSSValue* aValue,
                               nsStyleContext* aStyleContext,
                               nsPresContext* aPresContext,
@@ -1279,18 +1262,18 @@ static void SetStyleImageToImageRect(nsS
              aValue.EqualsFunction(eCSSKeyword__moz_image_rect),
              "the value is not valid -moz-image-rect()");
 
   nsCSSValue::Array* arr = aValue.GetArrayValue();
   MOZ_ASSERT(arr && arr->Count() == 6, "invalid number of arguments");
 
   // <uri>
   if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
-    SetStyleImageRequest([&](nsStyleImageRequest* req) {
-      aResult.SetImageRequest(do_AddRef(req));
+    SetImageRequest([&](imgRequestProxy* req) {
+      aResult.SetImageData(req);
     }, aStyleContext->PresContext(), arr->Item(1));
   } else {
     NS_WARNING("nsCSSValue::Image::Image() failed?");
   }
 
   // <top>, <right>, <bottom>, <left>
   nsStyleSides cropRect;
   NS_FOR_CSS_SIDES(side) {
@@ -1315,18 +1298,18 @@ static void SetStyleImage(nsStyleContext
   if (aValue.GetUnit() == eCSSUnit_Null) {
     return;
   }
 
   aResult.SetNull();
 
   switch (aValue.GetUnit()) {
     case eCSSUnit_Image:
-      SetStyleImageRequest([&](nsStyleImageRequest* req) {
-        aResult.SetImageRequest(do_AddRef(req));
+      SetImageRequest([&](imgRequestProxy* req) {
+        aResult.SetImageData(req);
       }, aStyleContext->PresContext(), aValue);
       break;
     case eCSSUnit_Function:
       if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
         SetStyleImageToImageRect(aStyleContext, aValue, aResult);
       } else {
         NS_NOTREACHED("-moz-image-rect() is the only expected function");
       }
@@ -7340,16 +7323,19 @@ nsRuleNode::ComputeBackgroundData(void* 
                         initialSize, parentBG->mImage.mSizeCount,
                         bg->mImage.mSizeCount, maxItemCount, rebuild,
                         conditions);
 
   if (rebuild) {
     FillAllBackgroundLists(bg->mImage, maxItemCount);
   }
 
+  // Now that the dust has settled, register the images with the document
+  bg->mImage.TrackImages(aContext->PresContext());
+
   COMPUTE_END_RESET(Background, bg)
 }
 
 const void*
 nsRuleNode::ComputeMarginData(void* aStartStruct,
                               const nsRuleData* aRuleData,
                               nsStyleContext* aContext,
                               nsRuleNode* aHighestNode,
@@ -7726,16 +7712,18 @@ nsRuleNode::ComputeBorderData(void* aSta
 
   SetValue(borderImageRepeat.mYValue,
            border->mBorderImageRepeatV,
            conditions,
            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
            parentBorder->mBorderImageRepeatV,
            NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH);
 
+  border->TrackImage(aContext->PresContext());
+
   COMPUTE_END_RESET(Border, border)
 }
 
 const void*
 nsRuleNode::ComputePaddingData(void* aStartStruct,
                                const nsRuleData* aRuleData,
                                nsStyleContext* aContext,
                                nsRuleNode* aHighestNode,
@@ -7958,28 +7946,28 @@ nsRuleNode::ComputeListData(void* aStart
       break;
     default:
       NS_NOTREACHED("Unexpected value unit");
   }
 
   // list-style-image: url, none, inherit
   const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
   if (eCSSUnit_Image == imageValue->GetUnit()) {
-    SetStyleImageRequest([&](nsStyleImageRequest* req) {
-      list->mListStyleImage = req;
+    SetImageRequest([&](imgRequestProxy* req) {
+      list->SetListStyleImage(req);
     }, mPresContext, *imageValue);
   }
   else if (eCSSUnit_None == imageValue->GetUnit() ||
            eCSSUnit_Initial == imageValue->GetUnit()) {
-    list->mListStyleImage = nullptr;
+    list->SetListStyleImage(nullptr);
   }
   else if (eCSSUnit_Inherit == imageValue->GetUnit() ||
            eCSSUnit_Unset == imageValue->GetUnit()) {
     conditions.SetUncacheable();
-    list->mListStyleImage = parentList->mListStyleImage;
+    list->SetListStyleImage(parentList->GetListStyleImage());
   }
 
   // list-style-position: enum, inherit, initial
   SetValue(*aRuleData->ValueForListStylePosition(),
            list->mListStylePosition, conditions,
            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
            parentList->mListStylePosition,
            NS_STYLE_LIST_STYLE_POSITION_OUTSIDE);
@@ -8992,18 +8980,17 @@ nsRuleNode::ComputeContentData(void* aSt
            SETCOORD_LH | SETCOORD_AUTO | SETCOORD_INITIAL_AUTO |
              SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INITIAL,
            aContext, mPresContext, conditions);
 
   // If we ended up with an image, track it.
   for (uint32_t i = 0; i < content->ContentCount(); ++i) {
     if ((content->ContentAt(i).mType == eStyleContentType_Image) &&
         content->ContentAt(i).mContent.mImage) {
-      content->ContentAt(i).TrackImage(
-          aContext->PresContext()->Document()->ImageTracker());
+      content->ContentAt(i).TrackImage(aContext->PresContext());
     }
   }
 
   COMPUTE_END_RESET(Content, content)
 }
 
 const void*
 nsRuleNode::ComputeXULData(void* aStartStruct,
@@ -10062,16 +10049,18 @@ nsRuleNode::ComputeSVGResetData(void* aS
     svgReset->mMask.mLayers[0].mSourceURI.SetNull();
   } else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
     conditions.SetUncacheable();
     svgReset->mMask.mLayers[0].mSourceURI =
       parentSVGReset->mMask.mLayers[0].mSourceURI;
   }
 #endif
 
+  svgReset->mMask.TrackImages(aContext->PresContext());
+
   COMPUTE_END_RESET(SVGReset, svgReset)
 }
 
 const void*
 nsRuleNode::ComputeVariablesData(void* aStartStruct,
                                  const nsRuleData* aRuleData,
                                  nsStyleContext* aContext,
                                  nsRuleNode* aHighestNode,
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -463,34 +463,18 @@ const void* nsStyleContext::StyleData(ns
   if (mSource.IsGeckoRuleNode()) {
     newData = mSource.AsGeckoRuleNode()->GetStyleData(aSID, this, true);
     if (!nsCachedStyleData::IsReset(aSID)) {
       // always cache inherited data on the style context; the rule
       // node set the bit in mBits for us if needed.
       mCachedInheritedData.mStyleStructs[aSID] = const_cast<void*>(newData);
     }
   } else {
+    // The Servo-backed StyleContextSource owns the struct.
     newData = StyleStructFromServoComputedValues(aSID);
-
-    // perform any remaining main thread work on the struct
-    switch (aSID) {
-#define STYLE_STRUCT(name_, checkdata_cb_)                                    \
-      case eStyleStruct_##name_: {                                            \
-        auto data = static_cast<const nsStyle##name_*>(newData);              \
-        const_cast<nsStyle##name_*>(data)->FinishStyle(PresContext());        \
-        break;                                                                \
-      }
-#include "nsStyleStructList.h"
-#undef STYLE_STRUCT
-      default:
-        MOZ_ASSERT_UNREACHABLE("unexpected nsStyleStructID value");
-        break;
-    }
-
-    // The Servo-backed StyleContextSource owns the struct.
     AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
 
     // XXXbholley: Unconditionally caching reset structs here defeats the memory
     // optimization where we lazily allocate mCachedResetData, so that we can avoid
     // performing an FFI call each time we want to get the style structs. We should
     // measure the tradeoffs at some point. If the FFI overhead is low and the memory
     // win significant, we should consider _always_ grabbing the struct over FFI, and
     // potentially giving mCachedInheritedData the same treatment.
--- a/layout/style/nsStyleContext.h
+++ b/layout/style/nsStyleContext.h
@@ -668,18 +668,16 @@ private:
           newData = mParent->DoGetStyle##name_<true>();                 \
           NS_WARNING_ASSERTION(                                         \
             newData == Servo_GetStyle##name_(mSource.AsServoComputedValues()), \
             "bad newData");                                             \
         } else {                                                        \
           newData =                                                     \
             Servo_GetStyle##name_(mSource.AsServoComputedValues());     \
         }                                                               \
-        /* perform any remaining main thread work on the struct */      \
-        const_cast<nsStyle##name_*>(newData)->FinishStyle(PresContext());\
         /* the Servo-backed StyleContextSource owns the struct */       \
         AddStyleBit(NS_STYLE_INHERIT_BIT(name_));                       \
       }                                                                 \
       /* always cache inherited data on the style context; the rule */  \
       /* node set the bit in mBits for us if needed. */                 \
       mCachedInheritedData.mStyleStructs[eStyleStruct_##name_] =        \
         const_cast<nsStyle##name_ *>(newData);                          \
       return newData;                                                   \
@@ -698,18 +696,16 @@ private:
       AUTO_CHECK_DEPENDENCY(eStyleStruct_##name_);                      \
       const nsStyle##name_ * newData;                                   \
       if (mSource.IsGeckoRuleNode()) {                                  \
         newData = mSource.AsGeckoRuleNode()->                           \
           GetStyle##name_<aComputeData>(this);                          \
       } else {                                                          \
         newData =                                                       \
           Servo_GetStyle##name_(mSource.AsServoComputedValues());       \
-        /* perform any remaining main thread work on the struct */      \
-        const_cast<nsStyle##name_*>(newData)->FinishStyle(PresContext());\
         /* The Servo-backed StyleContextSource owns the struct.         \
          *                                                              \
          * XXXbholley: Unconditionally caching reset structs here       \
          * defeats the memory optimization where we lazily allocate     \
          * mCachedResetData, so that we can avoid performing an FFI     \
          * call each time we want to get the style structs. We should   \
          * measure the tradeoffs at some point. If the FFI overhead is  \
          * low and the memory win significant, we should consider       \
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -88,31 +88,16 @@ EqualImages(imgIRequest *aImage1, imgIRe
   }
 
   nsCOMPtr<nsIURI> uri1, uri2;
   aImage1->GetURI(getter_AddRefs(uri1));
   aImage2->GetURI(getter_AddRefs(uri2));
   return EqualURIs(uri1, uri2);
 }
 
-static bool
-DefinitelyEqualImages(nsStyleImageRequest* aRequest1,
-                      nsStyleImageRequest* aRequest2)
-{
-  if (aRequest1 == aRequest2) {
-    return true;
-  }
-
-  if (!aRequest1 || !aRequest2) {
-    return false;
-  }
-
-  return aRequest1->DefinitelyEquals(*aRequest2);
-}
-
 // A nullsafe wrapper for strcmp. We depend on null-safety.
 static int
 safe_strcmp(const char16_t* a, const char16_t* b)
 {
   if (!a || !b) {
     return (int)(a - b);
   }
   return NS_strcmp(a, b);
@@ -446,25 +431,16 @@ nsStyleBorder::~nsStyleBorder()
   if (mBorderColors) {
     for (int32_t i = 0; i < 4; i++) {
       delete mBorderColors[i];
     }
     delete [] mBorderColors;
   }
 }
 
-void
-nsStyleBorder::FinishStyle(nsPresContext* aPresContext)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
-
-  mBorderImageSource.ResolveImage(aPresContext);
-}
-
 nsMargin
 nsStyleBorder::GetImageOutset() const
 {
   // We don't check whether there is a border-image (which is OK since
   // the initial values yields 0 outset) so that we don't have to
   // reflow to update overflow areas when an image loads.
   nsMargin outset;
   NS_FOR_CSS_SIDES(s) {
@@ -483,18 +459,18 @@ nsStyleBorder::GetImageOutset() const
         break;
     }
     outset.Side(s) = value;
   }
   return outset;
 }
 
 void
-nsStyleBorder::Destroy(nsPresContext* aContext)
-{
+nsStyleBorder::Destroy(nsPresContext* aContext) {
+  UntrackImage(aContext);
   this->~nsStyleBorder();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleBorder, this);
 }
 
 nsChangeHint
 nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
 {
@@ -661,36 +637,25 @@ nsStyleList::nsStyleList(StyleStructCont
 
 nsStyleList::~nsStyleList()
 {
   MOZ_COUNT_DTOR(nsStyleList);
 }
 
 nsStyleList::nsStyleList(const nsStyleList& aSource)
   : mListStylePosition(aSource.mListStylePosition)
-  , mListStyleImage(aSource.mListStyleImage)
   , mCounterStyle(aSource.mCounterStyle)
   , mQuotes(aSource.mQuotes)
   , mImageRegion(aSource.mImageRegion)
 {
+  SetListStyleImage(aSource.GetListStyleImage());
   MOZ_COUNT_CTOR(nsStyleList);
 }
 
 void
-nsStyleList::FinishStyle(nsPresContext* aPresContext)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
-
-  if (mListStyleImage && !mListStyleImage->IsResolved()) {
-    mListStyleImage->Resolve(aPresContext);
-  }
-}
-
-void
 nsStyleList::SetQuotesInherit(const nsStyleList* aOther)
 {
   mQuotes = aOther->mQuotes;
 }
 
 void
 nsStyleList::SetQuotesInitial()
 {
@@ -744,17 +709,17 @@ nsStyleList::CalcDifference(const nsStyl
   if (mQuotes != aNewData.mQuotes &&
       (mQuotes || aNewData.mQuotes) &&
       GetQuotePairs() != aNewData.GetQuotePairs()) {
     return nsChangeHint_ReconstructFrame;
   }
   if (mListStylePosition != aNewData.mListStylePosition) {
     return nsChangeHint_ReconstructFrame;
   }
-  if (DefinitelyEqualImages(mListStyleImage, aNewData.mListStyleImage) &&
+  if (EqualImages(mListStyleImage, aNewData.mListStyleImage) &&
       mCounterStyle == aNewData.mCounterStyle) {
     if (mImageRegion.IsEqualInterior(aNewData.mImageRegion)) {
       return nsChangeHint(0);
     }
     if (mImageRegion.width == aNewData.mImageRegion.width &&
         mImageRegion.height == aNewData.mImageRegion.height) {
       return NS_STYLE_HINT_VISUAL;
     }
@@ -1199,30 +1164,23 @@ nsStyleSVGReset::nsStyleSVGReset(const n
   , mMaskType(aSource.mMaskType)
 {
   MOZ_COUNT_CTOR(nsStyleSVGReset);
 }
 
 void
 nsStyleSVGReset::Destroy(nsPresContext* aContext)
 {
+  mMask.UntrackImages(aContext);
+
   this->~nsStyleSVGReset();
   aContext->PresShell()->
     FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
 }
 
-void
-nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
-
-  mMask.ResolveImages(aPresContext);
-}
-
 nsChangeHint
 nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   if (mClipPath != aNewData.mClipPath) {
     hint |= nsChangeHint_UpdateEffects |
             nsChangeHint_RepaintFrame;
@@ -1906,184 +1864,16 @@ nsStyleGradient::HasCalc()
     if (mStops[i].mLocation.IsCalcUnit()) {
       return true;
     }
   }
   return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() ||
          mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit();
 }
 
-
-// --------------------
-// nsStyleImageRequest
-
-/**
- * Runnable to release the nsStyleImageRequest's mRequestProxy,
- * mImageValue and mImageValue on the main thread, and to perform
- * any necessary unlocking and untracking of the image.
- */
-class StyleImageRequestCleanupTask : public mozilla::Runnable
-{
-public:
-  typedef nsStyleImageRequest::Mode Mode;
-
-  StyleImageRequestCleanupTask(Mode aModeFlags,
-                               already_AddRefed<imgRequestProxy> aRequestProxy,
-                               already_AddRefed<css::ImageValue> aImageValue,
-                               already_AddRefed<ImageTracker> aImageTracker)
-    : mModeFlags(aModeFlags)
-    , mRequestProxy(aRequestProxy)
-    , mImageValue(aImageValue)
-    , mImageTracker(aImageTracker)
-  {
-  }
-
-  NS_IMETHOD Run() final
-  {
-    MOZ_ASSERT(NS_IsMainThread());
-
-    if (!mRequestProxy) {
-      return NS_OK;
-    }
-
-    MOZ_ASSERT(mImageTracker);
-
-    if (mModeFlags & Mode::Lock) {
-      mRequestProxy->UnlockImage();
-    }
-
-    if (mModeFlags & Mode::Discard) {
-      mRequestProxy->RequestDiscard();
-    }
-
-    if (mModeFlags & Mode::Track) {
-      mImageTracker->Remove(mRequestProxy);
-    }
-
-    return NS_OK;
-  }
-
-protected:
-  virtual ~StyleImageRequestCleanupTask() { MOZ_ASSERT(NS_IsMainThread()); }
-
-private:
-  Mode mModeFlags;
-  // Since we always dispatch this runnable to the main thread, these will be
-  // released on the main thread when the runnable itself is released.
-  RefPtr<imgRequestProxy> mRequestProxy;
-  RefPtr<css::ImageValue> mImageValue;
-  RefPtr<ImageTracker> mImageTracker;
-};
-
-nsStyleImageRequest::nsStyleImageRequest(Mode aModeFlags,
-                                         imgRequestProxy* aRequestProxy,
-                                         css::ImageValue* aImageValue,
-                                         ImageTracker* aImageTracker)
-  : mRequestProxy(aRequestProxy)
-  , mImageValue(aImageValue)
-  , mImageTracker(aImageTracker)
-  , mModeFlags(aModeFlags)
-  , mResolved(true)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aRequestProxy);
-  MOZ_ASSERT(aImageValue);
-  MOZ_ASSERT(aImageTracker);
-
-  MaybeTrackAndLock();
-}
-
-nsStyleImageRequest::nsStyleImageRequest(
-    Mode aModeFlags,
-    nsStringBuffer* aURLBuffer,
-    already_AddRefed<PtrHolder<nsIURI>> aBaseURI,
-    already_AddRefed<PtrHolder<nsIURI>> aReferrer,
-    already_AddRefed<PtrHolder<nsIPrincipal>> aPrincipal)
-  : mModeFlags(aModeFlags)
-  , mResolved(false)
-{
-  mImageValue = new css::ImageValue(aURLBuffer, Move(aBaseURI),
-                                    Move(aReferrer), Move(aPrincipal));
-}
-
-nsStyleImageRequest::~nsStyleImageRequest()
-{
-  // We may or may not be being destroyed on the main thread.  To clean
-  // up, we must untrack and unlock the image (depending on mModeFlags),
-  // and release mRequestProxy and mImageValue, all on the main thread.
-  {
-    RefPtr<StyleImageRequestCleanupTask> task =
-        new StyleImageRequestCleanupTask(mModeFlags,
-                                         mRequestProxy.forget(),
-                                         mImageValue.forget(),
-                                         mImageTracker.forget());
-    if (NS_IsMainThread()) {
-      task->Run();
-    } else {
-      NS_DispatchToMainThread(task.forget());
-    }
-  }
-
-  MOZ_ASSERT(!mRequestProxy);
-  MOZ_ASSERT(!mImageValue);
-  MOZ_ASSERT(!mImageTracker);
-}
-
-bool
-nsStyleImageRequest::Resolve(nsPresContext* aPresContext)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(!IsResolved(), "already resolved");
-
-  mResolved = true;
-
-  // For now, just have unique nsCSSValue/ImageValue objects.  We should
-  // really store the ImageValue on the Servo specified value, so that we can
-  // share imgRequestProxys that come from the same rule in the same
-  // document.
-  mImageValue->Initialize(aPresContext->Document());
-
-  nsCSSValue value;
-  value.SetImageValue(mImageValue);
-  mRequestProxy = value.GetPossiblyStaticImageValue(aPresContext->Document(),
-                                                    aPresContext);
-
-  if (!mRequestProxy) {
-    // The URL resolution or image load failed.
-    return false;
-  }
-
-  mImageTracker = aPresContext->Document()->ImageTracker();
-  MaybeTrackAndLock();
-  return true;
-}
-
-void
-nsStyleImageRequest::MaybeTrackAndLock()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(IsResolved());
-  MOZ_ASSERT(mRequestProxy);
-  MOZ_ASSERT(mImageTracker);
-
-  if (mModeFlags & Mode::Track) {
-    mImageTracker->Add(mRequestProxy);
-  }
-
-  if (mModeFlags & Mode::Lock) {
-    mRequestProxy->LockImage();
-  }
-}
-
-bool
-nsStyleImageRequest::DefinitelyEquals(const nsStyleImageRequest& aOther) const
-{
-  return DefinitelyEqualURIs(mImageValue, aOther.mImageValue);
-}
-
 // --------------------
 // CachedBorderImageData
 //
 void
 CachedBorderImageData::SetCachedSVGViewportSize(
   const mozilla::Maybe<nsSize>& aSVGViewportSize)
 {
   mCachedSVGViewportSize = aSVGViewportSize;
@@ -2118,31 +1908,37 @@ CachedBorderImageData::GetSubImage(uint8
 
 // --------------------
 // nsStyleImage
 //
 
 nsStyleImage::nsStyleImage()
   : mType(eStyleImageType_Null)
   , mCropRect(nullptr)
+#ifdef DEBUG
+  , mImageTracked(false)
+#endif
 {
   MOZ_COUNT_CTOR(nsStyleImage);
 }
 
 nsStyleImage::~nsStyleImage()
 {
   MOZ_COUNT_DTOR(nsStyleImage);
   if (mType != eStyleImageType_Null) {
     SetNull();
   }
 }
 
 nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
   : mType(eStyleImageType_Null)
   , mCropRect(nullptr)
+#ifdef DEBUG
+  , mImageTracked(false)
+#endif
 {
   // We need our own copy constructor because we don't want
   // to copy the reference count
   MOZ_COUNT_CTOR(nsStyleImage);
   DoCopy(aOther);
 }
 
 nsStyleImage&
@@ -2156,64 +1952,110 @@ nsStyleImage::operator=(const nsStyleIma
 }
 
 void
 nsStyleImage::DoCopy(const nsStyleImage& aOther)
 {
   SetNull();
 
   if (aOther.mType == eStyleImageType_Image) {
-    SetImageRequest(do_AddRef(aOther.mImage));
+    SetImageData(aOther.mImage);
   } else if (aOther.mType == eStyleImageType_Gradient) {
     SetGradientData(aOther.mGradient);
   } else if (aOther.mType == eStyleImageType_Element) {
     SetElementId(aOther.mElementId);
   }
 
   UniquePtr<nsStyleSides> cropRectCopy;
   if (aOther.mCropRect) {
     cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
   }
   SetCropRect(Move(cropRectCopy));
 }
 
 void
 nsStyleImage::SetNull()
 {
+  MOZ_ASSERT(!mImageTracked,
+             "Calling SetNull() with image tracked!");
+
   if (mType == eStyleImageType_Gradient) {
     mGradient->Release();
   } else if (mType == eStyleImageType_Image) {
     NS_RELEASE(mImage);
   } else if (mType == eStyleImageType_Element) {
     free(mElementId);
   }
 
   mType = eStyleImageType_Null;
   mCropRect = nullptr;
 }
 
 void
-nsStyleImage::SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage)
+nsStyleImage::SetImageData(imgRequestProxy* aImage)
 {
-  RefPtr<nsStyleImageRequest> image = aImage;
+  MOZ_ASSERT(!mImageTracked,
+             "Setting a new image without untracking the old one!");
+
+  NS_IF_ADDREF(aImage);
 
   if (mType != eStyleImageType_Null) {
     SetNull();
   }
 
-  if (image) {
-    mImage = image.forget().take();
+  if (aImage) {
+    mImage = aImage;
     mType = eStyleImageType_Image;
   }
   if (mCachedBIData) {
     mCachedBIData->PurgeCachedImages();
   }
 }
 
 void
+nsStyleImage::TrackImage(nsPresContext* aContext)
+{
+  // Sanity
+  MOZ_ASSERT(!mImageTracked, "Already tracking image!");
+  MOZ_ASSERT(mType == eStyleImageType_Image,
+             "Can't track image when there isn't one!");
+
+  // Register the image with the document
+  nsIDocument* doc = aContext->Document();
+  if (doc) {
+    doc->ImageTracker()->Add(mImage);
+  }
+
+  // Mark state
+#ifdef DEBUG
+  mImageTracked = true;
+#endif
+}
+
+void
+nsStyleImage::UntrackImage(nsPresContext* aContext)
+{
+  // Sanity
+  MOZ_ASSERT(mImageTracked, "Image not tracked!");
+  MOZ_ASSERT(mType == eStyleImageType_Image,
+             "Can't untrack image when there isn't one!");
+
+  // Unregister the image with the document
+  nsIDocument* doc = aContext->Document();
+  if (doc) {
+    doc->ImageTracker()->Remove(mImage);
+  }
+
+  // Mark state
+#ifdef DEBUG
+  mImageTracked = false;
+#endif
+}
+
+void
 nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
 {
   if (aGradient) {
     aGradient->AddRef();
   }
 
   if (mType != eStyleImageType_Null) {
     SetNull();
@@ -2267,23 +2109,18 @@ ConvertToPixelCoord(const nsStyleCoord& 
 bool
 nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
                                     bool* aIsEntireImage) const
 {
   if (mType != eStyleImageType_Image) {
     return false;
   }
 
-  imgRequestProxy* req = GetImageData();
-  if (!req) {
-    return false;
-  }
-
   nsCOMPtr<imgIContainer> imageContainer;
-  req->GetImage(getter_AddRefs(imageContainer));
+  mImage->GetImage(getter_AddRefs(imageContainer));
   if (!imageContainer) {
     return false;
   }
 
   nsIntSize imageSize;
   imageContainer->GetWidth(&imageSize.width);
   imageContainer->GetHeight(&imageSize.height);
   if (imageSize.width <= 0 || imageSize.height <= 0) {
@@ -2305,21 +2142,17 @@ nsStyleImage::ComputeActualCropRect(nsIn
   }
   return true;
 }
 
 nsresult
 nsStyleImage::StartDecoding() const
 {
   if (mType == eStyleImageType_Image) {
-    imgRequestProxy* req = GetImageData();
-    if (!req) {
-      return NS_ERROR_FAILURE;
-    }
-    return req->StartDecoding();
+    return mImage->StartDecoding();
   }
   return NS_OK;
 }
 
 bool
 nsStyleImage::IsOpaque() const
 {
   if (!IsComplete()) {
@@ -2330,20 +2163,19 @@ nsStyleImage::IsOpaque() const
     return mGradient->IsOpaque();
   }
 
   if (mType == eStyleImageType_Element) {
     return false;
   }
 
   MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
-  MOZ_ASSERT(GetImageData(), "should've returned earlier above");
 
   nsCOMPtr<imgIContainer> imageContainer;
-  GetImageData()->GetImage(getter_AddRefs(imageContainer));
+  mImage->GetImage(getter_AddRefs(imageContainer));
   MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
 
   // Check if the crop region of the image is opaque.
   if (imageContainer->WillDrawOpaqueNow()) {
     if (!mCropRect) {
       return true;
     }
 
@@ -2362,23 +2194,20 @@ bool
 nsStyleImage::IsComplete() const
 {
   switch (mType) {
     case eStyleImageType_Null:
       return false;
     case eStyleImageType_Gradient:
     case eStyleImageType_Element:
       return true;
-    case eStyleImageType_Image: {
-      imgRequestProxy* req = GetImageData();
-      if (!req) {
-        return false;
-      }
+    case eStyleImageType_Image:
+    {
       uint32_t status = imgIRequest::STATUS_ERROR;
-      return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
+      return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
              (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
              (status & imgIRequest::STATUS_FRAME_COMPLETE);
     }
     default:
       NS_NOTREACHED("unexpected image type");
       return false;
   }
 }
@@ -2387,23 +2216,20 @@ bool
 nsStyleImage::IsLoaded() const
 {
   switch (mType) {
     case eStyleImageType_Null:
       return false;
     case eStyleImageType_Gradient:
     case eStyleImageType_Element:
       return true;
-    case eStyleImageType_Image: {
-      imgRequestProxy* req = GetImageData();
-      if (!req) {
-        return false;
-      }
+    case eStyleImageType_Image:
+    {
       uint32_t status = imgIRequest::STATUS_ERROR;
-      return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
+      return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
              !(status & imgIRequest::STATUS_ERROR) &&
              (status & imgIRequest::STATUS_LOAD_COMPLETE);
     }
     default:
       NS_NOTREACHED("unexpected image type");
       return false;
   }
 }
@@ -2422,17 +2248,17 @@ nsStyleImage::operator==(const nsStyleIm
     return false;
   }
 
   if (!EqualRects(mCropRect, aOther.mCropRect)) {
     return false;
   }
 
   if (mType == eStyleImageType_Image) {
-    return DefinitelyEqualImages(mImage, aOther.mImage);
+    return EqualImages(mImage, aOther.mImage);
   }
 
   if (mType == eStyleImageType_Gradient) {
     return *mGradient == *aOther.mGradient;
   }
 
   if (mType == eStyleImageType_Element) {
     return NS_strcmp(mElementId, aOther.mElementId) == 0;
@@ -2703,19 +2529,17 @@ nsStyleImageLayers::Size::DependsOnPosit
   //     according to the spec.  However, we don't implement the spec yet, so
   //     for now we bail and say element() plus auto affects ultimate size.
   if (type == eStyleImageType_Element) {
     return true;
   }
 
   if (type == eStyleImageType_Image) {
     nsCOMPtr<imgIContainer> imgContainer;
-    if (imgRequestProxy* req = aImage.GetImageData()) {
-      req->GetImage(getter_AddRefs(imgContainer));
-    }
+    aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer));
     if (imgContainer) {
       CSSIntSize imageSize;
       nsSize imageRatio;
       bool hasWidth, hasHeight;
       nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
                                            hasWidth, hasHeight);
 
       // If the image has a fixed width and height, rendering never depends on
@@ -2939,30 +2763,24 @@ nsStyleBackground::nsStyleBackground(con
 nsStyleBackground::~nsStyleBackground()
 {
   MOZ_COUNT_DTOR(nsStyleBackground);
 }
 
 void
 nsStyleBackground::Destroy(nsPresContext* aContext)
 {
+  // Untrack all the images stored in our layers
+  mImage.UntrackImages(aContext);
+
   this->~nsStyleBackground();
   aContext->PresShell()->
     FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
 }
 
-void
-nsStyleBackground::FinishStyle(nsPresContext* aPresContext)
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
-
-  mImage.ResolveImages(aPresContext);
-}
-
 nsChangeHint
 nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
 {
   nsChangeHint hint = nsChangeHint(0);
   if (mBackgroundColor != aNewData.mBackgroundColor) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
@@ -3604,44 +3422,52 @@ nsStyleContentData::operator==(const nsS
   if (mType == eStyleContentType_Counter ||
       mType == eStyleContentType_Counters) {
     return *mContent.mCounters == *aOther.mContent.mCounters;
   }
   return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
 }
 
 void
-nsStyleContentData::TrackImage(ImageTracker* aImageTracker)
+nsStyleContentData::TrackImage(nsPresContext* aContext)
 {
   // Sanity
   MOZ_ASSERT(!mImageTracked, "Already tracking image!");
   MOZ_ASSERT(mType == eStyleContentType_Image,
              "Trying to do image tracking on non-image!");
   MOZ_ASSERT(mContent.mImage,
              "Can't track image when there isn't one!");
 
-  aImageTracker->Add(mContent.mImage);
+  // Register the image with the document
+  nsIDocument* doc = aContext->Document();
+  if (doc) {
+    doc->ImageTracker()->Add(mContent.mImage);
+  }
 
   // Mark state
 #ifdef DEBUG
   mImageTracked = true;
 #endif
 }
 
 void
-nsStyleContentData::UntrackImage(ImageTracker* aImageTracker)
+nsStyleContentData::UntrackImage(nsPresContext* aContext)
 {
   // Sanity
   MOZ_ASSERT(mImageTracked, "Image not tracked!");
   MOZ_ASSERT(mType == eStyleContentType_Image,
              "Trying to do image tracking on non-image!");
   MOZ_ASSERT(mContent.mImage,
              "Can't untrack image when there isn't one!");
 
-  aImageTracker->Remove(mContent.mImage);
+  // Unregister the image with the document
+  nsIDocument* doc = aContext->Document();
+  if (doc) {
+    doc->ImageTracker()->Remove(mContent.mImage);
+  }
 
   // Mark state
 #ifdef DEBUG
   mImageTracked = false;
 #endif
 }
 
 
@@ -3661,17 +3487,17 @@ nsStyleContent::~nsStyleContent()
 }
 
 void
 nsStyleContent::Destroy(nsPresContext* aContext)
 {
   // Unregister any images we might have with the document.
   for (auto& content : mContents) {
     if (content.mType == eStyleContentType_Image && content.mContent.mImage) {
-      content.UntrackImage(aContext->Document()->ImageTracker());
+      content.UntrackImage(aContext);
     }
   }
 
   this->~nsStyleContent();
   aContext->PresShell()->FreeByObjectID(eArenaObjectID_nsStyleContent, this);
 }
 
 nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -41,21 +41,16 @@
 #include "X11UndefineNone.h"
 
 class nsIFrame;
 class nsIURI;
 class nsStyleContext;
 class nsTextFrame;
 class imgIContainer;
 struct nsStyleVisibility;
-namespace mozilla {
-namespace dom {
-class ImageTracker;
-} // namespace dom
-} // namespace mozilla
 
 typedef nsINode RawGeckoNode;
 typedef mozilla::dom::Element RawGeckoElement;
 typedef nsIDocument RawGeckoDocument;
 struct ServoNodeData;
 
 // Includes nsStyleStructID.
 #include "nsStyleStructFwd.h"
@@ -161,17 +156,16 @@ struct Position {
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleFont
 {
   nsStyleFont(const nsFont& aFont, StyleStructContext aContext);
   nsStyleFont(const nsStyleFont& aStyleFont);
   explicit nsStyleFont(StyleStructContext aContext);
   ~nsStyleFont() {
     MOZ_COUNT_DTOR(nsStyleFont);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   nsChangeHint CalcDifference(const nsStyleFont& aNewData) const;
   static nsChangeHint MaxDifference() {
     return NS_STYLE_HINT_REFLOW |
            nsChangeHint_NeutralChange;
   }
   static nsChangeHint DifferenceAlwaysHandledForDescendants() {
     // CalcDifference never returns the reflow hints that are sometimes
@@ -283,107 +277,16 @@ public:
 private:
   // Private destructor, to discourage deletion outside of Release():
   ~nsStyleGradient() {}
 
   nsStyleGradient(const nsStyleGradient& aOther) = delete;
   nsStyleGradient& operator=(const nsStyleGradient& aOther) = delete;
 };
 
-/**
- * A wrapper for an imgRequestProxy that supports off-main-thread creation
- * and equality comparison.
- *
- * An nsStyleImageRequest can be created in two ways:
- *
- * 1. Using the constructor that takes an imgRequestProxy.  This must
- *    be called from the main thread.  The nsStyleImageRequest is
- *    immediately considered "resolved", and the get() method that
- *    returns the imgRequestProxy can be called.
- *
- * 2. Using the constructor that takes the URL, base URI, referrer
- *    and principal that can be used to inititiate an image load and
- *    produce an imgRequestProxy later.  This can be called from
- *    any thread.  The nsStyleImageRequest is not considered "resolved"
- *    at this point, and the Resolve() method must be called later
- *    to initiate the image load and make calls to get() valid.
- *
- * Calls to TrackImage(), UntrackImage(), LockImage(), UnlockImage() and
- * RequestDiscard() are made to the imgRequestProxy and ImageTracker as
- * appropriate, according to the mode flags passed in to the constructor.
- *
- * The main thread constructor takes a pointer to the css::ImageValue that
- * is the specified url() value, while the off-main-thread constructor
- * creates a new css::ImageValue to represent the url() information passed
- * to the constructor.  This ImageValue is held on to for the comparisons done
- * in DefinitelyEquals(), so that we don't need to call into the non-OMT-safe
- * Equals() on the nsIURI objects returned from imgRequestProxy::GetURI().
- */
-class nsStyleImageRequest
-{
-public:
-  // Flags describing whether the imgRequestProxy must be tracked in the
-  // ImageTracker, whether LockImage/UnlockImage calls will be made
-  // when obtaining and releasing the imgRequestProxy, and whether
-  // RequestDiscard will be called on release.
-  enum class Mode : uint8_t {
-    Track   = 0x1,  // used by all except nsCursorImage
-    Lock    = 0x2,  // used by all except nsStyleContentData
-    Discard = 0x4,  // used only by nsCursorImage
-  };
-
-  // Must be called from the main thread.
-  nsStyleImageRequest(Mode aModeFlags,
-                      imgRequestProxy* aRequestProxy,
-                      mozilla::css::ImageValue* aImageValue,
-                      mozilla::dom::ImageTracker* aImageTracker);
-
-  // Can be called from any thread, but Resolve() must be called later
-  // on the main thread before get() can be used.
-  nsStyleImageRequest(
-      Mode aModeFlags,
-      nsStringBuffer* aURLBuffer,
-      already_AddRefed<mozilla::PtrHolder<nsIURI>> aBaseURI,
-      already_AddRefed<mozilla::PtrHolder<nsIURI>> aReferrer,
-      already_AddRefed<mozilla::PtrHolder<nsIPrincipal>> aPrincipal);
-
-  bool Resolve(nsPresContext* aPresContext);
-  bool IsResolved() const { return mResolved; }
-
-  imgRequestProxy* get() {
-    MOZ_ASSERT(IsResolved(), "Resolve() must be called first");
-    MOZ_ASSERT(NS_IsMainThread());
-    return mRequestProxy.get();
-  }
-  const imgRequestProxy* get() const {
-    return const_cast<nsStyleImageRequest*>(this)->get();
-  }
-
-  // Returns whether the ImageValue objects in the two nsStyleImageRequests
-  // return true from URLValueData::DefinitelyEqualURIs.
-  bool DefinitelyEquals(const nsStyleImageRequest& aOther) const;
-
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsStyleImageRequest);
-
-private:
-  ~nsStyleImageRequest();
-  nsStyleImageRequest& operator=(const nsStyleImageRequest& aOther) = delete;
-
-  void MaybeTrackAndLock();
-
-  RefPtr<imgRequestProxy> mRequestProxy;
-  RefPtr<mozilla::css::ImageValue> mImageValue;
-  RefPtr<mozilla::dom::ImageTracker> mImageTracker;
-
-  Mode mModeFlags;
-  bool mResolved;
-};
-
-MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(nsStyleImageRequest::Mode)
-
 enum nsStyleImageType {
   eStyleImageType_Null,
   eStyleImageType_Image,
   eStyleImageType_Gradient,
   eStyleImageType_Element
 };
 
 struct CachedBorderImageData
@@ -417,39 +320,33 @@ private:
 struct nsStyleImage
 {
   nsStyleImage();
   ~nsStyleImage();
   nsStyleImage(const nsStyleImage& aOther);
   nsStyleImage& operator=(const nsStyleImage& aOther);
 
   void SetNull();
-  void SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage);
+  void SetImageData(imgRequestProxy* aImage);
+  void TrackImage(nsPresContext* aContext);
+  void UntrackImage(nsPresContext* aContext);
   void SetGradientData(nsStyleGradient* aGradient);
   void SetElementId(const char16_t* aElementId);
   void SetCropRect(mozilla::UniquePtr<nsStyleSides> aCropRect);
 
-  void ResolveImage(nsPresContext* aContext) {
-    MOZ_ASSERT(mType != eStyleImageType_Image || mImage);
-    if (mType == eStyleImageType_Image && !mImage->IsResolved()) {
-      mImage->Resolve(aContext);
-    }
-  }
-
   nsStyleImageType GetType() const {
     return mType;
   }
-  nsStyleImageRequest* GetImageRequest() const {
+  imgRequestProxy* GetImageData() const {
     MOZ_ASSERT(mType == eStyleImageType_Image, "Data is not an image!");
     MOZ_ASSERT(mImage);
+    MOZ_ASSERT(mImageTracked,
+               "Should be tracking any image we're going to use!");
     return mImage;
   }
-  imgRequestProxy* GetImageData() const {
-    return GetImageRequest()->get();
-  }
   nsStyleGradient* GetGradientData() const {
     NS_ASSERTION(mType == eStyleImageType_Gradient, "Data is not a gradient!");
     return mGradient;
   }
   const char16_t* GetElementId() const {
     NS_ASSERTION(mType == eStyleImageType_Element, "Data is not an element!");
     return mElementId;
   }
@@ -532,33 +429,35 @@ private:
   void EnsureCachedBIData() const;
 
   // This variable keeps some cache data for border image and is lazily
   // allocated since it is only used in border image case.
   mozilla::UniquePtr<CachedBorderImageData> mCachedBIData;
 
   nsStyleImageType mType;
   union {
-    nsStyleImageRequest* mImage;
+    imgRequestProxy* mImage;
     nsStyleGradient* mGradient;
     char16_t* mElementId;
   };
 
   // This is _currently_ used only in conjunction with eStyleImageType_Image.
   mozilla::UniquePtr<nsStyleSides> mCropRect;
+#ifdef DEBUG
+  bool mImageTracked;
+#endif
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColor
 {
   explicit nsStyleColor(StyleStructContext aContext);
   nsStyleColor(const nsStyleColor& aOther);
   ~nsStyleColor() {
     MOZ_COUNT_DTOR(nsStyleColor);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   nscolor CalcComplexColor(const mozilla::StyleComplexColor& aColor) const {
     return mozilla::LinearBlendColors(aColor.mColor, mColor,
                                       aColor.mForegroundRatio);
   }
 
   nsChangeHint CalcDifference(const nsStyleColor& aNewData) const;
   static nsChangeHint MaxDifference() {
@@ -815,19 +714,26 @@ struct nsStyleImageLayers {
     // This constructor does not initialize mRepeat or mOrigin and Initialize()
     // must be called to do that.
     Layer();
     ~Layer();
 
     // Initialize mRepeat and mOrigin by specified layer type
     void Initialize(LayerType aType);
 
-    void ResolveImage(nsPresContext* aContext) {
+    // Register/unregister images with the document. We do this only
+    // after the dust has settled in ComputeBackgroundData.
+    void TrackImages(nsPresContext* aContext) {
       if (mImage.GetType() == eStyleImageType_Image) {
-        mImage.ResolveImage(aContext);
+        mImage.TrackImage(aContext);
+      }
+    }
+    void UntrackImages(nsPresContext* aContext) {
+      if (mImage.GetType() == eStyleImageType_Image) {
+        mImage.UntrackImage(aContext);
       }
     }
 
     // True if the rendering of this layer might change when the size
     // of the background positioning area changes.  This is true for any
     // non-solid-color background whose position or size depends on
     // the size of the positioning area.  It's also true for SVG images
     // whose root <svg> node has a viewBox.
@@ -867,21 +773,25 @@ struct nsStyleImageLayers {
   // background-clip applies to the background-color) may not be last
   // layer.  In layers below the bottom layer, properties will be
   // uninitialized unless their count, above, indicates that they are
   // present.
   nsStyleAutoArray<Layer> mLayers;
 
   const Layer& BottomLayer() const { return mLayers[mImageCount - 1]; }
 
-  void ResolveImages(nsPresContext* aContext) {
+  void TrackImages(nsPresContext* aContext) {
     for (uint32_t i = 0; i < mImageCount; ++i) {
-      mLayers[i].ResolveImage(aContext);
+        mLayers[i].TrackImages(aContext);
     }
   }
+  void UntrackImages(nsPresContext* aContext) {
+    for (uint32_t i = 0; i < mImageCount; ++i)
+      mLayers[i].UntrackImages(aContext);
+  }
 
   nsChangeHint CalcDifference(const nsStyleImageLayers& aNewLayers,
                               nsStyleImageLayers::LayerType aType) const;
 
   bool HasLayerWithImage() const;
 
   static const nsCSSPropertyID kBackgroundLayerTable[];
   static const nsCSSPropertyID kMaskLayerTable[];
@@ -894,21 +804,16 @@ struct nsStyleImageLayers {
     for (uint32_t var_ = (start_) + 1; var_-- != (uint32_t)((start_) + 1 - (count_)); )
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBackground {
   explicit nsStyleBackground(StyleStructContext aContext);
   nsStyleBackground(const nsStyleBackground& aOther);
   ~nsStyleBackground();
 
-  // Resolves and tracks the images in mImage.  Only called with a Servo-backed
-  // style system, where those images must be resolved later than the OMT
-  // nsStyleBackground constructor call.
-  void FinishStyle(nsPresContext* aPresContext);
-
   void* operator new(size_t sz, nsStyleBackground* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBackground, sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBackground& aNewData) const;
@@ -950,17 +855,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleMargin
 {
   explicit nsStyleMargin(StyleStructContext aContext);
   nsStyleMargin(const nsStyleMargin& aMargin);
   ~nsStyleMargin() {
     MOZ_COUNT_DTOR(nsStyleMargin);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleMargin* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleMargin, sz);
   }
   void Destroy(nsPresContext* aContext);
 
@@ -998,17 +902,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePadding
 {
   explicit nsStylePadding(StyleStructContext aContext);
   nsStylePadding(const nsStylePadding& aPadding);
   ~nsStylePadding() {
     MOZ_COUNT_DTOR(nsStylePadding);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStylePadding* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePadding, sz);
   }
   void Destroy(nsPresContext* aContext);
 
@@ -1207,21 +1110,16 @@ static bool IsVisibleBorderStyle(uint8_t
 }
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleBorder
 {
   explicit nsStyleBorder(StyleStructContext aContext);
   nsStyleBorder(const nsStyleBorder& aBorder);
   ~nsStyleBorder();
 
-  // Resolves and tracks mBorderImageSource.  Only called with a Servo-backed
-  // style system, where those images must be resolved later than the OMT
-  // nsStyleBorder constructor call.
-  void FinishStyle(nsPresContext* aPresContext);
-
   void* operator new(size_t sz, nsStyleBorder* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleBorder, sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleBorder& aNewData) const;
@@ -1314,20 +1212,26 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
       (HasVisibleStyle(aSide) ? mBorder.Side(aSide) : 0);
   }
 
   inline bool IsBorderImageLoaded() const
   {
     return mBorderImageSource.IsLoaded();
   }
 
-  void ResolveImage(nsPresContext* aContext)
+  void TrackImage(nsPresContext* aContext)
   {
     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
-      mBorderImageSource.ResolveImage(aContext);
+      mBorderImageSource.TrackImage(aContext);
+    }
+  }
+  void UntrackImage(nsPresContext* aContext)
+  {
+    if (mBorderImageSource.GetType() == eStyleImageType_Image) {
+      mBorderImageSource.UntrackImage(aContext);
     }
   }
 
   nsMargin GetImageOutset() const;
 
   void GetCompositeColors(int32_t aIndex, nsBorderColors** aColors) const
   {
     if (!mBorderColors) {
@@ -1434,17 +1338,16 @@ ASSERT_BORDER_COLOR_FIELD(Left);
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleOutline
 {
   explicit nsStyleOutline(StyleStructContext aContext);
   nsStyleOutline(const nsStyleOutline& aOutline);
   ~nsStyleOutline() {
     MOZ_COUNT_DTOR(nsStyleOutline);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleOutline* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleOutline, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleOutline();
@@ -1509,18 +1412,16 @@ private:
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleList
 {
   explicit nsStyleList(StyleStructContext aContext);
   nsStyleList(const nsStyleList& aStyleList);
   ~nsStyleList();
 
-  void FinishStyle(nsPresContext* aPresContext);
-
   void* operator new(size_t sz, nsStyleList* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleList, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleList();
     aContext->PresShell()->
@@ -1540,19 +1441,26 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
            nsChangeHint_ClearAncestorIntrinsics;
   }
 
   static void Shutdown() {
     sInitialQuotes = nullptr;
     sNoneQuotes = nullptr;
   }
 
-  imgRequestProxy* GetListStyleImage() const
+  imgRequestProxy* GetListStyleImage() const { return mListStyleImage; }
+  void SetListStyleImage(imgRequestProxy* aReq)
   {
-    return mListStyleImage ? mListStyleImage->get() : nullptr;
+    if (mListStyleImage) {
+      mListStyleImage->UnlockImage();
+    }
+    mListStyleImage = aReq;
+    if (mListStyleImage) {
+      mListStyleImage->LockImage();
+    }
   }
 
   void GetListStyleType(nsSubstring& aType) const { mCounterStyle->GetStyleName(aType); }
   mozilla::CounterStyle* GetCounterStyle() const
   {
     return mCounterStyle.get();
   }
   void SetCounterStyle(mozilla::CounterStyle* aStyle)
@@ -1570,20 +1478,20 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
 
   const nsStyleQuoteValues::QuotePairArray& GetQuotePairs() const;
 
   void SetQuotesInherit(const nsStyleList* aOther);
   void SetQuotesInitial();
   void SetQuotesNone();
   void SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues);
 
-  uint8_t mListStylePosition;                  // [inherited]
-  RefPtr<nsStyleImageRequest> mListStyleImage; // [inherited]
+  uint8_t   mListStylePosition;         // [inherited]
 private:
   RefPtr<mozilla::CounterStyle> mCounterStyle; // [inherited]
+  RefPtr<imgRequestProxy> mListStyleImage; // [inherited]
   RefPtr<nsStyleQuoteValues> mQuotes;   // [inherited]
   nsStyleList& operator=(const nsStyleList& aOther) = delete;
 public:
   nsRect        mImageRegion;           // [inherited] the rect to use within an image
 
 private:
   // nsStyleQuoteValues objects representing two common values, for sharing.
   static mozilla::StaticRefPtr<nsStyleQuoteValues> sInitialQuotes;
@@ -1732,17 +1640,16 @@ struct nsStyleGridTemplate
   }
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStylePosition
 {
   explicit nsStylePosition(StyleStructContext aContext);
   nsStylePosition(const nsStylePosition& aOther);
   ~nsStylePosition();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStylePosition* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStylePosition, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStylePosition();
@@ -1969,17 +1876,16 @@ struct nsStyleTextOverflow
   bool mLogicalDirections;  // true when only one value was specified
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTextReset
 {
   explicit nsStyleTextReset(StyleStructContext aContext);
   nsStyleTextReset(const nsStyleTextReset& aOther);
   ~nsStyleTextReset();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleTextReset* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTextReset, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleTextReset();
@@ -2018,17 +1924,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   mozilla::StyleComplexColor mTextDecorationColor; // [reset]
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleText
 {
   explicit nsStyleText(StyleStructContext aContext);
   nsStyleText(const nsStyleText& aOther);
   ~nsStyleText();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleText* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleText, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleText();
@@ -2237,17 +2142,16 @@ protected:
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVisibility
 {
   explicit nsStyleVisibility(StyleStructContext aContext);
   nsStyleVisibility(const nsStyleVisibility& aVisibility);
   ~nsStyleVisibility() {
     MOZ_COUNT_DTOR(nsStyleVisibility);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleVisibility* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVisibility, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleVisibility();
@@ -2745,17 +2649,16 @@ using StyleShapeOutside = StyleShapeSour
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
 {
   explicit nsStyleDisplay(StyleStructContext aContext);
   nsStyleDisplay(const nsStyleDisplay& aOther);
   ~nsStyleDisplay() {
     MOZ_COUNT_DTOR(nsStyleDisplay);
   }
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleDisplay* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleDisplay, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleDisplay();
@@ -3057,17 +2960,16 @@ public:
   inline mozilla::StyleClear PhysicalBreakType(mozilla::WritingMode aWM) const;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTable
 {
   explicit nsStyleTable(StyleStructContext aContext);
   nsStyleTable(const nsStyleTable& aOther);
   ~nsStyleTable();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleTable* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTable, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleTable();
@@ -3089,17 +2991,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   int32_t       mSpan;          // [reset] the number of columns spanned by a colgroup or col
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleTableBorder
 {
   explicit nsStyleTableBorder(StyleStructContext aContext);
   nsStyleTableBorder(const nsStyleTableBorder& aOther);
   ~nsStyleTableBorder();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleTableBorder* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleTableBorder, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleTableBorder();
@@ -3167,18 +3068,18 @@ struct nsStyleContentData
   ~nsStyleContentData();
   nsStyleContentData& operator=(const nsStyleContentData& aOther);
   bool operator==(const nsStyleContentData& aOther) const;
 
   bool operator!=(const nsStyleContentData& aOther) const {
     return !(*this == aOther);
   }
 
-  void TrackImage(mozilla::dom::ImageTracker* aImageTracker);
-  void UntrackImage(mozilla::dom::ImageTracker* aImageTracker);
+  void TrackImage(nsPresContext* aContext);
+  void UntrackImage(nsPresContext* aContext);
 
   void SetImage(imgRequestProxy* aRequest)
   {
     MOZ_ASSERT(!mImageTracked,
                "Setting a new image without untracking the old one!");
     MOZ_ASSERT(mType == eStyleContentType_Image, "Wrong type!");
     NS_IF_ADDREF(mContent.mImage = aRequest);
   }
@@ -3198,17 +3099,16 @@ struct nsStyleCounterData
   }
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent
 {
   explicit nsStyleContent(StyleStructContext aContext);
   nsStyleContent(const nsStyleContent& aContent);
   ~nsStyleContent();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleContent* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleContent, sz);
   }
   void Destroy(nsPresContext* aContext);
 
@@ -3281,17 +3181,16 @@ protected:
   nsTArray<nsStyleCounterData> mResets;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset
 {
   explicit nsStyleUIReset(StyleStructContext aContext);
   nsStyleUIReset(const nsStyleUIReset& aOther);
   ~nsStyleUIReset();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleUIReset* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUIReset, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleUIReset();
@@ -3354,17 +3253,16 @@ private:
   nsCOMPtr<imgIRequest> mImage;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUserInterface
 {
   explicit nsStyleUserInterface(StyleStructContext aContext);
   nsStyleUserInterface(const nsStyleUserInterface& aOther);
   ~nsStyleUserInterface();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleUserInterface* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleUserInterface, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleUserInterface();
@@ -3398,17 +3296,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   inline uint8_t GetEffectivePointerEvents(nsIFrame* aFrame) const;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleXUL
 {
   explicit nsStyleXUL(StyleStructContext aContext);
   nsStyleXUL(const nsStyleXUL& aSource);
   ~nsStyleXUL();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleXUL* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleXUL, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleXUL();
@@ -3438,17 +3335,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   bool          mStretchStack;          // [reset] see nsStyleConsts.h
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleColumn
 {
   explicit nsStyleColumn(StyleStructContext aContext);
   nsStyleColumn(const nsStyleColumn& aSource);
   ~nsStyleColumn();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleColumn* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleColumn, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleColumn();
@@ -3563,17 +3459,16 @@ private:
   nscolor mFallbackColor;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVG
 {
   explicit nsStyleSVG(StyleStructContext aContext);
   nsStyleSVG(const nsStyleSVG& aSource);
   ~nsStyleSVG();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleSVG* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVG, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleSVG();
@@ -3697,17 +3592,16 @@ private:
   uint8_t          mContextFlags;     // [inherited]
 };
 
 struct nsStyleFilter
 {
   nsStyleFilter();
   nsStyleFilter(const nsStyleFilter& aSource);
   ~nsStyleFilter();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   nsStyleFilter& operator=(const nsStyleFilter& aOther);
 
   bool operator==(const nsStyleFilter& aOther) const;
   bool operator!=(const nsStyleFilter& aOther) const {
     return !(*this == aOther);
   }
 
@@ -3755,21 +3649,16 @@ struct nsTArray_CopyChooser<nsStyleFilte
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleSVGReset
 {
   explicit nsStyleSVGReset(StyleStructContext aContext);
   nsStyleSVGReset(const nsStyleSVGReset& aSource);
   ~nsStyleSVGReset();
 
-  // Resolves and tracks the images in mMask.  Only called with a Servo-backed
-  // style system, where those images must be resolved later than the OMT
-  // nsStyleSVGReset constructor call.
-  void FinishStyle(nsPresContext* aPresContext);
-
   void* operator new(size_t sz, nsStyleSVGReset* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
   }
   void Destroy(nsPresContext* aContext);
 
   nsChangeHint CalcDifference(const nsStyleSVGReset& aNewData) const;
@@ -3811,17 +3700,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   uint8_t          mMaskType;         // [reset] see nsStyleConsts.h
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleVariables
 {
   explicit nsStyleVariables(StyleStructContext aContext);
   nsStyleVariables(const nsStyleVariables& aSource);
   ~nsStyleVariables();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleVariables* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleVariables, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleVariables();
@@ -3842,17 +3730,16 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   mozilla::CSSVariableValues mVariables;
 };
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleEffects
 {
   explicit nsStyleEffects(StyleStructContext aContext);
   nsStyleEffects(const nsStyleEffects& aSource);
   ~nsStyleEffects();
-  void FinishStyle(nsPresContext* aPresContext) {}
 
   void* operator new(size_t sz, nsStyleEffects* aSelf) { return aSelf; }
   void* operator new(size_t sz, nsPresContext* aContext) {
     return aContext->PresShell()->
       AllocateByObjectID(mozilla::eArenaObjectID_nsStyleEffects, sz);
   }
   void Destroy(nsPresContext* aContext) {
     this->~nsStyleEffects();