Bug 1109283 - Handle failure of nsExpirationTracker::AddObject in the SurfaceCache. r=dholbert
authorSeth Fowler <seth@mozilla.com>
Wed, 10 Dec 2014 02:53:47 -0800
changeset 219069 6bfaf3bde1a00cc8e5d02b406c2dd1d8af8052bf
parent 219068 28545193d61d93069c37816dbfd7a8b1eb441641
child 219070 411d617e59a0f598a8246d9e4a82659624a1f642
push id27954
push userryanvm@gmail.com
push dateWed, 10 Dec 2014 21:10:24 +0000
treeherdermozilla-central@0cf461e62ce5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1109283
milestone37.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 1109283 - Handle failure of nsExpirationTracker::AddObject in the SurfaceCache. r=dholbert
image/src/SurfaceCache.cpp
--- a/image/src/SurfaceCache.cpp
+++ b/image/src/SurfaceCache.cpp
@@ -7,16 +7,17 @@
  * SurfaceCache is a service for caching temporary surfaces in imagelib.
  */
 
 #include "SurfaceCache.h"
 
 #include <algorithm>
 #include "mozilla/Attributes.h"  // for MOZ_THIS_IN_INITIALIZER_LIST
 #include "mozilla/DebugOnly.h"
+#include "mozilla/Likely.h"
 #include "mozilla/Move.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/StaticPtr.h"
 #include "nsIMemoryReporter.h"
 #include "gfx2DGlue.h"
 #include "gfxPattern.h"  // Workaround for flaw in bug 921753 part 2.
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
@@ -380,33 +381,42 @@ public:
 
     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);
     }
   }
 
   void StopTracking(CachedSurface* aSurface)
   {
     MOZ_ASSERT(aSurface, "Should have a surface");
     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 {
-      mExpirationTracker.RemoveObject(aSurface);
+      if (MOZ_LIKELY(aSurface->GetExpirationState()->IsTracked())) {
+        mExpirationTracker.RemoveObject(aSurface);
+      } else {
+        // Our call to AddObject must have failed in StartTracking; most likely
+        // we're in XPCOM shutdown right now.
+        NS_WARNING("Not expiration-tracking an unlocked surface!");
+      }
+
       DebugOnly<bool> foundInCosts = mCosts.RemoveElementSorted(costEntry);
       MOZ_ASSERT(foundInCosts, "Lost track of costs for this surface");
     }
 
     mAvailableCost += costEntry.GetCost();
     MOZ_ASSERT(mAvailableCost <= mMaxCost,
                "More available cost than we started with");
   }