diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 112686ca652..1183344f4f1 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1492,6 +1492,11 @@ namespace dmd { static bool ReportAndDump(JSContext *cx, unsigned argc, JS::Value *vp) { + if (!dmd::IsRunning()) { + JS_ReportError(cx, "DMD is not running"); + return false; + } + JS::CallArgs args = JS::CallArgsFromVp(argc, vp); JSString *str = JS::ToString(cx, args.get(0)); if (!str) @@ -1508,7 +1513,6 @@ ReportAndDump(JSContext *cx, unsigned argc, JS::Value *vp) } dmd::ClearReports(); - fprintf(stderr, "DMD: running reporters...\n"); dmd::RunReportersForThisProcess(); dmd::Writer writer(FpWrite, fp); dmd::Dump(writer); diff --git a/memory/replace/dmd/DMD.cpp b/memory/replace/dmd/DMD.cpp index ff5877e407c..7310f528a72 100644 --- a/memory/replace/dmd/DMD.cpp +++ b/memory/replace/dmd/DMD.cpp @@ -6,6 +6,7 @@ #include "DMD.h" +#include #include #include #include @@ -178,10 +179,9 @@ StatusMsg(const char* aFmt, ...) __android_log_vprint(ANDROID_LOG_INFO, "DMD", aFmt, ap); #else // The +64 is easily enough for the "DMD[] " prefix and the NUL. - char* fmt = (char*) InfallibleAllocPolicy::malloc_(strlen(aFmt) + 64); + char* fmt = (char*) alloca(strlen(aFmt) + 64); sprintf(fmt, "DMD[%d] %s", getpid(), aFmt); vfprintf(stderr, fmt, ap); - InfallibleAllocPolicy::free_(fmt); #endif va_end(ap); } @@ -1935,7 +1935,7 @@ ClearReports() } MOZ_EXPORT bool -IsEnabled() +IsRunning() { return gIsDMDRunning; } diff --git a/memory/replace/dmd/DMD.h b/memory/replace/dmd/DMD.h index 1628eb2d741..40c3e61c755 100644 --- a/memory/replace/dmd/DMD.h +++ b/memory/replace/dmd/DMD.h @@ -78,9 +78,9 @@ struct Sizes MOZ_EXPORT void SizeOf(Sizes* aSizes); -// Indicates whether or not DMD is enabled. +// Indicates whether or not DMD is running. MOZ_EXPORT bool -IsEnabled(); +IsRunning(); } // namespace mozilla } // namespace dmd diff --git a/toolkit/components/aboutmemory/content/aboutMemory.js b/toolkit/components/aboutmemory/content/aboutMemory.js index f1f55abb814..38258b3e0f8 100644 --- a/toolkit/components/aboutmemory/content/aboutMemory.js +++ b/toolkit/components/aboutmemory/content/aboutMemory.js @@ -295,8 +295,9 @@ function onLoad() "WARNING: These logs may be large (>1GB)."; const DMDEnabledDesc = "Run DMD analysis and save it to '" + DMDFile + "'.\n"; - const DMDDisabledDesc = "DMD is not enabled. Please re-run with $DMD set " + - "appropriately\n"; + const DMDDisabledDesc = "DMD is not running. Please re-start with $DMD and " + + "the other relevant environment variables set " + + "appropriately."; let ops = appendElement(header, "div", ""); @@ -341,22 +342,19 @@ function onLoad() appendButton(row4, GCAndCCAllLogDesc, saveGCLogAndVerboseCCLog, "Save verbose", 'saveLogsVerbose'); - // This only succeeds in --enable-dmd builds. - if (typeof DMDReportAndDump == 'function') { - let env = Components.classes["@mozilla.org/process/environment;1"] - .getService(Components.interfaces.nsIEnvironment); - - // Gray the button out if DMD isn't enabled at start-up. - let dmd = env.get('DMD'); - let disabled = dmd === '' || dmd === '0'; - + // Three cases here: + // - DMD is disabled (i.e. not built): don't show the button. + // - DMD is enabled but is not running: show the button, but disable it. + // - DMD is enabled and is running: show the button and enable it. + if (gMgr.isDMDEnabled) { let row5 = appendElement(ops, "div", "opsRow"); appendElementWithText(row5, "div", "opsRowLabel", "Save DMD output"); + let enableButton = gMgr.isDMDRunning; let dmdButton = - appendButton(row5, disabled ? DMDDisabledDesc : DMDEnabledDesc, doDMD, - "Save", "dmdButton"); - dmdButton.disabled = disabled; + appendButton(row5, enableButton ? DMDEnabledDesc : DMDDisabledDesc, + doDMD, "Save", "dmdButton"); + dmdButton.disabled = !enableButton; } // Generate the main div, where content ("section" divs) will go. It's @@ -440,8 +438,12 @@ function saveGCLogAndVerboseCCLog() function doDMD() { updateMainAndFooter('Saving DMD output...', HIDE_FOOTER); - DMDReportAndDump('out.dmd'); - updateMainAndFooter('Saved DMD output to ' + DMDFile, HIDE_FOOTER); + try { + let x = DMDReportAndDump('out.dmd'); + updateMainAndFooter('Saved DMD output to ' + DMDFile, HIDE_FOOTER); + } catch (ex) { + updateMainAndFooter(ex.toString(), HIDE_FOOTER); + } } function dumpGCLogAndCCLog(aVerbose) diff --git a/xpcom/base/nsIMemoryReporter.idl b/xpcom/base/nsIMemoryReporter.idl index 5d98be5ed47..6709c044906 100644 --- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -178,7 +178,7 @@ interface nsIFinishReportingCallback : nsISupports void callback(in nsISupports data); }; -[scriptable, builtinclass, uuid(b6e5ec8a-71d9-48db-8ae9-68b4c5bbf2c3)] +[scriptable, builtinclass, uuid(c27f8662-a0b7-45b3-8207-14d66b02b9c5)] interface nsIMemoryReporterManager : nsISupports { /* @@ -371,6 +371,13 @@ interface nsIMemoryReporterManager : nsISupports */ [infallible] readonly attribute boolean hasMozMallocUsableSize; + /* + * These attributes indicate DMD's status. "Enabled" means enabled at + * build-time. + */ + [infallible] readonly attribute boolean isDMDEnabled; + [infallible] readonly attribute boolean isDMDRunning; + /* * Run a series of GC/CC's in an attempt to minimize the application's memory * usage. When we're finished, we invoke the given runnable if it's not diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index 79c8e40220f..f7e32036709 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -667,7 +667,7 @@ nsMemoryInfoDumper::DumpMemoryInfoToTempDir(const nsAString& aIdentifier, nsresult nsMemoryInfoDumper::DumpDMD(const nsAString& aIdentifier) { - if (!dmd::IsEnabled()) { + if (!dmd::IsRunning()) { return NS_OK; } diff --git a/xpcom/base/nsMemoryReporterManager.cpp b/xpcom/base/nsMemoryReporterManager.cpp index f12b350b656..22b10b3f70c 100644 --- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -1644,6 +1644,28 @@ nsMemoryReporterManager::GetHasMozMallocUsableSize(bool* aHas) return NS_OK; } +NS_IMETHODIMP +nsMemoryReporterManager::GetIsDMDEnabled(bool* aIsEnabled) +{ +#ifdef MOZ_DMD + *aIsEnabled = true; +#else + *aIsEnabled = false; +#endif + return NS_OK; +} + +NS_IMETHODIMP +nsMemoryReporterManager::GetIsDMDRunning(bool* aIsRunning) +{ +#ifdef MOZ_DMD + *aIsRunning = dmd::IsRunning(); +#else + *aIsRunning = false; +#endif + return NS_OK; +} + namespace { /**