Bug 1367497 - Part 2: Make gfxFontCache use an expiration tracker that can assert the Servo font metrics mutex is locked. r=bevis,jfkthame
☠☠ backed out by 389ff030c387 ☠ ☠
authorBevis Tseng <btseng@mozilla.com>
Tue, 15 Aug 2017 10:04:32 +0800
changeset 374785 26e12505e1aebb4fff765f4248d60dac73a71c48
parent 374784 0a273c823e19e1048d78f9e6b1ddedf8cc034bd6
child 374786 5322ba58976c4be04f11cec36676af2755562970
push id93762
push userbtseng@mozilla.com
push dateTue, 15 Aug 2017 13:48:33 +0000
treeherdermozilla-inbound@26e12505e1ae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbevis, jfkthame
bugs1367497
milestone57.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 1367497 - Part 2: Make gfxFontCache use an expiration tracker that can assert the Servo font metrics mutex is locked. r=bevis,jfkthame
gfx/thebes/gfxFont.cpp
gfx/thebes/gfxFont.h
--- a/gfx/thebes/gfxFont.cpp
+++ b/gfx/thebes/gfxFont.cpp
@@ -168,18 +168,17 @@ gfxFontCache::Shutdown()
     printf("Number of simple glyph extents eagerly requested=%d\n", gGlyphExtentsSetupEagerSimple);
     printf("Number of tight glyph extents eagerly requested=%d\n", gGlyphExtentsSetupEagerTight);
     printf("Number of tight glyph extents lazily requested=%d\n", gGlyphExtentsSetupLazyTight);
     printf("Number of simple glyph extent setups that fell back to tight=%d\n", gGlyphExtentsSetupFallBackToTight);
 #endif
 }
 
 gfxFontCache::gfxFontCache(nsIEventTarget* aEventTarget)
-    : nsExpirationTracker<gfxFont,3>(FONT_TIMEOUT_SECONDS * 1000,
-                                     "gfxFontCache", aEventTarget)
+    : gfxFontCacheExpirationTracker(aEventTarget)
 {
     nsCOMPtr<nsIObserverService> obs = GetObserverService();
     if (obs) {
         obs->AddObserver(new Observer, "memory-pressure", false);
     }
 
 #ifndef RELEASE_OR_BETA
     // Currently disabled for release builds, due to unexplained crashes
@@ -281,17 +280,17 @@ gfxFontCache::NotifyReleased(gfxFont *aF
     // Note that we might have fonts that aren't in the hashtable, perhaps because
     // of OOM adding to the hashtable or because someone did an AddNew where
     // we already had a font. These fonts are added to the expiration tracker
     // anyway, even though Lookup can't resurrect them. Eventually they will
     // expire and be deleted.
 }
 
 void
-gfxFontCache::NotifyExpired(gfxFont *aFont)
+gfxFontCache::NotifyExpired(gfxFont* aFont)
 {
     aFont->ClearCachedWords();
     RemoveObject(aFont);
     DestroyFont(aFont);
 }
 
 void
 gfxFontCache::DestroyFont(gfxFont *aFont)
--- a/gfx/thebes/gfxFont.h
+++ b/gfx/thebes/gfxFont.h
@@ -28,16 +28,17 @@
 #include "mozilla/TypedEnumBits.h"
 #include "MainThreadUtils.h"
 #include <algorithm>
 #include "DrawMode.h"
 #include "nsDataHashtable.h"
 #include "harfbuzz/hb.h"
 #include "mozilla/gfx/2D.h"
 #include "nsColor.h"
+#include "mozilla/ServoUtils.h"
 
 typedef struct _cairo cairo_t;
 typedef struct _cairo_scaled_font cairo_scaled_font_t;
 //typedef struct gr_face            gr_face;
 
 #ifdef DEBUG
 #include <stdio.h>
 #endif
@@ -250,22 +251,51 @@ struct FontCacheSizes {
     FontCacheSizes()
         : mFontInstances(0), mShapedWords(0)
     { }
 
     size_t mFontInstances; // memory used by instances of gfxFont subclasses
     size_t mShapedWords; // memory used by the per-font shapedWord caches
 };
 
-class gfxFontCache final : public nsExpirationTracker<gfxFont,3> {
+class gfxFontCacheExpirationTracker
+    : public ExpirationTrackerImpl<gfxFont, 3,
+                                   ::detail::PlaceholderLock,
+                                   ::detail::PlaceholderAutoLock>
+{
+protected:
+    typedef ::detail::PlaceholderLock Lock;
+    typedef ::detail::PlaceholderAutoLock AutoLock;
+
+    Lock mLock;
+
+    AutoLock FakeLock()
+    {
+        return AutoLock(mLock);
+    }
+
+    Lock& GetMutex() override
+    {
+        mozilla::AssertIsMainThreadOrServoFontMetricsLocked();
+        return mLock;
+    }
+
 public:
-    enum {
-        FONT_TIMEOUT_SECONDS = 10,
-        SHAPED_WORD_TIMEOUT_SECONDS = 60
-    };
+    enum { FONT_TIMEOUT_SECONDS = 10 };
+
+    gfxFontCacheExpirationTracker(nsIEventTarget* aEventTarget)
+        : ExpirationTrackerImpl<gfxFont, 3, Lock, AutoLock>(
+            FONT_TIMEOUT_SECONDS * 1000, "gfxFontCache", aEventTarget)
+    {
+    }
+};
+
+class gfxFontCache final : private gfxFontCacheExpirationTracker {
+public:
+    enum { SHAPED_WORD_TIMEOUT_SECONDS = 60 };
 
     explicit gfxFontCache(nsIEventTarget* aEventTarget);
     ~gfxFontCache();
 
     /*
      * Get the global gfxFontCache.  You must call Init() before
      * calling this method --- the result will not be null.
      */
@@ -289,36 +319,42 @@ public:
     // cache with the same key; we'll forget about the old one.
     void AddNew(gfxFont *aFont);
 
     // The font's refcount has gone to zero; give ownership of it to
     // the cache. We delete it if it's not acquired again after a certain
     // amount of time.
     void NotifyReleased(gfxFont *aFont);
 
-    // This gets called when the timeout has expired on a zero-refcount
-    // font; we just delete it.
-    virtual void NotifyExpired(gfxFont *aFont) override;
-
     // Cleans out the hashtable and removes expired fonts waiting for cleanup.
     // Other gfxFont objects may be still in use but they will be pushed
     // into the expiration queues and removed.
     void Flush() {
         mFonts.Clear();
         AgeAllGenerations();
     }
 
     void FlushShapedWordCaches();
     void NotifyGlyphsChanged();
 
     void AddSizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                 FontCacheSizes* aSizes) const;
     void AddSizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf,
                                 FontCacheSizes* aSizes) const;
 
+    void AgeAllGenerations()
+    {
+        AgeAllGenerationsLocked(FakeLock());
+    }
+
+    void RemoveObject(gfxFont* aFont)
+    {
+        RemoveObjectLocked(aFont, FakeLock());
+    }
+
 protected:
     class MemoryReporter final : public nsIMemoryReporter
     {
         ~MemoryReporter() {}
     public:
         NS_DECL_ISUPPORTS
         NS_DECL_NSIMEMORYREPORTER
     };
@@ -328,16 +364,30 @@ protected:
         : public nsIObserver
     {
         ~Observer() {}
     public:
         NS_DECL_ISUPPORTS
         NS_DECL_NSIOBSERVER
     };
 
+    nsresult AddObject(gfxFont* aFont)
+    {
+        return AddObjectLocked(aFont, FakeLock());
+    }
+
+    // This gets called when the timeout has expired on a zero-refcount
+    // font; we just delete it.
+    virtual void NotifyExpiredLocked(gfxFont* aFont, const AutoLock&) override
+    {
+        NotifyExpired(aFont);
+    }
+
+    void NotifyExpired(gfxFont* aFont);
+
     void DestroyFont(gfxFont *aFont);
 
     static gfxFontCache *gGlobalCache;
 
     struct MOZ_STACK_CLASS Key {
         const gfxFontEntry* mFontEntry;
         const gfxFontStyle* mStyle;
         const gfxCharacterMap* mUnicodeRangeMap;