mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 704400 - Implement --enable-dmd. r=khuey.
This commit is contained in:
parent
2f644b6b1b
commit
688c469bc9
21
configure.in
21
configure.in
@ -2114,10 +2114,24 @@ if test -n "$MOZ_VALGRIND"; then
|
||||
AC_MSG_ERROR(
|
||||
[--enable-valgrind specified but Valgrind is not installed]))
|
||||
AC_DEFINE(MOZ_VALGRIND)
|
||||
MOZ_VALGRIND=1
|
||||
fi
|
||||
AC_SUBST(MOZ_VALGRIND)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use DMD
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(dmd,
|
||||
[ --enable-dmd Enable DMD; also disables jemalloc (default=no)],
|
||||
MOZ_DMD=1,
|
||||
MOZ_DMD= )
|
||||
if test -n "$MOZ_DMD"; then
|
||||
MOZ_CHECK_HEADER([valgrind/valgrind.h], [],
|
||||
AC_MSG_ERROR(
|
||||
[--enable-dmd specified but Valgrind is not installed]))
|
||||
AC_DEFINE(MOZ_DMD)
|
||||
fi
|
||||
AC_SUBST(MOZ_DMD)
|
||||
|
||||
dnl ========================================================
|
||||
dnl jprof
|
||||
dnl ========================================================
|
||||
@ -7095,7 +7109,7 @@ dnl = Enable trace malloc
|
||||
dnl ========================================================
|
||||
NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC}
|
||||
MOZ_ARG_ENABLE_BOOL(trace-malloc,
|
||||
[ --enable-trace-malloc Enable malloc tracing],
|
||||
[ --enable-trace-malloc Enable malloc tracing; also disables jemalloc],
|
||||
NS_TRACE_MALLOC=1,
|
||||
NS_TRACE_MALLOC= )
|
||||
if test "$NS_TRACE_MALLOC"; then
|
||||
@ -7117,6 +7131,9 @@ MOZ_ARG_ENABLE_BOOL(jemalloc,
|
||||
if test "$NS_TRACE_MALLOC"; then
|
||||
MOZ_MEMORY=
|
||||
fi
|
||||
if test "$MOZ_DMD"; then
|
||||
MOZ_MEMORY=
|
||||
fi
|
||||
|
||||
if test "${OS_TARGET}" = "Android"; then
|
||||
dnl On Android, we use WRAP_LDFLAGS to link everything to mozutils
|
||||
|
@ -2944,6 +2944,25 @@ static JSFunctionSpec JProfFunctions[] = {
|
||||
|
||||
#endif /* defined(MOZ_JPROF) */
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
|
||||
// See https://wiki.mozilla.org/Performance/MemShrink/DMD for instructions on
|
||||
// how to use DMD.
|
||||
|
||||
static JSBool
|
||||
DMDCheckJS(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
mozilla::DMDCheckAndDump();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSFunctionSpec DMDFunctions[] = {
|
||||
{"DMD", DMDCheckJS, 0, 0},
|
||||
{nsnull, nsnull, 0, 0}
|
||||
};
|
||||
|
||||
#endif /* defined(MOZ_DMD) */
|
||||
|
||||
nsresult
|
||||
nsJSContext::InitClasses(JSObject* aGlobalObj)
|
||||
{
|
||||
@ -2967,6 +2986,11 @@ nsJSContext::InitClasses(JSObject* aGlobalObj)
|
||||
::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
// Attempt to initialize DMD functions
|
||||
::JS_DefineFunctions(mContext, aGlobalObj, DMDFunctions);
|
||||
#endif
|
||||
|
||||
JSOptionChangedCallback(js_options_dot_str, this);
|
||||
|
||||
return rv;
|
||||
|
@ -98,15 +98,16 @@ NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
|
||||
// Memory reporting stuff.
|
||||
static PRInt64 gHunspellAllocatedSize = 0;
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(HunspellMallocSizeOfForCounterInc, "hunspell")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(HunspellMallocSizeOfForCounterDec)
|
||||
|
||||
void HunspellReportMemoryAllocation(void* ptr) {
|
||||
// |computedSize| is zero because we don't know what it is.
|
||||
gHunspellAllocatedSize +=
|
||||
mozilla::MemoryReporterMallocSizeOfForCounterInc(ptr, 0);
|
||||
gHunspellAllocatedSize += HunspellMallocSizeOfForCounterInc(ptr, 0);
|
||||
}
|
||||
void HunspellReportMemoryDeallocation(void* ptr) {
|
||||
// |computedSize| is zero because we don't know what it is.
|
||||
gHunspellAllocatedSize -=
|
||||
mozilla::MemoryReporterMallocSizeOfForCounterDec(ptr, 0);
|
||||
gHunspellAllocatedSize -= HunspellMallocSizeOfForCounterDec(ptr, 0);
|
||||
}
|
||||
static PRInt64 HunspellGetCurrentAllocatedSize() {
|
||||
return gHunspellAllocatedSize;
|
||||
|
@ -1235,6 +1235,8 @@ XPCJSRuntime::~XPCJSRuntime()
|
||||
|
||||
namespace {
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
|
||||
|
||||
void
|
||||
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||
{
|
||||
@ -1253,9 +1255,9 @@ CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||
curr->mjitCode = method + unused;
|
||||
#endif
|
||||
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
|
||||
MemoryReporterMallocSizeOf);
|
||||
JsMallocSizeOf);
|
||||
curr->shapesCompartmentTables =
|
||||
js::GetCompartmentShapeTableSize(compartment, MemoryReporterMallocSizeOf);
|
||||
js::GetCompartmentShapeTableSize(compartment, JsMallocSizeOf);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1300,14 +1302,14 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
} else {
|
||||
curr->gcHeapObjectsNonFunction += thingSize;
|
||||
}
|
||||
curr->objectSlots += js::GetObjectDynamicSlotSize(obj, MemoryReporterMallocSizeOf);
|
||||
curr->objectSlots += js::GetObjectDynamicSlotSize(obj, JsMallocSizeOf);
|
||||
break;
|
||||
}
|
||||
case JSTRACE_STRING:
|
||||
{
|
||||
JSString *str = static_cast<JSString *>(thing);
|
||||
curr->gcHeapStrings += thingSize;
|
||||
curr->stringChars += str->charsHeapSize(MemoryReporterMallocSizeOf);
|
||||
curr->stringChars += str->charsHeapSize(JsMallocSizeOf);
|
||||
break;
|
||||
}
|
||||
case JSTRACE_SHAPE:
|
||||
@ -1316,13 +1318,13 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
if (shape->inDictionary()) {
|
||||
curr->gcHeapShapesDict += thingSize;
|
||||
curr->shapesExtraDictTables +=
|
||||
shape->sizeOfPropertyTable(MemoryReporterMallocSizeOf);
|
||||
shape->sizeOfPropertyTable(JsMallocSizeOf);
|
||||
} else {
|
||||
curr->gcHeapShapesTree += thingSize;
|
||||
curr->shapesExtraTreeTables +=
|
||||
shape->sizeOfPropertyTable(MemoryReporterMallocSizeOf);
|
||||
shape->sizeOfPropertyTable(JsMallocSizeOf);
|
||||
curr->shapesExtraTreeShapeKids +=
|
||||
shape->sizeOfKids(MemoryReporterMallocSizeOf);
|
||||
shape->sizeOfKids(JsMallocSizeOf);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1335,9 +1337,9 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
{
|
||||
JSScript *script = static_cast<JSScript *>(thing);
|
||||
curr->gcHeapScripts += thingSize;
|
||||
curr->scriptData += script->dataSize(MemoryReporterMallocSizeOf);
|
||||
curr->scriptData += script->dataSize(JsMallocSizeOf);
|
||||
#ifdef JS_METHODJIT
|
||||
curr->mjitData += script->jitDataSize(MemoryReporterMallocSizeOf);
|
||||
curr->mjitData += script->jitDataSize(JsMallocSizeOf);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@ -1346,7 +1348,7 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
||||
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
|
||||
curr->gcHeapTypeObjects += thingSize;
|
||||
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory,
|
||||
MemoryReporterMallocSizeOf);
|
||||
JsMallocSizeOf);
|
||||
break;
|
||||
}
|
||||
case JSTRACE_XML:
|
||||
@ -1558,12 +1560,12 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
||||
ArenaCallback, CellCallback);
|
||||
js::IterateChunks(cx, data, ChunkCallback);
|
||||
|
||||
data->runtimeObject = MemoryReporterMallocSizeOf(rt, sizeof(JSRuntime));
|
||||
data->runtimeObject = JsMallocSizeOf(rt, sizeof(JSRuntime));
|
||||
|
||||
// Nb: we use sizeOfExcludingThis() because atomState.atoms is within
|
||||
// JSRuntime, and so counted when JSRuntime is counted.
|
||||
data->runtimeAtomsTable =
|
||||
rt->atomState.atoms.sizeOfExcludingThis(MemoryReporterMallocSizeOf);
|
||||
rt->atomState.atoms.sizeOfExcludingThis(JsMallocSizeOf);
|
||||
|
||||
{
|
||||
#ifndef JS_THREADSAFE
|
||||
@ -1577,13 +1579,13 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
||||
JSContext *acx, *iter = NULL;
|
||||
while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL) {
|
||||
data->runtimeContexts +=
|
||||
acx->sizeOfIncludingThis(MemoryReporterMallocSizeOf);
|
||||
acx->sizeOfIncludingThis(JsMallocSizeOf);
|
||||
}
|
||||
|
||||
for (JSThread::Map::Range r = rt->threads.all(); !r.empty(); r.popFront()) {
|
||||
JSThread *thread = r.front().value;
|
||||
size_t normal, temporary, regexpCode, stackCommitted;
|
||||
thread->sizeOfIncludingThis(MemoryReporterMallocSizeOf,
|
||||
thread->sizeOfIncludingThis(JsMallocSizeOf,
|
||||
&normal,
|
||||
&temporary,
|
||||
®expCode,
|
||||
@ -1598,9 +1600,9 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
||||
|
||||
XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
|
||||
data->xpconnect +=
|
||||
xpcrt->SizeOfIncludingThis(MemoryReporterMallocSizeOf);
|
||||
xpcrt->SizeOfIncludingThis(JsMallocSizeOf);
|
||||
data->xpconnect +=
|
||||
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(MemoryReporterMallocSizeOf);
|
||||
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JsMallocSizeOf);
|
||||
}
|
||||
|
||||
JS_DestroyContextNoGC(cx);
|
||||
|
@ -622,6 +622,8 @@ struct MemoryReporterData
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(LayoutMallocSizeOf, "layout")
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
||||
void *userArg)
|
||||
@ -666,7 +668,7 @@ PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
||||
PRUint32 styleSize;
|
||||
styleSize = aShell->StyleSet()->SizeOf();
|
||||
|
||||
PRInt64 textRunsSize = aShell->SizeOfTextRuns(MemoryReporterMallocSizeOf);
|
||||
PRInt64 textRunsSize = aShell->SizeOfTextRuns(LayoutMallocSizeOf);
|
||||
|
||||
data->callback->
|
||||
Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP,
|
||||
@ -688,6 +690,8 @@ PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(GfxTextrunWordCacheMallocSizeOf, "gfx/textrun-word-cache")
|
||||
|
||||
NS_IMETHODIMP
|
||||
PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
nsISupports* aClosure)
|
||||
@ -709,7 +713,7 @@ PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||
|
||||
// now total up cached runs that aren't otherwise accounted for
|
||||
PRInt64 textRunWordCacheSize =
|
||||
gfxTextRunWordCache::MaybeSizeOfExcludingThis(MemoryReporterMallocSizeOf);
|
||||
gfxTextRunWordCache::MaybeSizeOfExcludingThis(GfxTextrunWordCacheMallocSizeOf);
|
||||
|
||||
aCb->Callback(EmptyCString(), kTextRunWordCachePath,
|
||||
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
|
||||
|
@ -59,6 +59,11 @@ else
|
||||
FORCE_SHARED_LIB= 1
|
||||
endif
|
||||
|
||||
# TODO: we do this in crashreporter and storage/src too, should be centralized
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
DEFINES += -DXP_LINUX
|
||||
endif
|
||||
|
||||
ifeq (,$(filter-out OS2,$(OS_ARCH)))
|
||||
# The strndup declaration in string.h is in an ifdef __USE_GNU section
|
||||
DEFINES += -D_GNU_SOURCE
|
||||
|
@ -259,7 +259,10 @@ moz_malloc_usable_size(void *ptr)
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
return malloc_size(ptr);
|
||||
#elif defined(MOZ_MEMORY)
|
||||
#elif defined(MOZ_MEMORY) || defined(XP_LINUX)
|
||||
// XXX: the |defined(XP_LINUX)| may be too lax; some Linux installations
|
||||
// might use a libc that doesn't have malloc_usable_size. Let's fix this
|
||||
// if/when it happens.
|
||||
return malloc_usable_size(ptr);
|
||||
#elif defined(XP_WIN)
|
||||
return _msize(ptr);
|
||||
|
@ -348,7 +348,7 @@ Service::shutdown()
|
||||
NS_IF_RELEASE(sXPConnect);
|
||||
}
|
||||
|
||||
sqlite3_vfs* ConstructTelemetryVFS();
|
||||
sqlite3_vfs *ConstructTelemetryVFS();
|
||||
|
||||
#ifdef MOZ_MEMORY
|
||||
|
||||
@ -385,17 +385,17 @@ namespace {
|
||||
// from the standard ones -- they use int instead of size_t. But we don't need
|
||||
// a wrapper for moz_free.
|
||||
|
||||
static void* sqliteMemMalloc(int n)
|
||||
static void *sqliteMemMalloc(int n)
|
||||
{
|
||||
return ::moz_malloc(n);
|
||||
}
|
||||
|
||||
static void* sqliteMemRealloc(void* p, int n)
|
||||
static void *sqliteMemRealloc(void *p, int n)
|
||||
{
|
||||
return ::moz_realloc(p, n);
|
||||
}
|
||||
|
||||
static int sqliteMemSize(void* p)
|
||||
static int sqliteMemSize(void *p)
|
||||
{
|
||||
return ::moz_malloc_usable_size(p);
|
||||
}
|
||||
@ -410,12 +410,12 @@ static int sqliteMemRoundup(int n)
|
||||
return n <= 8 ? 8 : n;
|
||||
}
|
||||
|
||||
static int sqliteMemInit(void* p)
|
||||
static int sqliteMemInit(void *p)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sqliteMemShutdown(void* p)
|
||||
static void sqliteMemShutdown(void *p)
|
||||
{
|
||||
}
|
||||
|
||||
@ -745,7 +745,7 @@ Service::SetQuotaForFilenamePattern(const nsACString &aPattern,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
Service::UpdateQutoaInformationForFile(nsIFile* aFile)
|
||||
Service::UpdateQutoaInformationForFile(nsIFile *aFile)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aFile);
|
||||
|
||||
|
@ -1301,12 +1301,15 @@ StoreAndNotifyEmbedVisit(VisitData& aPlace,
|
||||
(void)NS_DispatchToMainThread(event);
|
||||
}
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(HistoryLinksHashtableMallocSizeOf,
|
||||
"history-links-hashtable")
|
||||
|
||||
PRInt64 GetHistoryObserversSize()
|
||||
{
|
||||
History* history = History::GetService();
|
||||
if (!history)
|
||||
return 0;
|
||||
return history->SizeOfIncludingThis(MemoryReporterMallocSizeOf);
|
||||
return history->SizeOfIncludingThis(HistoryLinksHashtableMallocSizeOf);
|
||||
}
|
||||
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(HistoryService,
|
||||
|
@ -92,6 +92,7 @@ EXPORTS = \
|
||||
nsTraceRefcntImpl.h \
|
||||
nsWeakPtr.h \
|
||||
nsInterfaceRequestorAgg.h \
|
||||
dmd.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla
|
||||
|
83
xpcom/base/dmd.h
Normal file
83
xpcom/base/dmd.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
----------------------------------------------------------------
|
||||
The following BSD-style license applies to this one file (dmd.h) only.
|
||||
----------------------------------------------------------------
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
the Mozilla Foundation.
|
||||
Portions created by the Initial Developer are Copyright (C) 2011
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
Nicholas Nethercote <nnethercote@mozilla.com>
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must
|
||||
not claim that you wrote the original software. If you use this
|
||||
software in a product, an acknowledgment in the product
|
||||
documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must
|
||||
not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote
|
||||
products derived from this software without specific prior written
|
||||
permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
||||
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef __DMD_H
|
||||
#define __DMD_H
|
||||
|
||||
#include "valgrind/valgrind.h"
|
||||
|
||||
/* !! ABIWARNING !! ABIWARNING !! ABIWARNING !! ABIWARNING !!
|
||||
This enum comprises an ABI exported by Valgrind to programs
|
||||
which use client requests. DO NOT CHANGE THE ORDER OF THESE
|
||||
ENTRIES, NOR DELETE ANY -- add new ones at the end. */
|
||||
typedef
|
||||
enum {
|
||||
VG_USERREQ__DMD_REPORT = VG_USERREQ_TOOL_BASE('D','M'),
|
||||
VG_USERREQ__DMD_UNREPORT,
|
||||
VG_USERREQ__DMD_CHECK_REPORTING
|
||||
} Vg_DMDClientRequest;
|
||||
|
||||
|
||||
/* Mark heap block at _qzz_addr as reported for _qzz_len bytes.
|
||||
* _qzz_name is the name of the reporter. */
|
||||
#define VALGRIND_DMD_REPORT(_qzz_addr,_qzz_len,_qzz_name) \
|
||||
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||
VG_USERREQ__DMD_REPORT, \
|
||||
(_qzz_addr), (_qzz_len), (_qzz_name), 0, 0)
|
||||
|
||||
/* Mark heap block at _qzz_addr as not reported. */
|
||||
#define VALGRIND_DMD_UNREPORT(_qzz_addr) \
|
||||
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||
VG_USERREQ__DMD_UNREPORT, \
|
||||
(_qzz_addr), 0, 0, 0, 0)
|
||||
|
||||
/* Do a reporting check. */
|
||||
#define VALGRIND_DMD_CHECK_REPORTING \
|
||||
VALGRIND_DO_CLIENT_REQUEST_EXPR(0 /* default return */, \
|
||||
VG_USERREQ__DMD_CHECK_REPORTING, \
|
||||
0, 0, 0, 0, 0)
|
||||
|
||||
#endif
|
||||
|
@ -308,43 +308,45 @@ interface nsIMemoryReporterManager : nsISupports
|
||||
|
||||
#define NS_MEMORY_REPORTER_NAME(_classname) MemoryReporter_##_classname
|
||||
|
||||
nsresult NS_RegisterMemoryReporter (nsIMemoryReporter *reporter);
|
||||
nsresult NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter);
|
||||
nsresult NS_RegisterMemoryReporter(nsIMemoryReporter *reporter);
|
||||
nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
|
||||
|
||||
nsresult NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter);
|
||||
nsresult NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter);
|
||||
nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *reporter);
|
||||
nsresult NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
|
||||
|
||||
// Because DMD is not a tool that comes with the standard Valgrind
|
||||
// distribution, we have to #include our own local copy of dmd.h. Ugly but
|
||||
// unavoidable.
|
||||
#ifdef MOZ_DMD
|
||||
#if MOZ_MEMORY
|
||||
#error "--disable-jemalloc should have been forced when --enable-dmd was specified"
|
||||
#endif
|
||||
#include "dmd.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/*
|
||||
* This function should be used by all traversal-based memory reporters.
|
||||
* Functions generated via this macro should be used by all traversal-based
|
||||
* memory reporters.
|
||||
*
|
||||
* - On platforms where moz_malloc_usable_size() returns 0 it just returns
|
||||
* |computedSize| (this happens on platforms where malloc_usable_size() or
|
||||
* equivalent isn't available).
|
||||
* - Otherwise, it |returns moz_malloc_usable_size(p)|, but only after doing
|
||||
* |computedSize|. This happens on platforms where malloc_usable_size() or
|
||||
* equivalent isn't available.
|
||||
*
|
||||
* - Otherwise, it returns |moz_malloc_usable_size(p)|, but only after doing
|
||||
* some sanity checking -- it will assert if the usable size is too
|
||||
* dissimilar to |computedSize|. (However, this checking is skipped if
|
||||
* |computedSize| is zero, which is useful if the computation is not worth
|
||||
* the effort, e.g. because it's tricky and the |computedSize| would be
|
||||
* small.)
|
||||
*/
|
||||
size_t MemoryReporterMallocSizeOf(const void *ptr, size_t computedSize);
|
||||
|
||||
/*
|
||||
* These functions are like MemoryReporterMallocSizeOf(), and should be used by
|
||||
* all counter-based memory reporters when incrementing/decrementing a counter.
|
||||
*/
|
||||
size_t MemoryReporterMallocSizeOfForCounterInc(const void *ptr,
|
||||
size_t computedSize);
|
||||
size_t MemoryReporterMallocSizeOfForCounterDec(const void *ptr,
|
||||
size_t computedSize);
|
||||
|
||||
/*
|
||||
* For the purposes of debugging, temporary profiling, and DMD integration, it
|
||||
* is sometimes useful to temporarily create multiple variants of
|
||||
* MemoryReporterMallocSizeOf(), with each one distinguished by a string
|
||||
* |name|. This macro makes creating such variants easy. |name| isn't used,
|
||||
* but it will be if extra debugging code is temporarily added.
|
||||
*
|
||||
* You might be wondering why we have a macro that creates multiple functions
|
||||
* distinguished only by |name|, instead of a single MemoryReporterMallocSizeOf
|
||||
* function. It's mostly to help with DMD integration, though it sometimes
|
||||
* also helps with debugging and temporary ad hoc profiling. The |name| chosen
|
||||
* doesn't matter greatly, but it's best to make it similar to the path used by
|
||||
* the relevant memory reporter(s).
|
||||
*/
|
||||
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(fn, name) \
|
||||
size_t fn(const void *ptr, size_t computedSize) \
|
||||
@ -353,13 +355,30 @@ size_t MemoryReporterMallocSizeOfForCounterDec(const void *ptr,
|
||||
if (!usable) { \
|
||||
return computedSize; \
|
||||
} \
|
||||
VALGRIND_DMD_REPORT(ptr, usable, name); \
|
||||
NS_MEMORY_REPORTER_CHECK_SIZES(usable, computedSize); \
|
||||
return usable; \
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used by the MemoryReporterMallocSizeOf* functions for checking
|
||||
* usable against computedSize.
|
||||
* Like NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN, but the created function sends an
|
||||
* "unreport" message to DMD.
|
||||
*/
|
||||
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(fn) \
|
||||
size_t fn(const void *ptr, size_t computedSize) \
|
||||
{ \
|
||||
size_t usable = moz_malloc_usable_size((void*)ptr); \
|
||||
if (!usable) { \
|
||||
return computedSize; \
|
||||
} \
|
||||
VALGRIND_DMD_UNREPORT(ptr); \
|
||||
NS_MEMORY_REPORTER_CHECK_SIZES(usable, computedSize); \
|
||||
return usable; \
|
||||
}
|
||||
|
||||
/*
|
||||
* This is used by the NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN* macros for
|
||||
* checking |usable| against |computedSize|.
|
||||
*/
|
||||
#define NS_MEMORY_REPORTER_CHECK_SIZES(usable, computedSize) \
|
||||
do { \
|
||||
@ -370,12 +389,28 @@ size_t MemoryReporterMallocSizeOfForCounterDec(const void *ptr,
|
||||
/* because that's what the default allocator on Mac uses). Also, if */ \
|
||||
/* computedSize is 0 we don't check it against usable. */ \
|
||||
NS_ASSERTION(usable >= computedSize, \
|
||||
"MemoryReporterMallocSizeOf: computedSize is too big"); \
|
||||
"NS_MEMORY_REPORTER_CHECK_SIZES: computedSize is too big"); \
|
||||
NS_ASSERTION(usable < computedSize * 2 || usable <= 16 || \
|
||||
computedSize == 0, \
|
||||
"MemoryReporterMallocSizeOf: computedSize is too small"); \
|
||||
"NS_MEMORY_REPORTER_CHECK_SIZES: computedSize is too small");\
|
||||
} while(0)
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
|
||||
/*
|
||||
* This runs all the memory reporters but does nothing with the results; i.e.
|
||||
* it does the minimal amount of work possible for DMD to do its thing. Then
|
||||
* it dumps the DMD output to stderr (or somewhere else, if one of
|
||||
* DMD/Valgrind's logging options was used).
|
||||
*/
|
||||
void DMDCheckAndDump();
|
||||
|
||||
#else
|
||||
|
||||
#define VALGRIND_DMD_REPORT(ptr, usable, name)
|
||||
#define VALGRIND_DMD_UNREPORT(ptr)
|
||||
|
||||
#endif /* defined(MOZ_DMD) */
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -423,16 +423,28 @@ static PRInt64 GetHeapAllocated()
|
||||
|
||||
static PRInt64 GetHeapZone0Committed()
|
||||
{
|
||||
#ifdef MOZ_DMD
|
||||
// malloc_zone_statistics() crashes when run under DMD because Valgrind
|
||||
// doesn't intercept it. This measurement isn't important for DMD, so
|
||||
// don't even try.
|
||||
return (PRInt64) -1;
|
||||
#else
|
||||
malloc_statistics_t stats;
|
||||
malloc_zone_statistics(malloc_default_zone(), &stats);
|
||||
return stats.size_in_use;
|
||||
#endif
|
||||
}
|
||||
|
||||
static PRInt64 GetHeapZone0Used()
|
||||
{
|
||||
#ifdef MOZ_DMD
|
||||
// See comment in GetHeapZone0Committed above.
|
||||
return (PRInt64) -1;
|
||||
#else
|
||||
malloc_statistics_t stats;
|
||||
malloc_zone_statistics(malloc_default_zone(), &stats);
|
||||
return stats.size_allocated;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_MEMORY_REPORTER_IMPLEMENT(HeapZone0Committed,
|
||||
@ -859,9 +871,59 @@ NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MemoryReporterMallocSizeOf, "default")
|
||||
#ifdef MOZ_DMD
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MemoryReporterMallocSizeOfForCounterInc, "default")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MemoryReporterMallocSizeOfForCounterDec, "default")
|
||||
class NullMultiReporterCallback : public nsIMemoryMultiReporterCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
|
||||
NS_IMETHOD Callback(const nsACString &aProcess, const nsACString &aPath,
|
||||
PRInt32 aKind, PRInt32 aUnits, PRInt64 aAmount,
|
||||
const nsACString &aDescription,
|
||||
nsISupports *aData)
|
||||
{
|
||||
// Do nothing; the reporter has already reported to DMD.
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
NS_IMPL_ISUPPORTS1(
|
||||
NullMultiReporterCallback
|
||||
, nsIMemoryMultiReporterCallback
|
||||
)
|
||||
|
||||
void
|
||||
DMDCheckAndDump()
|
||||
{
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr =
|
||||
do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
|
||||
// Do vanilla reporters.
|
||||
nsCOMPtr<nsISimpleEnumerator> e;
|
||||
mgr->EnumerateReporters(getter_AddRefs(e));
|
||||
bool more;
|
||||
while (NS_SUCCEEDED(e->HasMoreElements(&more)) && more) {
|
||||
nsCOMPtr<nsIMemoryReporter> r;
|
||||
e->GetNext(getter_AddRefs(r));
|
||||
|
||||
// Just getting the amount is enough for the reporter to report to DMD.
|
||||
PRInt64 amount;
|
||||
(void)r->GetAmount(&amount);
|
||||
}
|
||||
|
||||
// Do multi-reporters.
|
||||
nsCOMPtr<nsISimpleEnumerator> e2;
|
||||
mgr->EnumerateMultiReporters(getter_AddRefs(e2));
|
||||
nsRefPtr<NullMultiReporterCallback> cb = new NullMultiReporterCallback();
|
||||
while (NS_SUCCEEDED(e2->HasMoreElements(&more)) && more) {
|
||||
nsCOMPtr<nsIMemoryMultiReporter> r;
|
||||
e2->GetNext(getter_AddRefs(r));
|
||||
r->CollectReports(cb, nsnull);
|
||||
}
|
||||
|
||||
VALGRIND_DMD_CHECK_REPORTING;
|
||||
}
|
||||
|
||||
#endif /* defined(MOZ_DMD) */
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user