Bug 1335045 - Make SurfaceCache mutex static to robustly control access to the image cache. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Tue, 31 Jan 2017 07:41:14 -0500
changeset 360859 deb00e365c842e596a870f66f437590ec18079a9
parent 360835 6accce6808bcecf24d035c5a7e9a78fe13a28ce4
child 360860 e807d24e9b10c0b78c63e8a597e329445c1d4bc2
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1335045
milestone54.0a1
Bug 1335045 - Make SurfaceCache mutex static to robustly control access to the image cache. r=tnikkel
image/SurfaceCache.cpp
--- a/image/SurfaceCache.cpp
+++ b/image/SurfaceCache.cpp
@@ -10,19 +10,19 @@
 #include "SurfaceCache.h"
 
 #include <algorithm>
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Likely.h"
 #include "mozilla/Move.h"
-#include "mozilla/Mutex.h"
 #include "mozilla/Pair.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/Tuple.h"
 #include "nsIMemoryReporter.h"
 #include "gfx2DGlue.h"
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "imgFrame.h"
 #include "Image.h"
@@ -50,16 +50,19 @@ class SurfaceCacheImpl;
 
 ///////////////////////////////////////////////////////////////////////////////
 // Static Data
 ///////////////////////////////////////////////////////////////////////////////
 
 // The single surface cache instance.
 static StaticRefPtr<SurfaceCacheImpl> sInstance;
 
+// The mutex protecting the surface cache.
+static StaticMutex sInstanceMutex;
+
 ///////////////////////////////////////////////////////////////////////////////
 // SurfaceCache Implementation
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * Cost models the cost of storing a surface in the cache. Right now, this is
  * simply an estimate of the size of the surface in bytes, but in the future it
  * may be worth taking into account the cost of rematerializing the surface as
@@ -386,17 +389,16 @@ class SurfaceCacheImpl final : public ns
 public:
   NS_DECL_ISUPPORTS
 
   SurfaceCacheImpl(uint32_t aSurfaceCacheExpirationTimeMS,
                    uint32_t aSurfaceCacheDiscardFactor,
                    uint32_t aSurfaceCacheSize)
     : mExpirationTracker(aSurfaceCacheExpirationTimeMS)
     , mMemoryPressureObserver(new MemoryPressureObserver)
-    , mMutex("SurfaceCache")
     , mDiscardFactor(aSurfaceCacheDiscardFactor)
     , mMaxCost(aSurfaceCacheSize)
     , mAvailableCost(aSurfaceCacheSize)
     , mLockedCost(0)
     , mOverflowCount(0)
   {
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (os) {
@@ -413,18 +415,16 @@ private:
     }
 
     UnregisterWeakMemoryReporter(this);
   }
 
 public:
   void InitMemoryReporter() { RegisterWeakMemoryReporter(this); }
 
-  Mutex& GetMutex() { return mMutex; }
-
   InsertOutcome Insert(NotNull<ISurfaceProvider*> aProvider,
                        bool                       aSetAvailable)
   {
     // 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(),
@@ -781,17 +781,17 @@ public:
     StartTracking(aSurface);
   }
 
   NS_IMETHOD
   CollectReports(nsIHandleReportCallback* aHandleReport,
                  nsISupports*             aData,
                  bool                     aAnonymize) override
   {
-    MutexAutoLock lock(mMutex);
+    StaticMutexAutoLock lock(sInstanceMutex);
 
     // We have explicit memory reporting for the surface cache which is more
     // accurate than the cost metrics we report here, but these metrics are
     // still useful to report, since they control the cache's behavior.
     MOZ_COLLECT_REPORT(
       "imagelib-surface-cache-estimated-total",
       KIND_OTHER, UNITS_BYTES, (mMaxCost - mAvailableCost),
 "Estimated total memory used by the imagelib surface cache.");
@@ -889,48 +889,47 @@ private:
     explicit SurfaceTracker(uint32_t aSurfaceCacheExpirationTimeMS)
       : nsExpirationTracker<CachedSurface, 2>(aSurfaceCacheExpirationTimeMS,
                                               "SurfaceTracker")
     { }
 
   protected:
     virtual void NotifyExpired(CachedSurface* aSurface) override
     {
+      StaticMutexAutoLock lock(sInstanceMutex);
       if (sInstance) {
-        MutexAutoLock lock(sInstance->GetMutex());
         sInstance->Remove(WrapNotNull(aSurface));
       }
     }
   };
 
   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) {
-        MutexAutoLock lock(sInstance->GetMutex());
         sInstance->DiscardForMemoryPressure();
       }
       return NS_OK;
     }
 
   private:
     virtual ~MemoryPressureObserver() { }
   };
 
   nsTArray<CostEntry>                     mCosts;
   nsRefPtrHashtable<nsPtrHashKey<Image>,
     ImageSurfaceCache> mImageCaches;
   SurfaceTracker                          mExpirationTracker;
   RefPtr<MemoryPressureObserver>        mMemoryPressureObserver;
-  Mutex                                   mMutex;
   const uint32_t                          mDiscardFactor;
   const Cost                              mMaxCost;
   Cost                                    mAvailableCost;
   Cost                                    mLockedCost;
   size_t                                  mOverflowCount;
 };
 
 NS_IMPL_ISUPPORTS(SurfaceCacheImpl, nsIMemoryReporter)
@@ -994,151 +993,154 @@ SurfaceCache::Initialize()
                                    surfaceCacheDiscardFactor,
                                    finalSurfaceCacheSizeBytes);
   sInstance->InitMemoryReporter();
 }
 
 /* static */ void
 SurfaceCache::Shutdown()
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(sInstance, "No singleton - was Shutdown() called twice?");
   sInstance = nullptr;
 }
 
 /* static */ LookupResult
 SurfaceCache::Lookup(const ImageKey         aImageKey,
                      const SurfaceKey&      aSurfaceKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return LookupResult(MatchType::NOT_FOUND);
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->Lookup(aImageKey, aSurfaceKey);
 }
 
 /* static */ LookupResult
 SurfaceCache::LookupBestMatch(const ImageKey         aImageKey,
                               const SurfaceKey&      aSurfaceKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return LookupResult(MatchType::NOT_FOUND);
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->LookupBestMatch(aImageKey, aSurfaceKey);
 }
 
 /* static */ InsertOutcome
 SurfaceCache::Insert(NotNull<ISurfaceProvider*> aProvider)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return InsertOutcome::FAILURE;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->Insert(aProvider, /* aSetAvailable = */ false);
 }
 
 /* static */ bool
 SurfaceCache::CanHold(const IntSize& aSize, uint32_t aBytesPerPixel /* = 4 */)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return false;
   }
 
   Cost cost = ComputeCost(aSize, aBytesPerPixel);
   return sInstance->CanHold(cost);
 }
 
 /* static */ bool
 SurfaceCache::CanHold(size_t aSize)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return false;
   }
 
   return sInstance->CanHold(aSize);
 }
 
 /* static */ void
 SurfaceCache::SurfaceAvailable(NotNull<ISurfaceProvider*> aProvider)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   sInstance->SurfaceAvailable(aProvider);
 }
 
 /* static */ void
 SurfaceCache::LockImage(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     return sInstance->LockImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::UnlockImage(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     return sInstance->UnlockImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::UnlockEntries(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     return sInstance->UnlockEntries(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::RemoveImage(const ImageKey aImageKey)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     sInstance->RemoveImage(aImageKey);
   }
 }
 
 /* static */ void
 SurfaceCache::DiscardAll()
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (sInstance) {
-    MutexAutoLock lock(sInstance->GetMutex());
     sInstance->DiscardAll();
   }
 }
 
 /* static */ void
 SurfaceCache::CollectSizeOfSurfaces(const ImageKey                  aImageKey,
                                     nsTArray<SurfaceMemoryCounter>& aCounters,
                                     MallocSizeOf                    aMallocSizeOf)
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->CollectSizeOfSurfaces(aImageKey, aCounters, aMallocSizeOf);
 }
 
 /* static */ size_t
 SurfaceCache::MaximumCapacity()
 {
+  StaticMutexAutoLock lock(sInstanceMutex);
   if (!sInstance) {
     return 0;
   }
 
-  MutexAutoLock lock(sInstance->GetMutex());
   return sInstance->MaximumCapacity();
 }
 
 } // namespace image
 } // namespace mozilla