--- 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,