diff --git a/mozilla/js/src/xpconnect/src/makefile.win b/mozilla/js/src/xpconnect/src/makefile.win index 1abc0c1eac7..285362aa093 100644 --- a/mozilla/js/src/xpconnect/src/makefile.win +++ b/mozilla/js/src/xpconnect/src/makefile.win @@ -44,7 +44,7 @@ DLL =.\$(OBJDIR)\$(DLLNAME).dll MODULE=xpconnect -DEFINES=-DWIN32_LEAN_AND_MEAN -DEXPORT_XPC_API -DJS_THREADSAFE +DEFINES=-DWIN32_LEAN_AND_MEAN -DEXPORT_XPC_API OBJS= \ .\$(OBJDIR)\nsXPConnect.obj \ diff --git a/mozilla/js/src/xpconnect/src/nsXPConnect.cpp b/mozilla/js/src/xpconnect/src/nsXPConnect.cpp index 0a19c772ab3..14682e750e8 100644 --- a/mozilla/js/src/xpconnect/src/nsXPConnect.cpp +++ b/mozilla/js/src/xpconnect/src/nsXPConnect.cpp @@ -270,6 +270,36 @@ nsXPConnect::nsXPConnect() nsServiceManager::GetService("nsThreadJSContextStack", NS_GET_IID(nsIJSContextStack), (nsISupports **)&mContextStack); + +#ifdef XPC_TOOLS_SUPPORT + nsCOMPtr prefs = do_GetService(NS_PREF_PROGID); + if(prefs) + { + char* filename; + if(NS_SUCCEEDED(prefs->CopyCharPref("xpctools.profiler.outputfilename", + &filename)) && filename) + { + mProfilerOutputFile = do_CreateInstance(NS_LOCAL_FILE_PROGID); + if(mProfilerOutputFile && + NS_SUCCEEDED(mProfilerOutputFile->InitWithPath(filename))) + { + mProfiler = do_GetService(XPCTOOLS_PROFILER_PROGID); + if(mProfiler) + { + if(NS_SUCCEEDED(mProfiler->Start())) + { +#ifdef DEBUG + printf("***** profiling JavaScript. Output to: %s\n", + filename); +#endif + } + } + } + nsCRT::free(filename); + } + } +#endif + } nsXPConnect::~nsXPConnect() @@ -317,14 +347,51 @@ nsXPConnect::GetXPConnect() return gSelf; } +// In order to enable this jsgc heap dumping you need to compile +// _both_ js/src/jsgc.c and this file with 'GC_MARK_DEBUG' #defined. +// Normally this is done by adding -DGC_MARK_DEBUG to the appropriate +// defines lists in the makefiles. + +#ifdef GC_MARK_DEBUG +extern "C" JS_FRIEND_DATA(FILE *) js_DumpGCHeap; +#endif + void nsXPConnect::ReleaseXPConnectSingleton() { nsXPConnect* xpc = gSelf; if (xpc) { + +#ifdef XPC_TOOLS_SUPPORT + if(xpc->mProfiler) + { + xpc->mProfiler->Stop(); + xpc->mProfiler->WriteResults(xpc->mProfilerOutputFile); + } +#endif + +#ifdef GC_MARK_DEBUG + // force a dump of the JavaScript gc heap if JS is still alive + if(GetRuntime() && GetRuntime()->GetJSRuntime()) + { + AutoPushCompatibleJSContext a(GetRuntime()->GetJSRuntime()); + if(a.GetJSContext()) + { + FILE* oldFileHandle = js_DumpGCHeap; + js_DumpGCHeap = stdout; + js_ForceGC(a.GetJSContext()); + js_DumpGCHeap = oldFileHandle; + } + } +#endif +#ifdef XPC_DUMP_AT_SHUTDOWN + // NOTE: to see really interesting stuff turn on the prlog stuff. + // See the comment at the top of xpclog.h to see how to do that. + xpc->DebugDump(4); +#endif nsrefcnt cnt; NS_RELEASE2(xpc, cnt); -#if defined(DEBUG_jband) +#ifdef XPC_DUMP_AT_SHUTDOWN if (0 != cnt) { printf("*** dangling reference to nsXPConnect: refcnt=%d\n", cnt); } @@ -426,7 +493,7 @@ nsXPConnect::IsISupportsDescendant(nsIInterfaceInfo* info) nsCOMPtr oldest = info; nsCOMPtr parent; - while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent)))) + while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent))) && parent) { oldest = parent; } diff --git a/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp b/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp index 8399ab14e0f..945d112a7b3 100644 --- a/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp +++ b/mozilla/js/src/xpconnect/src/xpcjsruntime.cpp @@ -53,7 +53,7 @@ const char* XPCJSRuntime::mStrings[] = { XPCJSRuntime::~XPCJSRuntime() { -#ifdef DEBUG_jband +#ifdef XPC_DUMP_AT_SHUTDOWN { // count the total JSContexts in use JSContext* iter = nsnull; @@ -75,7 +75,7 @@ XPCJSRuntime::~XPCJSRuntime() if(mWrappedJSMap) { -#ifdef DEBUG_jband +#ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedJSMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live wrapped JSObjects\n", (int)count); @@ -85,7 +85,7 @@ XPCJSRuntime::~XPCJSRuntime() if(mWrappedJSClassMap) { -#ifdef DEBUG_jband +#ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedJSClassMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live xpcwrappedjsclasses\n", (int)count); @@ -95,7 +95,7 @@ XPCJSRuntime::~XPCJSRuntime() if(mWrappedNativeClassMap) { -#ifdef DEBUG_jband +#ifdef XPC_DUMP_AT_SHUTDOWN uint32 count = mWrappedNativeClassMap->Count(); if(count) printf("deleting XPCJSRuntime with %d live xpcwrappednativeclasses\n", (int)count); @@ -132,7 +132,7 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect, #ifdef DEBUG if(mJSRuntime) xpc_InstallJSDebuggerKeywordHandler(mJSRuntime); -#endif +#endif } // static diff --git a/mozilla/js/src/xpconnect/src/xpcprivate.h b/mozilla/js/src/xpconnect/src/xpcprivate.h index f94c7437274..ad5be41d5d4 100644 --- a/mozilla/js/src/xpconnect/src/xpcprivate.h +++ b/mozilla/js/src/xpconnect/src/xpcprivate.h @@ -81,10 +81,19 @@ #include "nsIScriptContext.h" #include "nsIScriptGlobalObject.h" +#ifdef XPC_TOOLS_SUPPORT +#include "nsIXPCToolsProfiler.h" +#include "nsIPref.h" +#endif + #ifdef DEBUG #define XPC_DETECT_LEADING_UPPERCASE_ACCESS_ERRORS 1 #endif +#ifdef DEBUG_jband +#define XPC_DUMP_AT_SHUTDOWN 1 +#endif + /***************************************************************************/ // default initial sizes for maps (hashtables) @@ -161,6 +170,10 @@ private: nsIJSContextStack* mContextStack; nsIXPCSecurityManager* mDefaultSecurityManager; PRUint16 mDefaultSecurityManagerFlags; +#ifdef XPC_TOOLS_SUPPORT + nsCOMPtr mProfiler; + nsCOMPtr mProfilerOutputFile; +#endif }; /***************************************************************************/ diff --git a/mozilla/js/src/xpconnect/src/xpcthreadcontext.cpp b/mozilla/js/src/xpconnect/src/xpcthreadcontext.cpp index 71c642d2149..f80868d85a4 100644 --- a/mozilla/js/src/xpconnect/src/xpcthreadcontext.cpp +++ b/mozilla/js/src/xpconnect/src/xpcthreadcontext.cpp @@ -129,7 +129,7 @@ nsXPCThreadJSContextStackImpl::FreeSingleton() if (tcs) { nsrefcnt cnt; NS_RELEASE2(tcs, cnt); -#if defined(DEBUG_kipp) || defined(DEBUG_jband) +#ifdef XPC_DUMP_AT_SHUTDOWN if (0 != cnt) { printf("*** dangling reference to nsXPCThreadJSContextStackImpl: refcnt=%d\n", cnt); }