Bug 711901 - When possible, measure, don't compute, the size of imgFrame::mImageSurface. r=joedrew.
authorNicholas Nethercote <nnethercote@mozilla.com>
Mon, 26 Nov 2012 16:29:56 -0800
changeset 114327 8f83993bd9023c96928e89b8182da491c999ac51
parent 114326 50373599d928e4f17e9ab052457efec0cf65e88c
child 114328 3edb5bb92461d20787e0454124a33fadc70f149b
push id23913
push useremorley@mozilla.com
push dateWed, 28 Nov 2012 17:11:31 +0000
treeherdermozilla-central@17c267a881cf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoedrew
bugs711901
milestone20.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 711901 - When possible, measure, don't compute, the size of imgFrame::mImageSurface. r=joedrew.
gfx/thebes/gfxASurface.cpp
gfx/thebes/gfxASurface.h
gfx/thebes/gfxImageSurface.cpp
gfx/thebes/gfxImageSurface.h
image/src/imgFrame.cpp
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -644,16 +644,29 @@ void
 gfxASurface::RecordMemoryFreed()
 {
     if (mBytesRecorded) {
         RecordMemoryUsedForSurfaceType(GetType(), -mBytesRecorded);
         mBytesRecorded = 0;
     }
 }
 
+size_t
+gfxASurface::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+    // We don't measure mSurface because cairo doesn't allow it.
+    return 0;
+}
+
+size_t
+gfxASurface::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+}
+
 #ifdef MOZ_DUMP_IMAGES
 void
 gfxASurface::WriteAsPNG(const char* aFile)
 {
     FILE *file = fopen(aFile, "wb");
     if (file) {
       WriteAsPNG_internal(file, true);
       fclose(file);
--- a/gfx/thebes/gfxASurface.h
+++ b/gfx/thebes/gfxASurface.h
@@ -192,16 +192,19 @@ public:
      * in which case the value that was recorded for this surface will
      * be freed.
      */
     void RecordMemoryUsed(int32_t aBytes);
     void RecordMemoryFreed();
 
     virtual int32_t KnownMemoryUsed() { return mBytesRecorded; }
 
+    virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+    virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const;
+
     /**
      * The memory used by this surface (as reported by KnownMemoryUsed()) can
      * either live in this process's heap, in this process but outside the
      * heap, or in another process altogether.
      */
     enum MemoryLocation {
       MEMORY_IN_PROCESS_HEAP,
       MEMORY_IN_PROCESS_NONHEAP,
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -169,16 +169,32 @@ gfxImageSurface::ComputeStride(const gfx
         stride = aSize.width * 4;
     }
 
     stride = ((stride + 3) / 4) * 4;
 
     return stride;
 }
 
+size_t
+gfxImageSurface::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+    size_t n = gfxASurface::SizeOfExcludingThis(aMallocSizeOf);
+    if (mOwnsData) {
+        n += aMallocSizeOf(mData);
+    }
+    return n;
+}
+
+size_t
+gfxImageSurface::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+{
+    return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
+}
+
 // helper function for the CopyFrom methods
 static void
 CopyForStride(unsigned char* aDest, unsigned char* aSrc, const gfxIntSize& aSize, long aDestStride, long aSrcStride)
 {
     if (aDestStride == aSrcStride) {
         memcpy (aDest, aSrc, aSrcStride * aSize.height);
     } else {
         int lineSize = NS_MIN(aDestStride, aSrcStride);
--- a/gfx/thebes/gfxImageSurface.h
+++ b/gfx/thebes/gfxImageSurface.h
@@ -88,16 +88,22 @@ public:
 
     virtual already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
     /** See gfxASurface.h. */
     virtual void MovePixels(const nsIntRect& aSourceRect,
                             const nsIntPoint& aDestTopLeft) MOZ_OVERRIDE;
 
     static long ComputeStride(const gfxIntSize&, gfxImageFormat);
+
+    virtual size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+        MOZ_OVERRIDE;
+    virtual size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
+        MOZ_OVERRIDE;
+
 protected:
     gfxImageSurface();
     void InitWithData(unsigned char *aData, const gfxIntSize& aSize,
                       long aStride, gfxImageFormat aFormat);
     void InitFromSurface(cairo_surface_t *csurf);
     long ComputeStride() const { return ComputeStride(mSize, mFormat); }
 
 
--- a/image/src/imgFrame.cpp
+++ b/image/src/imgFrame.cpp
@@ -785,49 +785,59 @@ bool imgFrame::GetCompositingFailed() co
   return mCompositingFailed;
 }
 
 void imgFrame::SetCompositingFailed(bool val)
 {
   mCompositingFailed = val;
 }
 
+// If |aLocation| indicates this is heap memory, we try to measure things with
+// |aMallocSizeOf|.  If that fails (because the platform doesn't support it) or
+// it's non-heap memory, we fall back to computing the size analytically.
 size_t
 imgFrame::SizeOfExcludingThisWithComputedFallbackIfHeap(gfxASurface::MemoryLocation aLocation, nsMallocSizeOfFun aMallocSizeOf) const
 {
   // aMallocSizeOf is only used if aLocation==MEMORY_IN_PROCESS_HEAP.  It
   // should be NULL otherwise.
   NS_ABORT_IF_FALSE(
     (aLocation == gfxASurface::MEMORY_IN_PROCESS_HEAP &&  aMallocSizeOf) ||
     (aLocation != gfxASurface::MEMORY_IN_PROCESS_HEAP && !aMallocSizeOf),
     "mismatch between aLocation and aMallocSizeOf");
 
   size_t n = 0;
 
   if (mPalettedImageData && aLocation == gfxASurface::MEMORY_IN_PROCESS_HEAP) {
-    size_t usable = aMallocSizeOf(mPalettedImageData);
-    if (!usable) {
-      usable = GetImageDataLength() + PaletteDataLength();
+    size_t n2 = aMallocSizeOf(mPalettedImageData);
+    if (n2 == 0) {
+      n2 = GetImageDataLength() + PaletteDataLength();
     }
-    n += usable;
+    n += n2;
   }
 
   // XXX: should pass aMallocSizeOf here.  See bug 723827.
 #ifdef USE_WIN_SURFACE
   if (mWinSurface && aLocation == mWinSurface->GetMemoryLocation()) {
     n += mWinSurface->KnownMemoryUsed();
   } else
 #endif
 #ifdef XP_MACOSX
   if (mQuartzSurface && aLocation == gfxASurface::MEMORY_IN_PROCESS_HEAP) {
     n += mSize.width * mSize.height * 4;
   } else
 #endif
   if (mImageSurface && aLocation == mImageSurface->GetMemoryLocation()) {
-    n += mImageSurface->KnownMemoryUsed();
+    size_t n2 = 0;
+    if (aLocation == gfxASurface::MEMORY_IN_PROCESS_HEAP) { // HEAP: measure
+      n2 = mImageSurface->SizeOfIncludingThis(aMallocSizeOf);
+    }
+    if (n2 == 0) {  // non-HEAP or computed fallback for HEAP
+      n2 = mImageSurface->KnownMemoryUsed();
+    }
+    n += n2;
   }
 
   if (mOptSurface && aLocation == mOptSurface->GetMemoryLocation()) {
     n += mOptSurface->KnownMemoryUsed();
   }
 
   return n;
 }