imported patch 1072313-printfs.patch
authorGerald Squelart <gsquelart@mozilla.com>
Wed, 16 Sep 2015 22:07:43 +1000 (2015-09-16)
changeset 586243 8dffaf0d2acf564f09c11c5dbfafc7e815062ef0
parent 585756 3e8dde8f8c174cce2c0b65c951808f88e35d1875
child 586244 82a2107cd01e8a6630e8196f04816685b4a9f7b6
push id88585
push usergsquelart@mozilla.com
push dateWed, 16 Sep 2015 12:08:04 +0000 (2015-09-16)
treeherdertry@82a2107cd01e [default view] [failures only]
bugs1072313
milestone43.0a1
imported patch 1072313-printfs.patch
gfx/2d/MacIOSurface.cpp
gfx/2d/MacIOSurface.h
--- a/gfx/2d/MacIOSurface.cpp
+++ b/gfx/2d/MacIOSurface.cpp
@@ -271,16 +271,129 @@ void MacIOSurfaceLib::CloseLibrary() {
   if (sCoreVideoFramework) {
     dlclose(sCoreVideoFramework);
   }
   sIOSurfaceFramework = nullptr;
   sOpenGLFramework = nullptr;
   sCoreVideoFramework = nullptr;
 }
 
+#include "mozilla/Monitor.h"
+#include "mozilla/StackWalk.h"
+#include "nsTArray.h"
+#include <map>
+#include <vector>
+
+typedef nsAutoTArray<void*, 24> AcquisitionState;
+static
+void StackWalkCallback(uint32_t aFrameNumber, void* aPc, void* aSp, void* aClosure)
+{
+  AcquisitionState* state = (AcquisitionState*)aClosure;
+  state->AppendElement(aPc);
+}
+
+void GetStackTrace(AcquisitionState& aState)
+{
+  // Skip this function and the calling function.
+  const uint32_t kSkipFrames = 2;
+
+  aState.Clear();
+
+  // NB: Ignore the return value, there's nothing useful we can do if this
+  //     this fails.
+  MozStackWalk(StackWalkCallback, kSkipFrames, 24, &aState, 0, nullptr);
+}
+
+struct RecordMacIOSurfaces
+{
+  Monitor gMonitor;
+  struct Data
+  {
+    MozRefCountType mRefCount;
+    std::vector<int> mHistory; // +x: refcount after add, -x: refcount after release
+    std::vector<AcquisitionState> mStackHistory;
+  };
+  std::map<const MacIOSurface*, Data> mMacIOSurfaces;
+
+  void add(const MacIOSurface* aSurface, MozRefCountType aCountAfterAdd, AcquisitionState&& aStack)
+  {
+//    fprintf(stderr, "MacIOSurface[%p]::AddRef() - afterwards, refCount=%lu\n",
+//            aSurface, aCountAfterAdd);
+    mMacIOSurfaces[aSurface].mRefCount = aCountAfterAdd;
+    mMacIOSurfaces[aSurface].mHistory.push_back(int(aCountAfterAdd));
+    mMacIOSurfaces[aSurface].mStackHistory.push_back(Move(aStack));
+  }
+
+  void release(const MacIOSurface* aSurface, MozRefCountType aCountBeforeRelease, AcquisitionState&& aStack)
+  {
+//    fprintf(stderr, "MacIOSurface[%p]::Release() - before, refCount=%lu\n",
+//            aSurface, aCountBeforeRelease);
+    if (aCountBeforeRelease == 1) {
+      mMacIOSurfaces.erase(aSurface);
+    } else {
+      mMacIOSurfaces[aSurface].mRefCount = aCountBeforeRelease - 1;
+      mMacIOSurfaces[aSurface].mHistory.push_back(-(int(aCountBeforeRelease) - 1));
+      mMacIOSurfaces[aSurface].mStackHistory.push_back(Move(aStack));
+    }
+  }
+
+  RecordMacIOSurfaces()
+    : gMonitor("RecordMacIOSurface")
+  {
+  }
+  ~RecordMacIOSurfaces()
+  {
+    MonitorAutoLock mon(gMonitor);
+    fprintf(stderr, "~RecordMacIOSurfaces():\n");
+    for (auto it : mMacIOSurfaces) {
+      fprintf(stderr, "- %p: refCount=%lu history:", it.first, it.second.mRefCount);
+      for (auto h : it.second.mHistory) {
+        fprintf(stderr, " %d", h);
+      }
+      fprintf(stderr, "\n");
+      for (int i = 0; i < int(it.second.mHistory.size()); ++i) {
+        int refCount = it.second.mHistory[i];
+        if (refCount > 0) {
+          fprintf(stderr, "%d. AddRef  %d -> %d\n", i, int(refCount) - 1, int(refCount));
+        } else {
+          fprintf(stderr, "%d. Release %d -> %d\n", i, -int(refCount) + 1, -int(refCount));
+        }
+        const AcquisitionState& stack = it.second.mStackHistory[i];
+        MozCodeAddressDetails details;
+        const uint32_t bufferSize = 1024;
+        char buffer[bufferSize];
+        for (uint32_t f = 0; f < stack.Length(); ++f) {
+          void* pc = stack[f];
+          MozDescribeCodeAddress(pc, &details);
+          MozFormatCodeAddressDetails(buffer, bufferSize, f, pc, &details);
+          fprintf(stderr, "%s\n", buffer);
+        }
+      }
+    }
+  }
+};
+static RecordMacIOSurfaces gRecordMacIOSurfaces;
+
+void MacIOSurface::AddRef() const
+{
+  AcquisitionState stack;
+  GetStackTrace(stack);
+  MonitorAutoLock mon(gRecordMacIOSurfaces.gMonitor);
+  mozilla::RefCounted<MacIOSurface>::AddRef();
+  gRecordMacIOSurfaces.add(this, refCount(), Move(stack));
+}
+void MacIOSurface::Release() const
+{
+  AcquisitionState stack;
+  GetStackTrace(stack);
+  MonitorAutoLock mon(gRecordMacIOSurfaces.gMonitor);
+  gRecordMacIOSurfaces.release(this, refCount(), Move(stack));
+  mozilla::RefCounted<MacIOSurface>::Release();
+}
+
 MacIOSurface::MacIOSurface(const void* aIOSurfacePtr,
                            double aContentsScaleFactor, bool aHasAlpha)
   : mIOSurfacePtr(aIOSurfacePtr)
   , mContentsScaleFactor(aContentsScaleFactor)
   , mHasAlpha(aHasAlpha)
 {
   CFRetain(mIOSurfacePtr);
   IncrementUseCount();
--- a/gfx/2d/MacIOSurface.h
+++ b/gfx/2d/MacIOSurface.h
@@ -61,16 +61,20 @@ enum CGContextType {
   CG_CONTEXT_TYPE_IOSURFACE = 8
 };
 
 CGContextType GetContextType(CGContextRef ref);
 
 class MacIOSurface : public mozilla::RefCounted<MacIOSurface> {
 public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(MacIOSurface)
+
+  void AddRef() const;
+  void Release() const;
+
   typedef mozilla::gfx::SourceSurface SourceSurface;
 
   // The usage count of the IOSurface is increased by 1 during the lifetime
   // of the MacIOSurface instance.
   // MacIOSurface holds a reference to the corresponding IOSurface.
 
   static already_AddRefed<MacIOSurface> CreateIOSurface(int aWidth, int aHeight,
                                                              double aContentsScaleFactor = 1.0,