mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 717853 - Add a native version of DMD. r=jlebar,glandium.
--HG-- extra : rebase_source : 9b824556591abd63b42aa7ff823e9cd25976c162
This commit is contained in:
parent
188f6e9c8b
commit
0d84313efb
@ -54,6 +54,9 @@
|
||||
@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
|
||||
#ifdef MOZ_DMD
|
||||
@BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
@BINPATH@/XUL
|
||||
#else
|
||||
|
@ -199,17 +199,17 @@ endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Handle trace-malloc in optimized builds.
|
||||
# Handle trace-malloc and DMD in optimized builds.
|
||||
# No opt to give sane callstacks.
|
||||
#
|
||||
ifdef NS_TRACE_MALLOC
|
||||
ifneq (,$(NS_TRACE_MALLOC)$(MOZ_DMD))
|
||||
MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
|
||||
ifdef HAVE_64BIT_OS
|
||||
OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF,ICF
|
||||
else
|
||||
OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF
|
||||
endif
|
||||
endif # NS_TRACE_MALLOC
|
||||
endif # NS_TRACE_MALLOC || MOZ_DMD
|
||||
|
||||
endif # MOZ_DEBUG
|
||||
|
||||
@ -468,20 +468,20 @@ ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
|
||||
#//------------------------------------------------------------------------
|
||||
ifdef USE_STATIC_LIBS
|
||||
RTL_FLAGS=-MT # Statically linked multithreaded RTL
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)$(MOZ_DMD))
|
||||
ifndef MOZ_NO_DEBUG_RTL
|
||||
RTL_FLAGS=-MTd # Statically linked multithreaded MSVC4.0 debug RTL
|
||||
endif
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC || MOZ_DMD
|
||||
|
||||
else # !USE_STATIC_LIBS
|
||||
|
||||
RTL_FLAGS=-MD # Dynamically linked, multithreaded RTL
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)$(MOZ_DMD))
|
||||
ifndef MOZ_NO_DEBUG_RTL
|
||||
RTL_FLAGS=-MDd # Dynamically linked, multithreaded MSVC4.0 debug RTL
|
||||
endif
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC || MOZ_DMD
|
||||
endif # USE_STATIC_LIBS
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
35
configure.in
35
configure.in
@ -6994,7 +6994,7 @@ dnl = Enable trace malloc
|
||||
dnl ========================================================
|
||||
NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC}
|
||||
MOZ_ARG_ENABLE_BOOL(trace-malloc,
|
||||
[ --enable-trace-malloc Enable malloc tracing; also disables jemalloc],
|
||||
[ --enable-trace-malloc Enable malloc tracing; also disables DMD and jemalloc],
|
||||
NS_TRACE_MALLOC=1,
|
||||
NS_TRACE_MALLOC= )
|
||||
if test "$NS_TRACE_MALLOC"; then
|
||||
@ -7005,6 +7005,33 @@ if test "$NS_TRACE_MALLOC"; then
|
||||
fi
|
||||
AC_SUBST(NS_TRACE_MALLOC)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable DMD
|
||||
dnl ========================================================
|
||||
|
||||
MOZ_ARG_ENABLE_BOOL(dmd,
|
||||
[ --enable-dmd Enable DMD; also enables jemalloc and replace-malloc and disables DMDV],
|
||||
MOZ_DMD=1,
|
||||
MOZ_DMD= )
|
||||
|
||||
if test "$NS_TRACE_MALLOC"; then # trace-malloc disables DMD
|
||||
MOZ_DMD=
|
||||
fi
|
||||
if test "$MOZ_DMD"; then
|
||||
USE_ELF_DYNSTR_GC=
|
||||
AC_DEFINE(MOZ_DMD)
|
||||
|
||||
if test "${CPU_ARCH}" = "arm"; then
|
||||
CFLAGS="$CFLAGS -funwind-tables"
|
||||
CXXFLAGS="$CXXFLAGS -funwind-tables"
|
||||
fi
|
||||
|
||||
MOZ_MEMORY=1 # DMD enables jemalloc
|
||||
MOZ_REPLACE_MALLOC=1 # DMD enables replace-malloc
|
||||
MOZ_DMDV= # DMD disables DMDV
|
||||
fi
|
||||
AC_SUBST(MOZ_DMD)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable jemalloc
|
||||
dnl ========================================================
|
||||
@ -7600,9 +7627,9 @@ if test -z "$SKIP_LIBRARY_CHECKS"; then
|
||||
AC_LANG_RESTORE
|
||||
fi
|
||||
|
||||
# Demangle only for debug or trace-malloc builds
|
||||
# Demangle only for debug or trace-malloc or DMD builds
|
||||
MOZ_DEMANGLE_SYMBOLS=
|
||||
if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC"; then
|
||||
if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then
|
||||
MOZ_DEMANGLE_SYMBOLS=1
|
||||
AC_DEFINE(MOZ_DEMANGLE_SYMBOLS)
|
||||
fi
|
||||
@ -8407,7 +8434,7 @@ if test -n "$MOZ_SERVICES_SYNC"; then
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC"; then
|
||||
if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then
|
||||
MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS=
|
||||
fi
|
||||
|
||||
|
@ -2630,6 +2630,70 @@ static JSFunctionSpec TraceMallocFunctions[] = {
|
||||
|
||||
#endif /* NS_TRACE_MALLOC */
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
namespace mozilla {
|
||||
namespace dmd {
|
||||
|
||||
// See https://wiki.mozilla.org/Performance/MemShrink/DMD for instructions on
|
||||
// how to use DMD.
|
||||
|
||||
static JSBool
|
||||
MaybeReportAndDump(JSContext *cx, unsigned argc, jsval *vp, bool report)
|
||||
{
|
||||
JSString *str = JS_ValueToString(cx, argc ? JS_ARGV(cx, vp)[0] : JSVAL_VOID);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
JSAutoByteString pathname(cx, str);
|
||||
if (!pathname)
|
||||
return JS_FALSE;
|
||||
|
||||
FILE* fp = fopen(pathname.ptr(), "w");
|
||||
if (!fp) {
|
||||
JS_ReportError(cx, "DMD can't open %s: %s",
|
||||
pathname.ptr(), strerror(errno));
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
if (report) {
|
||||
fprintf(stderr, "DMD: running reporters...\n");
|
||||
dmd::RunReporters();
|
||||
}
|
||||
dmd::Writer writer(FpWrite, fp);
|
||||
dmd::Dump(writer);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ReportAndDump(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return MaybeReportAndDump(cx, argc, vp, /* report = */ true);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Dump(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
return MaybeReportAndDump(cx, argc, vp, /* report = */ false);
|
||||
}
|
||||
|
||||
|
||||
} // namespace dmd
|
||||
} // namespace mozilla
|
||||
|
||||
static JSFunctionSpec DMDFunctions[] = {
|
||||
JS_FS("DMDReportAndDump", dmd::ReportAndDump, 1, 0),
|
||||
JS_FS("DMDDump", dmd::Dump, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
#endif // defined(MOZ_DMD)
|
||||
|
||||
#ifdef MOZ_JPROF
|
||||
|
||||
#include <signal.h>
|
||||
@ -2739,15 +2803,22 @@ static JSFunctionSpec JProfFunctions[] = {
|
||||
// See https://wiki.mozilla.org/Performance/MemShrink/DMD for instructions on
|
||||
// how to use DMDV.
|
||||
|
||||
namespace mozilla {
|
||||
namespace dmdv {
|
||||
|
||||
static JSBool
|
||||
DMDVCheckAndDumpJS(JSContext *cx, unsigned argc, jsval *vp)
|
||||
ReportAndDump(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
mozilla::DMDVCheckAndDump();
|
||||
mozilla::dmd::RunReporters();
|
||||
mozilla::dmdv::Dump();
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
} // namespace dmdv
|
||||
} // namespace mozilla
|
||||
|
||||
static JSFunctionSpec DMDVFunctions[] = {
|
||||
JS_FS("DMDV", DMDVCheckAndDumpJS, 0, 0),
|
||||
JS_FS("DMDVReportAndDump", dmdv::ReportAndDump, 0, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
@ -2771,6 +2842,11 @@ nsJSContext::InitClasses(JSObject* aGlobalObj)
|
||||
::JS_DefineFunctions(mContext, aGlobalObj, TraceMallocFunctions);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
// Attempt to initialize DMD functions
|
||||
::JS_DefineFunctions(mContext, aGlobalObj, DMDFunctions);
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_JPROF
|
||||
// Attempt to initialize JProf functions
|
||||
::JS_DefineFunctions(mContext, aGlobalObj, JProfFunctions);
|
||||
|
@ -82,7 +82,12 @@ inline void* hunspell_realloc(void* ptr, size_t size)
|
||||
{
|
||||
HunspellReportMemoryDeallocation(ptr);
|
||||
void* result = moz_realloc(ptr, size);
|
||||
HunspellReportMemoryAllocation(result);
|
||||
if (result) {
|
||||
HunspellReportMemoryAllocation(result);
|
||||
} else {
|
||||
// realloc failed; undo the HunspellReportMemoryDeallocation from above
|
||||
HunspellReportMemoryAllocation(ptr);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#define realloc(ptr, size) hunspell_realloc(ptr, size)
|
||||
|
@ -98,14 +98,14 @@ NS_IMPL_CYCLE_COLLECTION_3(mozHunspell,
|
||||
// Memory reporting stuff.
|
||||
static int64_t gHunspellAllocatedSize = 0;
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(HunspellMallocSizeOfForCounterInc, "hunspell")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(HunspellMallocSizeOfForCounterDec)
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(HunspellMallocSizeOfOnAlloc, "hunspell")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(HunspellMallocSizeOfOnFree)
|
||||
|
||||
void HunspellReportMemoryAllocation(void* ptr) {
|
||||
gHunspellAllocatedSize += HunspellMallocSizeOfForCounterInc(ptr);
|
||||
gHunspellAllocatedSize += HunspellMallocSizeOfOnAlloc(ptr);
|
||||
}
|
||||
void HunspellReportMemoryDeallocation(void* ptr) {
|
||||
gHunspellAllocatedSize -= HunspellMallocSizeOfForCounterDec(ptr);
|
||||
gHunspellAllocatedSize -= HunspellMallocSizeOfOnFree(ptr);
|
||||
}
|
||||
static int64_t HunspellGetCurrentAllocatedSize() {
|
||||
return gHunspellAllocatedSize;
|
||||
|
@ -46,34 +46,34 @@ NS_MEMORY_REPORTER_IMPLEMENT(Freetype,
|
||||
"Memory used by Freetype."
|
||||
)
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(FreetypeMallocSizeOfForCounterInc, "freetype")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(FreetypeMallocSizeOfForCounterDec)
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(FreetypeMallocSizeOfOnAlloc, "freetype")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(FreetypeMallocSizeOfOnFree)
|
||||
|
||||
static void*
|
||||
CountingAlloc(FT_Memory memory, long size)
|
||||
{
|
||||
void *p = malloc(size);
|
||||
sFreetypeMemoryUsed += FreetypeMallocSizeOfForCounterInc(p);
|
||||
sFreetypeMemoryUsed += FreetypeMallocSizeOfOnAlloc(p);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
CountingFree(FT_Memory memory, void* p)
|
||||
{
|
||||
sFreetypeMemoryUsed -= FreetypeMallocSizeOfForCounterDec(p);
|
||||
sFreetypeMemoryUsed -= FreetypeMallocSizeOfOnFree(p);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void*
|
||||
CountingRealloc(FT_Memory memory, long cur_size, long new_size, void* p)
|
||||
{
|
||||
sFreetypeMemoryUsed -= FreetypeMallocSizeOfForCounterDec(p);
|
||||
sFreetypeMemoryUsed -= FreetypeMallocSizeOfOnFree(p);
|
||||
void *pnew = realloc(p, new_size);
|
||||
if (pnew) {
|
||||
sFreetypeMemoryUsed += FreetypeMallocSizeOfForCounterInc(pnew);
|
||||
sFreetypeMemoryUsed += FreetypeMallocSizeOfOnAlloc(pnew);
|
||||
} else {
|
||||
// realloc failed; undo the decrement from above
|
||||
sFreetypeMemoryUsed += FreetypeMallocSizeOfForCounterInc(p);
|
||||
sFreetypeMemoryUsed += FreetypeMallocSizeOfOnAlloc(p);
|
||||
}
|
||||
return pnew;
|
||||
}
|
||||
|
@ -199,17 +199,17 @@ endif
|
||||
endif
|
||||
|
||||
#
|
||||
# Handle trace-malloc in optimized builds.
|
||||
# Handle trace-malloc and DMD in optimized builds.
|
||||
# No opt to give sane callstacks.
|
||||
#
|
||||
ifdef NS_TRACE_MALLOC
|
||||
ifneq (,$(NS_TRACE_MALLOC)$(MOZ_DMD))
|
||||
MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
|
||||
ifdef HAVE_64BIT_OS
|
||||
OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF,ICF
|
||||
else
|
||||
OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF
|
||||
endif
|
||||
endif # NS_TRACE_MALLOC
|
||||
endif # NS_TRACE_MALLOC || MOZ_DMD
|
||||
|
||||
endif # MOZ_DEBUG
|
||||
|
||||
@ -468,20 +468,20 @@ ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_)
|
||||
#//------------------------------------------------------------------------
|
||||
ifdef USE_STATIC_LIBS
|
||||
RTL_FLAGS=-MT # Statically linked multithreaded RTL
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)$(MOZ_DMD))
|
||||
ifndef MOZ_NO_DEBUG_RTL
|
||||
RTL_FLAGS=-MTd # Statically linked multithreaded MSVC4.0 debug RTL
|
||||
endif
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC || MOZ_DMD
|
||||
|
||||
else # !USE_STATIC_LIBS
|
||||
|
||||
RTL_FLAGS=-MD # Dynamically linked, multithreaded RTL
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
|
||||
ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)$(MOZ_DMD))
|
||||
ifndef MOZ_NO_DEBUG_RTL
|
||||
RTL_FLAGS=-MDd # Dynamically linked, multithreaded MSVC4.0 debug RTL
|
||||
endif
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC
|
||||
endif # MOZ_DEBUG || NS_TRACE_MALLOC || MOZ_DMD
|
||||
endif # USE_STATIC_LIBS
|
||||
endif # WINNT && !GNU_CC
|
||||
|
||||
|
2051
memory/replace/dmd/DMD.cpp
Normal file
2051
memory/replace/dmd/DMD.cpp
Normal file
File diff suppressed because it is too large
Load Diff
55
memory/replace/dmd/DMD.h
Normal file
55
memory/replace/dmd/DMD.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DMD_h___
|
||||
#define DMD_h___
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dmd {
|
||||
|
||||
// Mark a heap block as reported by a memory reporter.
|
||||
MOZ_EXPORT void
|
||||
Report(const void* aPtr, const char* aReporterName);
|
||||
|
||||
// Mark a heap block as reported immediately on allocation.
|
||||
MOZ_EXPORT void
|
||||
ReportOnAlloc(const void* aPtr, const char* aReporterName);
|
||||
|
||||
class Writer
|
||||
{
|
||||
public:
|
||||
typedef void (*WriterFun)(void* aWriteState, const char* aFmt, va_list aAp);
|
||||
|
||||
Writer(WriterFun aWriterFun, void* aWriteState)
|
||||
: mWriterFun(aWriterFun), mWriteState(aWriteState)
|
||||
{}
|
||||
|
||||
void Write(const char* aFmt, ...) const;
|
||||
|
||||
private:
|
||||
WriterFun mWriterFun;
|
||||
void* mWriteState;
|
||||
};
|
||||
|
||||
// Checks which heap blocks have been reported, and dumps a human-readable
|
||||
// summary (via |aWrite|). If |aWrite| is nullptr it will dump to stderr.
|
||||
// Beware: this output may have very long lines.
|
||||
MOZ_EXPORT void
|
||||
Dump(Writer aWriter);
|
||||
|
||||
// A useful |WriterFun|. If |fp| is a FILE* you want |Dump|'s output to be
|
||||
// written to, call |Dump(FpWrite, fp)|.
|
||||
MOZ_EXPORT void
|
||||
FpWrite(void* aFp, const char* aFmt, va_list aAp);
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace dmd
|
||||
|
||||
#endif /* DMD_h___ */
|
39
memory/replace/dmd/Makefile.in
Normal file
39
memory/replace/dmd/Makefile.in
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = dmd
|
||||
LIBRARY_NAME = dmd
|
||||
FORCE_SHARED_LIB= 1
|
||||
|
||||
DEFINES += -DMOZ_NO_MOZALLOC
|
||||
|
||||
CPPSRCS = DMD.cpp
|
||||
|
||||
VPATH += $(topsrcdir)/xpcom/base
|
||||
CPPSRCS += nsStackWalk.cpp
|
||||
|
||||
VPATH += $(topsrcdir)/nsprpub/lib/libc/src
|
||||
CSRCS += strcpy.c
|
||||
|
||||
VPATH += $(topsrcdir)/mfbt
|
||||
CPPSRCS += HashFunctions.cpp
|
||||
|
||||
EXPORTS = DMD.h
|
||||
|
||||
# Disable mozglue.
|
||||
WRAP_LDFLAGS =
|
||||
MOZ_GLUE_LDFLAGS=
|
||||
|
||||
STL_FLAGS =
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
2
memory/replace/dmd/README
Normal file
2
memory/replace/dmd/README
Normal file
@ -0,0 +1,2 @@
|
||||
This is DMD. See https://wiki.mozilla.org/Performance/MemShrink/DMD for
|
||||
details on how to use it.
|
355
memory/replace/dmd/test-expected.dmd
Normal file
355
memory/replace/dmd/test-expected.dmd
Normal file
@ -0,0 +1,355 @@
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
------------------------------------------------------------------
|
||||
|
||||
$DMD = '--mode=test'
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Unreported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: 0 bytes
|
||||
Reported: 0 bytes ( 0.00%)
|
||||
Unreported: 0 bytes ( 0.00%)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
------------------------------------------------------------------
|
||||
|
||||
$DMD = '--mode=test'
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Double-reported: 3 blocks in block group 1 of 1
|
||||
96 bytes (90 requested / 6 slop)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Previously reported by 'c' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Now reported by 'c' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Unreported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Unreported: 1 block in block group 1 of 4
|
||||
4,096 bytes (1 requested / 4,095 slop)
|
||||
27.44% of the heap (27.44% cumulative); 76.88% of unreported (76.88% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 9 blocks in block group 2 of 4
|
||||
1,008 bytes (900 requested / 108 slop)
|
||||
6.75% of the heap (34.19% cumulative); 18.92% of unreported (95.80% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 2 blocks in block group 3 of 4
|
||||
112 bytes (112 requested / 0 slop)
|
||||
0.75% of the heap (34.94% cumulative); 2.10% of unreported (97.90% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 2 blocks in block group 4 of 4
|
||||
112 bytes (112 requested / 0 slop)
|
||||
0.75% of the heap (35.69% cumulative); 2.10% of unreported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Reported: 1 block in block group 1 of 12
|
||||
8,192 bytes (4,097 requested / 4,095 slop)
|
||||
54.88% of the heap (54.88% cumulative); 85.33% of reported (85.33% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'e' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 2 of 12
|
||||
512 bytes (512 requested / 0 slop)
|
||||
3.43% of the heap (58.31% cumulative); 5.33% of reported (90.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'e2' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 2 blocks in block group 3 of 12
|
||||
240 bytes (240 requested / 0 slop)
|
||||
1.61% of the heap (59.91% cumulative); 2.50% of reported (93.17% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a01' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 2 blocks in block group 4 of 12
|
||||
240 bytes (240 requested / 0 slop)
|
||||
1.61% of the heap (61.52% cumulative); 2.50% of reported (95.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a01' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 5 of 12
|
||||
96 bytes (96 requested / 0 slop)
|
||||
0.64% of the heap (62.17% cumulative); 1.00% of reported (96.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a23' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 6 of 12
|
||||
96 bytes (96 requested / 0 slop)
|
||||
0.64% of the heap (62.81% cumulative); 1.00% of reported (97.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a23' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 7 of 12
|
||||
80 bytes (80 requested / 0 slop)
|
||||
0.54% of the heap (63.34% cumulative); 0.83% of reported (98.50% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a23' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 8 of 12
|
||||
80 bytes (80 requested / 0 slop)
|
||||
0.54% of the heap (63.88% cumulative); 0.83% of reported (99.33% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a23' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 9 of 12
|
||||
32 bytes (30 requested / 2 slop)
|
||||
0.21% of the heap (64.09% cumulative); 0.33% of reported (99.67% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'c' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 10 of 12
|
||||
16 bytes (10 requested / 6 slop)
|
||||
0.11% of the heap (64.20% cumulative); 0.17% of reported (99.83% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'b' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 11 of 12
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.05% of the heap (64.26% cumulative); 0.08% of reported (99.92% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a2' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 12 of 12
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.05% of the heap (64.31% cumulative); 0.08% of reported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a2' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: 14,928 bytes
|
||||
Reported: 9,600 bytes (64.31%)
|
||||
Unreported: 5,328 bytes (35.69%)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
------------------------------------------------------------------
|
||||
|
||||
$DMD = '--mode=test'
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Double-reported: 1 block in block group 1 of 1
|
||||
8 bytes (0 requested / 8 slop)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Previously reported by 'a2b' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Now reported by 'a2b' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Unreported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Unreported: 9 blocks in block group 1 of 3
|
||||
1,008 bytes (900 requested / 108 slop)
|
||||
38.77% of the heap (38.77% cumulative); 48.84% of unreported (48.84% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 6 blocks in block group 2 of 3
|
||||
528 bytes (528 requested / 0 slop)
|
||||
20.31% of the heap (59.08% cumulative); 25.58% of unreported (74.42% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 6 blocks in block group 3 of 3
|
||||
528 bytes (528 requested / 0 slop)
|
||||
20.31% of the heap (79.38% cumulative); 25.58% of unreported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Reported: 1 block in block group 1 of 3
|
||||
512 bytes (512 requested / 0 slop)
|
||||
19.69% of the heap (19.69% cumulative); 95.52% of reported (95.52% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'e2b' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 2 of 3
|
||||
16 bytes (10 requested / 6 slop)
|
||||
0.62% of the heap (20.31% cumulative); 2.99% of reported (98.51% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'b' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported: 1 block in block group 3 of 3
|
||||
8 bytes (0 requested / 8 slop)
|
||||
0.31% of the heap (20.62% cumulative); 1.49% of reported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Reported by 'a2b' at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: 2,600 bytes
|
||||
Reported: 536 bytes (20.62%)
|
||||
Unreported: 2,064 bytes (79.38%)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Invocation
|
||||
------------------------------------------------------------------
|
||||
|
||||
$DMD = '--mode=test'
|
||||
|
||||
------------------------------------------------------------------
|
||||
Double-reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Unreported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
Unreported: ~4 blocks in block group 1 of 7
|
||||
~512 bytes (~512 requested / ~0 slop)
|
||||
35.96% of the heap (35.96% cumulative); 35.96% of unreported (35.96% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 1 block in block group 2 of 7
|
||||
256 bytes (256 requested / 0 slop)
|
||||
17.98% of the heap (53.93% cumulative); 17.98% of unreported (53.93% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 1 block in block group 3 of 7
|
||||
144 bytes (144 requested / 0 slop)
|
||||
10.11% of the heap (64.04% cumulative); 10.11% of unreported (64.04% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: 1 block in block group 4 of 7
|
||||
128 bytes (128 requested / 0 slop)
|
||||
8.99% of the heap (73.03% cumulative); 8.99% of unreported (73.03% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: ~1 block in block group 5 of 7
|
||||
~128 bytes (~128 requested / ~0 slop)
|
||||
8.99% of the heap (82.02% cumulative); 8.99% of unreported (82.02% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: ~1 block in block group 6 of 7
|
||||
~128 bytes (~128 requested / ~0 slop)
|
||||
8.99% of the heap (91.01% cumulative); 8.99% of unreported (91.01% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
Unreported: ~1 block in block group 7 of 7
|
||||
~128 bytes (~128 requested / ~0 slop)
|
||||
8.99% of the heap (100.00% cumulative); 8.99% of unreported (100.00% cumulative)
|
||||
Allocated at
|
||||
(stack omitted due to test mode)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Reported blocks
|
||||
------------------------------------------------------------------
|
||||
|
||||
(none)
|
||||
|
||||
------------------------------------------------------------------
|
||||
Summary
|
||||
------------------------------------------------------------------
|
||||
|
||||
Total: ~1,424 bytes
|
||||
Reported: ~0 bytes ( 0.00%)
|
||||
Unreported: ~1,424 bytes (100.00%)
|
||||
|
@ -518,14 +518,57 @@ namespace {
|
||||
// from the standard ones -- they use int instead of size_t. But we don't need
|
||||
// a wrapper for moz_free.
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
|
||||
#include "DMD.h"
|
||||
|
||||
// sqlite does its own memory accounting, and we use its numbers in our memory
|
||||
// reporters. But we don't want sqlite's heap blocks to show up in DMD's
|
||||
// output as unreported, so we mark them as reported when they're allocated and
|
||||
// mark them as unreported when they are freed.
|
||||
//
|
||||
// In other words, we are marking all sqlite heap blocks as reported even
|
||||
// though we're not reporting them ourselves. Instead we're trusting that
|
||||
// sqlite is fully and correctly accounting for all of its heap blocks via its
|
||||
// own memory accounting.
|
||||
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(sqliteMallocSizeOfOnAlloc, "sqlite")
|
||||
NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(sqliteMallocSizeOfOnFree)
|
||||
|
||||
#endif
|
||||
|
||||
static void *sqliteMemMalloc(int n)
|
||||
{
|
||||
return ::moz_malloc(n);
|
||||
void* p = ::moz_malloc(n);
|
||||
#ifdef MOZ_DMD
|
||||
sqliteMallocSizeOfOnAlloc(p);
|
||||
#endif
|
||||
return p;
|
||||
}
|
||||
|
||||
static void sqliteMemFree(void *p)
|
||||
{
|
||||
#ifdef MOZ_DMD
|
||||
sqliteMallocSizeOfOnFree(p);
|
||||
#endif
|
||||
::moz_free(p);
|
||||
}
|
||||
|
||||
static void *sqliteMemRealloc(void *p, int n)
|
||||
{
|
||||
#ifdef MOZ_DMD
|
||||
sqliteMallocSizeOfOnFree(p);
|
||||
void *pnew = ::moz_realloc(p, n);
|
||||
if (pnew) {
|
||||
sqliteMallocSizeOfOnAlloc(pnew);
|
||||
} else {
|
||||
// realloc failed; undo the sqliteMallocSizeOfOnFree from above
|
||||
sqliteMallocSizeOfOnAlloc(p);
|
||||
}
|
||||
return pnew;
|
||||
#else
|
||||
return ::moz_realloc(p, n);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int sqliteMemSize(void *p)
|
||||
@ -554,14 +597,14 @@ static void sqliteMemShutdown(void *p)
|
||||
|
||||
const sqlite3_mem_methods memMethods = {
|
||||
&sqliteMemMalloc,
|
||||
&moz_free,
|
||||
&sqliteMemFree,
|
||||
&sqliteMemRealloc,
|
||||
&sqliteMemSize,
|
||||
&sqliteMemRoundup,
|
||||
&sqliteMemInit,
|
||||
&sqliteMemShutdown,
|
||||
NULL
|
||||
};
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
@ -394,6 +394,10 @@ ifndef MOZ_TREE_PIXMAN
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_PIXMAN_LIBS)
|
||||
endif
|
||||
|
||||
ifdef MOZ_DMD
|
||||
EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,dmd,$(DIST)/lib)
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME_PATH,gkmedias,$(DIST)/lib)
|
||||
|
||||
ifdef MOZ_WEBRTC
|
||||
|
@ -1597,6 +1597,12 @@ if [ "$NS_TRACE_MALLOC" ]; then
|
||||
"
|
||||
fi
|
||||
|
||||
if [ "$MOZ_DMD" ]; then
|
||||
add_makefiles "
|
||||
memory/replace/dmd/Makefile
|
||||
"
|
||||
fi
|
||||
|
||||
if [ "$MOZ_MAPINFO" ]; then
|
||||
add_makefiles "
|
||||
tools/codesighs/Makefile
|
||||
|
@ -15,6 +15,10 @@ ifdef NS_TRACE_MALLOC
|
||||
tier_platform_dirs = tools/trace-malloc/lib
|
||||
endif
|
||||
|
||||
ifdef MOZ_DMD
|
||||
tier_platform_dirs += memory/replace/dmd
|
||||
endif
|
||||
|
||||
ifdef MOZ_TREE_FREETYPE
|
||||
tier_platform_staticdirs += modules/freetype2
|
||||
endif
|
||||
|
@ -357,66 +357,91 @@ nsresult NS_RegisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
|
||||
nsresult NS_UnregisterMemoryReporter(nsIMemoryReporter *reporter);
|
||||
nsresult NS_UnregisterMemoryMultiReporter(nsIMemoryMultiReporter *reporter);
|
||||
|
||||
#if defined(MOZ_DMDV) || defined(MOZ_DMD)
|
||||
namespace mozilla {
|
||||
namespace 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/DMDV to do its thing.
|
||||
void RunReporters();
|
||||
}
|
||||
}
|
||||
#endif // defined(MOZ_DMDV) || defined(MOZ_DMD)
|
||||
|
||||
#ifdef MOZ_DMDV
|
||||
|
||||
#if defined(MOZ_MEMORY)
|
||||
#error "MOZ_DMDV precludes MOZ_MEMORY"
|
||||
#endif
|
||||
|
||||
// Because DMDV is not a tool that comes with the standard Valgrind
|
||||
// distribution, we have to #include our own local copy of dmdv.h. Ugly but
|
||||
// unavoidable.
|
||||
#ifdef MOZ_DMDV
|
||||
#if MOZ_MEMORY
|
||||
#error "--disable-jemalloc should have been forced when --enable-dmdv was specified"
|
||||
#endif
|
||||
#include "dmdv.h"
|
||||
#endif
|
||||
|
||||
#define MOZ_REPORT(ptr, usable, name) VALGRIND_DMDV_REPORT(ptr, usable, name)
|
||||
#define MOZ_REPORT_ON_ALLOC(ptr, usable, name) VALGRIND_DMDV_REPORT(ptr, usable, name)
|
||||
|
||||
namespace mozilla {
|
||||
namespace dmdv {
|
||||
// This dumps the DMDV output to stderr (or somewhere else, if one of
|
||||
// DMDV/Valgrind's logging options was used).
|
||||
void Dump();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions generated via this macro should be used by all traversal-based
|
||||
* memory reporters. Such functions return |moz_malloc_size_of(ptr)|; this
|
||||
* will always be zero on some obscure platforms.
|
||||
*
|
||||
* 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 DMDV 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).
|
||||
*/
|
||||
#elif defined(MOZ_DMD)
|
||||
|
||||
#if !defined(MOZ_MEMORY)
|
||||
#error "MOZ_DMD requires MOZ_MEMORY"
|
||||
#endif
|
||||
|
||||
#include "DMD.h"
|
||||
|
||||
#define MOZ_REPORT(ptr, usable, name) mozilla::dmd::Report(ptr, name)
|
||||
#define MOZ_REPORT_ON_ALLOC(ptr, usable, name) mozilla::dmd::ReportOnAlloc(ptr, name)
|
||||
|
||||
#else
|
||||
|
||||
#define MOZ_REPORT(ptr, usable, name)
|
||||
#define MOZ_REPORT_ON_ALLOC(ptr, usable, name)
|
||||
|
||||
#endif /* defined(MOZ_DMDV) || defined(MOZ_DMD) */
|
||||
|
||||
// Functions generated via this macro should be used by all traversal-based
|
||||
// memory reporters. Such functions return |moz_malloc_size_of(ptr)|; this
|
||||
// will always be zero on some obscure platforms.
|
||||
//
|
||||
// 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 DMDV/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) \
|
||||
static size_t fn(const void *ptr) \
|
||||
{ \
|
||||
size_t usable = moz_malloc_size_of(ptr); \
|
||||
VALGRIND_DMDV_REPORT(ptr, usable, name); \
|
||||
MOZ_REPORT(ptr, usable, name); \
|
||||
return usable; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Like NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN, but the created function sends an
|
||||
* "unreport" message to DMDV.
|
||||
*/
|
||||
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN_UN(fn) \
|
||||
// Functions generated by the next two macros should be used by wrapping
|
||||
// allocators that report heap blocks as soon as they are allocated and
|
||||
// unreport them as soon as they are freed. Such allocators are used in cases
|
||||
// where we have third-party code that we cannot modify. The two functions
|
||||
// must always be used in tandem.
|
||||
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_ALLOC_FUN(fn, name) \
|
||||
static size_t fn(const void *ptr) \
|
||||
{ \
|
||||
size_t usable = moz_malloc_size_of(ptr); \
|
||||
VALGRIND_DMDV_UNREPORT(ptr); \
|
||||
MOZ_REPORT_ON_ALLOC(ptr, usable, name); \
|
||||
return usable; \
|
||||
}
|
||||
|
||||
#ifdef MOZ_DMDV
|
||||
|
||||
/*
|
||||
* This runs all the memory reporters but does nothing with the results; i.e.
|
||||
* it does the minimal amount of work possible for DMDV to do its thing. Then
|
||||
* it dumps the DMDV output to stderr (or somewhere else, if one of
|
||||
* DMDV/Valgrind's logging options was used).
|
||||
*/
|
||||
void DMDVCheckAndDump();
|
||||
|
||||
#else
|
||||
|
||||
#define VALGRIND_DMDV_REPORT(ptr, usable, name)
|
||||
#define VALGRIND_DMDV_UNREPORT(ptr)
|
||||
|
||||
#endif /* defined(MOZ_DMDV) */
|
||||
}
|
||||
#define NS_MEMORY_REPORTER_MALLOC_SIZEOF_ON_FREE_FUN(fn) \
|
||||
static size_t fn(const void *ptr) \
|
||||
{ \
|
||||
return moz_malloc_size_of(ptr); \
|
||||
}
|
||||
|
||||
%}
|
||||
|
@ -469,13 +469,73 @@ NS_IMPL_ISUPPORTS1(
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
static void
|
||||
MakeFilename(const char *aPrefix, const nsAString &aIdentifier,
|
||||
const char *aSuffix, nsACString &aResult)
|
||||
{
|
||||
aResult = nsPrintfCString("%s-%s-%d.%s",
|
||||
aPrefix,
|
||||
NS_ConvertUTF16toUTF8(aIdentifier).get(),
|
||||
getpid(), aSuffix);
|
||||
}
|
||||
|
||||
static nsresult
|
||||
OpenTempFile(const nsACString &aFilename, nsIFile* *aFile)
|
||||
{
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, aFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIFile> file(*aFile);
|
||||
|
||||
rv = file->AppendNative(aFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = file->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef ANDROID
|
||||
{
|
||||
// On android the default system umask is 0077 which makes these files
|
||||
// unreadable to the shell user. In order to pull the dumps off a non-rooted
|
||||
// device we need to chmod them to something world-readable.
|
||||
nsAutoCString path;
|
||||
rv = file->GetNativePath(path);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
chmod(PromiseFlatCString(path).get(), 0644);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
struct DMDWriteState
|
||||
{
|
||||
static const size_t kBufSize = 4096;
|
||||
char mBuf[kBufSize];
|
||||
nsRefPtr<nsGZFileWriter> mGZWriter;
|
||||
|
||||
DMDWriteState(nsGZFileWriter *aGZWriter)
|
||||
: mGZWriter(aGZWriter)
|
||||
{}
|
||||
};
|
||||
|
||||
static void DMDWrite(void* aState, const char* aFmt, va_list ap)
|
||||
{
|
||||
DMDWriteState *state = (DMDWriteState*)aState;
|
||||
vsnprintf(state->mBuf, state->kBufSize, aFmt, ap);
|
||||
unused << state->mGZWriter->Write(state->mBuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* static */ nsresult
|
||||
nsMemoryInfoDumper::DumpMemoryReportsToFileImpl(
|
||||
const nsAString& aIdentifier)
|
||||
{
|
||||
MOZ_ASSERT(!aIdentifier.IsEmpty());
|
||||
|
||||
// Open a new file named something like
|
||||
//
|
||||
// incomplete-memory-report-<-identifier>-<pid>-42.json.gz
|
||||
// incomplete-memory-report-<identifier>-<pid>.json.gz
|
||||
//
|
||||
// in NS_OS_TEMP_DIR for writing. When we're finished writing the report,
|
||||
// we'll rename this file and get rid of the "incomplete-" prefix.
|
||||
@ -484,43 +544,19 @@ nsMemoryInfoDumper::DumpMemoryReportsToFileImpl(
|
||||
// looking for memory report dumps to grab a file before we're finished
|
||||
// writing to it.
|
||||
|
||||
nsCOMPtr<nsIFile> tmpFile;
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR,
|
||||
getter_AddRefs(tmpFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Note that |filename| is missing the "incomplete-" prefix; we'll tack
|
||||
// Note that |mrFilename| is missing the "incomplete-" prefix; we'll tack
|
||||
// that on in a moment.
|
||||
nsAutoCString filename;
|
||||
filename.AppendLiteral("memory-report");
|
||||
if (!aIdentifier.IsEmpty()) {
|
||||
filename.AppendLiteral("-");
|
||||
filename.Append(NS_ConvertUTF16toUTF8(aIdentifier));
|
||||
}
|
||||
filename.AppendLiteral("-");
|
||||
filename.AppendInt(getpid());
|
||||
filename.AppendLiteral(".json.gz");
|
||||
nsCString mrFilename;
|
||||
MakeFilename("memory-report", aIdentifier, ".json.gz", mrFilename);
|
||||
|
||||
rv = tmpFile->AppendNative(NS_LITERAL_CSTRING("incomplete-") + filename);
|
||||
nsCOMPtr<nsIFile> mrTmpFile;
|
||||
nsresult rv;
|
||||
rv = OpenTempFile(NS_LITERAL_CSTRING("incomplete-") + mrFilename,
|
||||
getter_AddRefs(mrTmpFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = tmpFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0644);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef ANDROID
|
||||
{
|
||||
// On android the default system umask is 0077 which makes these files
|
||||
// unreadable to the shell user. In order to pull the dumps off a non-rooted
|
||||
// device we need to chmod them to something world-readable.
|
||||
nsAutoCString path;
|
||||
rv = tmpFile->GetNativePath(path);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
chmod(PromiseFlatCString(path).get(), 0644);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsRefPtr<nsGZFileWriter> writer = new nsGZFileWriter();
|
||||
rv = writer->Init(tmpFile);
|
||||
rv = writer->Init(mrTmpFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Dump the memory reports to the file.
|
||||
@ -593,24 +629,55 @@ nsMemoryInfoDumper::DumpMemoryReportsToFileImpl(
|
||||
rv = writer->Finish();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef MOZ_DMD
|
||||
// Open a new file named something like
|
||||
//
|
||||
// dmd-<identifier>-<pid>.txt.gz
|
||||
//
|
||||
// in NS_OS_TEMP_DIR for writing, and dump DMD output to it. This must occur
|
||||
// after the memory reporters have been run (above), but before the
|
||||
// memory-reports file has been renamed (so scripts can detect the DMD file,
|
||||
// if present).
|
||||
|
||||
nsCString dmdFilename;
|
||||
MakeFilename("dmd", aIdentifier, ".txt.gz", dmdFilename);
|
||||
|
||||
nsCOMPtr<nsIFile> dmdFile;
|
||||
rv = OpenTempFile(dmdFilename, getter_AddRefs(dmdFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsRefPtr<nsGZFileWriter> dmdWriter = new nsGZFileWriter();
|
||||
rv = dmdWriter->Init(dmdFile);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Dump DMD output to the file.
|
||||
|
||||
DMDWriteState state(dmdWriter);
|
||||
dmd::Writer w(DMDWrite, &state);
|
||||
mozilla::dmd::Dump(w);
|
||||
|
||||
rv = dmdWriter->Finish();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#endif // MOZ_DMD
|
||||
|
||||
// Rename the file, now that we're done dumping the report. The file's
|
||||
// ultimate destination is "memory-report<-identifier>-<pid>.json.gz".
|
||||
|
||||
nsCOMPtr<nsIFile> dstFile;
|
||||
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(dstFile));
|
||||
nsCOMPtr<nsIFile> mrFinalFile;
|
||||
rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(mrFinalFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dstFile->AppendNative(filename);
|
||||
rv = mrFinalFile->AppendNative(mrFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = dstFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
||||
rv = mrFinalFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0600);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString dstFileName;
|
||||
rv = dstFile->GetLeafName(dstFileName);
|
||||
nsAutoString mrActualFinalFilename;
|
||||
rv = mrFinalFile->GetLeafName(mrActualFinalFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = tmpFile->MoveTo(/* directory */ nullptr, dstFileName);
|
||||
rv = mrTmpFile->MoveTo(/* directory */ nullptr, mrActualFinalFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIConsoleService> cs =
|
||||
@ -618,7 +685,7 @@ nsMemoryInfoDumper::DumpMemoryReportsToFileImpl(
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString path;
|
||||
tmpFile->GetPath(path);
|
||||
mrTmpFile->GetPath(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsString msg = NS_LITERAL_STRING(
|
||||
|
@ -710,7 +710,7 @@ struct MemoryReport {
|
||||
int64_t amount;
|
||||
};
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) && !defined(MOZ_DMD)
|
||||
// This is just a wrapper for int64_t that implements nsISupports, so it can be
|
||||
// passed to nsIMemoryMultiReporter::CollectReports.
|
||||
class Int64Wrapper MOZ_FINAL : public nsISupports {
|
||||
@ -746,7 +746,7 @@ NS_IMPL_ISUPPORTS1(
|
||||
ExplicitNonHeapCountingCallback
|
||||
, nsIMemoryMultiReporterCallback
|
||||
)
|
||||
#endif
|
||||
#endif // defined(DEBUG) && !defined(MOZ_DMD)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMemoryReporterManager::GetExplicit(int64_t *aExplicit)
|
||||
@ -805,7 +805,9 @@ nsMemoryReporterManager::GetExplicit(int64_t *aExplicit)
|
||||
// (Actually, in debug builds we also do it the slow way and compare the
|
||||
// result to the result obtained from GetExplicitNonHeap(). This
|
||||
// guarantees the two measurement paths are equivalent. This is wise
|
||||
// because it's easy for memory reporters to have bugs.)
|
||||
// because it's easy for memory reporters to have bugs. But there's an
|
||||
// exception if DMD is enabled, because that makes DMD think that all the
|
||||
// blocks are double-counted.)
|
||||
|
||||
int64_t explicitNonHeapMultiSize = 0;
|
||||
nsCOMPtr<nsISimpleEnumerator> e2;
|
||||
@ -819,7 +821,7 @@ nsMemoryReporterManager::GetExplicit(int64_t *aExplicit)
|
||||
explicitNonHeapMultiSize += n;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(DEBUG) && !defined(MOZ_DMD)
|
||||
nsRefPtr<ExplicitNonHeapCountingCallback> cb =
|
||||
new ExplicitNonHeapCountingCallback();
|
||||
nsRefPtr<Int64Wrapper> wrappedExplicitNonHeapMultiSize2 =
|
||||
@ -842,7 +844,7 @@ nsMemoryReporterManager::GetExplicit(int64_t *aExplicit)
|
||||
explicitNonHeapMultiSize,
|
||||
explicitNonHeapMultiSize2).get());
|
||||
}
|
||||
#endif // DEBUG
|
||||
#endif // defined(DEBUG) && !defined(MOZ_DMD)
|
||||
|
||||
*aExplicit = heapAllocated + explicitNonHeapNormalSize + explicitNonHeapMultiSize;
|
||||
return NS_OK;
|
||||
@ -1017,9 +1019,10 @@ NS_UnregisterMemoryMultiReporter (nsIMemoryMultiReporter *reporter)
|
||||
return mgr->UnregisterMultiReporter(reporter);
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
#if defined(MOZ_DMDV) || defined(MOZ_DMD)
|
||||
|
||||
#ifdef MOZ_DMDV
|
||||
namespace mozilla {
|
||||
namespace dmd {
|
||||
|
||||
class NullMultiReporterCallback : public nsIMemoryMultiReporterCallback
|
||||
{
|
||||
@ -1041,7 +1044,7 @@ NS_IMPL_ISUPPORTS1(
|
||||
)
|
||||
|
||||
void
|
||||
DMDVCheckAndDump()
|
||||
RunReporters()
|
||||
{
|
||||
nsCOMPtr<nsIMemoryReporterManager> mgr =
|
||||
do_GetService("@mozilla.org/memory-reporter-manager;1");
|
||||
@ -1089,10 +1092,25 @@ DMDVCheckAndDump()
|
||||
e2->GetNext(getter_AddRefs(r));
|
||||
r->CollectReports(cb, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dmd
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // defined(MOZ_DMDV) || defined(MOZ_DMD)
|
||||
|
||||
#ifdef MOZ_DMDV
|
||||
namespace mozilla {
|
||||
namespace dmdv {
|
||||
|
||||
void
|
||||
Dump()
|
||||
{
|
||||
VALGRIND_DMDV_CHECK_REPORTING;
|
||||
}
|
||||
|
||||
} // namespace dmdv
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* defined(MOZ_DMDV) */
|
||||
|
||||
}
|
||||
|
@ -1180,7 +1180,9 @@ NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
|
||||
#elif defined(HAVE__UNWIND_BACKTRACE)
|
||||
|
||||
// libgcc_s.so symbols _Unwind_Backtrace@@GCC_3.3 and _Unwind_GetIP@@GCC_3.0
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <unwind.h>
|
||||
|
||||
struct unwind_info {
|
||||
|
Loading…
Reference in New Issue
Block a user