mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Added 'Bloaty' refcounting and memory bloat statistics code
This commit is contained in:
parent
3a7ce2580e
commit
37676fadb0
@ -84,7 +84,7 @@ _class::AddRef(void) \
|
||||
NS_IMETHODIMP_(nsrefcnt) \
|
||||
_class::Release(void) \
|
||||
{ \
|
||||
return fOuter->Release(); \
|
||||
return fOuter->Release(); \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP \
|
||||
@ -98,15 +98,21 @@ NS_IMETHODIMP_(nsrefcnt) \
|
||||
_class::Internal::AddRef(void) \
|
||||
{ \
|
||||
_class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
|
||||
return ++agg->mRefCnt; \
|
||||
NS_PRECONDITION(PRInt32(agg->mRefCnt) >= 0, "illegal refcnt"); \
|
||||
++agg->mRefCnt; \
|
||||
NS_LOG_ADDREF(this, agg->mRefCnt, #_class); \
|
||||
return agg->mRefCnt; \
|
||||
} \
|
||||
\
|
||||
NS_IMETHODIMP_(nsrefcnt) \
|
||||
_class::Internal::Release(void) \
|
||||
{ \
|
||||
_class* agg = (_class*)((char*)(this) - offsetof(_class, fAggregated)); \
|
||||
if (--agg->mRefCnt == 0) { \
|
||||
delete agg; \
|
||||
NS_PRECONDITION(0 != agg->mRefCnt, "dup release"); \
|
||||
--agg->mRefCnt; \
|
||||
NS_LOG_RELEASE(this, agg->mRefCnt, #_class); \
|
||||
if (agg->mRefCnt == 0) { \
|
||||
NS_DELETEXPCOM(agg); \
|
||||
return 0; \
|
||||
} \
|
||||
return agg->mRefCnt; \
|
||||
|
@ -76,6 +76,20 @@ typedef unsigned long nsrefcnt;
|
||||
typedef PRUint32 nsrefcnt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* "Bloaty" is a facility to dump statistics on object allocations and
|
||||
* refcounting. To turn it on, you must define BLOATY in this file, and
|
||||
* rebuild the world. (That seems easier than hacking makefiles to ensure
|
||||
* that environment variables get checked everywhere.)
|
||||
*/
|
||||
#ifdef DEBUG_warrenx
|
||||
#define BLOATY 1
|
||||
#endif
|
||||
|
||||
#ifdef BLOATY
|
||||
#define MOZ_LOG_REFCNT 1
|
||||
#endif
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
/**
|
||||
@ -768,10 +782,10 @@ NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
|
||||
|
||||
#ifdef MOZ_LOG_REFCNT
|
||||
#define NS_LOG_ADDREF(_ptr, _refcnt, _class) \
|
||||
nsTraceRefcnt::LogAddRef((_ptr), (_refcnt), (_class))
|
||||
nsTraceRefcnt::LogAddRef((_ptr), (_refcnt), (_class), (sizeof(*this)))
|
||||
|
||||
#define NS_LOG_RELEASE(_ptr, _refcnt, _class) \
|
||||
nsTraceRefcnt::LogRelease((_ptr), (_refcnt), (_class))
|
||||
nsTraceRefcnt::LogRelease((_ptr), (_refcnt), (_class), (sizeof(*this)))
|
||||
|
||||
#else
|
||||
#define NS_LOG_ADDREF(_ptr, _refcnt, _class)
|
||||
|
@ -16,6 +16,7 @@
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "prprf.h"
|
||||
@ -54,6 +55,119 @@ static PRLock* gTraceLock;
|
||||
|
||||
static PRLogModuleInfo* gTraceRefcntLog;
|
||||
|
||||
#ifdef BLOATY
|
||||
#include "plhash.h"
|
||||
#include <math.h>
|
||||
|
||||
PLHashTable* gBloatView;
|
||||
|
||||
class BloatEntry {
|
||||
public:
|
||||
BloatEntry(const char* className, PRUint32 classSize)
|
||||
: mClassName(className), mClassSize(classSize) {
|
||||
Clear();
|
||||
}
|
||||
~BloatEntry() {}
|
||||
void Clear() {
|
||||
mAddRefs = 0;
|
||||
mReleases = 0;
|
||||
mRefsOutstandingTotal = 0;
|
||||
mRefsOutstandingVariance = 0;
|
||||
mCreates = 0;
|
||||
mDestroys = 0;
|
||||
mObjsOutstandingTotal = 0;
|
||||
mObjsOutstandingVariance = 0;
|
||||
}
|
||||
void AddRef(nsrefcnt refcnt) {
|
||||
mAddRefs++;
|
||||
if (refcnt == 1) {
|
||||
mCreates++;
|
||||
AccountObjs();
|
||||
}
|
||||
AccountRefs();
|
||||
}
|
||||
void Release(nsrefcnt refcnt) {
|
||||
mReleases++;
|
||||
if (refcnt == 0) {
|
||||
mDestroys++;
|
||||
AccountObjs();
|
||||
}
|
||||
AccountRefs();
|
||||
}
|
||||
void AccountRefs() {
|
||||
PRInt32 cnt = (mAddRefs - mReleases);
|
||||
// NS_ASSERTION(cnt >= 0, "too many releases");
|
||||
mRefsOutstandingTotal += cnt;
|
||||
mRefsOutstandingVariance += cnt * cnt;
|
||||
}
|
||||
void AccountObjs() {
|
||||
PRInt32 cnt = (mAddRefs - mReleases);
|
||||
// NS_ASSERTION(cnt >= 0, "too many releases");
|
||||
mObjsOutstandingTotal += cnt;
|
||||
mObjsOutstandingVariance += cnt * cnt;
|
||||
}
|
||||
static PRIntn DumpEntry(PLHashEntry *he, PRIntn i, void *arg) {
|
||||
BloatEntry* entry = (BloatEntry*)he->value;
|
||||
entry->Dump(i, (FILE*)arg);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
void Dump(PRIntn i, FILE* fp) {
|
||||
#if 1
|
||||
double meanRefCnts = mRefsOutstandingTotal / (mAddRefs + mReleases);
|
||||
double varRefCnts = fabs(mRefsOutstandingVariance /
|
||||
mRefsOutstandingTotal - meanRefCnts * meanRefCnts);
|
||||
double meanObjs = mObjsOutstandingTotal / (mCreates + mDestroys);
|
||||
double varObjs = fabs(mObjsOutstandingVariance /
|
||||
mObjsOutstandingTotal - meanObjs * meanObjs);
|
||||
fprintf(fp, "%4d %-20.20s %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f) %8d %8d\n",
|
||||
i, mClassName,
|
||||
(mAddRefs - mReleases),
|
||||
mAddRefs,
|
||||
meanRefCnts,
|
||||
sqrt(varRefCnts),
|
||||
(mCreates - mDestroys),
|
||||
mCreates,
|
||||
meanObjs,
|
||||
sqrt(varObjs),
|
||||
mClassSize,
|
||||
(mCreates - mDestroys) * mClassSize);
|
||||
#else
|
||||
fprintf(fp, "%4d %-20.20s %8d %8d %8d %8d %8d %8d\n",
|
||||
i, mClassName,
|
||||
mCreates,
|
||||
(mCreates - mDestroys),
|
||||
mAddRefs,
|
||||
(mAddRefs - mReleases),
|
||||
mClassSize,
|
||||
(mCreates - mDestroys) * mClassSize);
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
const char* mClassName;
|
||||
PRUint32 mClassSize;
|
||||
PRInt32 mAddRefs;
|
||||
PRInt32 mReleases;
|
||||
double mRefsOutstandingTotal;
|
||||
double mRefsOutstandingVariance;
|
||||
PRInt32 mCreates;
|
||||
PRInt32 mDestroys;
|
||||
double mObjsOutstandingTotal;
|
||||
double mObjsOutstandingVariance;
|
||||
};
|
||||
|
||||
extern "C" void
|
||||
NS_DumpBloatStatistics(void)
|
||||
{
|
||||
// fprintf(stdout, " Name AddRefs [mean / stddev] Objects [mean / stddev] Size TotalSize\n");
|
||||
// fprintf(stdout, " Name Tot-Objs Rem-Objs Tot-Adds Rem-Adds Obj-Size Mem-Use\n");
|
||||
fprintf(stdout, " Bloaty: Refcounting and Memory Bloat Statistics\n");
|
||||
fprintf(stdout, " |<-------Name------>|<--------------References-------------->|<----------------Objects---------------->|<------Size----->|\n");
|
||||
fprintf(stdout, " Rem Total Mean StdDev Rem Total Mean StdDev Per-Class Rem\n");
|
||||
PL_HashTableDump(gBloatView, BloatEntry::DumpEntry, stdout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void InitTraceLog(void)
|
||||
{
|
||||
if (0 == gTraceRefcntLog) {
|
||||
@ -62,6 +176,15 @@ static void InitTraceLog(void)
|
||||
#if defined(NS_MT_SUPPORTED)
|
||||
gTraceLock = PR_NewLock();
|
||||
#endif /* NS_MT_SUPPORTED */
|
||||
|
||||
#ifdef BLOATY
|
||||
gBloatView = PL_NewHashTable(256,
|
||||
PL_HashString,
|
||||
PL_CompareStrings,
|
||||
PL_CompareValues,
|
||||
NULL, NULL);
|
||||
NS_ASSERTION(gBloatView, "out of memory");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,8 +572,8 @@ nsTraceRefcnt::Create(void* aPtr,
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::Destroy(void* aPtr,
|
||||
const char* aFile,
|
||||
PRIntn aLine)
|
||||
const char* aFile,
|
||||
PRIntn aLine)
|
||||
{
|
||||
#ifdef MOZ_TRACE_XPCOM_REFCNT
|
||||
InitTraceLog();
|
||||
@ -471,30 +594,68 @@ nsTraceRefcnt::Destroy(void* aPtr,
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogAddRef(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClazz)
|
||||
const char* aClazz,
|
||||
PRUint32 classSize)
|
||||
{
|
||||
InitTraceLog();
|
||||
#ifdef BLOATY
|
||||
LOCK_TRACELOG();
|
||||
BloatEntry* entry =
|
||||
(BloatEntry*)PL_HashTableLookup(gBloatView, aClazz);
|
||||
if (entry == NULL) {
|
||||
entry = new BloatEntry(aClazz, classSize);
|
||||
PLHashEntry* e = PL_HashTableAdd(gBloatView, aClazz, entry);
|
||||
if (e == NULL) {
|
||||
delete entry;
|
||||
entry = NULL;
|
||||
}
|
||||
}
|
||||
if (entry) {
|
||||
entry->AddRef(aRefCnt);
|
||||
}
|
||||
UNLOCK_TRACELOG();
|
||||
#else
|
||||
if (PR_LOG_TEST(gTraceRefcntLog, PR_LOG_DEBUG)) {
|
||||
char sb[16384];
|
||||
WalkTheStack(sb, sizeof(sb));
|
||||
// Can't use PR_LOG(), b/c it truncates the line
|
||||
printf("%s\t%p\tAddRef\t%d\t%s\n", aClazz, aPtr, aRefCnt, sb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogRelease(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClazz)
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClazz,
|
||||
PRUint32 classSize)
|
||||
{
|
||||
InitTraceLog();
|
||||
#ifdef BLOATY
|
||||
LOCK_TRACELOG();
|
||||
BloatEntry* entry =
|
||||
(BloatEntry*)PL_HashTableLookup(gBloatView, aClazz);
|
||||
if (entry == NULL) {
|
||||
entry = new BloatEntry(aClazz, classSize);
|
||||
PLHashEntry* e = PL_HashTableAdd(gBloatView, aClazz, entry);
|
||||
if (e == NULL) {
|
||||
delete entry;
|
||||
entry = NULL;
|
||||
}
|
||||
}
|
||||
if (entry) {
|
||||
entry->Release(aRefCnt);
|
||||
}
|
||||
UNLOCK_TRACELOG();
|
||||
#else
|
||||
if (PR_LOG_TEST(gTraceRefcntLog, PR_LOG_DEBUG)) {
|
||||
char sb[16384];
|
||||
WalkTheStack(sb, sizeof(sb));
|
||||
// Can't use PR_LOG(), b/c it truncates the line
|
||||
printf("%s\t%p\tRelease\t%d\t%s\n", aClazz, aPtr, aRefCnt, sb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// This thing is exported by libiberty.a (-liberty)
|
||||
|
@ -73,11 +73,13 @@ public:
|
||||
|
||||
static NS_COM void LogAddRef(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClass);
|
||||
const char* aClass,
|
||||
PRUint32 classSize);
|
||||
|
||||
static NS_COM void LogRelease(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClass);
|
||||
const char* aClass,
|
||||
PRUint32 classSize);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
@ -137,4 +139,9 @@ PR_END_MACRO
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef BLOATY
|
||||
extern "C" void
|
||||
NS_DumpBloatStatistics(void);
|
||||
#endif
|
||||
|
||||
#endif /* nsTraceRefcnt_h___ */
|
||||
|
@ -16,6 +16,7 @@
|
||||
* Corporation. Portions created by Netscape are Copyright (C) 1998
|
||||
* Netscape Communications Corporation. All Rights Reserved.
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "prprf.h"
|
||||
@ -54,6 +55,119 @@ static PRLock* gTraceLock;
|
||||
|
||||
static PRLogModuleInfo* gTraceRefcntLog;
|
||||
|
||||
#ifdef BLOATY
|
||||
#include "plhash.h"
|
||||
#include <math.h>
|
||||
|
||||
PLHashTable* gBloatView;
|
||||
|
||||
class BloatEntry {
|
||||
public:
|
||||
BloatEntry(const char* className, PRUint32 classSize)
|
||||
: mClassName(className), mClassSize(classSize) {
|
||||
Clear();
|
||||
}
|
||||
~BloatEntry() {}
|
||||
void Clear() {
|
||||
mAddRefs = 0;
|
||||
mReleases = 0;
|
||||
mRefsOutstandingTotal = 0;
|
||||
mRefsOutstandingVariance = 0;
|
||||
mCreates = 0;
|
||||
mDestroys = 0;
|
||||
mObjsOutstandingTotal = 0;
|
||||
mObjsOutstandingVariance = 0;
|
||||
}
|
||||
void AddRef(nsrefcnt refcnt) {
|
||||
mAddRefs++;
|
||||
if (refcnt == 1) {
|
||||
mCreates++;
|
||||
AccountObjs();
|
||||
}
|
||||
AccountRefs();
|
||||
}
|
||||
void Release(nsrefcnt refcnt) {
|
||||
mReleases++;
|
||||
if (refcnt == 0) {
|
||||
mDestroys++;
|
||||
AccountObjs();
|
||||
}
|
||||
AccountRefs();
|
||||
}
|
||||
void AccountRefs() {
|
||||
PRInt32 cnt = (mAddRefs - mReleases);
|
||||
// NS_ASSERTION(cnt >= 0, "too many releases");
|
||||
mRefsOutstandingTotal += cnt;
|
||||
mRefsOutstandingVariance += cnt * cnt;
|
||||
}
|
||||
void AccountObjs() {
|
||||
PRInt32 cnt = (mAddRefs - mReleases);
|
||||
// NS_ASSERTION(cnt >= 0, "too many releases");
|
||||
mObjsOutstandingTotal += cnt;
|
||||
mObjsOutstandingVariance += cnt * cnt;
|
||||
}
|
||||
static PRIntn DumpEntry(PLHashEntry *he, PRIntn i, void *arg) {
|
||||
BloatEntry* entry = (BloatEntry*)he->value;
|
||||
entry->Dump(i, (FILE*)arg);
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
void Dump(PRIntn i, FILE* fp) {
|
||||
#if 1
|
||||
double meanRefCnts = mRefsOutstandingTotal / (mAddRefs + mReleases);
|
||||
double varRefCnts = fabs(mRefsOutstandingVariance /
|
||||
mRefsOutstandingTotal - meanRefCnts * meanRefCnts);
|
||||
double meanObjs = mObjsOutstandingTotal / (mCreates + mDestroys);
|
||||
double varObjs = fabs(mObjsOutstandingVariance /
|
||||
mObjsOutstandingTotal - meanObjs * meanObjs);
|
||||
fprintf(fp, "%4d %-20.20s %8d %8d (%8.2f +/- %8.2f) %8d %8d (%8.2f +/- %8.2f) %8d %8d\n",
|
||||
i, mClassName,
|
||||
(mAddRefs - mReleases),
|
||||
mAddRefs,
|
||||
meanRefCnts,
|
||||
sqrt(varRefCnts),
|
||||
(mCreates - mDestroys),
|
||||
mCreates,
|
||||
meanObjs,
|
||||
sqrt(varObjs),
|
||||
mClassSize,
|
||||
(mCreates - mDestroys) * mClassSize);
|
||||
#else
|
||||
fprintf(fp, "%4d %-20.20s %8d %8d %8d %8d %8d %8d\n",
|
||||
i, mClassName,
|
||||
mCreates,
|
||||
(mCreates - mDestroys),
|
||||
mAddRefs,
|
||||
(mAddRefs - mReleases),
|
||||
mClassSize,
|
||||
(mCreates - mDestroys) * mClassSize);
|
||||
#endif
|
||||
}
|
||||
protected:
|
||||
const char* mClassName;
|
||||
PRUint32 mClassSize;
|
||||
PRInt32 mAddRefs;
|
||||
PRInt32 mReleases;
|
||||
double mRefsOutstandingTotal;
|
||||
double mRefsOutstandingVariance;
|
||||
PRInt32 mCreates;
|
||||
PRInt32 mDestroys;
|
||||
double mObjsOutstandingTotal;
|
||||
double mObjsOutstandingVariance;
|
||||
};
|
||||
|
||||
extern "C" void
|
||||
NS_DumpBloatStatistics(void)
|
||||
{
|
||||
// fprintf(stdout, " Name AddRefs [mean / stddev] Objects [mean / stddev] Size TotalSize\n");
|
||||
// fprintf(stdout, " Name Tot-Objs Rem-Objs Tot-Adds Rem-Adds Obj-Size Mem-Use\n");
|
||||
fprintf(stdout, " Bloaty: Refcounting and Memory Bloat Statistics\n");
|
||||
fprintf(stdout, " |<-------Name------>|<--------------References-------------->|<----------------Objects---------------->|<------Size----->|\n");
|
||||
fprintf(stdout, " Rem Total Mean StdDev Rem Total Mean StdDev Per-Class Rem\n");
|
||||
PL_HashTableDump(gBloatView, BloatEntry::DumpEntry, stdout);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void InitTraceLog(void)
|
||||
{
|
||||
if (0 == gTraceRefcntLog) {
|
||||
@ -62,6 +176,15 @@ static void InitTraceLog(void)
|
||||
#if defined(NS_MT_SUPPORTED)
|
||||
gTraceLock = PR_NewLock();
|
||||
#endif /* NS_MT_SUPPORTED */
|
||||
|
||||
#ifdef BLOATY
|
||||
gBloatView = PL_NewHashTable(256,
|
||||
PL_HashString,
|
||||
PL_CompareStrings,
|
||||
PL_CompareValues,
|
||||
NULL, NULL);
|
||||
NS_ASSERTION(gBloatView, "out of memory");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,8 +572,8 @@ nsTraceRefcnt::Create(void* aPtr,
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::Destroy(void* aPtr,
|
||||
const char* aFile,
|
||||
PRIntn aLine)
|
||||
const char* aFile,
|
||||
PRIntn aLine)
|
||||
{
|
||||
#ifdef MOZ_TRACE_XPCOM_REFCNT
|
||||
InitTraceLog();
|
||||
@ -471,30 +594,68 @@ nsTraceRefcnt::Destroy(void* aPtr,
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogAddRef(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClazz)
|
||||
const char* aClazz,
|
||||
PRUint32 classSize)
|
||||
{
|
||||
InitTraceLog();
|
||||
#ifdef BLOATY
|
||||
LOCK_TRACELOG();
|
||||
BloatEntry* entry =
|
||||
(BloatEntry*)PL_HashTableLookup(gBloatView, aClazz);
|
||||
if (entry == NULL) {
|
||||
entry = new BloatEntry(aClazz, classSize);
|
||||
PLHashEntry* e = PL_HashTableAdd(gBloatView, aClazz, entry);
|
||||
if (e == NULL) {
|
||||
delete entry;
|
||||
entry = NULL;
|
||||
}
|
||||
}
|
||||
if (entry) {
|
||||
entry->AddRef(aRefCnt);
|
||||
}
|
||||
UNLOCK_TRACELOG();
|
||||
#else
|
||||
if (PR_LOG_TEST(gTraceRefcntLog, PR_LOG_DEBUG)) {
|
||||
char sb[16384];
|
||||
WalkTheStack(sb, sizeof(sb));
|
||||
// Can't use PR_LOG(), b/c it truncates the line
|
||||
printf("%s\t%p\tAddRef\t%d\t%s\n", aClazz, aPtr, aRefCnt, sb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogRelease(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClazz)
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClazz,
|
||||
PRUint32 classSize)
|
||||
{
|
||||
InitTraceLog();
|
||||
#ifdef BLOATY
|
||||
LOCK_TRACELOG();
|
||||
BloatEntry* entry =
|
||||
(BloatEntry*)PL_HashTableLookup(gBloatView, aClazz);
|
||||
if (entry == NULL) {
|
||||
entry = new BloatEntry(aClazz, classSize);
|
||||
PLHashEntry* e = PL_HashTableAdd(gBloatView, aClazz, entry);
|
||||
if (e == NULL) {
|
||||
delete entry;
|
||||
entry = NULL;
|
||||
}
|
||||
}
|
||||
if (entry) {
|
||||
entry->Release(aRefCnt);
|
||||
}
|
||||
UNLOCK_TRACELOG();
|
||||
#else
|
||||
if (PR_LOG_TEST(gTraceRefcntLog, PR_LOG_DEBUG)) {
|
||||
char sb[16384];
|
||||
WalkTheStack(sb, sizeof(sb));
|
||||
// Can't use PR_LOG(), b/c it truncates the line
|
||||
printf("%s\t%p\tRelease\t%d\t%s\n", aClazz, aPtr, aRefCnt, sb);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// This thing is exported by libiberty.a (-liberty)
|
||||
|
@ -73,11 +73,13 @@ public:
|
||||
|
||||
static NS_COM void LogAddRef(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClass);
|
||||
const char* aClass,
|
||||
PRUint32 classSize);
|
||||
|
||||
static NS_COM void LogRelease(void* aPtr,
|
||||
nsrefcnt aRefCnt,
|
||||
const char* aClass);
|
||||
const char* aClass,
|
||||
PRUint32 classSize);
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
@ -137,4 +139,9 @@ PR_END_MACRO
|
||||
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef BLOATY
|
||||
extern "C" void
|
||||
NS_DumpBloatStatistics(void);
|
||||
#endif
|
||||
|
||||
#endif /* nsTraceRefcnt_h___ */
|
||||
|
@ -483,6 +483,7 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
||||
// libraries:
|
||||
NS_RELEASE2(nsComponentManagerImpl::gComponentManager, cnt);
|
||||
NS_ASSERTION(cnt == 0, "Component Manager being held past XPCOM shutdown.");
|
||||
|
||||
#ifdef DEBUG
|
||||
extern void _FreeAutoLockStatics();
|
||||
_FreeAutoLockStatics();
|
||||
@ -490,6 +491,10 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
||||
|
||||
NS_PurgeAtomTable();
|
||||
|
||||
#ifdef BLOATY
|
||||
NS_DumpBloatStatistics();
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG) && (defined(_WIN32) || defined(XP_UNIX))
|
||||
if (getenv("MOZ_DUMP_LEAKS")) {
|
||||
nsTraceRefcnt::DumpLeaks(stderr);
|
||||
|
@ -76,6 +76,20 @@ typedef unsigned long nsrefcnt;
|
||||
typedef PRUint32 nsrefcnt;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* "Bloaty" is a facility to dump statistics on object allocations and
|
||||
* refcounting. To turn it on, you must define BLOATY in this file, and
|
||||
* rebuild the world. (That seems easier than hacking makefiles to ensure
|
||||
* that environment variables get checked everywhere.)
|
||||
*/
|
||||
#ifdef DEBUG_warrenx
|
||||
#define BLOATY 1
|
||||
#endif
|
||||
|
||||
#ifdef BLOATY
|
||||
#define MOZ_LOG_REFCNT 1
|
||||
#endif
|
||||
|
||||
#include "nsTraceRefcnt.h"
|
||||
|
||||
/**
|
||||
@ -768,10 +782,10 @@ NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
|
||||
|
||||
#ifdef MOZ_LOG_REFCNT
|
||||
#define NS_LOG_ADDREF(_ptr, _refcnt, _class) \
|
||||
nsTraceRefcnt::LogAddRef((_ptr), (_refcnt), (_class))
|
||||
nsTraceRefcnt::LogAddRef((_ptr), (_refcnt), (_class), (sizeof(*this)))
|
||||
|
||||
#define NS_LOG_RELEASE(_ptr, _refcnt, _class) \
|
||||
nsTraceRefcnt::LogRelease((_ptr), (_refcnt), (_class))
|
||||
nsTraceRefcnt::LogRelease((_ptr), (_refcnt), (_class), (sizeof(*this)))
|
||||
|
||||
#else
|
||||
#define NS_LOG_ADDREF(_ptr, _refcnt, _class)
|
||||
|
Loading…
Reference in New Issue
Block a user