Fix for 205023. Adds nsTraceRefcnt stubs that access a global to allow tracing refcnt to work with the GRE/xpcom glue builds. r=dbaron

This commit is contained in:
dougt%meer.net 2003-08-05 05:29:10 +00:00
Родитель fb79cd3a13
Коммит ed09f93043
26 изменённых файлов: 654 добавлений и 591 удалений

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsNetUtil.h"
#include "nsDirectoryServiceDefs.h"
#include "nsILocalFile.h"
#include "nsTraceRefcntImpl.h"
#ifdef XP_MAC
extern "C" void GC_gcollect(void);
@ -64,7 +65,7 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
rv = aURI->GetPath(path);
if (NS_FAILED(rv)) return rv;
nsTraceRefcnt::StatisticsType statType = nsTraceRefcnt::ALL_STATS;
nsTraceRefcntImpl::StatisticsType statType = nsTraceRefcntImpl::ALL_STATS;
PRBool clear = PR_FALSE;
PRBool leaks = PR_FALSE;
@ -73,7 +74,7 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
nsCAutoString param;
(void)path.Right(param, path.Length() - (pos+1));
if (param.Equals("new"))
statType = nsTraceRefcnt::NEW_STATS;
statType = nsTraceRefcntImpl::NEW_STATS;
else if (param.Equals("clear"))
clear = PR_TRUE;
else if (param.Equals("leaks"))
@ -82,7 +83,7 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
nsCOMPtr<nsIInputStream> inStr;
if (clear) {
nsTraceRefcnt::ResetStatistics();
nsTraceRefcntImpl::ResetStatistics();
const char* msg = "Bloat statistics cleared.";
rv = NS_NewCStringInputStream(getter_AddRefs(inStr), nsDependentCString(msg));
@ -98,7 +99,7 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
}
else {
nsCOMPtr<nsIFile> file;
rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR,
rv = NS_GetSpecialDirectory(NS_OS_CURRENT_PROCESS_DIR,
getter_AddRefs(file));
if (NS_FAILED(rv)) return rv;
@ -118,7 +119,7 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
}
nsCAutoString dumpFileName;
if (statType == nsTraceRefcnt::ALL_STATS)
if (statType == nsTraceRefcntImpl::ALL_STATS)
dumpFileName += "all-";
else
dumpFileName += "new-";
@ -137,7 +138,7 @@ nsAboutBloat::NewChannel(nsIURI *aURI, nsIChannel **result)
rv = lfile->OpenANSIFileDesc("w", &out);
if (NS_FAILED(rv)) return rv;
rv = nsTraceRefcnt::DumpStatistics(statType, out);
rv = nsTraceRefcntImpl::DumpStatistics(statType, out);
::fclose(out);
if (NS_FAILED(rv)) return rv;

Просмотреть файл

@ -77,7 +77,7 @@ static PRBool track_illegal = PR_TRUE;
static PRBool track_latin1 = PR_TRUE;
#ifdef XP_UNIX
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
class CTraceFile {
public:
CTraceFile() {
@ -104,7 +104,7 @@ public:
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
nsTraceRefcntImpl::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
@ -127,7 +127,7 @@ public:
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
nsTraceRefcntImpl::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);

Просмотреть файл

@ -150,7 +150,7 @@ void abnormal_exit_handler(int signum)
#if 0
printf("stack logged to someplace\n");
printf("need to fix xpcom/base/nsTraceRefCnt.cpp in WalkTheStack.\n");
nsTraceRefcnt::WalkTheStack(stdout);
nsTraceRefcntImpl::WalkTheStack(stdout);
#endif
printf("Sleeping for 5 minutes.\n");

Просмотреть файл

@ -137,7 +137,7 @@ nsNativeBrowserWindow::DispatchMenuItem(PRInt32 aID)
#include <signal.h>
#include <unistd.h>
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
extern "C" char * strsignal(int);
@ -154,7 +154,7 @@ ah_crap_handler(int signum)
strsignal(signum));
printf("stack logged to someplace\n");
nsTraceRefcnt::WalkTheStack(stdout);
nsTraceRefcntImpl::WalkTheStack(stdout);
printf("Sleeping for 5 minutes.\n");
printf("Type 'gdb %s %d' to attach your debugger to this thread.\n",

Просмотреть файл

@ -135,7 +135,7 @@ nsNativeBrowserWindow::DispatchMenuItem(PRInt32 aID)
#include <signal.h>
#include <unistd.h>
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
extern "C" char * strsignal(int);
@ -152,7 +152,7 @@ ah_crap_handler(int signum)
strsignal(signum));
printf("stack logged to someplace\n");
nsTraceRefcnt::WalkTheStack(stdout);
nsTraceRefcntImpl::WalkTheStack(stdout);
printf("Sleeping for 5 minutes.\n");
printf("Type 'gdb %s %d' to attach your debugger to this thread.\n",

Просмотреть файл

@ -36,15 +36,15 @@ REQUIRES = string \
CPPSRCS = \
nsAllocator.cpp \
nsMemoryImpl.cpp \
nsErrorService.cpp \
nsTraceRefcnt.cpp \
nsID.cpp \
nsCWeakReference.cpp \
nsConsoleService.cpp \
nsConsoleMessage.cpp \
nsConsoleService.cpp \
nsDebugImpl.cpp \
nsErrorService.cpp \
nsExceptionService.cpp \
nsID.cpp \
nsMemoryImpl.cpp \
nsTraceRefcntImpl.cpp \
$(NULL)
ifdef GC_LEAK_DETECTOR
@ -56,14 +56,14 @@ endif
EXPORTS = \
nsAgg.h \
nsAutoPtr.h \
nsIAllocator.h \
nsCWeakReference.h \
nsCom.h \
nsComObsolete.h \
nsCWeakReference.h \
nsDebugImpl.h \
nsIAllocator.h \
nsIID.h \
nsISupportsObsolete.h \
nsTraceRefcnt.h \
nsTraceRefcntImpl.h \
nsWeakPtr.h \
$(NULL)
@ -80,26 +80,26 @@ CPPSRCS += nsStackFrameUnix.cpp
endif
SDK_XPIDLSRCS = \
nsIDebug.idl \
nsIInterfaceRequestor.idl \
nsIMemory.idl \
nsIProgrammingLanguage.idl \
nsISupports.idl \
nsITraceRefcnt.idl \
nsIWeakReference.idl \
nsIMemory.idl \
nsIDebug.idl \
nsrootidl.idl \
SDK_HEADERS = \
nsError.h \
nsID.h \
nsISupportsBase.h \
nscore.h \
nsID.h \
XPIDLSRCS = \
nsIErrorService.idl \
nsIConsoleService.idl \
nsIConsoleMessage.idl \
nsIConsoleListener.idl \
nsIConsoleMessage.idl \
nsIConsoleService.idl \
nsIErrorService.idl \
nsIException.idl \
nsIExceptionService.idl \
$(NULL)

Просмотреть файл

@ -37,8 +37,13 @@
#include "nsISupports.idl"
/**
/**
* nsIDebug is an interface between XPCOM Glue and XPCOM. Users should access
* the nsIDebug interface through the static class nsDebug.
* @see nsDebug.h
*
* @status UNDER_REVIEW
*
*/
[scriptable, uuid(3bf0c3d7-3bd9-4cf2-a971-33572c503e1e)]

Просмотреть файл

@ -0,0 +1,72 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is XPCOM
*
* The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
*
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/**
* nsITraceRefcnt is an interface between XPCOM Glue and XPCOM. Users should
* access the nsITraceRefcnt interface through the static class nsTraceRefcnt.
* @see nsTraceRefcnt.h
*
* @status UNDER_REVIEW
*/
[uuid(273dc92f-0fe6-4545-96a9-21be77828039)]
interface nsITraceRefcnt : nsISupports
{
void logAddRef(in voidPtr aPtr,
in nsrefcnt aNewRefcnt,
in string aTypeName,
in unsigned long aInstanceSize);
void logRelease(in voidPtr aPtr,
in nsrefcnt aNewRefcnt,
in string aTypeName);
void logCtor(in voidPtr aPtr,
in string aTypeName,
in unsigned long aInstanceSize);
void logDtor(in voidPtr aPtr,
in string aTypeName,
in unsigned long aInstanceSize);
void logAddCOMPtr(in voidPtr aPtr, in nsISupports aObject);
void logReleaseCOMPtr(in voidPtr aPtr, in nsISupports aObject);
};

Просмотреть файл

@ -36,6 +36,7 @@
*
* ***** END LICENSE BLOCK ***** */
#include "nsTraceRefcntImpl.h"
#include "nscore.h"
#include "nsISupports.h"
#include "nsVoidArray.h"
@ -127,21 +128,33 @@ 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
#define XPCOM_REFCNT_LOG_SOME 0x4
#define XPCOM_REFCNT_LOG_TO_LEAKY 0x8
// Should only use this on NS_LOSING_ARCHITECTURE...
#define XPCOM_REFCNT_LOG_CALLS 0x10
#define XPCOM_REFCNT_LOG_NEW 0x20
struct serialNumberRecord {
PRInt32 serialNumber;
PRInt32 refCount;
PRInt32 COMPtrCount;
};
struct nsTraceRefcntStats {
nsrefcnt mAddRefs;
nsrefcnt mReleases;
nsrefcnt mCreates;
nsrefcnt mDestroys;
double mRefsOutstandingTotal;
double mRefsOutstandingSquared;
double mObjsOutstandingTotal;
double mObjsOutstandingSquared;
};
#ifdef DEBUG_dbaron_off
// 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
// These functions are copied from nsprpub/lib/ds/plhash.c, with changes
// to the functions not called Default* to free the serialNumberRecord or
// the BloatEntry.
@ -215,11 +228,6 @@ static const PLHashAllocOps typesToLogHashAllocOps = {
////////////////////////////////////////////////////////////////////////////////
struct GatherArgs {
nsTraceRefcntStatFunc func;
void* closure;
};
class BloatEntry {
public:
BloatEntry(const char* className, PRUint32 classSize)
@ -333,21 +341,7 @@ public:
nsresult DumpTotal(PRUint32 nClasses, FILE* out) {
mClassSize /= mAllStats.mCreates;
return Dump(-1, out, nsTraceRefcnt::ALL_STATS);
}
static PRIntn PR_CALLBACK GatherEntry(PLHashEntry *he, PRIntn i, void *arg) {
BloatEntry* entry = (BloatEntry*)he->value;
GatherArgs* ga = (GatherArgs*) arg;
if (arg && entry && ga->func) {
PRBool stop = (*ga->func)(entry->mClassName, (PRUint32)entry->mClassSize,
&entry->mNewStats, &entry->mAllStats,
ga->closure);
if (stop) {
return HT_ENUMERATE_STOP;
}
}
return HT_ENUMERATE_NEXT;
return Dump(-1, out, nsTraceRefcntImpl::ALL_STATS);
}
static PRBool HaveLeaks(nsTraceRefcntStats* stats) {
@ -364,8 +358,8 @@ public:
return NS_OK;
}
nsresult Dump(PRIntn i, FILE* out, nsTraceRefcnt::StatisticsType type) {
nsTraceRefcntStats* stats = (type == nsTraceRefcnt::NEW_STATS) ? &mNewStats : &mAllStats;
nsresult Dump(PRIntn i, FILE* out, nsTraceRefcntImpl::StatisticsType type) {
nsTraceRefcntStats* stats = (type == nsTraceRefcntImpl::NEW_STATS) ? &mNewStats : &mAllStats;
if (gLogLeaksOnly && !HaveLeaks(stats)) {
return NS_OK;
}
@ -491,7 +485,7 @@ static PRIntn PR_CALLBACK DumpSerialNumbers(PLHashEntry* aHashEntry, PRIntn aInd
#endif /* NS_BUILD_REFCNT_LOGGING */
nsresult
nsTraceRefcnt::DumpStatistics(StatisticsType type, FILE* out)
nsTraceRefcntImpl::DumpStatistics(StatisticsType type, FILE* out)
{
nsresult rv = NS_OK;
#ifdef NS_BUILD_REFCNT_LOGGING
@ -531,7 +525,7 @@ nsTraceRefcnt::DumpStatistics(StatisticsType type, FILE* out)
nsVoidArray entries;
PL_HashTableEnumerateEntries(gBloatView, BloatEntry::DumpEntry, &entries);
fprintf(stdout, "nsTraceRefcnt::DumpStatistics: %d entries\n",
fprintf(stdout, "nsTraceRefcntImpl::DumpStatistics: %d entries\n",
entries.Count());
// Sort the entries alphabetically by classname.
@ -568,7 +562,7 @@ done:
}
void
nsTraceRefcnt::ResetStatistics()
nsTraceRefcntImpl::ResetStatistics()
{
#ifdef NS_BUILD_REFCNT_LOGGING
LOCK_TRACELOG();
@ -580,25 +574,6 @@ nsTraceRefcnt::ResetStatistics()
#endif
}
void
nsTraceRefcnt::GatherStatistics(nsTraceRefcntStatFunc aFunc,
void* aClosure)
{
#ifdef NS_BUILD_REFCNT_LOGGING
LOCK_TRACELOG();
if (gBloatView) {
GatherArgs ga;
ga.func = aFunc;
ga.closure = aClosure;
PL_HashTableEnumerateEntries(gBloatView, BloatEntry::GatherEntry,
(void*) &ga);
}
UNLOCK_TRACELOG();
#endif
}
#ifdef NS_BUILD_REFCNT_LOGGING
static PRBool LogThisType(const char* aTypeName)
{
@ -876,7 +851,7 @@ static void InitTraceLog(void)
#if defined(_WIN32) && defined(_M_IX86) // WIN32 x86 stack walking code
#include "nsStackFrameWin.h"
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
{
DumpStackToFile(aStream);
}
@ -886,7 +861,7 @@ nsTraceRefcnt::WalkTheStack(FILE* aStream)
#elif (defined(linux) && defined(__GLIBC__) && (defined(__i386) || defined(PPC))) || (defined(__sun) && (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)))
#include "nsStackFrameUnix.h"
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
{
DumpStackToFile(aStream);
}
@ -927,7 +902,6 @@ static char* pc2name(long* pc, char name[], long size)
while (instructionsToLook--) {
if (instruction[0] == 0x4E800020 && instruction[1] == 0x00000000) {
traceback_table* tb = (traceback_table*)&instruction[1];
long nameLength = (tb->nameLength > --size ? size : tb->nameLength);
memcpy(name, tb->name + 1, --nameLength);
name[nameLength] = '\0';
break;
@ -955,9 +929,9 @@ static asm stack_frame* getStackFrame()
}
NS_COM void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
{
stack_frame* currentFrame = getStackFrame(); // WalkTheStack's frame.
stack_frame* currentFrame = getStackFrame(); // WalkTheStack's frame.
currentFrame = currentFrame->next; // WalkTheStack's caller's frame.
currentFrame = currentFrame->next; // WalkTheStack's caller's caller's frame.
@ -987,7 +961,7 @@ nsTraceRefcnt::WalkTheStack(FILE* aStream)
#else // unsupported platform.
void
nsTraceRefcnt::WalkTheStack(FILE* aStream)
nsTraceRefcntImpl::WalkTheStack(FILE* aStream)
{
fprintf(aStream, "write me, dammit!\n");
}
@ -1006,7 +980,7 @@ extern "C" char * cplus_demangle(const char *,int);
#if (defined(__linux__) || defined(__sun)) && defined(__GNUC__)
NS_COM void
nsTraceRefcnt::DemangleSymbol(const char * aSymbol,
nsTraceRefcntImpl::DemangleSymbol(const char * aSymbol,
char * aBuffer,
int aBufLen)
{
@ -1032,7 +1006,7 @@ nsTraceRefcnt::DemangleSymbol(const char * aSymbol,
#else // ( __linux__ || __sun) && __GNUC__
NS_COM void
nsTraceRefcnt::DemangleSymbol(const char * aSymbol,
nsTraceRefcntImpl::DemangleSymbol(const char * aSymbol,
char * aBuffer,
int aBufLen)
{
@ -1047,7 +1021,7 @@ nsTraceRefcnt::DemangleSymbol(const char * aSymbol,
//----------------------------------------------------------------------
NS_COM void
nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName,
nsTraceRefcntImpl::LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle)
{
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1104,69 +1078,48 @@ nsTraceRefcnt::LoadLibrarySymbols(const char* aLibraryName,
//----------------------------------------------------------------------
NS_COM void
nsTraceRefcnt::Startup()
// don't use the logging ones. :-)
NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::AddRef(void)
{
#ifdef NS_BUILD_REFCNT_LOGGING
SetActivityIsLegal(PR_TRUE);
#endif
NS_PRECONDITION(PRInt32(mRefCnt) >= 0, "illegal refcnt");
++mRefCnt;
return mRefCnt;
}
NS_COM void
nsTraceRefcnt::Shutdown()
{
#ifdef NS_BUILD_REFCNT_LOGGING
if (gBloatView) {
PL_HashTableDestroy(gBloatView);
gBloatView = nsnull;
NS_IMETHODIMP_(nsrefcnt) nsTraceRefcntImpl::Release(void)
{
NS_PRECONDITION(0 != mRefCnt, "dup release");
--mRefCnt;
if (mRefCnt == 0) {
mRefCnt = 1; /* stabilize */
delete this;
return 0;
}
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
return mRefCnt;
}
NS_COM void
nsTraceRefcnt::SetActivityIsLegal(PRBool aLegal)
NS_IMPL_QUERY_INTERFACE1(nsTraceRefcntImpl, nsITraceRefcnt)
nsTraceRefcntImpl::nsTraceRefcntImpl()
{
#ifdef NS_BUILD_REFCNT_LOGGING
gActivityIsLegal = aLegal;
#endif
/* member initializers and constructor code */
}
#ifdef DEBUG_dbaron_off
// 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
nsTraceRefcntImpl::~nsTraceRefcntImpl()
{
/* destructor code */
}
/*
For consistency, and ease of munging the output, the following record format will be used:
<TypeName> 0xADDRESS Verb [optional data]
*/
NS_COM void
nsTraceRefcnt::LogAddRef(void* aPtr,
nsrefcnt aRefCnt,
const char* aClazz,
PRUint32 classSize)
NS_IMETHODIMP
nsTraceRefcntImpl::LogAddRef(void* aPtr,
nsrefcnt aRefcnt,
const char* aClazz,
PRUint32 classSize)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
@ -1178,19 +1131,17 @@ nsTraceRefcnt::LogAddRef(void* aPtr,
if (gBloatLog) {
BloatEntry* entry = GetBloatEntry(aClazz, classSize);
if (entry) {
entry->AddRef(aRefCnt);
entry->AddRef(aRefcnt);
}
}
// Here's the case where neither NS_NEWXPCOM nor MOZ_COUNT_CTOR were used,
// yet we still want to see creation information:
#ifndef NS_LOSING_ARCHITECTURE
// (If we're on a losing architecture, don't do this because we'll be
// using LogNewXPCOM instead to get file and line numbers.)
PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz));
PRInt32 serialno = 0;
if (gSerialNumbers && loggingThisType) {
serialno = GetSerialNumber(aPtr, aRefCnt == 1);
serialno = GetSerialNumber(aPtr, aRefcnt == 1);
PRInt32* count = GetRefCount(aPtr);
if(count)
(*count)++;
@ -1198,37 +1149,33 @@ nsTraceRefcnt::LogAddRef(void* aPtr,
}
PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
if (aRefCnt == 1 && gAllocLog && loggingThisType && loggingThisObject) {
if (aRefcnt == 1 && gAllocLog && loggingThisType && loggingThisObject) {
fprintf(gAllocLog, "\n<%s> 0x%08X %d Create\n",
aClazz, NS_PTR_TO_INT32(aPtr), serialno);
WalkTheStack(gAllocLog);
}
// (If we're on a losing architecture, don't do this because we'll be
// using LogAddRefCall instead to get file and line numbers.)
if (gRefcntsLog && loggingThisType && loggingThisObject) {
if (gLogToLeaky) {
(*leakyLogAddRef)(aPtr, aRefCnt - 1, aRefCnt);
(*leakyLogAddRef)(aPtr, aRefcnt - 1, aRefcnt);
}
else {
// Can't use PR_LOG(), b/c it truncates the line
fprintf(gRefcntsLog,
"\n<%s> 0x%08X %d AddRef %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefCnt);
"\n<%s> 0x%08X %d AddRef %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
WalkTheStack(gRefcntsLog);
fflush(gRefcntsLog);
}
}
#endif
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM void
nsTraceRefcnt::LogRelease(void* aPtr,
nsrefcnt aRefCnt,
NS_IMETHODIMP
nsTraceRefcntImpl::LogRelease(void* aPtr,
nsrefcnt aRefcnt,
const char* aClazz)
{
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1241,13 +1188,10 @@ nsTraceRefcnt::LogRelease(void* aPtr,
if (gBloatLog) {
BloatEntry* entry = GetBloatEntry(aClazz, 0);
if (entry) {
entry->Release(aRefCnt);
entry->Release(aRefcnt);
}
}
#ifndef NS_LOSING_ARCHITECTURE
// (If we're on a losing architecture, don't do this because we'll be
// using LogReleaseCall instead to get file and line numbers.)
PRBool loggingThisType = (!gTypesToLog || LogThisType(aClazz));
PRInt32 serialno = 0;
if (gSerialNumbers && loggingThisType) {
@ -1261,12 +1205,12 @@ nsTraceRefcnt::LogRelease(void* aPtr,
PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
if (gRefcntsLog && loggingThisType && loggingThisObject) {
if (gLogToLeaky) {
(*leakyLogRelease)(aPtr, aRefCnt + 1, aRefCnt);
(*leakyLogRelease)(aPtr, aRefcnt + 1, aRefcnt);
}
else {
// Can't use PR_LOG(), b/c it truncates the line
fprintf(gRefcntsLog,
"\n<%s> 0x%08X %d Release %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefCnt);
"\n<%s> 0x%08X %d Release %d\n", aClazz, NS_PTR_TO_INT32(aPtr), serialno, aRefcnt);
WalkTheStack(gRefcntsLog);
fflush(gRefcntsLog);
}
@ -1275,130 +1219,27 @@ nsTraceRefcnt::LogRelease(void* aPtr,
// Here's the case where neither NS_DELETEXPCOM nor MOZ_COUNT_DTOR were used,
// yet we still want to see deletion information:
// (If we're on a losing architecture, don't do this because we'll be
// using LogDeleteXPCOM instead to get file and line numbers.)
if (aRefCnt == 0 && gAllocLog && loggingThisType && loggingThisObject) {
if (aRefcnt == 0 && gAllocLog && loggingThisType && loggingThisObject) {
fprintf(gAllocLog,
"\n<%s> 0x%08X %d Destroy\n",
aClazz, NS_PTR_TO_INT32(aPtr), serialno);
WalkTheStack(gAllocLog);
}
if (aRefCnt == 0 && gSerialNumbers && loggingThisType) {
if (aRefcnt == 0 && gSerialNumbers && loggingThisType) {
RecycleSerialNumberPtr(aPtr);
}
#endif
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM nsrefcnt
nsTraceRefcnt::LogAddRefCall(void* aPtr,
nsrefcnt aNewRefcnt,
const char* aFile,
int aLine)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
#ifdef NS_LOSING_ARCHITECTURE
if (!gInitialized)
InitTraceLog();
if (gRefcntsLog) {
LOCK_TRACELOG();
fprintf(gRefcntsLog, "\n<Call> 0x%08X AddRef %d=>%d in %s (line %d)\n",
aPtr, aNewRefcnt-1, aNewRefcnt, aFile, aLine);
WalkTheStack(gRefcntsLog);
UNLOCK_TRACELOG();
}
#endif
#endif
return aNewRefcnt;
}
NS_COM nsrefcnt
nsTraceRefcnt::LogReleaseCall(void* aPtr,
nsrefcnt aNewRefcnt,
const char* aFile,
int aLine)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
#ifdef NS_LOSING_ARCHITECTURE
if (!gInitialized)
InitTraceLog();
if (gRefcntsLog) {
LOCK_TRACELOG();
fprintf(gRefcntsLog, "\n<Call> 0x%08X Release %d=>%d in %s (line %d)\n",
aPtr, aNewRefcnt+1, aNewRefcnt, aFile, aLine);
WalkTheStack(gRefcntsLog);
UNLOCK_TRACELOG();
}
#endif
#endif
return aNewRefcnt;
}
NS_COM void
nsTraceRefcnt::LogNewXPCOM(void* aPtr,
NS_IMETHODIMP
nsTraceRefcntImpl::LogCtor(void* aPtr,
const char* aType,
PRUint32 aInstanceSize,
const char* aFile,
int aLine)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
#ifdef NS_LOSING_ARCHITECTURE
if (!gInitialized)
InitTraceLog();
if (gAllocLog) {
LOCK_TRACELOG();
fprintf(gAllocLog, "\n<%s> 0x%08X NewXPCOM in %s (line %d)\n",
aType, aPtr, aFile, aLine);
WalkTheStack(gAllocLog);
UNLOCK_TRACELOG();
}
#endif
#endif
}
NS_COM void
nsTraceRefcnt::LogDeleteXPCOM(void* aPtr,
const char* aFile,
int aLine)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
#ifdef NS_LOSING_ARCHITECTURE
if (!gInitialized)
InitTraceLog();
if (gAllocLog) {
LOCK_TRACELOG();
fprintf(gAllocLog, "\n<%s> 0x%08X Destroy in %s (line %d)\n",
"?", aPtr, aFile, aLine);
WalkTheStack(gAllocLog);
UNLOCK_TRACELOG();
}
#endif
#endif
}
NS_COM void
nsTraceRefcnt::LogCtor(void* aPtr,
const char* aType,
PRUint32 aInstanceSize)
PRUint32 aInstanceSize)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
@ -1415,31 +1256,30 @@ nsTraceRefcnt::LogCtor(void* aPtr,
}
}
#ifndef NS_LOSING_ARCHITECTURE
PRBool loggingThisType = (!gTypesToLog || LogThisType(aType));
PRInt32 serialno = 0;
if (gSerialNumbers && loggingThisType) {
serialno = GetSerialNumber(aPtr, PR_TRUE);
}
// (If we're on a losing architecture, don't do this because we'll be
// using LogNewXPCOM instead to get file and line numbers.)
PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
if (gAllocLog && loggingThisType && loggingThisObject) {
fprintf(gAllocLog, "\n<%s> 0x%08X %d Ctor (%d)\n",
aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
WalkTheStack(gAllocLog);
}
#endif
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM void
nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
PRUint32 aInstanceSize)
NS_IMETHODIMP
nsTraceRefcntImpl::LogDtor(void* aPtr,
const char* aType,
PRUint32 aInstanceSize)
{
#ifdef NS_BUILD_REFCNT_LOGGING
ASSERT_ACTIVITY_IS_LEGAL;
@ -1456,7 +1296,6 @@ nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
}
}
#ifndef NS_LOSING_ARCHITECTURE
PRBool loggingThisType = (!gTypesToLog || LogThisType(aType));
PRInt32 serialno = 0;
if (gSerialNumbers && loggingThisType) {
@ -1473,15 +1312,16 @@ nsTraceRefcnt::LogDtor(void* aPtr, const char* aType,
aType, NS_PTR_TO_INT32(aPtr), serialno, aInstanceSize);
WalkTheStack(gAllocLog);
}
#endif
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM void
nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
NS_IMETHODIMP
nsTraceRefcntImpl::LogAddCOMPtr(void* aCOMPtr,
nsISupports* aObject)
{
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
@ -1508,7 +1348,6 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
if(count)
(*count)++;
#ifndef NS_LOSING_ARCHITECTURE
PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
if (gCOMPtrLog && loggingThisObject) {
@ -1516,16 +1355,17 @@ nsTraceRefcnt::LogAddCOMPtr(void* aCOMPtr,
NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
WalkTheStack(gCOMPtrLog);
}
#endif
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM void
nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
nsISupports* aObject)
NS_IMETHODIMP
nsTraceRefcntImpl::LogReleaseCOMPtr(void* aCOMPtr,
nsISupports* aObject)
{
#if defined(NS_BUILD_REFCNT_LOGGING) && defined(HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR)
// Get the most-derived object.
@ -1551,7 +1391,6 @@ nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
if(count)
(*count)--;
#ifndef NS_LOSING_ARCHITECTURE
PRBool loggingThisObject = (!gObjectsToLog || LogThisObj(serialno));
if (gCOMPtrLog && loggingThisObject) {
@ -1559,10 +1398,69 @@ nsTraceRefcnt::LogReleaseCOMPtr(void* aCOMPtr,
NS_PTR_TO_INT32(object), serialno, count?(*count):-1, NS_PTR_TO_INT32(aCOMPtr));
WalkTheStack(gCOMPtrLog);
}
#endif
UNLOCK_TRACELOG();
}
#endif
return NS_OK;
}
NS_COM void
nsTraceRefcntImpl::Startup()
{
#ifdef NS_BUILD_REFCNT_LOGGING
SetActivityIsLegal(PR_TRUE);
#endif
}
NS_COM void
nsTraceRefcntImpl::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
nsTraceRefcntImpl::SetActivityIsLegal(PRBool aLegal)
{
#ifdef NS_BUILD_REFCNT_LOGGING
gActivityIsLegal = aLegal;
#endif
}
NS_METHOD
nsTraceRefcntImpl::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
{
*aInstancePtr = nsnull;
nsITraceRefcnt* tracer = new nsTraceRefcntImpl();
if (!tracer)
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = tracer->QueryInterface(aIID, aInstancePtr);
if (NS_FAILED(rv)) {
delete tracer;
}
return rv;
}

Просмотреть файл

@ -35,199 +35,23 @@
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTraceRefcnt_h___
#define nsTraceRefcnt_h___
#ifndef nsTraceRefcntImpl_h___
#define nsTraceRefcntImpl_h___
#include "nsCom.h"
#include "nsITraceRefcnt.h"
#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
// function, then define this to symbol. When the symbol is defined
// then the NS_LOG_ADDREF_CALL and NS_LOG_RELEASE_CALL will expand
// differently.
#undef NS_LOSING_ARCHITECTURE
// By default refcnt logging is not part of the build.
#undef NS_BUILD_REFCNT_LOGGING
#if (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
// Make refcnt logging part of the build. This doesn't mean that
// actual logging will occur (that requires a separate enable; see
// nsTraceRefcnt.h for more information).
#define NS_BUILD_REFCNT_LOGGING 1
#endif
// If NO_BUILD_REFCNT_LOGGING is defined then disable refcnt logging
// in the build. This overrides FORCE_BUILD_REFCNT_LOGGING.
#if defined(NO_BUILD_REFCNT_LOGGING)
#undef NS_BUILD_REFCNT_LOGGING
#endif
// Disable refcnt logging if we are in xpcom glue
// Bug #151072
#if defined(XPCOM_GLUE)
#undef NS_BUILD_REFCNT_LOGGING
#endif
#ifdef NS_BUILD_REFCNT_LOGGING
#define NS_LOG_ADDREF(_p, _rc, _type, _size) \
nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32) (_size))
#define NS_LOG_RELEASE(_p, _rc, _type) \
nsTraceRefcnt::LogRelease((_p), (_rc), (_type))
#ifdef NS_LOSING_ARCHITECTURE
#define NS_LOG_ADDREF_CALL(_p,_rc,_file,_line) \
nsTraceRefcnt::LogAddRefCall((_p), (_rc), (_file), (_line))
#define NS_LOG_RELEASE_CALL(_p,_rc,_file,_line) \
nsTraceRefcnt::LogReleaseCall((_p), (_rc), (_file), (_line))
#define NS_LOG_NEW_XPCOM(_p,_type,_size,_file,_line) \
nsTraceRefcnt::LogNewXPCOM((_p),(_type),(PRUint32)(_size),(_file),(_line))
#define NS_LOG_DELETE_XPCOM(_p,_file,_line) \
nsTraceRefcnt::LogDeleteXPCOM((_p),(_file),(_line))
#else
#define NS_LOG_ADDREF_CALL(_p,_rc,_file,_line) _rc
#define NS_LOG_RELEASE_CALL(_p,_rc,_file,_line) _rc
#define NS_LOG_NEW_XPCOM(_p,_type,_size,_file,_line)
#define NS_LOG_DELETE_XPCOM(_p,_file,_line)
#endif
#define MOZ_DECL_CTOR_COUNTER(_type)
#define MOZ_COUNT_CTOR(_type) \
PR_BEGIN_MACRO \
nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this)); \
PR_END_MACRO
#define MOZ_COUNT_DTOR(_type) \
PR_BEGIN_MACRO \
nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this)); \
PR_END_MACRO
#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR // from autoconf (XXX needs to be
// set for non-autoconf platforms)
// nsCOMPtr.h allows these macros to be defined by clients
// 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),NS_STATIC_CAST(nsISupports*,_p))
#define NSCAP_LOG_RELEASE(_c, _p) \
if (_p) \
nsTraceRefcnt::LogReleaseCOMPtr((_c), NS_STATIC_CAST(nsISupports*,_p))
#define NSCAP_ADDREF(_c, _p) NS_ADDREF(_p)
#define NSCAP_RELEASE(_c, _p) NS_RELEASE(_p)
#endif /* HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR */
#else /* !NS_BUILD_REFCNT_LOGGING */
#define NS_LOG_ADDREF(_p, _rc, _type, _size)
#define NS_LOG_RELEASE(_p, _rc, _type)
#define NS_LOG_NEW_XPCOM(_p,_type,_size,_file,_line)
#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_COUNT_CTOR(_type)
#define MOZ_COUNT_DTOR(_type)
#endif /* NS_BUILD_REFCNT_LOGGING */
//----------------------------------------------------------------------
struct nsTraceRefcntStats {
nsrefcnt mAddRefs;
nsrefcnt mReleases;
nsrefcnt mCreates;
nsrefcnt mDestroys;
double mRefsOutstandingTotal;
double mRefsOutstandingSquared;
double mObjsOutstandingTotal;
double mObjsOutstandingSquared;
};
// Function type used by GatherStatistics. For each type that data has
// been gathered for, this function is called with the counts of the
// various operations that have been logged. The function can return
// PR_FALSE if the gathering should stop.
//
// aCurrentStats is the current value of the counters. aPrevStats is
// the previous value of the counters which is established by the
// nsTraceRefcnt::SnapshotStatistics call.
typedef PRBool (PR_CALLBACK *nsTraceRefcntStatFunc)
(const char* aTypeName,
PRUint32 aInstanceSize,
nsTraceRefcntStats* aCurrentStats,
nsTraceRefcntStats* aPrevStats,
void *aClosure);
/**
* Note: The implementations for these methods are no-ops in a build
* where NS_BUILD_REFCNT_LOGGING is disabled.
*/
class nsTraceRefcnt {
class nsTraceRefcntImpl : public nsITraceRefcnt
{
public:
static NS_COM void Startup();
NS_DECL_ISUPPORTS
NS_DECL_NSITRACEREFCNT
nsTraceRefcntImpl();
virtual ~nsTraceRefcntImpl();
static NS_COM void Startup();
static NS_COM void Shutdown();
static NS_COM void LogAddRef(void* aPtr,
nsrefcnt aNewRefCnt,
const char* aTypeName,
PRUint32 aInstanceSize);
static NS_COM void LogRelease(void* aPtr,
nsrefcnt aNewRefCnt,
const char* aTypeName);
static NS_COM void LogNewXPCOM(void* aPtr,
const char* aTypeName,
PRUint32 aInstanceSize,
const char* aFile,
int aLine);
static NS_COM void LogDeleteXPCOM(void* aPtr,
const char* aFile,
int aLine);
static NS_COM nsrefcnt LogAddRefCall(void* aPtr,
nsrefcnt aNewRefcnt,
const char* aFile,
int aLine);
static NS_COM nsrefcnt LogReleaseCall(void* aPtr,
nsrefcnt aNewRefcnt,
const char* aFile,
int aLine);
static NS_COM void LogCtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize);
static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize);
static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
enum StatisticsType {
ALL_STATS,
NEW_STATS
@ -238,28 +62,35 @@ public:
static NS_COM void ResetStatistics(void);
static NS_COM void GatherStatistics(nsTraceRefcntStatFunc aFunc,
void* aClosure);
static NS_COM void LoadLibrarySymbols(const char* aLibraryName,
void* aLibrayHandle);
static NS_COM void DemangleSymbol(const char * aSymbol,
char * aBuffer,
int aBufLen);
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);
static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
};
#define NS_TRACE_REFCNT_CONTRACTID "@mozilla.org/xpcom/trace-refcnt;1"
#define NS_TRACE_REFCNT_CLASSNAME "nsTraceRefcnt Interface"
#define NS_TRACE_REFCNT_CID \
{ /* e3e7511e-a395-4924-94b1-d527861cded4 */ \
0xe3e7511e, \
0xa395, \
0x4924, \
{0x94, 0xb1, 0xd5, 0x27, 0x86, 0x1c, 0xde, 0xd4} \
} \
////////////////////////////////////////////////////////////////////////////////
// And now for that utility that you've all been asking for...
@ -268,4 +99,4 @@ NS_MeanAndStdDev(double n, double sumOfValues, double sumOfSquaredValues,
double *meanResult, double *stdDevResult);
////////////////////////////////////////////////////////////////////////////////
#endif /* nsTraceRefcnt_h___ */
#endif

Просмотреть файл

@ -48,6 +48,7 @@
#include "nsIThread.h"
#include "nsDeque.h"
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
#include "nsXPIDLString.h"
#include "nsIEnumerator.h"
#include "nsEnumeratorUtils.h"
@ -117,7 +118,8 @@ void XXXNeverCalled()
a.Free(0, 0);
nsIThread::GetCurrent(nsnull);
nsDeque(nsnull);
nsTraceRefcnt::DumpStatistics();
nsTraceRefcnt::LogAddCOMPtr(nsnull, nsnull);
nsTraceRefcntImpl::DumpStatistics();
NS_NewEmptyEnumerator(nsnull);
nsArrayEnumerator(nsnull);
NS_QuickSort(nsnull, 0, 0, nsnull, nsnull);

Просмотреть файл

@ -52,6 +52,7 @@ class nsILocalFile;
class nsIDirectoryServiceProvider;
class nsIMemory;
class nsIDebug;
class nsITraceRefcnt;
/**
* Initialises XPCOM. You must call this method before proceeding
@ -197,4 +198,7 @@ NS_NewNativeLocalFile(const nsACString &path,
extern "C" NS_COM nsresult
NS_GetDebug(nsIDebug* *result);
extern "C" NS_COM nsresult
NS_GetTraceRefcnt(nsITraceRefcnt* *result);
#endif

Просмотреть файл

@ -81,6 +81,7 @@ typedef nsresult (PR_CALLBACK *NewLocalFileFunc)(const nsAString &path, PRBool f
typedef nsresult (PR_CALLBACK *NewNativeLocalFileFunc)(const nsACString &path, PRBool followLinks, nsILocalFile* *result);
typedef nsresult (PR_CALLBACK *GetDebugFunc)(nsIDebug* *result);
typedef nsresult (PR_CALLBACK *GetTraceRefcntFunc)(nsITraceRefcnt* *result);
// PRIVATE
typedef nsresult (PR_CALLBACK *RegisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine, PRUint32 priority);
typedef nsresult (PR_CALLBACK *UnregisterXPCOMExitRoutineFunc)(XPCOMExitRoutine exitRoutine);
@ -103,6 +104,7 @@ typedef struct XPCOMFunctions{
// Added Post 1.4
GetDebugFunc getDebug;
GetTraceRefcntFunc getTraceRefcnt;
} XPCOMFunctions;

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsMemoryImpl.h"
#include "nsDebugImpl.h"
#include "nsTraceRefcntImpl.h"
#include "nsErrorService.h"
#include "nsByteBuffer.h"
@ -385,6 +386,27 @@ nsresult NS_COM NS_GetDebug(nsIDebug** result)
return rv;
}
#ifdef NS_BUILD_REFCNT_LOGGING
// gTraceRefcnt will be freed during shutdown.
static nsITraceRefcnt* gTraceRefcnt = nsnull;
#endif
nsresult NS_COM NS_GetTraceRefcnt(nsITraceRefcnt** result)
{
#ifdef NS_BUILD_REFCNT_LOGGING
nsresult rv = NS_OK;
if (!gTraceRefcnt)
{
rv = nsTraceRefcntImpl::Create(nsnull,
NS_GET_IID(nsITraceRefcnt),
(void**)&gTraceRefcnt);
}
NS_IF_ADDREF(*result = gTraceRefcnt);
return rv;
#else
return NS_ERROR_NOT_INITIALIZED;
#endif
}
nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
nsIFile* binDirectory)
@ -406,7 +428,7 @@ nsresult NS_COM NS_InitXPCOM2(nsIServiceManager* *result,
gXPCOMShuttingDown = PR_FALSE;
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::Startup();
nsTraceRefcntImpl::Startup();
#endif
// Establish the main thread here.
@ -777,9 +799,9 @@ nsresult NS_COM NS_ShutdownXPCOM(nsIServiceManager* servMgr)
NS_IF_RELEASE(gDebug);
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::DumpStatistics();
nsTraceRefcnt::ResetStatistics();
nsTraceRefcnt::Shutdown();
nsTraceRefcntImpl::DumpStatistics();
nsTraceRefcntImpl::ResetStatistics();
nsTraceRefcntImpl::Shutdown();
#endif
#ifdef GC_LEAK_DETECTOR
@ -857,7 +879,13 @@ NS_GetFrozenFunctions(XPCOMFunctions *functions, const char* libraryPath)
}
functions->getDebug = (GetDebugFunc) PR_FindSymbol(xpcomLib, "NS_GetDebug");
if (! functions->unregisterExitRoutine) {
if (! functions->getDebug) {
PR_UnloadLibrary(xpcomLib);
return NS_ERROR_FAILURE;
}
functions->getTraceRefcnt = (GetTraceRefcntFunc) PR_FindSymbol(xpcomLib, "NS_GetTraceRefcnt");
if (! functions->getTraceRefcnt) {
PR_UnloadLibrary(xpcomLib);
return NS_ERROR_FAILURE;
}

Просмотреть файл

@ -457,7 +457,7 @@ nsNativeComponentLoader::SelfRegisterDll(nsDll *dll,
//
#if defined(MOZ_DEMANGLE_SYMBOLS)
#include "nsTraceRefcnt.h" // for nsTraceRefcnt::DemangleSymbol()
#include "nsTraceRefcntImpl.h" // for nsTraceRefcntImpl::DemangleSymbol()
#endif
nsresult
@ -491,7 +491,7 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll,
char demangled[4096] = "\0";
nsTraceRefcnt::DemangleSymbol(symbol.get(),demangled,sizeof(demangled));
nsTraceRefcntImpl::DemangleSymbol(symbol.get(),demangled,sizeof(demangled));
if (demangled && *demangled != '\0')
demangledSymbol = demangled;

Просмотреть файл

@ -64,6 +64,8 @@
#endif
#endif /* defined(DEBUG) */
#include "nsTraceRefcntImpl.h"
#define UNLOAD_DEPENDENT_LIBS
#ifdef HPUX
#undef UNLOAD_DEPENDENT_LIBS
@ -131,7 +133,7 @@ PRBool nsDll::Load(void)
if (m_dllSpec)
{
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::SetActivityIsLegal(PR_FALSE);
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
#endif
// Load any library dependencies
@ -250,13 +252,13 @@ PRBool nsDll::Load(void)
#endif
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::SetActivityIsLegal(PR_TRUE);
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
if (m_instance) {
// Inform refcnt tracer of new library so that calls through the
// new library can be traced.
nsXPIDLCString displayPath;
GetDisplayPath(displayPath);
nsTraceRefcnt::LoadLibrarySymbols(displayPath.get(), m_instance);
nsTraceRefcntImpl::LoadLibrarySymbols(displayPath.get(), m_instance);
}
#endif
}
@ -282,11 +284,11 @@ PRBool nsDll::Unload(void)
Shutdown();
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::SetActivityIsLegal(PR_FALSE);
nsTraceRefcntImpl::SetActivityIsLegal(PR_FALSE);
#endif
PRStatus ret = PR_UnloadLibrary(m_instance);
#ifdef NS_BUILD_REFCNT_LOGGING
nsTraceRefcnt::SetActivityIsLegal(PR_TRUE);
nsTraceRefcntImpl::SetActivityIsLegal(PR_TRUE);
#endif
if (ret == PR_SUCCESS)

Просмотреть файл

@ -22,7 +22,7 @@
#include "nscore.h"
#include "nsStatistics.h"
#include "nsISupportsUtils.h"
#include "nsTraceRefcnt.h" // for NS_MeanAndStdDev
#include "nsTraceRefcntImpl.h" // for NS_MeanAndStdDev
#include "plhash.h"
inline PLHashNumber

Просмотреть файл

@ -200,7 +200,7 @@ struct PLDHashTable {
PRUint32 steps; /* hash chain links traversed */
PRUint32 hits; /* searches that found key */
PRUint32 misses; /* searches that didn't find key */
PRUint32 lookups; /* number of PL_DHASH_LOOKUPs */
PRUint32 lookups; /* number of PL_DHASH_LIVEOKUPs */
PRUint32 addMisses; /* adds that miss, and do work */
PRUint32 addOverRemoved; /* adds that recycled a removed entry */
PRUint32 addHits; /* adds that hit an existing entry */

Просмотреть файл

@ -49,21 +49,7 @@
#include "pratom.h" /* needed for PR_AtomicIncrement and PR_AtomicDecrement */
#include "nsDebug.h"
#ifdef XPCOM_GLUE
// nsTraceRefcnt needs a cleaning...
#define NS_LOG_ADDREF(_p, _rc, _type, _size)
#define NS_LOG_RELEASE(_p, _rc, _type)
#define NS_LOG_NEW_XPCOM(_p,_type,_size,_file,_line)
#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_COUNT_CTOR(_type)
#define MOZ_COUNT_DTOR(_type)
#else
#include "nsTraceRefcnt.h"
#endif
////////////////////////////////////////////////////////////////////////////////
// Macros to help detect thread-safety:

Просмотреть файл

@ -63,7 +63,6 @@
/**
* Macro for instantiating a new object that implements nsISupports.
* Use this in your factory methods to allow for refcnt tracing.
* Note that you can only use this if you adhere to the no arguments
* constructor com policy (which you really should!).
* @param _result Where the new instance pointer is stored
@ -72,17 +71,14 @@
#define NS_NEWXPCOM(_result,_type) \
PR_BEGIN_MACRO \
_result = new _type(); \
NS_LOG_NEW_XPCOM(_result, #_type, sizeof(_type), __FILE__, __LINE__); \
PR_END_MACRO
/**
* Macro for deleting an object that implements nsISupports.
* Use this in your Release methods to allow for refcnt tracing.
* @param _ptr The object to delete.
*/
#define NS_DELETEXPCOM(_ptr) \
PR_BEGIN_MACRO \
NS_LOG_DELETE_XPCOM((_ptr), __FILE__, __LINE__); \
delete (_ptr); \
PR_END_MACRO
@ -91,7 +87,7 @@
* @param _ptr The interface pointer.
*/
#define NS_ADDREF(_ptr) \
NS_LOG_ADDREF_CALL((_ptr), (_ptr)->AddRef(), __FILE__, __LINE__)
(_ptr)->AddRef()
/**
* Macro for adding a reference to this. This macro should be used
@ -100,23 +96,23 @@
* that entire problem.
*/
#define NS_ADDREF_THIS() \
NS_LOG_ADDREF_CALL(this, AddRef(), __FILE__, __LINE__)
AddRef()
extern "C++" {
// ...because some one is accidentally including this file inside
// an |extern "C"|
// Making this a |inline| |template| allows |expr| to be evaluated only once,
// yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
template <class T>
inline
nsrefcnt
ns_if_addref( T expr )
// Making this a |inline| |template| allows |expr| to be evaluated only once,
// yet still denies you the ability to |AddRef()| an |nsCOMPtr|.
// Note that |NS_ADDREF()| already has this property in the non-logging case.
{
{
return expr ? expr->AddRef() : 0;
}
}
} /* extern "C++" */
@ -124,18 +120,10 @@ ns_if_addref( T expr )
* Macro for adding a reference to an interface that checks for NULL.
* @param _expr The interface pointer.
*/
#ifdef NS_BUILD_REFCNT_LOGGING
#define NS_IF_ADDREF(_expr) \
((0 != (_expr)) \
? NS_LOG_ADDREF_CALL((_expr), ns_if_addref(_expr), __FILE__, __LINE__) \
: 0)
#else
#define NS_IF_ADDREF(_expr) ns_if_addref(_expr)
#endif
/*
* Given these declarations, it explicitly OK and (in the non-logging build) efficient
* to end a `getter' with:
* Given these declarations, it explicitly OK and efficient to end a `getter' with:
*
* NS_IF_ADDREF(*result = mThing);
*
@ -143,37 +131,22 @@ ns_if_addref( T expr )
* _illegal_ to say |NS_IF_ADDREF(mThing)|.
*/
/**
* Macro for releasing a reference to an interface.
*
* Note that when NS_LOSING_ARCHITECTURE is defined that the release will
* be done before the trace message is logged. If the reference count
* goes to zero and implementation of Release logs a message, the two
* messages will be logged out of order.
*
* @param _ptr The interface pointer.
*/
#define NS_RELEASE(_ptr) \
PR_BEGIN_MACRO \
NS_LOG_RELEASE_CALL((_ptr), (_ptr)->Release(), __FILE__, __LINE__); \
(_ptr)->Release(); \
(_ptr) = 0; \
PR_END_MACRO
/**
* Macro for releasing a reference to an interface.
*
* Note that when NS_LOSING_ARCHITECTURE is defined that the release will
* be done before the trace message is logged. If the reference count
* goes to zero and implementation of Release logs a message, the two
* messages will be logged out of order.
*
* @param _ptr The interface pointer.
*/
#define NS_RELEASE_THIS() \
NS_LOG_RELEASE_CALL(this, Release(), __FILE__, __LINE__)
Release()
/**
* Macro for releasing a reference to an interface, except that this
@ -181,33 +154,22 @@ ns_if_addref( T expr )
* The interface pointer argument will only be NULLed if the reference count
* goes to zero.
*
* Note that when NS_LOSING_ARCHITECTURE is defined that the release will
* be done before the trace message is logged. If the reference count
* goes to zero and implementation of Release logs a message, the two
* messages will be logged out of order.
*
* @param _ptr The interface pointer.
*/
#define NS_RELEASE2(_ptr,_rv) \
PR_BEGIN_MACRO \
_rv = NS_LOG_RELEASE_CALL((_ptr), (_ptr)->Release(),__FILE__,__LINE__); \
_rv = (_ptr)->Release(); \
if (0 == (_rv)) (_ptr) = 0; \
PR_END_MACRO
/**
* Macro for releasing a reference to an interface that checks for NULL;
*
* Note that when NS_LOSING_ARCHITECTURE is defined that the release will
* be done before the trace message is logged. If the reference count
* goes to zero and implementation of Release logs a message, the two
* messages will be logged out of order.
*
* @param _ptr The interface pointer.
*/
#define NS_IF_RELEASE(_ptr) \
PR_BEGIN_MACRO \
if (_ptr) { \
NS_LOG_RELEASE_CALL((_ptr), (_ptr)->Release(), __FILE__, __LINE__); \
(_ptr)->Release(); \
(_ptr) = 0; \
} \
PR_END_MACRO
@ -228,9 +190,6 @@ ns_if_addref( T expr )
#define NS_ISUPPORTS_CAST(__unambiguousBase, __expr) \
NS_STATIC_CAST(nsISupports*, NS_STATIC_CAST(__unambiguousBase, __expr))
extern "C++" {
// ...because some one is accidentally including this file inside
// an |extern "C"|
@ -239,17 +198,17 @@ class nsISupports;
template <class T>
struct nsCOMTypeInfo
{
{
static const nsIID& GetIID() { return T::GetIID(); }
};
};
NS_SPECIALIZE_TEMPLATE
struct nsCOMTypeInfo<nsISupports>
{
{
static const nsIID& GetIID() {
static const nsIID iid_NS_ISUPPORTS_IID = NS_ISUPPORTS_IID; return iid_NS_ISUPPORTS_IID;
}
};
};
#define NS_GET_IID(T) nsCOMTypeInfo<T>::GetIID()
@ -258,13 +217,13 @@ template <class T, class DestinationType>
inline
nsresult
CallQueryInterface( T* aSource, DestinationType** aDestination )
{
{
NS_PRECONDITION(aSource, "null parameter");
NS_PRECONDITION(aDestination, "null parameter");
return aSource->QueryInterface(NS_GET_IID(DestinationType),
NS_REINTERPRET_CAST(void**, aDestination));
}
}
} // extern "C++"

Просмотреть файл

@ -0,0 +1,125 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is XPCOM
*
* The Initial Developer of the Original Code is Doug Turner <dougt@meer.net>
*
* Portions created by the Initial Developer are Copyright (C) 2003
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsXPCOM.h"
#include "nsXPCOMPrivate.h"
#include "nsCOMPtr.h"
#include "nsIServiceManager.h"
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
static nsITraceRefcnt* gTraceRefcntObject = nsnull;
static NS_METHOD FreeTraceRefcntObject(void)
{
NS_IF_RELEASE(gTraceRefcntObject);
return NS_OK;
}
#define ENSURE_TRACEOBJECT \
(gTraceRefcntObject || SetupTraceRefcntObject() != nsnull)
static nsITraceRefcnt* SetupTraceRefcntObject()
{
NS_GetTraceRefcnt(&gTraceRefcntObject);
if (gTraceRefcntObject)
NS_RegisterXPCOMExitRoutine(FreeTraceRefcntObject, 0);
return gTraceRefcntObject;
}
#ifdef XPCOM_GLUE
nsresult GlueStartupTraceRefcnt()
{
NS_GetTraceRefcnt(&gTraceRefcntObject);
if (!gTraceRefcntObject)
return NS_ERROR_FAILURE;
return NS_OK;
}
void GlueShutdownTraceRefcnt()
{
NS_IF_RELEASE(gTraceRefcntObject);
}
#endif
NS_COM void
nsTraceRefcnt::LogAddRef(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName, PRUint32 aInstanceSize)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogAddRef(aPtr, aNewRefcnt, aTypeName, aInstanceSize);
}
NS_COM void
nsTraceRefcnt::LogRelease(void * aPtr, nsrefcnt aNewRefcnt, const char *aTypeName)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogRelease(aPtr, aNewRefcnt, aTypeName);
}
NS_COM void
nsTraceRefcnt::LogCtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogCtor(aPtr, aTypeName, aInstanceSize);
}
NS_COM void
nsTraceRefcnt::LogDtor(void * aPtr, const char *aTypeName, PRUint32 aInstanceSize)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogDtor(aPtr, aTypeName, aInstanceSize);
}
NS_COM void
nsTraceRefcnt::LogAddCOMPtr(void * aPtr, nsISupports *aObject)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogAddCOMPtr(aPtr, aObject);
}
NS_COM void
nsTraceRefcnt::LogReleaseCOMPtr(void * aPtr, nsISupports *aObject)
{
if (!ENSURE_TRACEOBJECT)
return;
gTraceRefcntObject->LogReleaseCOMPtr(aPtr, aObject);
}

137
xpcom/glue/nsTraceRefcnt.h Normal file
Просмотреть файл

@ -0,0 +1,137 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Netscape Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Communicator client code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* L. David Baron <dbaron@dbaron.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the NPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the NPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsTraceRefcnt_h___
#define nsTraceRefcnt_h___
#include "nsCom.h"
#include <stdio.h>
class nsISupports;
// By default refcnt logging is not part of the build.
#undef NS_BUILD_REFCNT_LOGGING
#if (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
// Make refcnt logging part of the build. This doesn't mean that
// actual logging will occur (that requires a separate enable; see
// nsTraceRefcnt.h for more information).
#define NS_BUILD_REFCNT_LOGGING 1
#endif
// If NO_BUILD_REFCNT_LOGGING is defined then disable refcnt logging
// in the build. This overrides FORCE_BUILD_REFCNT_LOGGING.
#if defined(NO_BUILD_REFCNT_LOGGING)
#undef NS_BUILD_REFCNT_LOGGING
#endif
#ifdef NS_BUILD_REFCNT_LOGGING
#define NS_LOG_ADDREF(_p, _rc, _type, _size) \
nsTraceRefcnt::LogAddRef((_p), (_rc), (_type), (PRUint32) (_size))
#define NS_LOG_RELEASE(_p, _rc, _type) \
nsTraceRefcnt::LogRelease((_p), (_rc), (_type))
#define MOZ_DECL_CTOR_COUNTER(_type)
#define MOZ_COUNT_CTOR(_type) \
PR_BEGIN_MACRO \
nsTraceRefcnt::LogCtor((void*)this, #_type, sizeof(*this)); \
PR_END_MACRO
#define MOZ_COUNT_DTOR(_type) \
PR_BEGIN_MACRO \
nsTraceRefcnt::LogDtor((void*)this, #_type, sizeof(*this)); \
PR_END_MACRO
#ifdef HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR // from autoconf (XXX needs to be
// set for non-autoconf platforms)
// nsCOMPtr.h allows these macros to be defined by clients
// 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),NS_STATIC_CAST(nsISupports*,_p))
#define NSCAP_LOG_RELEASE(_c, _p) \
if (_p) \
nsTraceRefcnt::LogReleaseCOMPtr((_c), NS_STATIC_CAST(nsISupports*,_p))
#endif /* HAVE_CPP_DYNAMIC_CAST_TO_VOID_PTR */
#else /* !NS_BUILD_REFCNT_LOGGING */
#define NS_LOG_ADDREF(_p, _rc, _type, _size)
#define NS_LOG_RELEASE(_p, _rc, _type)
#define MOZ_DECL_CTOR_COUNTER(_type)
#define MOZ_COUNT_CTOR(_type)
#define MOZ_COUNT_DTOR(_type)
#endif /* NS_BUILD_REFCNT_LOGGING */
//----------------------------------------------------------------------
/**
* Note: The implementations for these methods are no-ops in a build
* where NS_BUILD_REFCNT_LOGGING is disabled.
*/
class nsTraceRefcnt {
public:
static NS_COM void LogAddRef(void* aPtr,
nsrefcnt aNewRefCnt,
const char* aTypeName,
PRUint32 aInstanceSize);
static NS_COM void LogRelease(void* aPtr,
nsrefcnt aNewRefCnt,
const char* aTypeName);
static NS_COM void LogCtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize);
static NS_COM void LogDtor(void* aPtr, const char* aTypeName,
PRUint32 aInstanceSize);
static NS_COM void LogAddCOMPtr(void *aCOMPtr, nsISupports *aObject);
static NS_COM void LogReleaseCOMPtr(void *aCOMPtr, nsISupports *aObject);
};
#endif /* nsTraceRefcnt_h___ */

Просмотреть файл

@ -34,22 +34,24 @@
#
# ***** END LICENSE BLOCK *****
XPCOM_GLUE_SRC_LCSRCS = \
nsCOMPtr.cpp \
nsDebug.cpp \
nsGenericFactory.cpp \
XPCOM_GLUE_SRC_LCSRCS = \
nsCOMPtr.cpp \
nsComponentManagerUtils.cpp \
nsDebug.cpp \
nsGenericFactory.cpp \
nsIInterfaceRequestorUtils.cpp \
nsMemory.cpp \
nsWeakReference.cpp \
nsComponentManagerUtils.cpp \
$(NULL)
nsMemory.cpp \
nsTraceRefcnt.cpp \
nsWeakReference.cpp \
$(NULL) \
XPCOM_GLUE_SRC_LEXPORTS = \
nsCOMPtr.h \
nsDebug.h \
nsIGenericFactory.h \
nsGenericFactory.h \
nsIGenericFactory.h \
nsMemory.h \
nsTraceRefcnt.h \
nsWeakReference.h \
$(NULL)

Просмотреть файл

@ -240,6 +240,15 @@ NS_GetDebug(nsIDebug* *result)
return xpcomFunctions->getDebug(result);
}
extern "C" NS_COM nsresult
NS_GetTraceRefcnt(nsITraceRefcnt* *result)
{
if (!xpcomFunctions)
return NS_ERROR_NOT_INITIALIZED;
return xpcomFunctions->getTraceRefcnt(result);
}
#endif // #ifndef XPCOM_GLUE_NO_DYNAMIC_LOADING

Просмотреть файл

@ -77,7 +77,7 @@ static PRBool track_illegal = PR_TRUE;
static PRBool track_latin1 = PR_TRUE;
#ifdef XP_UNIX
#include "nsTraceRefcnt.h"
#include "nsTraceRefcntImpl.h"
class CTraceFile {
public:
CTraceFile() {
@ -104,7 +104,7 @@ public:
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
nsTraceRefcntImpl::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);
@ -127,7 +127,7 @@ public:
fprintf(mFile, "\n");
fprintf(mFile, "ENDDATA\n");
fprintf(mFile, "BEGINSTACK\n");
nsTraceRefcnt::WalkTheStack(mFile);
nsTraceRefcntImpl::WalkTheStack(mFile);
fprintf(mFile, "\n");
fprintf(mFile, "ENDSTACK\n");
fflush(mFile);

Просмотреть файл

@ -1,11 +1,11 @@
#include <stdio.h>
#include "nsISupportsUtils.h"
#include "nsTraceRefCnt.h"
#include "nsTraceRefCntImpl.h"
int main(int argc, char* argv[])
{
nsTraceRefcnt::WalkTheStack(stdout);
nsTraceRefcntImpl::WalkTheStack(stdout);
return 0;
}