Bug 1341724 - Part 4: stylo: Make font metrics usage threadsafe; r=heycam
authorManish Goregaokar <manishearth@gmail.com>
Fri, 07 Apr 2017 15:49:44 -0700
changeset 400269 4d87363051a3101ac41a91583a587c7dc6194346
parent 400268 846fa6a6196ef4d9846c815070806eb2ae3335b1
child 400270 e6a2e2cadcf0b323b12a4963f24fb1353962da0a
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1341724
milestone55.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 1341724 - Part 4: stylo: Make font metrics usage threadsafe; r=heycam MozReview-Commit-ID: 3EqpUy09UuI
gfx/src/nsDeviceContext.cpp
gfx/src/nsDeviceContext.h
gfx/src/nsFontMetrics.cpp
gfx/src/nsFontMetrics.h
gfx/thebes/gfxFcPlatformFontList.cpp
gfx/thebes/gfxFcPlatformFontList.h
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
gfx/thebes/gfxFontEntry.cpp
gfx/thebes/gfxFontEntry.h
gfx/thebes/gfxPlatformFontList.cpp
gfx/thebes/gfxPlatformFontList.h
gfx/thebes/gfxTextRun.cpp
gfx/thebes/gfxUserFontSet.cpp
gfx/thebes/gfxUserFontSet.h
gfx/thebes/moz.build
layout/style/ServoBindings.cpp
layout/style/ServoStyleSet.cpp
--- a/gfx/src/nsDeviceContext.cpp
+++ b/gfx/src/nsDeviceContext.cpp
@@ -203,25 +203,30 @@ nsDeviceContext::nsDeviceContext()
 
 nsDeviceContext::~nsDeviceContext()
 {
     if (mFontCache) {
         mFontCache->Destroy();
     }
 }
 
-already_AddRefed<nsFontMetrics>
-nsDeviceContext::GetMetricsFor(const nsFont& aFont,
-                               const nsFontMetrics::Params& aParams)
+void
+nsDeviceContext::InitFontCache()
 {
     if (!mFontCache) {
         mFontCache = new nsFontCache();
         mFontCache->Init(this);
     }
+}
 
+already_AddRefed<nsFontMetrics>
+nsDeviceContext::GetMetricsFor(const nsFont& aFont,
+                               const nsFontMetrics::Params& aParams)
+{
+    InitFontCache();
     return mFontCache->GetMetricsFor(aFont, aParams);
 }
 
 nsresult
 nsDeviceContext::FlushFontCache(void)
 {
     if (mFontCache)
         mFontCache->Flush();
--- a/gfx/src/nsDeviceContext.h
+++ b/gfx/src/nsDeviceContext.h
@@ -50,16 +50,22 @@ public:
 
     /**
      * Initialize the device context from a widget
      * @param aWidget a widget to initialize the device context from
      * @return error status
      */
     nsresult Init(nsIWidget *aWidget);
 
+    /*
+     * Initialize the font cache if it hasn't been initialized yet.
+     * (Needed for stylo)
+     */
+    void InitFontCache();
+
     /**
      * Initialize the device context from a device context spec
      * @param aDevSpec the specification of the printing device
      * @return error status
      */
     nsresult InitForPrinting(nsIDeviceContextSpec *aDevSpec);
 
     /**
--- a/gfx/src/nsFontMetrics.cpp
+++ b/gfx/src/nsFontMetrics.cpp
@@ -141,16 +141,18 @@ nsFontMetrics::nsFontMetrics(const nsFon
         gfxFloat(mDeviceContext->AppUnitsPerCSSPixel());
     mFontGroup = gfxPlatform::GetPlatform()->
         CreateFontGroup(aFont.fontlist, &style, aParams.textPerf,
                         aParams.userFontSet, devToCssSize);
 }
 
 nsFontMetrics::~nsFontMetrics()
 {
+    // Should not be dropped by stylo
+    MOZ_ASSERT(NS_IsMainThread());
     if (mDeviceContext) {
         mDeviceContext->FontMetricsDeleted(this);
     }
 }
 
 void
 nsFontMetrics::Destroy()
 {
--- a/gfx/src/nsFontMetrics.h
+++ b/gfx/src/nsFontMetrics.h
@@ -56,17 +56,18 @@ public:
       gfxFont::Orientation orientation = gfxFont::eHorizontal;
       gfxUserFontSet* userFontSet = nullptr;
       gfxTextPerfMetrics* textPerf = nullptr;
     };
 
     nsFontMetrics(const nsFont& aFont, const Params& aParams,
                   nsDeviceContext *aContext);
 
-    NS_INLINE_DECL_REFCOUNTING(nsFontMetrics)
+    // Used by stylo
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsFontMetrics)
 
     /**
      * Destroy this font metrics. This breaks the association between
      * the font metrics and the device context.
      */
     void Destroy();
 
     /**
--- a/gfx/thebes/gfxFcPlatformFontList.cpp
+++ b/gfx/thebes/gfxFcPlatformFontList.cpp
@@ -1113,16 +1113,23 @@ gfxFontconfigFontFamily::FindAllFontsFor
         skipped++;
     }
     // Remove any compacted entries from the current group.
     if (skipped) {
         aFontEntryList.TruncateLength(aFontEntryList.Length() - skipped);
     }
 }
 
+/* virtual */
+gfxFontconfigFontFamily::~gfxFontconfigFontFamily()
+ {
+    // Should not be dropped by stylo
+    MOZ_ASSERT(NS_IsMainThread());
+}
+
 gfxFontconfigFont::gfxFontconfigFont(const RefPtr<UnscaledFontFontconfig>& aUnscaledFont,
                                      cairo_scaled_font_t *aScaledFont,
                                      FcPattern *aPattern,
                                      gfxFloat aAdjustedSize,
                                      gfxFontEntry *aFontEntry,
                                      const gfxFontStyle *aFontStyle,
                                      bool aNeedsBold) :
     gfxFontconfigFontBase(aUnscaledFont, aScaledFont, aPattern, aFontEntry, aFontStyle)
--- a/gfx/thebes/gfxFcPlatformFontList.h
+++ b/gfx/thebes/gfxFcPlatformFontList.h
@@ -210,17 +210,17 @@ public:
     }
 
     void
     FindAllFontsForStyle(const gfxFontStyle& aFontStyle,
                          nsTArray<gfxFontEntry*>& aFontEntryList,
                          bool& aNeedsSyntheticBold) override;
 
 protected:
-    virtual ~gfxFontconfigFontFamily() { }
+    virtual ~gfxFontconfigFontFamily();
 
     nsTArray<nsCountedRef<FcPattern> > mFontPatterns;
 
     bool      mContainsAppFonts;
     bool      mHasNonScalableFaces;
 };
 
 class gfxFontconfigFont : public gfxFontconfigFontBase {
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -89,16 +89,23 @@ uint32_t gGlyphExtentsSetupFallBackToTig
  * observes memory-pressure notification and tells fonts to clear their
  * shaped-word caches to free up memory.
  */
 
 MOZ_DEFINE_MALLOC_SIZE_OF(FontCacheMallocSizeOf)
 
 NS_IMPL_ISUPPORTS(gfxFontCache::MemoryReporter, nsIMemoryReporter)
 
+/*virtual*/
+gfxTextRunFactory::~gfxTextRunFactory()
+{
+    // Should not be dropped by stylo
+    MOZ_ASSERT(NS_IsMainThread());
+}
+
 NS_IMETHODIMP
 gfxFontCache::MemoryReporter::CollectReports(
     nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize)
 {
     FontCacheSizes sizes;
 
     gfxFontCache::GetCache()->AddSizeOfIncludingThis(&FontCacheMallocSizeOf,
                                                      &sizes);
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -20,16 +20,17 @@
 #include "nsExpirationTracker.h"
 #include "gfxPlatform.h"
 #include "nsIAtom.h"
 #include "mozilla/HashFunctions.h"
 #include "nsIMemoryReporter.h"
 #include "nsIObserver.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Attributes.h"
+#include "MainThreadUtils.h"
 #include <algorithm>
 #include "DrawMode.h"
 #include "nsDataHashtable.h"
 #include "harfbuzz/hb.h"
 #include "mozilla/gfx/2D.h"
 #include "nsColor.h"
 
 typedef struct _cairo cairo_t;
@@ -448,17 +449,18 @@ public:
         cumulative.textrunConst += current.textrunConst;
         cumulative.textrunDestr += current.textrunDestr;
         cumulative.genericLookups += current.genericLookups;
         memset(&current, 0, sizeof(current));
     }
 };
 
 class gfxTextRunFactory {
-    NS_INLINE_DECL_REFCOUNTING(gfxTextRunFactory)
+    // Used by stylo
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxTextRunFactory)
 
 public:
     typedef mozilla::gfx::DrawTarget DrawTarget;
 
     // Flags in the mask 0xFFFF0000 are reserved for textrun clients
     // Flags in the mask 0x0000F000 are reserved for per-platform fonts
     // Flags in the mask 0x00000FFF are set by the textrun creator.
     enum {
@@ -587,17 +589,17 @@ public:
         uint32_t     *mInitialBreaks;
         uint32_t      mInitialBreakCount;
         // The ratio to use to convert device pixels to application layout units
         int32_t       mAppUnitsPerDevUnit;
     };
 
 protected:
     // Protected destructor, to discourage deletion outside of Release():
-    virtual ~gfxTextRunFactory() {}
+    virtual ~gfxTextRunFactory();
 };
 
 /**
  * gfxFontShaper
  *
  * This class implements text shaping (character to glyph mapping and
  * glyph layout). There is a gfxFontShaper subclass for each text layout
  * technology (uniscribe, core text, harfbuzz,....) we support.
--- a/gfx/thebes/gfxFontEntry.cpp
+++ b/gfx/thebes/gfxFontEntry.cpp
@@ -136,16 +136,18 @@ gfxFontEntry::gfxFontEntry(const nsAStri
     mComputedSizeOfUserFont(0)
 {
     memset(&mDefaultSubSpaceFeatures, 0, sizeof(mDefaultSubSpaceFeatures));
     memset(&mNonDefaultSubSpaceFeatures, 0, sizeof(mNonDefaultSubSpaceFeatures));
 }
 
 gfxFontEntry::~gfxFontEntry()
 {
+    // Should not be dropped by stylo
+    MOZ_ASSERT(NS_IsMainThread());
     if (mCOLR) {
         hb_blob_destroy(mCOLR);
     }
 
     if (mCPAL) {
         hb_blob_destroy(mCPAL);
     }
 
@@ -1531,16 +1533,23 @@ gfxFontFamily::SearchAllFontsForChar(Glo
                 aMatchData->mBestMatch = fe;
                 aMatchData->mMatchedFamily = this;
                 aMatchData->mMatchRank = rank;
             }
         }
     }
 }
 
+/*virtual*/
+gfxFontFamily::~gfxFontFamily()
+{
+    // Should not be dropped by stylo
+    MOZ_ASSERT(NS_IsMainThread());
+}
+
 /*static*/ void
 gfxFontFamily::ReadOtherFamilyNamesForFace(const nsAString& aFamilyName,
                                            const char *aNameData,
                                            uint32_t aDataLength,
                                            nsTArray<nsString>& aOtherFamilyNames,
                                            bool useFullName)
 {
     const gfxFontUtils::NameHeader *nameHeader =
--- a/gfx/thebes/gfxFontEntry.h
+++ b/gfx/thebes/gfxFontEntry.h
@@ -10,16 +10,17 @@
 #include "nsString.h"
 #include "gfxFontConstants.h"
 #include "gfxFontFeatures.h"
 #include "gfxFontUtils.h"
 #include "nsTArray.h"
 #include "nsTHashtable.h"
 #include "mozilla/HashFunctions.h"
 #include "mozilla/MemoryReporting.h"
+#include "MainThreadUtils.h"
 #include "nsUnicodeScriptCodes.h"
 #include "nsDataHashtable.h"
 #include "harfbuzz/hb.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/WeakPtr.h"
 
 typedef struct gr_face gr_face;
@@ -97,17 +98,18 @@ private:
     gfxCharacterMap& operator=(const gfxCharacterMap&);
 };
 
 class gfxFontEntry {
 public:
     typedef mozilla::gfx::DrawTarget DrawTarget;
     typedef mozilla::unicode::Script Script;
 
-    NS_INLINE_DECL_REFCOUNTING(gfxFontEntry)
+    // Used by stylo
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontEntry)
 
     explicit gfxFontEntry(const nsAString& aName, bool aIsStandardFace = false);
 
     // unique name for the face, *not* the family; not necessarily the
     // "real" or user-friendly name, may be an internal identifier
     const nsString& Name() const { return mName; }
 
     // family name
@@ -583,17 +585,18 @@ struct GlobalFontMatch {
     RefPtr<gfxFontEntry> mBestMatch;   // current best match
     RefPtr<gfxFontFamily> mMatchedFamily; // the family it belongs to
     uint32_t               mCount;       // number of fonts matched
     uint32_t               mCmapsTested; // number of cmaps tested
 };
 
 class gfxFontFamily {
 public:
-    NS_INLINE_DECL_REFCOUNTING(gfxFontFamily)
+    // Used by stylo
+    NS_INLINE_DECL_THREADSAFE_REFCOUNTING(gfxFontFamily)
 
     explicit gfxFontFamily(const nsAString& aName) :
         mName(aName),
         mOtherFamilyNamesInitialized(false),
         mHasOtherFamilyNames(false),
         mFaceNamesInitialized(false),
         mHasStyles(false),
         mIsSimpleFamily(false),
@@ -726,19 +729,17 @@ public:
 #endif
 
     void SetSkipSpaceFeatureCheck(bool aSkipCheck) {
         mSkipDefaultFeatureSpaceCheck = aSkipCheck;
     }
 
 protected:
     // Protected destructor, to discourage deletion outside of Release():
-    virtual ~gfxFontFamily()
-    {
-    }
+    virtual ~gfxFontFamily();
 
     bool ReadOtherFamilyNamesForFace(gfxPlatformFontList *aPlatformFontList,
                                      hb_blob_t           *aNameTable,
                                      bool                 useFullName = false);
 
     // set whether this font family is in "bad" underline offset blacklist.
     void SetBadUnderlineFonts() {
         uint32_t i, numFonts = mAvailableFonts.Length();
--- a/gfx/thebes/gfxPlatformFontList.cpp
+++ b/gfx/thebes/gfxPlatformFontList.cpp
@@ -1245,22 +1245,28 @@ void
 gfxPlatformFontList::GetFontFamilyNames(nsTArray<nsString>& aFontFamilyNames)
 {
     for (auto iter = mFontFamilies.Iter(); !iter.Done(); iter.Next()) {
         RefPtr<gfxFontFamily>& family = iter.Data();
         aFontFamilyNames.AppendElement(family->Name());
     }
 }
 
-nsILanguageAtomService*
-gfxPlatformFontList::GetLangService()
+void
+gfxPlatformFontList::InitLangService()
 {
     if (!mLangService) {
         mLangService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
     }
+}
+
+nsILanguageAtomService*
+gfxPlatformFontList::GetLangService()
+{
+    InitLangService();
     NS_ASSERTION(mLangService, "no language service!");
     return mLangService;
 }
 
 nsIAtom*
 gfxPlatformFontList::GetLangGroup(nsIAtom* aLanguage)
 {
     // map lang ==> langGroup
--- a/gfx/thebes/gfxPlatformFontList.h
+++ b/gfx/thebes/gfxPlatformFontList.h
@@ -117,16 +117,19 @@ public:
     nsresult InitFontList();
 
     virtual void GetFontList(nsIAtom *aLangGroup,
                              const nsACString& aGenericFamily,
                              nsTArray<nsString>& aListOfFonts);
 
     void UpdateFontList();
 
+    // Initialize the contained mLangService (for stylo, must be done in advance on main thread)
+    void InitLangService();
+
     virtual void ClearLangGroupPrefFonts();
 
     virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray);
 
     gfxFontEntry*
     SystemFindFontForChar(uint32_t aCh, uint32_t aNextCh,
                           Script aRunScript,
                           const gfxFontStyle* aStyle);
--- a/gfx/thebes/gfxTextRun.cpp
+++ b/gfx/thebes/gfxTextRun.cpp
@@ -1715,16 +1715,18 @@ gfxFontGroup::gfxFontGroup(const FontFam
     // We don't use SetUserFontSet() here, as we want to unconditionally call
     // BuildFontList() rather than only do UpdateUserFonts() if it changed.
     mCurrGeneration = GetGeneration();
     BuildFontList();
 }
 
 gfxFontGroup::~gfxFontGroup()
 {
+    // Should not be dropped by stylo
+    MOZ_ASSERT(NS_IsMainThread());
 }
 
 void
 gfxFontGroup::BuildFontList()
 {
     // initialize fonts in the font family list
     AutoTArray<gfxFontFamily*,10> fonts;
     gfxPlatformFontList *pfl = gfxPlatformFontList::PlatformFontList();
--- a/gfx/thebes/gfxUserFontSet.cpp
+++ b/gfx/thebes/gfxUserFontSet.cpp
@@ -317,16 +317,23 @@ gfxUserFontData::SizeOfIncludingThis(Mal
 {
     return aMallocSizeOf(this)
            + mMetadata.ShallowSizeOfExcludingThis(aMallocSizeOf)
            + mLocalName.SizeOfExcludingThisIfUnshared(aMallocSizeOf)
            + mRealName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
     // Not counting mURI and mPrincipal, as those will be shared.
 }
 
+/*virtual*/
+gfxUserFontFamily::~gfxUserFontFamily()
+{
+  // Should not be dropped by stylo
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
 void
 gfxUserFontEntry::GetFamilyNameAndURIForLogging(nsACString& aFamilyName,
                                                 nsACString& aURI)
 {
   aFamilyName.Assign(NS_ConvertUTF16toUTF8(mFamilyName));
 
   aURI.Truncate();
   if (mSrcIndex == mSrcList.Length()) {
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -129,17 +129,17 @@ public:
 
 class gfxUserFontFamily : public gfxFontFamily {
 public:
     friend class gfxUserFontSet;
 
     explicit gfxUserFontFamily(const nsAString& aName)
         : gfxFontFamily(aName) { }
 
-    virtual ~gfxUserFontFamily() { }
+    virtual ~gfxUserFontFamily();
 
     // add the given font entry to the end of the family's list
     void AddFontEntry(gfxFontEntry* aFontEntry) {
         // keep ref while removing existing entry
         RefPtr<gfxFontEntry> fe = aFontEntry;
         // remove existing entry, if already present
         mAvailableFonts.RemoveElement(aFontEntry);
         // insert at the beginning so that the last-defined font is the first
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -34,16 +34,17 @@ EXPORTS += [
     'gfxFontVariations.h',
     'gfxGradientCache.h',
     'gfxImageSurface.h',
     'gfxLineSegment.h',
     'gfxMathTable.h',
     'gfxMatrix.h',
     'gfxPattern.h',
     'gfxPlatform.h',
+    'gfxPlatformFontList.h',
     'gfxPoint.h',
     'gfxPrefs.h',
     'gfxQuad.h',
     'gfxQuaternion.h',
     'gfxRect.h',
     'gfxSharedImageSurface.h',
     'gfxSkipChars.h',
     'gfxSVGGlyphs.h',
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1633,21 +1633,21 @@ ShutdownServo()
 GeckoFontMetrics
 Gecko_GetFontMetrics(RawGeckoPresContextBorrowed aPresContext,
                      bool aIsVertical,
                      const nsStyleFont* aFont,
                      nscoord aFontSize,
                      bool aUseUserFontSet)
 {
   MutexAutoLock lock(*sServoFontMetricsLock);
-  aPresContext->SetUsesExChUnits(true);
   GeckoFontMetrics ret;
   // Safe because we are locked, and this function is only
   // ever called from Servo parallel traversal or the main thread
   nsPresContext* presContext = const_cast<nsPresContext*>(aPresContext);
+  presContext->SetUsesExChUnits(true);
   RefPtr<nsFontMetrics> fm = nsRuleNode::GetMetricsFor(presContext, aIsVertical,
                                                        aFont, aFontSize,
                                                        aUseUserFontSet);
   ret.mXSize = fm->XHeight();
   gfxFloat zeroWidth = fm->GetThebesFontGroup()->GetFirstValidFont()->
                            GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
   ret.mChSize = ceil(aPresContext->AppUnitsPerDevPixel() * zeroWidth);
   return ret;
--- a/layout/style/ServoStyleSet.cpp
+++ b/layout/style/ServoStyleSet.cpp
@@ -1,25 +1,27 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/ServoStyleSet.h"
 
+#include "gfxPlatformFontList.h"
 #include "mozilla/DocumentStyleRootIterator.h"
 #include "mozilla/ServoRestyleManager.h"
 #include "mozilla/dom/AnonymousContent.h"
 #include "mozilla/dom/ChildIterator.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/ElementInlines.h"
 #include "mozilla/dom/KeyframeEffectReadOnly.h"
 #include "nsCSSAnonBoxes.h"
 #include "nsCSSPseudoElements.h"
+#include "nsDeviceContext.h"
 #include "nsHTMLStyleSheet.h"
 #include "nsIDocumentInlines.h"
 #include "nsPrintfCString.h"
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -36,16 +38,19 @@ ServoStyleSet::~ServoStyleSet()
 }
 
 void
 ServoStyleSet::Init(nsPresContext* aPresContext)
 {
   mPresContext = aPresContext;
   mRawSet.reset(Servo_StyleSet_Init(aPresContext));
 
+  mPresContext->DeviceContext()->InitFontCache();
+  gfxPlatformFontList::PlatformFontList()->InitLangService();
+
   // Now that we have an mRawSet, go ahead and notify about whatever stylesheets
   // we have so far.
   for (auto& sheetArray : mSheets) {
     for (auto& sheet : sheetArray) {
       // There's no guarantee this will create a list on the servo side whose
       // ordering matches the list that would have been created had all those
       // sheets been appended/prepended/etc after we had mRawSet.  But hopefully
       // that's OK (e.g. because servo doesn't care about the relative ordering
@@ -206,16 +211,19 @@ ServoStyleSet::ResolveMappedAttrDeclarat
 void
 ServoStyleSet::PreTraverseSync()
 {
   ResolveMappedAttrDeclarationBlocks();
 
   // This is lazily computed and pseudo matching needs to access
   // it so force computation early.
   mPresContext->Document()->GetDocumentState();
+
+  // Ensure that the @font-face data is not stale
+  mPresContext->Document()->GetUserFontSet();
 }
 
 void
 ServoStyleSet::PreTraverse(Element* aRoot)
 {
   PreTraverseSync();
 
   // Process animation stuff that we should avoid doing during the parallel