зеркало из https://github.com/mozilla/pjs.git
Fix the use of dynamic_cast for nsCOMPtr logging so it doesn't appear in a macro. b=61243
Implement (without enabling, yet) assertions to warn about static constructors. b=62006 Partly fix warnings about MOZ_DECL_CTOR_COUNTER on Mac builds by removing extra semicolon. b=60145 Start to fix the longstanding leaks of nsTraceRefcnt's own hashtables. r=waterson@netscape.com sr=brendan@mozilla.org
This commit is contained in:
Родитель
2ff6dea99f
Коммит
c9b346ca28
|
@ -18,7 +18,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron (dbaron@fas.harvard.edu)
|
||||
* L. David Baron <dbaron@fas.harvard.edu>
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
@ -114,6 +114,7 @@ static FILE *gRefcntsLog = nsnull;
|
|||
static FILE *gAllocLog = nsnull;
|
||||
static FILE *gLeakyLog = nsnull;
|
||||
static FILE *gCOMPtrLog = nsnull;
|
||||
static PRBool gActivityIsLegal = PR_FALSE;
|
||||
|
||||
#define XPCOM_REFCNT_TRACK_BLOAT 0x1
|
||||
#define XPCOM_REFCNT_LOG_ALL 0x2
|
||||
|
@ -1520,6 +1521,58 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName,
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::Startup()
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
SetActivityIsLegal(PR_TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::Shutdown()
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
||||
if (gBloatView) {
|
||||
PL_HashTableDestroy(gBloatView);
|
||||
gBloatView = nsnull;
|
||||
}
|
||||
if (gTypesToLog) {
|
||||
PL_HashTableDestroy(gTypesToLog);
|
||||
gTypesToLog = nsnull;
|
||||
}
|
||||
if (gObjectsToLog) {
|
||||
PL_HashTableDestroy(gObjectsToLog);
|
||||
gObjectsToLog = nsnull;
|
||||
}
|
||||
if (gSerialNumbers) {
|
||||
PL_HashTableDestroy(gSerialNumbers);
|
||||
gSerialNumbers = nsnull;
|
||||
}
|
||||
|
||||
SetActivityIsLegal(PR_FALSE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::SetActivityIsLegal(PRBool aLegal)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
gActivityIsLegal = aLegal;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_dbaron
|
||||
// I hope to turn this on for everybody once we hit it a little less.
|
||||
#define ASSERT_ACTIVITY_IS_LEGAL \
|
||||
NS_WARN_IF_FALSE(gActivityIsLegal, \
|
||||
"XPCOM objects created/destroyed from static ctor/dtor")
|
||||
#else
|
||||
#define ASSERT_ACTIVITY_IS_LEGAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
For consistency, and ease of munging the output, the following record format will be used:
|
||||
|
||||
|
@ -1533,6 +1586,7 @@ nsTraceRefcnt::LogAddRef(void* aPtr,
|
|||
PRUint32 classSize)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
if (gLogging) {
|
||||
|
@ -1595,6 +1649,7 @@ nsTraceRefcnt::LogRelease(void* aPtr,
|
|||
const char* aClazz)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
if (gLogging) {
|
||||
|
@ -1663,6 +1718,7 @@ nsTraceRefcnt::LogAddRefCall(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1687,6 +1743,7 @@ nsTraceRefcnt::LogReleaseCall(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1713,6 +1770,7 @@ nsTraceRefcnt::LogNewXPCOM(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1736,6 +1794,7 @@ nsTraceRefcnt::LogDeleteXPCOM(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1759,6 +1818,7 @@ nsTraceRefcnt::LogCtor(void* aPtr,
|
|||
PRUint32 aInstanceSize)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
||||
|
@ -1799,6 +1859,7 @@ nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
|
|||
PRUint32 aInstanceSize)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
||||
|
@ -1838,16 +1899,19 @@ nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
|
|||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
||||
void* aObject)
|
||||
nsISupports* aObject)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
|
||||
// Get the most-derived object.
|
||||
void *object = dynamic_cast<void *>(aObject);
|
||||
|
||||
// This is a very indirect way of finding out what the class is
|
||||
// of the object being logged. If we're logging a specific type,
|
||||
// then
|
||||
if (!gTypesToLog || !gSerialNumbers) {
|
||||
return;
|
||||
}
|
||||
PRInt32 serialno = GetSerialNumber(aObject, PR_FALSE);
|
||||
PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
|
||||
if (serialno == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1857,7 +1921,7 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
|||
if (gLogging) {
|
||||
LOCK_TRACELOG();
|
||||
|
||||
PRInt32* count = GetCOMPtrCount(aObject);
|
||||
PRInt32* count = GetCOMPtrCount(object);
|
||||
if(count)
|
||||
(*count)++;
|
||||
|
||||
|
@ -1866,7 +1930,7 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
|||
|
||||
if (gCOMPtrLog && loggingThisObject) {
|
||||
fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrAddRef %d 0x%08X\n",
|
||||
PRInt32(aObject), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
PRInt32(object), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
WalkTheStack(gCOMPtrLog);
|
||||
}
|
||||
#endif
|
||||
|
@ -1878,16 +1942,19 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
|||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
|
||||
void* aObject)
|
||||
nsISupports* aObject)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
|
||||
// Get the most-derived object.
|
||||
void *object = dynamic_cast<void *>(aObject);
|
||||
|
||||
// This is a very indirect way of finding out what the class is
|
||||
// of the object being logged. If we're logging a specific type,
|
||||
// then
|
||||
if (!gTypesToLog || !gSerialNumbers) {
|
||||
return;
|
||||
}
|
||||
PRInt32 serialno = GetSerialNumber(aObject, PR_FALSE);
|
||||
PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
|
||||
if (serialno == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1897,7 +1964,7 @@ nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
|
|||
if (gLogging) {
|
||||
LOCK_TRACELOG();
|
||||
|
||||
PRInt32* count = GetCOMPtrCount(aObject);
|
||||
PRInt32* count = GetCOMPtrCount(object);
|
||||
if(count)
|
||||
(*count)--;
|
||||
|
||||
|
@ -1906,7 +1973,7 @@ nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
|
|||
|
||||
if (gCOMPtrLog && loggingThisObject) {
|
||||
fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrRelease %d 0x%08X\n",
|
||||
PRInt32(aObject), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
PRInt32(object), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
WalkTheStack(gCOMPtrLog);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@fas.harvard.edu>
|
||||
*/
|
||||
#ifndef nsTraceRefcnt_h___
|
||||
#define nsTraceRefcnt_h___
|
||||
|
@ -26,6 +27,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
class nsISupports;
|
||||
|
||||
// Normaly, the implementation of NS_LOG_ADDREF and NS_LOG_RELEASE
|
||||
// will use a stack crawl to determine who called Addref/Release on an
|
||||
// xpcom object. If your platform can't implement a stack crawling
|
||||
|
@ -82,7 +85,7 @@
|
|||
|
||||
#endif
|
||||
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type);
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type)
|
||||
|
||||
#define MOZ_COUNT_CTOR(_type) \
|
||||
PR_BEGIN_MACRO \
|
||||
|
@ -98,13 +101,14 @@ PR_END_MACRO
|
|||
// set for non-autoconf platforms)
|
||||
|
||||
// nsCOMPtr.h allows these macros to be defined by clients
|
||||
// a dynamic_cast to void* gives the most derived object
|
||||
// These logging functions require dynamic_cast<void *>, so we don't
|
||||
// define these macros if we don't have dynamic_cast.
|
||||
#define NSCAP_LOG_ASSIGNMENT(_c, _p) \
|
||||
if ((_p)) nsTraceRefcnt::LogAddCOMPtr((_c),dynamic_cast<void *>(NS_STATIC_CAST(nsISupports*,_p)))
|
||||
if ((_p)) nsTraceRefcnt::LogAddCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p))
|
||||
|
||||
#define NSCAP_RELEASE(_c, _p); \
|
||||
if ((_p)) { \
|
||||
nsTraceRefcnt::LogReleaseCOMPtr((_c),dynamic_cast<void *>(NS_STATIC_CAST(nsISupports*,_p))); \
|
||||
nsTraceRefcnt::LogReleaseCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p)); \
|
||||
NS_RELEASE(_p); \
|
||||
}
|
||||
|
||||
|
@ -118,7 +122,7 @@ PR_END_MACRO
|
|||
#define NS_LOG_DELETE_XPCOM(_p,_file,_line)
|
||||
#define NS_LOG_ADDREF_CALL(_p,_rc,_file,_line) _rc
|
||||
#define NS_LOG_RELEASE_CALL(_p,_rc,_file,_line) _rc
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type);
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type)
|
||||
#define MOZ_COUNT_CTOR(_type)
|
||||
#define MOZ_COUNT_DTOR(_type)
|
||||
|
||||
|
@ -158,6 +162,10 @@ typedef PRBool (PR_CALLBACK *nsTraceRefcntStatFunc)
|
|||
*/
|
||||
class nsTraceRefcnt {
|
||||
public:
|
||||
static NS_COM void Startup();
|
||||
|
||||
static NS_COM void Shutdown();
|
||||
|
||||
static NS_COM void LogAddRef(void* aPtr,
|
||||
nsrefcnt aNewRefCnt,
|
||||
const char* aTypeName,
|
||||
|
@ -193,9 +201,9 @@ public:
|
|||
static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
|
||||
PRUint32 aInstanceSize);
|
||||
|
||||
static NS_COM void LogAddCOMPtr(void *aCOMPtr, void* aObject);
|
||||
static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
|
||||
|
||||
static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, void* aObject);
|
||||
static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
|
||||
|
||||
enum StatisticsType {
|
||||
ALL_STATS,
|
||||
|
@ -220,6 +228,13 @@ public:
|
|||
static NS_COM void WalkTheStack(FILE* aStream);
|
||||
|
||||
static NS_COM void SetPrefServiceAvailability(PRBool avail);
|
||||
|
||||
/**
|
||||
* Tell nsTraceRefcnt whether refcounting, allocation, and destruction
|
||||
* activity is legal. This is used to trigger assertions for any such
|
||||
* activity that occurs because of static constructors or destructors.
|
||||
*/
|
||||
static NS_COM void SetActivityIsLegal(PRBool aLegal);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron (dbaron@fas.harvard.edu)
|
||||
* L. David Baron <dbaron@fas.harvard.edu>
|
||||
*/
|
||||
|
||||
#include "nsISupports.h"
|
||||
|
@ -114,6 +114,7 @@ static FILE *gRefcntsLog = nsnull;
|
|||
static FILE *gAllocLog = nsnull;
|
||||
static FILE *gLeakyLog = nsnull;
|
||||
static FILE *gCOMPtrLog = nsnull;
|
||||
static PRBool gActivityIsLegal = PR_FALSE;
|
||||
|
||||
#define XPCOM_REFCNT_TRACK_BLOAT 0x1
|
||||
#define XPCOM_REFCNT_LOG_ALL 0x2
|
||||
|
@ -1520,6 +1521,58 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName,
|
|||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::Startup()
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
SetActivityIsLegal(PR_TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::Shutdown()
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
|
||||
if (gBloatView) {
|
||||
PL_HashTableDestroy(gBloatView);
|
||||
gBloatView = nsnull;
|
||||
}
|
||||
if (gTypesToLog) {
|
||||
PL_HashTableDestroy(gTypesToLog);
|
||||
gTypesToLog = nsnull;
|
||||
}
|
||||
if (gObjectsToLog) {
|
||||
PL_HashTableDestroy(gObjectsToLog);
|
||||
gObjectsToLog = nsnull;
|
||||
}
|
||||
if (gSerialNumbers) {
|
||||
PL_HashTableDestroy(gSerialNumbers);
|
||||
gSerialNumbers = nsnull;
|
||||
}
|
||||
|
||||
SetActivityIsLegal(PR_FALSE);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::SetActivityIsLegal(PRBool aLegal)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
gActivityIsLegal = aLegal;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_dbaron
|
||||
// I hope to turn this on for everybody once we hit it a little less.
|
||||
#define ASSERT_ACTIVITY_IS_LEGAL \
|
||||
NS_WARN_IF_FALSE(gActivityIsLegal, \
|
||||
"XPCOM objects created/destroyed from static ctor/dtor")
|
||||
#else
|
||||
#define ASSERT_ACTIVITY_IS_LEGAL
|
||||
#endif
|
||||
|
||||
/*
|
||||
For consistency, and ease of munging the output, the following record format will be used:
|
||||
|
||||
|
@ -1533,6 +1586,7 @@ nsTraceRefcnt::LogAddRef(void* aPtr,
|
|||
PRUint32 classSize)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
if (gLogging) {
|
||||
|
@ -1595,6 +1649,7 @@ nsTraceRefcnt::LogRelease(void* aPtr,
|
|||
const char* aClazz)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
if (gLogging) {
|
||||
|
@ -1663,6 +1718,7 @@ nsTraceRefcnt::LogAddRefCall(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1687,6 +1743,7 @@ nsTraceRefcnt::LogReleaseCall(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1713,6 +1770,7 @@ nsTraceRefcnt::LogNewXPCOM(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1736,6 +1794,7 @@ nsTraceRefcnt::LogDeleteXPCOM(void* aPtr,
|
|||
int aLine)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
#ifdef NS_LOSING_ARCHITECTURE
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
@ -1759,6 +1818,7 @@ nsTraceRefcnt::LogCtor(void* aPtr,
|
|||
PRUint32 aInstanceSize)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
||||
|
@ -1799,6 +1859,7 @@ nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
|
|||
PRUint32 aInstanceSize)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
ASSERT_ACTIVITY_IS_LEGAL;
|
||||
if (!gInitialized)
|
||||
InitTraceLog();
|
||||
|
||||
|
@ -1838,16 +1899,19 @@ nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
|
|||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
||||
void* aObject)
|
||||
nsISupports* aObject)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
|
||||
// Get the most-derived object.
|
||||
void *object = dynamic_cast<void *>(aObject);
|
||||
|
||||
// This is a very indirect way of finding out what the class is
|
||||
// of the object being logged. If we're logging a specific type,
|
||||
// then
|
||||
if (!gTypesToLog || !gSerialNumbers) {
|
||||
return;
|
||||
}
|
||||
PRInt32 serialno = GetSerialNumber(aObject, PR_FALSE);
|
||||
PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
|
||||
if (serialno == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1857,7 +1921,7 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
|||
if (gLogging) {
|
||||
LOCK_TRACELOG();
|
||||
|
||||
PRInt32* count = GetCOMPtrCount(aObject);
|
||||
PRInt32* count = GetCOMPtrCount(object);
|
||||
if(count)
|
||||
(*count)++;
|
||||
|
||||
|
@ -1866,7 +1930,7 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
|||
|
||||
if (gCOMPtrLog && loggingThisObject) {
|
||||
fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrAddRef %d 0x%08X\n",
|
||||
PRInt32(aObject), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
PRInt32(object), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
WalkTheStack(gCOMPtrLog);
|
||||
}
|
||||
#endif
|
||||
|
@ -1878,16 +1942,19 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
|
|||
|
||||
NS_COM void
|
||||
nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
|
||||
void* aObject)
|
||||
nsISupports* aObject)
|
||||
{
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
|
||||
// Get the most-derived object.
|
||||
void *object = dynamic_cast<void *>(aObject);
|
||||
|
||||
// This is a very indirect way of finding out what the class is
|
||||
// of the object being logged. If we're logging a specific type,
|
||||
// then
|
||||
if (!gTypesToLog || !gSerialNumbers) {
|
||||
return;
|
||||
}
|
||||
PRInt32 serialno = GetSerialNumber(aObject, PR_FALSE);
|
||||
PRInt32 serialno = GetSerialNumber(object, PR_FALSE);
|
||||
if (serialno == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1897,7 +1964,7 @@ nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
|
|||
if (gLogging) {
|
||||
LOCK_TRACELOG();
|
||||
|
||||
PRInt32* count = GetCOMPtrCount(aObject);
|
||||
PRInt32* count = GetCOMPtrCount(object);
|
||||
if(count)
|
||||
(*count)--;
|
||||
|
||||
|
@ -1906,7 +1973,7 @@ nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
|
|||
|
||||
if (gCOMPtrLog && loggingThisObject) {
|
||||
fprintf(gCOMPtrLog, "\n<?> 0x%08X %d nsCOMPtrRelease %d 0x%08X\n",
|
||||
PRInt32(aObject), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
PRInt32(object), serialno, count?(*count):-1, PRInt32(aCOMPtr));
|
||||
WalkTheStack(gCOMPtrLog);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
* Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* L. David Baron <dbaron@fas.harvard.edu>
|
||||
*/
|
||||
#ifndef nsTraceRefcnt_h___
|
||||
#define nsTraceRefcnt_h___
|
||||
|
@ -26,6 +27,8 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
class nsISupports;
|
||||
|
||||
// Normaly, the implementation of NS_LOG_ADDREF and NS_LOG_RELEASE
|
||||
// will use a stack crawl to determine who called Addref/Release on an
|
||||
// xpcom object. If your platform can't implement a stack crawling
|
||||
|
@ -82,7 +85,7 @@
|
|||
|
||||
#endif
|
||||
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type);
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type)
|
||||
|
||||
#define MOZ_COUNT_CTOR(_type) \
|
||||
PR_BEGIN_MACRO \
|
||||
|
@ -98,13 +101,14 @@ PR_END_MACRO
|
|||
// set for non-autoconf platforms)
|
||||
|
||||
// nsCOMPtr.h allows these macros to be defined by clients
|
||||
// a dynamic_cast to void* gives the most derived object
|
||||
// These logging functions require dynamic_cast<void *>, so we don't
|
||||
// define these macros if we don't have dynamic_cast.
|
||||
#define NSCAP_LOG_ASSIGNMENT(_c, _p) \
|
||||
if ((_p)) nsTraceRefcnt::LogAddCOMPtr((_c),dynamic_cast<void *>(NS_STATIC_CAST(nsISupports*,_p)))
|
||||
if ((_p)) nsTraceRefcnt::LogAddCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p))
|
||||
|
||||
#define NSCAP_RELEASE(_c, _p); \
|
||||
if ((_p)) { \
|
||||
nsTraceRefcnt::LogReleaseCOMPtr((_c),dynamic_cast<void *>(NS_STATIC_CAST(nsISupports*,_p))); \
|
||||
nsTraceRefcnt::LogReleaseCOMPtr((_c),NS_STATIC_CAST(nsISupports*,_p)); \
|
||||
NS_RELEASE(_p); \
|
||||
}
|
||||
|
||||
|
@ -118,7 +122,7 @@ PR_END_MACRO
|
|||
#define NS_LOG_DELETE_XPCOM(_p,_file,_line)
|
||||
#define NS_LOG_ADDREF_CALL(_p,_rc,_file,_line) _rc
|
||||
#define NS_LOG_RELEASE_CALL(_p,_rc,_file,_line) _rc
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type);
|
||||
#define MOZ_DECL_CTOR_COUNTER(_type)
|
||||
#define MOZ_COUNT_CTOR(_type)
|
||||
#define MOZ_COUNT_DTOR(_type)
|
||||
|
||||
|
@ -158,6 +162,10 @@ typedef PRBool (PR_CALLBACK *nsTraceRefcntStatFunc)
|
|||
*/
|
||||
class nsTraceRefcnt {
|
||||
public:
|
||||
static NS_COM void Startup();
|
||||
|
||||
static NS_COM void Shutdown();
|
||||
|
||||
static NS_COM void LogAddRef(void* aPtr,
|
||||
nsrefcnt aNewRefCnt,
|
||||
const char* aTypeName,
|
||||
|
@ -193,9 +201,9 @@ public:
|
|||
static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
|
||||
PRUint32 aInstanceSize);
|
||||
|
||||
static NS_COM void LogAddCOMPtr(void *aCOMPtr, void* aObject);
|
||||
static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
|
||||
|
||||
static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, void* aObject);
|
||||
static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
|
||||
|
||||
enum StatisticsType {
|
||||
ALL_STATS,
|
||||
|
@ -220,6 +228,13 @@ public:
|
|||
static NS_COM void WalkTheStack(FILE* aStream);
|
||||
|
||||
static NS_COM void SetPrefServiceAvailability(PRBool avail);
|
||||
|
||||
/**
|
||||
* Tell nsTraceRefcnt whether refcounting, allocation, and destruction
|
||||
* activity is legal. This is used to trigger assertions for any such
|
||||
* activity that occurs because of static constructors or destructors.
|
||||
*/
|
||||
static NS_COM void SetActivityIsLegal(PRBool aLegal);
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -210,6 +210,10 @@ nsresult NS_COM NS_InitXPCOM2(const char* productName,
|
|||
{
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::Startup();
|
||||
#endif
|
||||
|
||||
// Establish the main thread here.
|
||||
rv = nsIThread::SetMainThread();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
@ -695,9 +699,10 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
|
|||
nsThread::Shutdown();
|
||||
NS_PurgeAtomTable();
|
||||
|
||||
#if (defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING))
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::DumpStatistics();
|
||||
nsTraceRefcnt::ResetStatistics();
|
||||
nsTraceRefcnt::Shutdown();
|
||||
#endif
|
||||
|
||||
#ifdef GC_LEAK_DETECTOR
|
||||
|
|
|
@ -313,10 +313,14 @@ PRBool nsDll::Load(void)
|
|||
{
|
||||
nsCOMPtr<nsILocalFile> localFile = do_QueryInterface(m_dllSpec);
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::SetActivityIsLegal(PR_FALSE);
|
||||
#endif
|
||||
if (localFile)
|
||||
localFile->Load(&m_instance);
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::SetActivityIsLegal(PR_TRUE);
|
||||
if (m_instance) {
|
||||
// Inform refcnt tracer of new library so that calls through the
|
||||
// new library can be traced.
|
||||
|
@ -330,9 +334,13 @@ PRBool nsDll::Load(void)
|
|||
else if (m_dllName)
|
||||
{
|
||||
// if there is not an nsIFile, but there is a dll name, just try to load that..
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::SetActivityIsLegal(PR_FALSE);
|
||||
#endif
|
||||
m_instance = PR_LoadLibrary(m_dllName);
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::SetActivityIsLegal(PR_TRUE);
|
||||
if (m_instance) {
|
||||
// Inform refcnt tracer of new library so that calls through the
|
||||
// new library can be traced.
|
||||
|
@ -359,7 +367,14 @@ PRBool nsDll::Unload(void)
|
|||
// Shutdown the dll
|
||||
Shutdown();
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::SetActivityIsLegal(PR_FALSE);
|
||||
#endif
|
||||
PRStatus ret = PR_UnloadLibrary(m_instance);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsTraceRefcnt::SetActivityIsLegal(PR_TRUE);
|
||||
#endif
|
||||
|
||||
if (ret == PR_SUCCESS)
|
||||
{
|
||||
m_instance = NULL;
|
||||
|
|
Загрузка…
Ссылка в новой задаче