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(
|
AC_MSG_ERROR(
|
||||||
[--enable-valgrind specified but Valgrind is not installed]))
|
[--enable-valgrind specified but Valgrind is not installed]))
|
||||||
AC_DEFINE(MOZ_VALGRIND)
|
AC_DEFINE(MOZ_VALGRIND)
|
||||||
MOZ_VALGRIND=1
|
|
||||||
fi
|
fi
|
||||||
AC_SUBST(MOZ_VALGRIND)
|
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 ========================================================
|
||||||
dnl jprof
|
dnl jprof
|
||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
@ -7095,7 +7109,7 @@ dnl = Enable trace malloc
|
|||||||
dnl ========================================================
|
dnl ========================================================
|
||||||
NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC}
|
NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC}
|
||||||
MOZ_ARG_ENABLE_BOOL(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=1,
|
||||||
NS_TRACE_MALLOC= )
|
NS_TRACE_MALLOC= )
|
||||||
if test "$NS_TRACE_MALLOC"; then
|
if test "$NS_TRACE_MALLOC"; then
|
||||||
@ -7117,6 +7131,9 @@ MOZ_ARG_ENABLE_BOOL(jemalloc,
|
|||||||
if test "$NS_TRACE_MALLOC"; then
|
if test "$NS_TRACE_MALLOC"; then
|
||||||
MOZ_MEMORY=
|
MOZ_MEMORY=
|
||||||
fi
|
fi
|
||||||
|
if test "$MOZ_DMD"; then
|
||||||
|
MOZ_MEMORY=
|
||||||
|
fi
|
||||||
|
|
||||||
if test "${OS_TARGET}" = "Android"; then
|
if test "${OS_TARGET}" = "Android"; then
|
||||||
dnl On Android, we use WRAP_LDFLAGS to link everything to mozutils
|
dnl On Android, we use WRAP_LDFLAGS to link everything to mozutils
|
||||||
|
@ -2944,6 +2944,25 @@ static JSFunctionSpec JProfFunctions[] = {
|
|||||||
|
|
||||||
#endif /* defined(MOZ_JPROF) */
|
#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
|
nsresult
|
||||||
nsJSContext::InitClasses(JSObject* aGlobalObj)
|
nsJSContext::InitClasses(JSObject* aGlobalObj)
|
||||||
{
|
{
|
||||||
@ -2967,6 +2986,11 @@ nsJSContext::InitClasses(JSObject* aGlobalObj)
|
|||||||
::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
|
::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef MOZ_DMD
|
||||||
|
// Attempt to initialize DMD functions
|
||||||
|
::JS_DefineFunctions(mContext, aGlobalObj, DMDFunctions);
|
||||||
|
#endif
|
||||||
|
|
||||||
JSOptionChangedCallback(js_options_dot_str, this);
|
JSOptionChangedCallback(js_options_dot_str, this);
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -98,15 +98,16 @@ NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
|
|||||||
// Memory reporting stuff.
|
// Memory reporting stuff.
|
||||||
static PRInt64 gHunspellAllocatedSize = 0;
|
static PRInt64 gHunspellAllocatedSize = 0;
|
||||||
|
|
||||||
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(HunspellMallocSizeOfForCounterInc, "hunspell")
|
||||||
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(HunspellMallocSizeOfForCounterDec)
|
||||||
|
|
||||||
void HunspellReportMemoryAllocation(void* ptr) {
|
void HunspellReportMemoryAllocation(void* ptr) {
|
||||||
// |computedSize| is zero because we don't know what it is.
|
// |computedSize| is zero because we don't know what it is.
|
||||||
gHunspellAllocatedSize +=
|
gHunspellAllocatedSize += HunspellMallocSizeOfForCounterInc(ptr, 0);
|
||||||
mozilla::MemoryReporterMallocSizeOfForCounterInc(ptr, 0);
|
|
||||||
}
|
}
|
||||||
void HunspellReportMemoryDeallocation(void* ptr) {
|
void HunspellReportMemoryDeallocation(void* ptr) {
|
||||||
// |computedSize| is zero because we don't know what it is.
|
// |computedSize| is zero because we don't know what it is.
|
||||||
gHunspellAllocatedSize -=
|
gHunspellAllocatedSize -= HunspellMallocSizeOfForCounterDec(ptr, 0);
|
||||||
mozilla::MemoryReporterMallocSizeOfForCounterDec(ptr, 0);
|
|
||||||
}
|
}
|
||||||
static PRInt64 HunspellGetCurrentAllocatedSize() {
|
static PRInt64 HunspellGetCurrentAllocatedSize() {
|
||||||
return gHunspellAllocatedSize;
|
return gHunspellAllocatedSize;
|
||||||
|
@ -1235,6 +1235,8 @@ XPCJSRuntime::~XPCJSRuntime()
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(JsMallocSizeOf, "js")
|
||||||
|
|
||||||
void
|
void
|
||||||
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
||||||
{
|
{
|
||||||
@ -1253,9 +1255,9 @@ CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
|
|||||||
curr->mjitCode = method + unused;
|
curr->mjitCode = method + unused;
|
||||||
#endif
|
#endif
|
||||||
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
|
JS_GetTypeInferenceMemoryStats(cx, compartment, &curr->typeInferenceMemory,
|
||||||
MemoryReporterMallocSizeOf);
|
JsMallocSizeOf);
|
||||||
curr->shapesCompartmentTables =
|
curr->shapesCompartmentTables =
|
||||||
js::GetCompartmentShapeTableSize(compartment, MemoryReporterMallocSizeOf);
|
js::GetCompartmentShapeTableSize(compartment, JsMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1300,14 +1302,14 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
|||||||
} else {
|
} else {
|
||||||
curr->gcHeapObjectsNonFunction += thingSize;
|
curr->gcHeapObjectsNonFunction += thingSize;
|
||||||
}
|
}
|
||||||
curr->objectSlots += js::GetObjectDynamicSlotSize(obj, MemoryReporterMallocSizeOf);
|
curr->objectSlots += js::GetObjectDynamicSlotSize(obj, JsMallocSizeOf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JSTRACE_STRING:
|
case JSTRACE_STRING:
|
||||||
{
|
{
|
||||||
JSString *str = static_cast<JSString *>(thing);
|
JSString *str = static_cast<JSString *>(thing);
|
||||||
curr->gcHeapStrings += thingSize;
|
curr->gcHeapStrings += thingSize;
|
||||||
curr->stringChars += str->charsHeapSize(MemoryReporterMallocSizeOf);
|
curr->stringChars += str->charsHeapSize(JsMallocSizeOf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JSTRACE_SHAPE:
|
case JSTRACE_SHAPE:
|
||||||
@ -1316,13 +1318,13 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
|||||||
if (shape->inDictionary()) {
|
if (shape->inDictionary()) {
|
||||||
curr->gcHeapShapesDict += thingSize;
|
curr->gcHeapShapesDict += thingSize;
|
||||||
curr->shapesExtraDictTables +=
|
curr->shapesExtraDictTables +=
|
||||||
shape->sizeOfPropertyTable(MemoryReporterMallocSizeOf);
|
shape->sizeOfPropertyTable(JsMallocSizeOf);
|
||||||
} else {
|
} else {
|
||||||
curr->gcHeapShapesTree += thingSize;
|
curr->gcHeapShapesTree += thingSize;
|
||||||
curr->shapesExtraTreeTables +=
|
curr->shapesExtraTreeTables +=
|
||||||
shape->sizeOfPropertyTable(MemoryReporterMallocSizeOf);
|
shape->sizeOfPropertyTable(JsMallocSizeOf);
|
||||||
curr->shapesExtraTreeShapeKids +=
|
curr->shapesExtraTreeShapeKids +=
|
||||||
shape->sizeOfKids(MemoryReporterMallocSizeOf);
|
shape->sizeOfKids(JsMallocSizeOf);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1335,9 +1337,9 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
|||||||
{
|
{
|
||||||
JSScript *script = static_cast<JSScript *>(thing);
|
JSScript *script = static_cast<JSScript *>(thing);
|
||||||
curr->gcHeapScripts += thingSize;
|
curr->gcHeapScripts += thingSize;
|
||||||
curr->scriptData += script->dataSize(MemoryReporterMallocSizeOf);
|
curr->scriptData += script->dataSize(JsMallocSizeOf);
|
||||||
#ifdef JS_METHODJIT
|
#ifdef JS_METHODJIT
|
||||||
curr->mjitData += script->jitDataSize(MemoryReporterMallocSizeOf);
|
curr->mjitData += script->jitDataSize(JsMallocSizeOf);
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1346,7 +1348,7 @@ CellCallback(JSContext *cx, void *vdata, void *thing, JSGCTraceKind traceKind,
|
|||||||
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
|
js::types::TypeObject *obj = static_cast<js::types::TypeObject *>(thing);
|
||||||
curr->gcHeapTypeObjects += thingSize;
|
curr->gcHeapTypeObjects += thingSize;
|
||||||
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory,
|
JS_GetTypeInferenceObjectStats(obj, &curr->typeInferenceMemory,
|
||||||
MemoryReporterMallocSizeOf);
|
JsMallocSizeOf);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case JSTRACE_XML:
|
case JSTRACE_XML:
|
||||||
@ -1558,12 +1560,12 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
|||||||
ArenaCallback, CellCallback);
|
ArenaCallback, CellCallback);
|
||||||
js::IterateChunks(cx, data, ChunkCallback);
|
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
|
// Nb: we use sizeOfExcludingThis() because atomState.atoms is within
|
||||||
// JSRuntime, and so counted when JSRuntime is counted.
|
// JSRuntime, and so counted when JSRuntime is counted.
|
||||||
data->runtimeAtomsTable =
|
data->runtimeAtomsTable =
|
||||||
rt->atomState.atoms.sizeOfExcludingThis(MemoryReporterMallocSizeOf);
|
rt->atomState.atoms.sizeOfExcludingThis(JsMallocSizeOf);
|
||||||
|
|
||||||
{
|
{
|
||||||
#ifndef JS_THREADSAFE
|
#ifndef JS_THREADSAFE
|
||||||
@ -1577,13 +1579,13 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
|||||||
JSContext *acx, *iter = NULL;
|
JSContext *acx, *iter = NULL;
|
||||||
while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL) {
|
while ((acx = JS_ContextIteratorUnlocked(rt, &iter)) != NULL) {
|
||||||
data->runtimeContexts +=
|
data->runtimeContexts +=
|
||||||
acx->sizeOfIncludingThis(MemoryReporterMallocSizeOf);
|
acx->sizeOfIncludingThis(JsMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JSThread::Map::Range r = rt->threads.all(); !r.empty(); r.popFront()) {
|
for (JSThread::Map::Range r = rt->threads.all(); !r.empty(); r.popFront()) {
|
||||||
JSThread *thread = r.front().value;
|
JSThread *thread = r.front().value;
|
||||||
size_t normal, temporary, regexpCode, stackCommitted;
|
size_t normal, temporary, regexpCode, stackCommitted;
|
||||||
thread->sizeOfIncludingThis(MemoryReporterMallocSizeOf,
|
thread->sizeOfIncludingThis(JsMallocSizeOf,
|
||||||
&normal,
|
&normal,
|
||||||
&temporary,
|
&temporary,
|
||||||
®expCode,
|
®expCode,
|
||||||
@ -1598,9 +1600,9 @@ CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
|
|||||||
|
|
||||||
XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
|
XPCJSRuntime *xpcrt = nsXPConnect::GetRuntimeInstance();
|
||||||
data->xpconnect +=
|
data->xpconnect +=
|
||||||
xpcrt->SizeOfIncludingThis(MemoryReporterMallocSizeOf);
|
xpcrt->SizeOfIncludingThis(JsMallocSizeOf);
|
||||||
data->xpconnect +=
|
data->xpconnect +=
|
||||||
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(MemoryReporterMallocSizeOf);
|
XPCWrappedNativeScope::SizeOfAllScopesIncludingThis(JsMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_DestroyContextNoGC(cx);
|
JS_DestroyContextNoGC(cx);
|
||||||
|
@ -622,6 +622,8 @@ struct MemoryReporterData
|
|||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(LayoutMallocSizeOf, "layout")
|
||||||
|
|
||||||
/* static */ PLDHashOperator
|
/* static */ PLDHashOperator
|
||||||
PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
||||||
void *userArg)
|
void *userArg)
|
||||||
@ -666,7 +668,7 @@ PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
|||||||
PRUint32 styleSize;
|
PRUint32 styleSize;
|
||||||
styleSize = aShell->StyleSet()->SizeOf();
|
styleSize = aShell->StyleSet()->SizeOf();
|
||||||
|
|
||||||
PRInt64 textRunsSize = aShell->SizeOfTextRuns(MemoryReporterMallocSizeOf);
|
PRInt64 textRunsSize = aShell->SizeOfTextRuns(LayoutMallocSizeOf);
|
||||||
|
|
||||||
data->callback->
|
data->callback->
|
||||||
Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP,
|
Callback(EmptyCString(), arenaPath, nsIMemoryReporter::KIND_HEAP,
|
||||||
@ -688,6 +690,8 @@ PresShell::MemoryReporter::SizeEnumerator(PresShellPtrKey *aEntry,
|
|||||||
return PL_DHASH_NEXT;
|
return PL_DHASH_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(GfxTextrunWordCacheMallocSizeOf, "gfx/textrun-word-cache")
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
||||||
nsISupports* aClosure)
|
nsISupports* aClosure)
|
||||||
@ -709,7 +713,7 @@ PresShell::MemoryReporter::CollectReports(nsIMemoryMultiReporterCallback* aCb,
|
|||||||
|
|
||||||
// now total up cached runs that aren't otherwise accounted for
|
// now total up cached runs that aren't otherwise accounted for
|
||||||
PRInt64 textRunWordCacheSize =
|
PRInt64 textRunWordCacheSize =
|
||||||
gfxTextRunWordCache::MaybeSizeOfExcludingThis(MemoryReporterMallocSizeOf);
|
gfxTextRunWordCache::MaybeSizeOfExcludingThis(GfxTextrunWordCacheMallocSizeOf);
|
||||||
|
|
||||||
aCb->Callback(EmptyCString(), kTextRunWordCachePath,
|
aCb->Callback(EmptyCString(), kTextRunWordCachePath,
|
||||||
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
|
nsIMemoryReporter::KIND_HEAP, nsIMemoryReporter::UNITS_BYTES,
|
||||||
|
@ -59,6 +59,11 @@ else
|
|||||||
FORCE_SHARED_LIB= 1
|
FORCE_SHARED_LIB= 1
|
||||||
endif
|
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)))
|
ifeq (,$(filter-out OS2,$(OS_ARCH)))
|
||||||
# The strndup declaration in string.h is in an ifdef __USE_GNU section
|
# The strndup declaration in string.h is in an ifdef __USE_GNU section
|
||||||
DEFINES += -D_GNU_SOURCE
|
DEFINES += -D_GNU_SOURCE
|
||||||
|
@ -259,7 +259,10 @@ moz_malloc_usable_size(void *ptr)
|
|||||||
|
|
||||||
#if defined(XP_MACOSX)
|
#if defined(XP_MACOSX)
|
||||||
return malloc_size(ptr);
|
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);
|
return malloc_usable_size(ptr);
|
||||||
#elif defined(XP_WIN)
|
#elif defined(XP_WIN)
|
||||||
return _msize(ptr);
|
return _msize(ptr);
|
||||||
|
@ -348,7 +348,7 @@ Service::shutdown()
|
|||||||
NS_IF_RELEASE(sXPConnect);
|
NS_IF_RELEASE(sXPConnect);
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_vfs* ConstructTelemetryVFS();
|
sqlite3_vfs *ConstructTelemetryVFS();
|
||||||
|
|
||||||
#ifdef MOZ_MEMORY
|
#ifdef MOZ_MEMORY
|
||||||
|
|
||||||
@ -385,17 +385,17 @@ namespace {
|
|||||||
// from the standard ones -- they use int instead of size_t. But we don't need
|
// from the standard ones -- they use int instead of size_t. But we don't need
|
||||||
// a wrapper for moz_free.
|
// a wrapper for moz_free.
|
||||||
|
|
||||||
static void* sqliteMemMalloc(int n)
|
static void *sqliteMemMalloc(int n)
|
||||||
{
|
{
|
||||||
return ::moz_malloc(n);
|
return ::moz_malloc(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* sqliteMemRealloc(void* p, int n)
|
static void *sqliteMemRealloc(void *p, int n)
|
||||||
{
|
{
|
||||||
return ::moz_realloc(p, n);
|
return ::moz_realloc(p, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sqliteMemSize(void* p)
|
static int sqliteMemSize(void *p)
|
||||||
{
|
{
|
||||||
return ::moz_malloc_usable_size(p);
|
return ::moz_malloc_usable_size(p);
|
||||||
}
|
}
|
||||||
@ -410,12 +410,12 @@ static int sqliteMemRoundup(int n)
|
|||||||
return n <= 8 ? 8 : n;
|
return n <= 8 ? 8 : n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sqliteMemInit(void* p)
|
static int sqliteMemInit(void *p)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sqliteMemShutdown(void* p)
|
static void sqliteMemShutdown(void *p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +745,7 @@ Service::SetQuotaForFilenamePattern(const nsACString &aPattern,
|
|||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
Service::UpdateQutoaInformationForFile(nsIFile* aFile)
|
Service::UpdateQutoaInformationForFile(nsIFile *aFile)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(aFile);
|
NS_ENSURE_ARG_POINTER(aFile);
|
||||||
|
|
||||||
|
@ -1301,12 +1301,15 @@ StoreAndNotifyEmbedVisit(VisitData& aPlace,
|
|||||||
(void)NS_DispatchToMainThread(event);
|
(void)NS_DispatchToMainThread(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(HistoryLinksHashtableMallocSizeOf,
|
||||||
|
"history-links-hashtable")
|
||||||
|
|
||||||
PRInt64 GetHistoryObserversSize()
|
PRInt64 GetHistoryObserversSize()
|
||||||
{
|
{
|
||||||
History* history = History::GetService();
|
History* history = History::GetService();
|
||||||
if (!history)
|
if (!history)
|
||||||
return 0;
|
return 0;
|
||||||
return history->SizeOfIncludingThis(MemoryReporterMallocSizeOf);
|
return history->SizeOfIncludingThis(HistoryLinksHashtableMallocSizeOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_MEMORY_REPORTER_IMPLEMENT(HistoryService,
|
NS_MEMORY_REPORTER_IMPLEMENT(HistoryService,
|
||||||
|
@ -92,6 +92,7 @@ EXPORTS = \
|
|||||||
nsTraceRefcntImpl.h \
|
nsTraceRefcntImpl.h \
|
||||||
nsWeakPtr.h \
|
nsWeakPtr.h \
|
||||||
nsInterfaceRequestorAgg.h \
|
nsInterfaceRequestorAgg.h \
|
||||||
|
dmd.h \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXPORTS_NAMESPACES = mozilla
|
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
|
#define NS_MEMORY_REPORTER_NAME(_classname) MemoryReporter_##_classname
|
||||||
|
|
||||||
nsresult NS_RegisterMemoryReporter (nsIMemoryReporter *reporter);
|
nsresult NS_RegisterMemoryReporter(nsIMemoryReporter *reporter);
|
||||||
nsresult NS_RegisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter);
|
nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
|
||||||
|
|
||||||
nsresult NS_UnregisterMemoryReporter (nsIMemoryReporter *reporter);
|
nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *reporter);
|
||||||
nsresult NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *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 {
|
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
|
* - On platforms where moz_malloc_usable_size() returns 0 it just returns
|
||||||
* |computedSize| (this happens on platforms where malloc_usable_size() or
|
* |computedSize|. This happens on platforms where malloc_usable_size() or
|
||||||
* equivalent isn't available).
|
* equivalent isn't available.
|
||||||
* - Otherwise, it |returns moz_malloc_usable_size(p)|, but only after doing
|
*
|
||||||
|
* - Otherwise, it returns |moz_malloc_usable_size(p)|, but only after doing
|
||||||
* some sanity checking -- it will assert if the usable size is too
|
* some sanity checking -- it will assert if the usable size is too
|
||||||
* dissimilar to |computedSize|. (However, this checking is skipped if
|
* dissimilar to |computedSize|. (However, this checking is skipped if
|
||||||
* |computedSize| is zero, which is useful if the computation is not worth
|
* |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
|
* the effort, e.g. because it's tricky and the |computedSize| would be
|
||||||
* small.)
|
* small.)
|
||||||
*/
|
*
|
||||||
size_t MemoryReporterMallocSizeOf(const void *ptr, size_t computedSize);
|
* 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
|
||||||
* These functions are like MemoryReporterMallocSizeOf(), and should be used by
|
* also helps with debugging and temporary ad hoc profiling. The |name| chosen
|
||||||
* all counter-based memory reporters when incrementing/decrementing a counter.
|
* doesn't matter greatly, but it's best to make it similar to the path used by
|
||||||
*/
|
* the relevant memory reporter(s).
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(fn, name) \
|
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(fn, name) \
|
||||||
size_t fn(const void *ptr, size_t computedSize) \
|
size_t fn(const void *ptr, size_t computedSize) \
|
||||||
@ -353,13 +355,30 @@ size_t MemoryReporterMallocSizeOfForCounterDec(const void *ptr,
|
|||||||
if (!usable) { \
|
if (!usable) { \
|
||||||
return computedSize; \
|
return computedSize; \
|
||||||
} \
|
} \
|
||||||
|
VALGRIND_DMD_REPORT(ptr, usable, name); \
|
||||||
NS_MEMORY_REPORTER_CHECK_SIZES(usable, computedSize); \
|
NS_MEMORY_REPORTER_CHECK_SIZES(usable, computedSize); \
|
||||||
return usable; \
|
return usable; \
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is used by the MemoryReporterMallocSizeOf* functions for checking
|
* Like NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN, but the created function sends an
|
||||||
* usable against computedSize.
|
* "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) \
|
#define NS_MEMORY_REPORTER_CHECK_SIZES(usable, computedSize) \
|
||||||
do { \
|
do { \
|
||||||
@ -370,12 +389,28 @@ size_t MemoryReporterMallocSizeOfForCounterDec(const void *ptr,
|
|||||||
/* because that's what the default allocator on Mac uses). Also, if */ \
|
/* because that's what the default allocator on Mac uses). Also, if */ \
|
||||||
/* computedSize is 0 we don't check it against usable. */ \
|
/* computedSize is 0 we don't check it against usable. */ \
|
||||||
NS_ASSERTION(usable >= computedSize, \
|
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 || \
|
NS_ASSERTION(usable < computedSize * 2 || usable <= 16 || \
|
||||||
computedSize == 0, \
|
computedSize == 0, \
|
||||||
"MemoryReporterMallocSizeOf: computedSize is too small"); \
|
"NS_MEMORY_REPORTER_CHECK_SIZES: computedSize is too small");\
|
||||||
} while(0)
|
} 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()
|
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_statistics_t stats;
|
||||||
malloc_zone_statistics(malloc_default_zone(), &stats);
|
malloc_zone_statistics(malloc_default_zone(), &stats);
|
||||||
return stats.size_in_use;
|
return stats.size_in_use;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static PRInt64 GetHeapZone0Used()
|
static PRInt64 GetHeapZone0Used()
|
||||||
{
|
{
|
||||||
|
#ifdef MOZ_DMD
|
||||||
|
// See comment in GetHeapZone0Committed above.
|
||||||
|
return (PRInt64) -1;
|
||||||
|
#else
|
||||||
malloc_statistics_t stats;
|
malloc_statistics_t stats;
|
||||||
malloc_zone_statistics(malloc_default_zone(), &stats);
|
malloc_zone_statistics(malloc_default_zone(), &stats);
|
||||||
return stats.size_allocated;
|
return stats.size_allocated;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_MEMORY_REPORTER_IMPLEMENT(HeapZone0Committed,
|
NS_MEMORY_REPORTER_IMPLEMENT(HeapZone0Committed,
|
||||||
@ -859,9 +871,59 @@ NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
|
|||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MemoryReporterMallocSizeOf, "default")
|
#ifdef MOZ_DMD
|
||||||
|
|
||||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MemoryReporterMallocSizeOfForCounterInc, "default")
|
class NullMultiReporterCallback : public nsIMemoryMultiReporterCallback
|
||||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(MemoryReporterMallocSizeOfForCounterDec, "default")
|
{
|
||||||
|
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