Bug 1350177 - Part 3: Refactor SurfaceCache with ExpirationTrackerImpl. r=froydnj,aosmond
authorBevis Tseng <btseng@mozilla.com>
Mon, 27 Mar 2017 21:47:23 -0400
changeset 399420 3ee3add6393dd5923d91328ba47f0a6f55f33f41
parent 399419 8f496e855383001c787bc218281594abafb7bf2b
child 399421 899fd5a47a205adc5ce28ea57e8426a299c79dd3
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)
reviewersfroydnj, aosmond
bugs1350177
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 1350177 - Part 3: Refactor SurfaceCache with ExpirationTrackerImpl. r=froydnj,aosmond Always acquire StaticMutexAutoLock for the use of ExpirationTrackerImpl.
image/SurfaceCache.cpp
--- a/image/SurfaceCache.cpp
+++ b/image/SurfaceCache.cpp
@@ -418,30 +418,32 @@ private:
 
     UnregisterWeakMemoryReporter(this);
   }
 
 public:
   void InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
 
   InsertOutcome Insert(NotNull<ISurfaceProvider*> aProvider,
-                       bool                       aSetAvailable)
+                       bool                       aSetAvailable,
+                       const StaticMutexAutoLock& aAutoLock)
   {
     // If this is a duplicate surface, refuse to replace the original.
     // XXX(seth): Calling Lookup() and then RemoveEntry() does the lookup
     // twice. We'll make this more efficient in bug 1185137.
     LookupResult result = Lookup(aProvider->GetImageKey(),
                                  aProvider->GetSurfaceKey(),
+                                 aAutoLock,
                                  /* aMarkUsed = */ false);
     if (MOZ_UNLIKELY(result)) {
       return InsertOutcome::FAILURE_ALREADY_PRESENT;
     }
 
     if (result.Type() == MatchType::PENDING) {
-      RemoveEntry(aProvider->GetImageKey(), aProvider->GetSurfaceKey());
+      RemoveEntry(aProvider->GetImageKey(), aProvider->GetSurfaceKey(), aAutoLock);
     }
 
     MOZ_ASSERT(result.Type() == MatchType::NOT_FOUND ||
                result.Type() == MatchType::PENDING,
                "A LookupResult with no surface should be NOT_FOUND or PENDING");
 
     // If this is bigger than we can hold after discarding everything we can,
     // refuse to cache it.
@@ -451,17 +453,17 @@ public:
       return InsertOutcome::FAILURE;
     }
 
     // Remove elements in order of cost until we can fit this in the cache. Note
     // that locked surfaces aren't in mCosts, so we never remove them here.
     while (cost > mAvailableCost) {
       MOZ_ASSERT(!mCosts.IsEmpty(),
                  "Removed everything and it still won't fit");
-      Remove(mCosts.LastElement().Surface());
+      Remove(mCosts.LastElement().Surface(), aAutoLock);
     }
 
     // Locate the appropriate per-image cache. If there's not an existing cache
     // for this image, create it.
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aProvider->GetImageKey());
     if (!cache) {
       cache = new ImageSurfaceCache;
       mImageCaches.Put(aProvider->GetImageKey(), cache);
@@ -483,75 +485,78 @@ public:
       if (!surface->IsLocked()) {
         return InsertOutcome::FAILURE;
       }
     }
 
     // Insert.
     MOZ_ASSERT(cost <= mAvailableCost, "Inserting despite too large a cost");
     cache->Insert(surface);
-    StartTracking(surface);
+    StartTracking(surface, aAutoLock);
 
     return InsertOutcome::SUCCESS;
   }
 
-  void Remove(NotNull<CachedSurface*> aSurface)
+  void Remove(NotNull<CachedSurface*> aSurface,
+              const StaticMutexAutoLock& aAutoLock)
   {
     ImageKey imageKey = aSurface->GetImageKey();
 
     RefPtr<ImageSurfaceCache> cache = GetImageCache(imageKey);
     MOZ_ASSERT(cache, "Shouldn't try to remove a surface with no image cache");
 
     // If the surface was not a placeholder, tell its image that we discarded it.
     if (!aSurface->IsPlaceholder()) {
       static_cast<Image*>(imageKey)->OnSurfaceDiscarded(aSurface->GetSurfaceKey());
     }
 
-    StopTracking(aSurface);
+    StopTracking(aSurface, aAutoLock);
     cache->Remove(aSurface);
 
     // Remove the per-image cache if it's unneeded now. (Keep it if the image is
     // locked, since the per-image cache is where we store that state.)
     if (cache->IsEmpty() && !cache->IsLocked()) {
       mImageCaches.Remove(imageKey);
     }
   }
 
-  void StartTracking(NotNull<CachedSurface*> aSurface)
+  void StartTracking(NotNull<CachedSurface*> aSurface,
+                     const StaticMutexAutoLock& aAutoLock)
   {
     CostEntry costEntry = aSurface->GetCostEntry();
     MOZ_ASSERT(costEntry.GetCost() <= mAvailableCost,
                "Cost too large and the caller didn't catch it");
 
     mAvailableCost -= costEntry.GetCost();
 
     if (aSurface->IsLocked()) {
       mLockedCost += costEntry.GetCost();
       MOZ_ASSERT(mLockedCost <= mMaxCost, "Locked more than we can hold?");
     } else {
       mCosts.InsertElementSorted(costEntry);
       // This may fail during XPCOM shutdown, so we need to ensure the object is
       // tracked before calling RemoveObject in StopTracking.
-      mExpirationTracker.AddObject(aSurface);
+      mExpirationTracker.AddObjectLocked(aSurface, aAutoLock);
     }
   }
 
-  void StopTracking(NotNull<CachedSurface*> aSurface)
+  void StopTracking(NotNull<CachedSurface*> aSurface,
+                    const StaticMutexAutoLock& aAutoLock)
   {
     CostEntry costEntry = aSurface->GetCostEntry();
 
     if (aSurface->IsLocked()) {
       MOZ_ASSERT(mLockedCost >= costEntry.GetCost(), "Costs don't balance");
       mLockedCost -= costEntry.GetCost();
       // XXX(seth): It'd be nice to use an O(log n) lookup here. This is O(n).
       MOZ_ASSERT(!mCosts.Contains(costEntry),
                  "Shouldn't have a cost entry for a locked surface");
     } else {
       if (MOZ_LIKELY(aSurface->GetExpirationState()->IsTracked())) {
-        mExpirationTracker.RemoveObject(aSurface);
+        mExpirationTracker.RemoveObjectLocked(aSurface, aAutoLock);
       } else {
         // Our call to AddObject must have failed in StartTracking; most likely
         // we're in XPCOM shutdown right now.
         NS_ASSERTION(ShutdownTracker::ShutdownHasStarted(),
                      "Not expiration-tracking an unlocked surface!");
       }
 
       DebugOnly<bool> foundInCosts = mCosts.RemoveElementSorted(costEntry);
@@ -560,16 +565,17 @@ public:
 
     mAvailableCost += costEntry.GetCost();
     MOZ_ASSERT(mAvailableCost <= mMaxCost,
                "More available cost than we started with");
   }
 
   LookupResult Lookup(const ImageKey    aImageKey,
                       const SurfaceKey& aSurfaceKey,
+                      const StaticMutexAutoLock& aAutoLock,
                       bool aMarkUsed = true)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache) {
       // No cached surfaces for this image.
       return LookupResult(MatchType::NOT_FOUND);
     }
 
@@ -582,31 +588,32 @@ public:
     if (surface->IsPlaceholder()) {
       return LookupResult(MatchType::PENDING);
     }
 
     DrawableSurface drawableSurface = surface->GetDrawableSurface();
     if (!drawableSurface) {
       // The surface was released by the operating system. Remove the cache
       // entry as well.
-      Remove(WrapNotNull(surface));
+      Remove(WrapNotNull(surface), aAutoLock);
       return LookupResult(MatchType::NOT_FOUND);
     }
 
     if (aMarkUsed) {
-      MarkUsed(WrapNotNull(surface), WrapNotNull(cache));
+      MarkUsed(WrapNotNull(surface), WrapNotNull(cache), aAutoLock);
     }
 
     MOZ_ASSERT(surface->GetSurfaceKey() == aSurfaceKey,
                "Lookup() not returning an exact match?");
     return LookupResult(Move(drawableSurface), MatchType::EXACT);
   }
 
   LookupResult LookupBestMatch(const ImageKey         aImageKey,
-                               const SurfaceKey&      aSurfaceKey)
+                               const SurfaceKey&      aSurfaceKey,
+                               const StaticMutexAutoLock& aAutoLock)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache) {
       // No cached surfaces for this image.
       return LookupResult(MatchType::NOT_FOUND);
     }
 
     // Repeatedly look up the best match, trying again if the resulting surface
@@ -627,166 +634,168 @@ public:
 
       drawableSurface = surface->GetDrawableSurface();
       if (drawableSurface) {
         break;
       }
 
       // The surface was released by the operating system. Remove the cache
       // entry as well.
-      Remove(WrapNotNull(surface));
+      Remove(WrapNotNull(surface), aAutoLock);
     }
 
     MOZ_ASSERT_IF(matchType == MatchType::EXACT,
                   surface->GetSurfaceKey() == aSurfaceKey);
     MOZ_ASSERT_IF(matchType == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND ||
                   matchType == MatchType::SUBSTITUTE_BECAUSE_PENDING,
       surface->GetSurfaceKey().SVGContext() == aSurfaceKey.SVGContext() &&
       surface->GetSurfaceKey().Playback() == aSurfaceKey.Playback() &&
       surface->GetSurfaceKey().Flags() == aSurfaceKey.Flags());
 
     if (matchType == MatchType::EXACT) {
-      MarkUsed(WrapNotNull(surface), WrapNotNull(cache));
+      MarkUsed(WrapNotNull(surface), WrapNotNull(cache), aAutoLock);
     }
 
     return LookupResult(Move(drawableSurface), matchType);
   }
 
   bool CanHold(const Cost aCost) const
   {
     return aCost <= mMaxCost;
   }
 
   size_t MaximumCapacity() const
   {
     return size_t(mMaxCost);
   }
 
-  void SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider)
+  void SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider,
+                        const StaticMutexAutoLock& aAutoLock)
   {
     if (!aProvider->Availability().IsPlaceholder()) {
       MOZ_ASSERT_UNREACHABLE("Calling SurfaceAvailable on non-placeholder");
       return;
     }
 
     // Reinsert the provider, requesting that Insert() mark it available. This
     // may or may not succeed, depending on whether some other decoder has
     // beaten us to the punch and inserted a non-placeholder version of this
     // surface first, but it's fine either way.
     // XXX(seth): This could be implemented more efficiently; we should be able
     // to just update our data structures without reinserting.
-    Insert(aProvider, /* aSetAvailable = */ true);
+    Insert(aProvider, /* aSetAvailable = */ true, aAutoLock);
   }
 
   void LockImage(const ImageKey aImageKey)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache) {
       cache = new ImageSurfaceCache;
       mImageCaches.Put(aImageKey, cache);
     }
 
     cache->SetLocked(true);
 
     // We don't relock this image's existing surfaces right away; instead, the
     // image should arrange for Lookup() to touch them if they are still useful.
   }
 
-  void UnlockImage(const ImageKey aImageKey)
+  void UnlockImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache || !cache->IsLocked()) {
       return;  // Already unlocked.
     }
 
     cache->SetLocked(false);
-    DoUnlockSurfaces(WrapNotNull(cache), /* aStaticOnly = */ false);
+    DoUnlockSurfaces(WrapNotNull(cache), /* aStaticOnly = */ false, aAutoLock);
   }
 
-  void UnlockEntries(const ImageKey aImageKey)
+  void UnlockEntries(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache || !cache->IsLocked()) {
       return;  // Already unlocked.
     }
 
     // (Note that we *don't* unlock the per-image cache here; that's the
     // difference between this and UnlockImage.)
     DoUnlockSurfaces(WrapNotNull(cache),
-      /* aStaticOnly = */ !gfxPrefs::ImageMemAnimatedDiscardable());
+      /* aStaticOnly = */ !gfxPrefs::ImageMemAnimatedDiscardable(), aAutoLock);
   }
 
-  void RemoveImage(const ImageKey aImageKey)
+  void RemoveImage(const ImageKey aImageKey, const StaticMutexAutoLock& aAutoLock)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache) {
       return;  // No cached surfaces for this image, so nothing to do.
     }
 
     // Discard all of the cached surfaces for this image.
     // XXX(seth): This is O(n^2) since for each item in the cache we are
     // removing an element from the costs array. Since n is expected to be
     // small, performance should be good, but if usage patterns change we should
     // change the data structure used for mCosts.
     for (auto iter = cache->ConstIter(); !iter.Done(); iter.Next()) {
-      StopTracking(WrapNotNull(iter.UserData()));
+      StopTracking(WrapNotNull(iter.UserData()), aAutoLock);
     }
 
     // The per-image cache isn't needed anymore, so remove it as well.
     // This implicitly unlocks the image if it was locked.
     mImageCaches.Remove(aImageKey);
   }
 
-  void DiscardAll()
+  void DiscardAll(const StaticMutexAutoLock& aAutoLock)
   {
     // Remove in order of cost because mCosts is an array and the other data
     // structures are all hash tables. Note that locked surfaces are not
     // removed, since they aren't present in mCosts.
     while (!mCosts.IsEmpty()) {
-      Remove(mCosts.LastElement().Surface());
+      Remove(mCosts.LastElement().Surface(), aAutoLock);
     }
   }
 
-  void DiscardForMemoryPressure()
+  void DiscardForMemoryPressure(const StaticMutexAutoLock& aAutoLock)
   {
     // Compute our discardable cost. Since locked surfaces aren't discardable,
     // we exclude them.
     const Cost discardableCost = (mMaxCost - mAvailableCost) - mLockedCost;
     MOZ_ASSERT(discardableCost <= mMaxCost, "Discardable cost doesn't add up");
 
     // Our target is to raise our available cost by (1 / mDiscardFactor) of our
     // discardable cost - in other words, we want to end up with about
     // (discardableCost / mDiscardFactor) fewer bytes stored in the surface
     // cache after we're done.
     const Cost targetCost = mAvailableCost + (discardableCost / mDiscardFactor);
 
     if (targetCost > mMaxCost - mLockedCost) {
       MOZ_ASSERT_UNREACHABLE("Target cost is more than we can discard");
-      DiscardAll();
+      DiscardAll(aAutoLock);
       return;
     }
 
     // Discard surfaces until we've reduced our cost to our target cost.
     while (mAvailableCost < targetCost) {
       MOZ_ASSERT(!mCosts.IsEmpty(), "Removed everything and still not done");
-      Remove(mCosts.LastElement().Surface());
+      Remove(mCosts.LastElement().Surface(), aAutoLock);
     }
   }
 
-  void LockSurface(NotNull<CachedSurface*> aSurface)
+  void LockSurface(NotNull<CachedSurface*> aSurface,
+                   const StaticMutexAutoLock& aAutoLock)
   {
     if (aSurface->IsPlaceholder() || aSurface->IsLocked()) {
       return;
     }
 
-    StopTracking(aSurface);
+    StopTracking(aSurface, aAutoLock);
 
     // Lock the surface. This can fail.
     aSurface->SetLocked(true);
-    StartTracking(aSurface);
+    StartTracking(aSurface, aAutoLock);
   }
 
   NS_IMETHOD
   CollectReports(nsIHandleReportCallback* aHandleReport,
                  nsISupports*             aData,
                  bool                     aAnonymize) override
   {
     StaticMutexAutoLock lock(sInstanceMutex);
@@ -843,86 +852,95 @@ private:
   // means that the result would be meaningless: another thread could insert a
   // surface or lock an image at any time.
   bool CanHoldAfterDiscarding(const Cost aCost) const
   {
     return aCost <= mMaxCost - mLockedCost;
   }
 
   void MarkUsed(NotNull<CachedSurface*> aSurface,
-                NotNull<ImageSurfaceCache*> aCache)
+                NotNull<ImageSurfaceCache*> aCache,
+                const StaticMutexAutoLock& aAutoLock)
   {
     if (aCache->IsLocked()) {
-      LockSurface(aSurface);
+      LockSurface(aSurface, aAutoLock);
     } else {
-      mExpirationTracker.MarkUsed(aSurface);
+      mExpirationTracker.MarkUsedLocked(aSurface, aAutoLock);
     }
   }
 
-  void DoUnlockSurfaces(NotNull<ImageSurfaceCache*> aCache, bool aStaticOnly)
+  void DoUnlockSurfaces(NotNull<ImageSurfaceCache*> aCache, bool aStaticOnly,
+                        const StaticMutexAutoLock& aAutoLock)
   {
     // Unlock all the surfaces the per-image cache is holding.
     for (auto iter = aCache->ConstIter(); !iter.Done(); iter.Next()) {
       NotNull<CachedSurface*> surface = WrapNotNull(iter.UserData());
       if (surface->IsPlaceholder() || !surface->IsLocked()) {
         continue;
       }
       if (aStaticOnly && surface->GetSurfaceKey().Playback() != PlaybackType::eStatic) {
         continue;
       }
-      StopTracking(surface);
+      StopTracking(surface, aAutoLock);
       surface->SetLocked(false);
-      StartTracking(surface);
+      StartTracking(surface, aAutoLock);
     }
   }
 
   void RemoveEntry(const ImageKey    aImageKey,
-                   const SurfaceKey& aSurfaceKey)
+                   const SurfaceKey& aSurfaceKey,
+                   const StaticMutexAutoLock& aAutoLock)
   {
     RefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
     if (!cache) {
       return;  // No cached surfaces for this image.
     }
 
     RefPtr<CachedSurface> surface = cache->Lookup(aSurfaceKey);
     if (!surface) {
       return;  // Lookup in the per-image cache missed.
     }
 
-    Remove(WrapNotNull(surface));
+    Remove(WrapNotNull(surface), aAutoLock);
   }
 
-  struct SurfaceTracker : public nsExpirationTracker<CachedSurface, 2>
+  struct SurfaceTracker : public ExpirationTrackerImpl<CachedSurface, 2,
+                                                       StaticMutex,
+                                                       StaticMutexAutoLock>
   {
     explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
-      : nsExpirationTracker<CachedSurface, 2>(aSurfaceCacheExpirationTimeMS,
-                                              "SurfaceTracker")
+      : ExpirationTrackerImpl<CachedSurface, 2,
+                              StaticMutex, StaticMutexAutoLock>(
+          aSurfaceCacheExpirationTimeMS, "SurfaceTracker")
     { }
 
   protected:
-    virtual void NotifyExpired(CachedSurface* aSurface) override
+    void NotifyExpiredLocked(CachedSurface* aSurface,
+                             const StaticMutexAutoLock& aAutoLock) override
     {
-      StaticMutexAutoLock lock(sInstanceMutex);
-      if (sInstance) {
-        sInstance->Remove(WrapNotNull(aSurface));
-      }
+      sInstance->Remove(WrapNotNull(aSurface), aAutoLock);
+    }
+
+    StaticMutex& GetMutex() override
+    {
+      return sInstanceMutex;
     }
   };
 
   struct MemoryPressureObserver : public nsIObserver
   {
     NS_DECL_ISUPPORTS
 
     NS_IMETHOD Observe(nsISupports*,
                        const char* aTopic,
                        const char16_t*) override
     {
       StaticMutexAutoLock lock(sInstanceMutex);
       if (sInstance && strcmp(aTopic, "memory-pressure") == 0) {
-        sInstance->DiscardForMemoryPressure();
+        sInstance->DiscardForMemoryPressure(lock);
       }
       return NS_OK;
     }
 
   private:
     virtual ~MemoryPressureObserver() { }
   };
 
@@ -1014,40 +1032,40 @@ SurfaceCache::Shutdown()
 SurfaceCache::Lookup(const ImageKey         aImageKey,
                      const SurfaceKey&      aSurfaceKey)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return LookupResult(MatchType::NOT_FOUND);
   }
 
-  return sInstance->Lookup(aImageKey, aSurfaceKey);
+  return sInstance->Lookup(aImageKey, aSurfaceKey, lock);
 }
 
 /* static */ LookupResult
 SurfaceCache::LookupBestMatch(const ImageKey         aImageKey,
                               const SurfaceKey&      aSurfaceKey)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return LookupResult(MatchType::NOT_FOUND);
   }
 
-  return sInstance->LookupBestMatch(aImageKey, aSurfaceKey);
+  return sInstance->LookupBestMatch(aImageKey, aSurfaceKey, lock);
 }
 
 /* static */ InsertOutcome
 SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return InsertOutcome::FAILURE;
   }
 
-  return sInstance->Insert(aProvider, /* aSetAvailable = */ false);
+  return sInstance->Insert(aProvider, /* aSetAvailable = */ false, lock);
 }
 
 /* static */ bool
 SurfaceCache::CanHold(const IntSize& aSize, uint32_t aBytesPerPixel /* = 4 */)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return false;
@@ -1071,61 +1089,61 @@ SurfaceCache::CanHold(size_t aSize)
 /* static */ void
 SurfaceCache::SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return;
   }
 
-  sInstance->SurfaceAvailable(aProvider);
+  sInstance->SurfaceAvailable(aProvider, lock);
 }
 
 /* static */ void
 SurfaceCache::LockImage(const ImageKey aImageKey)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
     return sInstance->LockImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::UnlockImage(const ImageKey aImageKey)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    return sInstance->UnlockImage(aImageKey);
+    return sInstance->UnlockImage(aImageKey, lock);
   }
 }
 
 /* static */ void
 SurfaceCache::UnlockEntries(const ImageKey aImageKey)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    return sInstance->UnlockEntries(aImageKey);
+    return sInstance->UnlockEntries(aImageKey, lock);
   }
 }
 
 /* static */ void
 SurfaceCache::RemoveImage(const ImageKey aImageKey)
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    sInstance->RemoveImage(aImageKey);
+    sInstance->RemoveImage(aImageKey, lock);
   }
 }
 
 /* static */ void
 SurfaceCache::DiscardAll()
 {
   StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    sInstance->DiscardAll();
+    sInstance->DiscardAll(lock);
   }
 }
 
 /* static */ void
 SurfaceCache::CollectSizeOfSurfaces(const ImageKey                  aImageKey,
                                     nsTArray<SurfaceMemoryCounter>& aCounters,
                                     MallocSizeOf                    aMallocSizeOf)
 {