diff --git a/mozilla/netwerk/protocol/about/src/nsAboutBloat.cpp b/mozilla/netwerk/protocol/about/src/nsAboutBloat.cpp index 305ef0b418d..c267e96c983 100644 --- a/mozilla/netwerk/protocol/about/src/nsAboutBloat.cpp +++ b/mozilla/netwerk/protocol/about/src/nsAboutBloat.cpp @@ -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 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 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; diff --git a/mozilla/string/obsolete/bufferRoutines.h b/mozilla/string/obsolete/bufferRoutines.h index 5a0ac46b0e1..19d4b47a04c 100644 --- a/mozilla/string/obsolete/bufferRoutines.h +++ b/mozilla/string/obsolete/bufferRoutines.h @@ -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); diff --git a/mozilla/webshell/tests/viewer/nsPhMain.cpp b/mozilla/webshell/tests/viewer/nsPhMain.cpp index 163d5f9b6a6..87fa779685d 100644 --- a/mozilla/webshell/tests/viewer/nsPhMain.cpp +++ b/mozilla/webshell/tests/viewer/nsPhMain.cpp @@ -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"); diff --git a/mozilla/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp b/mozilla/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp index 6bc9608037a..e3bd61ed4ef 100644 --- a/mozilla/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp +++ b/mozilla/webshell/tests/viewer/unix/gtk/nsGtkMain.cpp @@ -137,7 +137,7 @@ nsNativeBrowserWindow::DispatchMenuItem(PRInt32 aID) #include #include -#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", diff --git a/mozilla/webshell/tests/viewer/unix/gtk2/nsGtkMain.cpp b/mozilla/webshell/tests/viewer/unix/gtk2/nsGtkMain.cpp index 84f6ee56a2b..e22790fc424 100644 --- a/mozilla/webshell/tests/viewer/unix/gtk2/nsGtkMain.cpp +++ b/mozilla/webshell/tests/viewer/unix/gtk2/nsGtkMain.cpp @@ -135,7 +135,7 @@ nsNativeBrowserWindow::DispatchMenuItem(PRInt32 aID) #include #include -#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", diff --git a/mozilla/xpcom/base/Makefile.in b/mozilla/xpcom/base/Makefile.in index 2ff8ff27ce5..3180c74874c 100644 --- a/mozilla/xpcom/base/Makefile.in +++ b/mozilla/xpcom/base/Makefile.in @@ -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) diff --git a/mozilla/xpcom/base/nsIDebug.idl b/mozilla/xpcom/base/nsIDebug.idl index 0ab3836e990..73b3912a7a0 100644 --- a/mozilla/xpcom/base/nsIDebug.idl +++ b/mozilla/xpcom/base/nsIDebug.idl @@ -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)] diff --git a/mozilla/xpcom/base/nsITraceRefcnt.idl b/mozilla/xpcom/base/nsITraceRefcnt.idl new file mode 100644 index 00000000000..536861a02f8 --- /dev/null +++ b/mozilla/xpcom/base/nsITraceRefcnt.idl @@ -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 + * + * 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); +}; diff --git a/mozilla/xpcom/base/nsTraceRefcntImpl.cpp b/mozilla/xpcom/base/nsTraceRefcntImpl.cpp index ca06b068ff6..0ca7b16cfbd 100644 --- a/mozilla/xpcom/base/nsTraceRefcntImpl.cpp +++ b/mozilla/xpcom/base/nsTraceRefcntImpl.cpp @@ -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: - - 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 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 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; +} diff --git a/mozilla/xpcom/base/nsTraceRefcntImpl.h b/mozilla/xpcom/base/nsTraceRefcntImpl.h index 35c3e4148c5..aa6ba7a12b5 100644 --- a/mozilla/xpcom/base/nsTraceRefcntImpl.h +++ b/mozilla/xpcom/base/nsTraceRefcntImpl.h @@ -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 - -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, 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 diff --git a/mozilla/xpcom/build/dlldeps.cpp b/mozilla/xpcom/build/dlldeps.cpp index ad1cffd92f8..f71c55088bf 100644 --- a/mozilla/xpcom/build/dlldeps.cpp +++ b/mozilla/xpcom/build/dlldeps.cpp @@ -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); diff --git a/mozilla/xpcom/build/nsXPCOM.h b/mozilla/xpcom/build/nsXPCOM.h index 61fcf617466..389c1686af6 100644 --- a/mozilla/xpcom/build/nsXPCOM.h +++ b/mozilla/xpcom/build/nsXPCOM.h @@ -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 diff --git a/mozilla/xpcom/build/nsXPCOMPrivate.h b/mozilla/xpcom/build/nsXPCOMPrivate.h index dca1b984d29..67b21c24478 100644 --- a/mozilla/xpcom/build/nsXPCOMPrivate.h +++ b/mozilla/xpcom/build/nsXPCOMPrivate.h @@ -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; diff --git a/mozilla/xpcom/build/nsXPComInit.cpp b/mozilla/xpcom/build/nsXPComInit.cpp index 622e0073cb7..96119b6687f 100644 --- a/mozilla/xpcom/build/nsXPComInit.cpp +++ b/mozilla/xpcom/build/nsXPComInit.cpp @@ -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; } diff --git a/mozilla/xpcom/components/nsNativeComponentLoader.cpp b/mozilla/xpcom/components/nsNativeComponentLoader.cpp index 7637dc278fe..ce5c8d4cb4e 100644 --- a/mozilla/xpcom/components/nsNativeComponentLoader.cpp +++ b/mozilla/xpcom/components/nsNativeComponentLoader.cpp @@ -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; diff --git a/mozilla/xpcom/components/xcDll.cpp b/mozilla/xpcom/components/xcDll.cpp index 6cdca2a14ac..9ed758c381f 100644 --- a/mozilla/xpcom/components/xcDll.cpp +++ b/mozilla/xpcom/components/xcDll.cpp @@ -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) diff --git a/mozilla/xpcom/ds/nsStatistics.cpp b/mozilla/xpcom/ds/nsStatistics.cpp index dd857bd0ac1..8008a942523 100644 --- a/mozilla/xpcom/ds/nsStatistics.cpp +++ b/mozilla/xpcom/ds/nsStatistics.cpp @@ -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 diff --git a/mozilla/xpcom/ds/pldhash.h b/mozilla/xpcom/ds/pldhash.h index 7329a60dc0b..4bc77b07a7f 100644 --- a/mozilla/xpcom/ds/pldhash.h +++ b/mozilla/xpcom/ds/pldhash.h @@ -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 */ diff --git a/mozilla/xpcom/glue/nsISupportsImpl.h b/mozilla/xpcom/glue/nsISupportsImpl.h index 5e5b9ba3944..d1c9b312441 100644 --- a/mozilla/xpcom/glue/nsISupportsImpl.h +++ b/mozilla/xpcom/glue/nsISupportsImpl.h @@ -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: diff --git a/mozilla/xpcom/glue/nsISupportsUtils.h b/mozilla/xpcom/glue/nsISupportsUtils.h index e909fd9757b..0fdf20215b1 100644 --- a/mozilla/xpcom/glue/nsISupportsUtils.h +++ b/mozilla/xpcom/glue/nsISupportsUtils.h @@ -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 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 struct nsCOMTypeInfo - { +{ static const nsIID& GetIID() { return T::GetIID(); } - }; +}; NS_SPECIALIZE_TEMPLATE struct nsCOMTypeInfo - { +{ 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::GetIID() @@ -258,13 +217,13 @@ template 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++" diff --git a/mozilla/xpcom/glue/nsTraceRefcnt.cpp b/mozilla/xpcom/glue/nsTraceRefcnt.cpp new file mode 100644 index 00000000000..14e9469b16d --- /dev/null +++ b/mozilla/xpcom/glue/nsTraceRefcnt.cpp @@ -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 + * + * 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); +} + diff --git a/mozilla/xpcom/glue/nsTraceRefcnt.h b/mozilla/xpcom/glue/nsTraceRefcnt.h new file mode 100644 index 00000000000..d332f5172d0 --- /dev/null +++ b/mozilla/xpcom/glue/nsTraceRefcnt.h @@ -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 + * + * 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 + +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, 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___ */ diff --git a/mozilla/xpcom/glue/objs.mk b/mozilla/xpcom/glue/objs.mk index c59a20a0cce..d6d04a5ac62 100644 --- a/mozilla/xpcom/glue/objs.mk +++ b/mozilla/xpcom/glue/objs.mk @@ -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) diff --git a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp index 2c714dd4ea7..2b2c7115dd1 100644 --- a/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp +++ b/mozilla/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -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 diff --git a/mozilla/xpcom/string/obsolete/bufferRoutines.h b/mozilla/xpcom/string/obsolete/bufferRoutines.h index 5a0ac46b0e1..19d4b47a04c 100644 --- a/mozilla/xpcom/string/obsolete/bufferRoutines.h +++ b/mozilla/xpcom/string/obsolete/bufferRoutines.h @@ -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); diff --git a/mozilla/xpcom/tests/TestStackCrawl.cpp b/mozilla/xpcom/tests/TestStackCrawl.cpp index d6a5a741a01..76187edd4a0 100644 --- a/mozilla/xpcom/tests/TestStackCrawl.cpp +++ b/mozilla/xpcom/tests/TestStackCrawl.cpp @@ -1,11 +1,11 @@ #include #include "nsISupportsUtils.h" -#include "nsTraceRefCnt.h" +#include "nsTraceRefCntImpl.h" int main(int argc, char* argv[]) { - nsTraceRefcnt::WalkTheStack(stdout); + nsTraceRefcntImpl::WalkTheStack(stdout); return 0; }