diff --git a/js/xpconnect/src/nsXPConnect.cpp b/js/xpconnect/src/nsXPConnect.cpp index 68df65d32743..61605be61f28 100644 --- a/js/xpconnect/src/nsXPConnect.cpp +++ b/js/xpconnect/src/nsXPConnect.cpp @@ -2772,6 +2772,21 @@ Base64Decode(JSContext *cx, JS::Value val, JS::Value *out) return true; } +#ifdef DEBUG +void +DumpJSHeap(FILE* file) +{ + NS_ABORT_IF_FALSE(NS_IsMainThread(), "Must dump GC heap on main thread."); + JSContext *cx; + nsXPConnect* xpc = nsXPConnect::GetXPConnect(); + if (!xpc || NS_FAILED(xpc->GetSafeJSContext(&cx)) || !cx) { + NS_ERROR("Failed to get safe JSContext!"); + return; + } + js::DumpHeapComplete(cx, file); +} +#endif + } // namespace xpc NS_IMETHODIMP diff --git a/js/xpconnect/src/xpcpublic.h b/js/xpconnect/src/xpcpublic.h index 63c06695aa93..7b07e40b4e0e 100644 --- a/js/xpconnect/src/xpcpublic.h +++ b/js/xpconnect/src/xpcpublic.h @@ -216,6 +216,9 @@ bool StringToJsval(JSContext *cx, nsString &str, JS::Value *rval); void *GetCompartmentName(JSContext *cx, JSCompartment *c); void DestroyCompartmentName(void *string); +#ifdef DEBUG +void DumpJSHeap(FILE* file); +#endif } // namespace xpc class nsIMemoryMultiReporterCallback; diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index 8b1e8cc56f66..efdd34ab8c2b 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -1418,30 +1418,54 @@ public: NS_IMETHOD Begin() { - char name[MAXPATHLEN] = {'\0'}; + char basename[MAXPATHLEN] = {'\0'}; + char ccname[MAXPATHLEN] = {'\0'}; #ifdef XP_WIN // On Windows, tmpnam returns useless stuff, such as "\\s164.". // Therefore we need to call the APIs directly. - GetTempPathA(mozilla::ArrayLength(name), name); + GetTempPathA(mozilla::ArrayLength(basename), basename); #else - tmpnam(name); - char *lastSlash = strrchr(name, XPCOM_FILE_PATH_SEPARATOR[0]); + tmpnam(basename); + char *lastSlash = strrchr(basename, XPCOM_FILE_PATH_SEPARATOR[0]); if (lastSlash) { *lastSlash = '\0'; } #endif - sprintf(name, "%s%scc-edges-%d.%d.log", name, + + ++gLogCounter; + +#ifdef DEBUG + // Dump the JS heap. + char gcname[MAXPATHLEN] = {'\0'}; + sprintf(gcname, "%s%sgc-edges-%d.%d.log", basename, XPCOM_FILE_PATH_SEPARATOR, - ++gLogCounter, base::GetCurrentProcId()); - mStream = fopen(name, "w"); + gLogCounter, base::GetCurrentProcId()); + + FILE* gcDumpFile = fopen(gcname, "w"); + if (!gcDumpFile) + return NS_ERROR_FAILURE; + xpc::DumpJSHeap(gcDumpFile); + fclose(gcDumpFile); +#endif + + // Open a file for dumping the CC graph. + sprintf(ccname, "%s%scc-edges-%d.%d.log", basename, + XPCOM_FILE_PATH_SEPARATOR, + gLogCounter, base::GetCurrentProcId()); + mStream = fopen(ccname, "w"); + if (!mStream) + return NS_ERROR_FAILURE; nsCOMPtr cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID); if (cs) { - cs->LogStringMessage(NS_ConvertUTF8toUTF16(name).get()); + cs->LogStringMessage(NS_ConvertUTF8toUTF16(ccname).get()); +#ifdef DEBUG + cs->LogStringMessage(NS_ConvertUTF8toUTF16(gcname).get()); +#endif } - return mStream ? NS_OK : NS_ERROR_FAILURE; + return NS_OK; } NS_IMETHOD NoteRefCountedObject(PRUint64 aAddress, PRUint32 refCount, const char *aObjectDescription)