diff --git a/addon-sdk/source/python-lib/cuddlefish/runner.py b/addon-sdk/source/python-lib/cuddlefish/runner.py index 868b08e4a6c9..6527eca14fe1 100644 --- a/addon-sdk/source/python-lib/cuddlefish/runner.py +++ b/addon-sdk/source/python-lib/cuddlefish/runner.py @@ -492,7 +492,6 @@ def run_app(harness_root_dir, manifest_rdf, harness_options, env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1' env['MOZ_NO_REMOTE'] = '1' env['XPCOM_DEBUG_BREAK'] = 'stack' - env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1' env.update(extra_environment) if norun: cmdargs.append("-no-remote") diff --git a/build/automation.py.in b/build/automation.py.in index f2a2103e2a68..2d46460ce542 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -504,7 +504,6 @@ class Automation(object): env['GNOME_DISABLE_CRASH_DIALOG'] = '1' env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' - env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1' # Set WebRTC logging in case it is not set yet env.setdefault('NSPR_LOG_MODULES', 'signaling:5,mtransport:5,datachannel:5,jsep:5,MediaPipelineFactory:5') diff --git a/build/automationutils.py b/build/automationutils.py index a9ed760bdf4c..ec892b669b5f 100644 --- a/build/automationutils.py +++ b/build/automationutils.py @@ -330,7 +330,6 @@ def environment(xrePath, env=None, crashreporter=True, debugger=False, dmdPath=N # crashreporter env['GNOME_DISABLE_CRASH_DIALOG'] = '1' env['XRE_NO_WINDOWS_CRASH_DIALOG'] = '1' - env['NS_TRACE_MALLOC_DISABLE_STACKS'] = '1' if crashreporter and not debugger: env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' diff --git a/config/config.mk b/config/config.mk index 141dda16fa5f..e03b31a22ab9 100644 --- a/config/config.mk +++ b/config/config.mk @@ -228,17 +228,17 @@ endif endif # -# Handle trace-malloc and DMD in optimized builds. +# Handle DMD in optimized builds. # No opt to give sane callstacks. # -ifneq (,$(NS_TRACE_MALLOC)$(MOZ_DMD)) +ifdef MOZ_DMD MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG ifdef HAVE_64BIT_BUILD OS_LDFLAGS = -DEBUG -OPT:REF,ICF else OS_LDFLAGS = -DEBUG -OPT:REF endif -endif # NS_TRACE_MALLOC || MOZ_DMD +endif # MOZ_DMD endif # MOZ_DEBUG @@ -421,20 +421,20 @@ ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_) #//------------------------------------------------------------------------ ifdef USE_STATIC_LIBS RTL_FLAGS=-MT # Statically linked multithreaded RTL -ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)) +ifdef MOZ_DEBUG 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 else # !USE_STATIC_LIBS RTL_FLAGS=-MD # Dynamically linked, multithreaded RTL -ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC)) +ifdef MOZ_DEBUG 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 endif # USE_STATIC_LIBS endif # WINNT && !GNU_CC diff --git a/configure.in b/configure.in index 9d1af15d8231..8b9dce5b454c 100644 --- a/configure.in +++ b/configure.in @@ -7046,21 +7046,6 @@ if test -n "$MOZ_DEBUG"; then AC_DEFINE(MOZ_DUMP_PAINTING) fi -dnl ======================================================== -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 DMD and jemalloc], - NS_TRACE_MALLOC=1, - NS_TRACE_MALLOC= ) -if test "$NS_TRACE_MALLOC"; then - # Please, Mr. Linker Man, don't take away our symbol names - MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= - AC_DEFINE(NS_TRACE_MALLOC) -fi -AC_SUBST(NS_TRACE_MALLOC) - dnl ======================================================== dnl = Enable DMD dnl ======================================================== @@ -7070,11 +7055,6 @@ MOZ_ARG_ENABLE_BOOL(dmd, MOZ_DMD=1, MOZ_DMD= ) -dnl The two options are conflicting. Fails the configure to alert the user. -if test "$NS_TRACE_MALLOC" -a "$MOZ_DMD"; then - AC_MSG_ERROR([--enable-trace-malloc and --enable-dmd are conflicting options]) -fi - if test "$MOZ_DMD"; then AC_DEFINE(MOZ_DMD) @@ -7096,10 +7076,6 @@ MOZ_ARG_ENABLE_BOOL(jemalloc, MOZ_MEMORY=1, MOZ_MEMORY=) -if test "$NS_TRACE_MALLOC"; then - MOZ_MEMORY= -fi - case "${OS_TARGET}" in Android|WINNT|Darwin) MOZ_GLUE_IN_PROGRAM= @@ -7122,11 +7098,6 @@ MOZ_ARG_ENABLE_BOOL(replace-malloc, MOZ_REPLACE_MALLOC=1, MOZ_REPLACE_MALLOC= ) -dnl The two options are conflicting. Fails the configure to alert the user. -if test "$NS_TRACE_MALLOC" -a "$MOZ_REPLACE_MALLOC"; then - AC_MSG_ERROR([--enable-trace-malloc and --enable-replace-malloc are conflicting options]) -fi - if test -n "$MOZ_REPLACE_MALLOC" -a -z "$MOZ_MEMORY"; then dnl We don't want to enable jemalloc unconditionally because it may be a dnl deliberate choice not to enable it (bug 702250, for instance) @@ -7601,9 +7572,9 @@ if test -z "$SKIP_LIBRARY_CHECKS"; then AC_LANG_RESTORE fi -# Demangle only for debug or trace-malloc or DMD builds +# Demangle only for debug or DMD builds MOZ_DEMANGLE_SYMBOLS= -if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_DEMANGLE_SYMBOLS=1 AC_DEFINE(MOZ_DEMANGLE_SYMBOLS) fi @@ -8423,7 +8394,7 @@ if test -n "$MOZ_DEVICES"; then fi dnl ======================================================== -if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index 23a490e577cf..edf7a29ad16e 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1087,177 +1087,6 @@ nsJSContext::AddSupportsPrimitiveTojsvals(nsISupports *aArg, JS::Value *aArgv) return NS_OK; } -#ifdef NS_TRACE_MALLOC - -#include // XXX assume Linux if NS_TRACE_MALLOC -#include -#ifdef XP_UNIX -#include -#endif -#ifdef XP_WIN32 -#include -#endif -#include "nsTraceMalloc.h" - -static bool -CheckUniversalXPConnectForTraceMalloc(JSContext *cx) -{ - if (nsContentUtils::IsCallerChrome()) - return true; - JS_ReportError(cx, "trace-malloc functions require UniversalXPConnect"); - return false; -} - -static bool -TraceMallocDisable(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - NS_TraceMallocDisable(); - args.rval().setUndefined(); - return true; -} - -static bool -TraceMallocEnable(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - NS_TraceMallocEnable(); - args.rval().setUndefined(); - return true; -} - -static bool -TraceMallocOpenLogFile(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - int fd; - if (argc == 0) { - fd = -1; - } else { - JSString *str = JS::ToString(cx, args[0]); - if (!str) - return false; - JSAutoByteString filename(cx, str); - if (!filename) - return false; - fd = open(filename.ptr(), O_CREAT | O_WRONLY | O_TRUNC, 0644); - if (fd < 0) { - JS_ReportError(cx, "can't open %s: %s", filename.ptr(), strerror(errno)); - return false; - } - } - args.rval().setInt32(fd); - return true; -} - -static bool -TraceMallocChangeLogFD(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - int32_t fd, oldfd; - if (args.length() == 0) { - oldfd = -1; - } else { - if (!JS::ToInt32(cx, args[0], &fd)) - return false; - oldfd = NS_TraceMallocChangeLogFD(fd); - if (oldfd == -2) { - JS_ReportOutOfMemory(cx); - return false; - } - } - args.rval().setInt32(oldfd); - return true; -} - -static bool -TraceMallocCloseLogFD(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = CallArgsFromVp(argc, vp); - - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - int32_t fd; - if (args.length() == 0) { - args.rval().setUndefined(); - return true; - } - if (!JS::ToInt32(cx, args[0], &fd)) - return false; - NS_TraceMallocCloseLogFD((int) fd); - args.rval().setInt32(fd); - return true; -} - -static bool -TraceMallocLogTimestamp(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - JSString *str = JS::ToString(cx, args.get(0)); - if (!str) - return false; - JSAutoByteString caption(cx, str); - if (!caption) - return false; - NS_TraceMallocLogTimestamp(caption.ptr()); - args.rval().setUndefined(); - return true; -} - -static bool -TraceMallocDumpAllocations(JSContext *cx, unsigned argc, JS::Value *vp) -{ - JS::CallArgs args = JS::CallArgsFromVp(argc, vp); - if (!CheckUniversalXPConnectForTraceMalloc(cx)) - return false; - - JSString *str = JS::ToString(cx, args.get(0)); - if (!str) - return false; - JSAutoByteString pathname(cx, str); - if (!pathname) - return false; - if (NS_TraceMallocDumpAllocations(pathname.ptr()) < 0) { - JS_ReportError(cx, "can't dump to %s: %s", pathname.ptr(), strerror(errno)); - return false; - } - args.rval().setUndefined(); - return true; -} - -static const JSFunctionSpec TraceMallocFunctions[] = { - JS_FS("TraceMallocDisable", TraceMallocDisable, 0, 0), - JS_FS("TraceMallocEnable", TraceMallocEnable, 0, 0), - JS_FS("TraceMallocOpenLogFile", TraceMallocOpenLogFile, 1, 0), - JS_FS("TraceMallocChangeLogFD", TraceMallocChangeLogFD, 1, 0), - JS_FS("TraceMallocCloseLogFD", TraceMallocCloseLogFD, 1, 0), - JS_FS("TraceMallocLogTimestamp", TraceMallocLogTimestamp, 1, 0), - JS_FS("TraceMallocDumpAllocations", TraceMallocDumpAllocations, 1, 0), - JS_FS_END -}; - -#endif /* NS_TRACE_MALLOC */ - #ifdef MOZ_JPROF #include @@ -1374,13 +1203,6 @@ nsJSContext::InitClasses(JS::Handle aGlobalObj) // Attempt to initialize profiling functions ::JS_DefineProfilingFunctions(cx, aGlobalObj); -#ifdef NS_TRACE_MALLOC - if (nsContentUtils::IsCallerChrome()) { - // Attempt to initialize TraceMalloc functions - ::JS_DefineFunctions(cx, aGlobalObj, TraceMallocFunctions); - } -#endif - #ifdef MOZ_JPROF // Attempt to initialize JProf functions ::JS_DefineFunctions(cx, aGlobalObj, JProfFunctions); diff --git a/gfx/thebes/gfxPlatform.cpp b/gfx/thebes/gfxPlatform.cpp index c9aee1a284f9..548d8914c8af 100644 --- a/gfx/thebes/gfxPlatform.cpp +++ b/gfx/thebes/gfxPlatform.cpp @@ -702,7 +702,7 @@ gfxPlatform::~gfxPlatform() // cairo_debug_* function unconditionally. // // because cairo can assert and thus crash on shutdown, don't do this in release builds -#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC) || defined(MOZ_VALGRIND) +#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(MOZ_VALGRIND) #ifdef USE_SKIA // must do Skia cleanup before Cairo cleanup, because Skia may be referencing // Cairo objects e.g. through SkCairoFTTypeface diff --git a/js/src/configure.in b/js/src/configure.in index a0bb06cef79e..709ed9622093 100644 --- a/js/src/configure.in +++ b/js/src/configure.in @@ -2988,21 +2988,6 @@ elif test "$GNU_CC"; then fi fi -dnl ======================================================== -dnl = Enable trace malloc -dnl ======================================================== -NS_TRACE_MALLOC=${MOZ_TRACE_MALLOC} -MOZ_ARG_ENABLE_BOOL(trace-malloc, -[ --enable-trace-malloc Enable malloc tracing], - NS_TRACE_MALLOC=1, - NS_TRACE_MALLOC= ) -if test "$NS_TRACE_MALLOC"; then - # Please, Mr. Linker Man, don't take away our symbol names - MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= - AC_DEFINE(NS_TRACE_MALLOC) -fi -AC_SUBST(NS_TRACE_MALLOC) - dnl ======================================================== dnl = Enable DMD dnl ======================================================== @@ -3012,9 +2997,6 @@ MOZ_ARG_ENABLE_BOOL(dmd, MOZ_DMD=1, MOZ_DMD= ) -if test "$NS_TRACE_MALLOC"; then # trace-malloc disables DMD - MOZ_DMD= -fi if test "$MOZ_DMD"; then AC_DEFINE(MOZ_DMD) @@ -3032,10 +3014,6 @@ MOZ_ARG_ENABLE_BOOL(jemalloc, MOZ_MEMORY=1, MOZ_MEMORY=) -if test "$NS_TRACE_MALLOC"; then - MOZ_MEMORY= -fi - if test "$MOZ_MEMORY"; then AC_DEFINE(MOZ_MEMORY) if test "x$MOZ_DEBUG" = "x1"; then @@ -3429,9 +3407,9 @@ if test -z "$SKIP_LIBRARY_CHECKS"; then AC_LANG_RESTORE fi -# Demangle only for debug or trace-malloc or DMD builds +# Demangle only for debug or DMD builds MOZ_DEMANGLE_SYMBOLS= -if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$HAVE_DEMANGLE" && test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_DEMANGLE_SYMBOLS=1 AC_DEFINE(MOZ_DEMANGLE_SYMBOLS) fi @@ -3671,7 +3649,7 @@ if test "$JS_HAS_CTYPES"; then AC_DEFINE(JS_HAS_CTYPES) fi -if test "$MOZ_DEBUG" -o "$NS_TRACE_MALLOC" -o "$MOZ_DMD"; then +if test "$MOZ_DEBUG" -o "$MOZ_DMD"; then MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS= fi diff --git a/testing/xpcshell/runxpcshelltests.py b/testing/xpcshell/runxpcshelltests.py index 21e9422bf895..4cd6a65632b4 100755 --- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -836,9 +836,6 @@ class XPCShellTests(object): self.env["MOZ_CRASHREPORTER"] = "1" # Don't launch the crash reporter client self.env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" - # Capturing backtraces is very slow on some platforms, and it's - # disabled by automation.py too - self.env["NS_TRACE_MALLOC_DISABLE_STACKS"] = "1" # Don't permit remote connections by default. # MOZ_DISABLE_NONLOCAL_CONNECTIONS can be set to "0" to temporarily # enable non-local connections for the purposes of local testing. diff --git a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul index ff1b881833af..3e1ac901d921 100644 --- a/toolkit/components/aboutmemory/tests/test_aboutmemory.xul +++ b/toolkit/components/aboutmemory/tests/test_aboutmemory.xul @@ -126,7 +126,7 @@ // and subsequent processes. // // Nb: mgr.explicit will throw NS_ERROR_NOT_AVAILABLE if this is a - // --enable-trace-malloc build. Allow for that exception, but *only* that + // --disable-jemalloc build. Allow for that exception, but *only* that // exception. try { is(mgr.explicit, 500*MB + (100 + 13 + 10)*MB + 599*KB, "mgr.explicit"); diff --git a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul index aaadc6f265b5..28096b4b69de 100644 --- a/toolkit/components/aboutmemory/tests/test_memoryReporters.xul +++ b/toolkit/components/aboutmemory/tests/test_memoryReporters.xul @@ -139,7 +139,7 @@ // non-deterministic. // // Nb: mgr.explicit will throw NS_ERROR_NOT_AVAILABLE if this is a - // --enable-trace-malloc build. Allow for that exception, but *only* that + // --disable-jemalloc build. Allow for that exception, but *only* that // exception. let dummy; let haveExplicit = true; diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild index 2dcea0d5122c..b0bd02d149aa 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -21,9 +21,6 @@ DIRS += [ if CONFIG['MOZ_UPDATER']: DIRS += ['/modules/libmar'] -if CONFIG['NS_TRACE_MALLOC']: - DIRS += ['/tools/trace-malloc/lib'] - DIRS += [ '/config/external/freetype2', '/xpcom', @@ -163,9 +160,6 @@ DIRS += [ '/toolkit/library', ] -if CONFIG['NS_TRACE_MALLOC']: - DIRS += ['/tools/trace-malloc'] - if CONFIG['MOZ_ENABLE_GNOME_COMPONENT']: DIRS += ['/toolkit/system/gnome'] diff --git a/toolkit/xre/nsAppRunner.cpp b/toolkit/xre/nsAppRunner.cpp index aff17ea511f2..b23b3edb79d4 100644 --- a/toolkit/xre/nsAppRunner.cpp +++ b/toolkit/xre/nsAppRunner.cpp @@ -160,10 +160,6 @@ #include "nsIRemoteService.h" #endif -#ifdef NS_TRACE_MALLOC -#include "nsTraceMalloc.h" -#endif - #if defined(DEBUG) && defined(XP_WIN32) #include #endif @@ -224,8 +220,7 @@ static char **gQtOnlyArgv; #endif #if defined(MOZ_WIDGET_GTK) -#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) \ - || defined(NS_TRACE_MALLOC) +#if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) #define CLEANUP_MEMORY 1 #define PANGO_ENABLE_BACKEND #include @@ -3327,10 +3322,6 @@ XREMain::XRE_mainInit(bool* aExitFlag) *aExitFlag = true; return 0; } - -#ifdef NS_TRACE_MALLOC - gArgc = NS_TraceMallocStartupArgs(gArgc, gArgv); -#endif rv = XRE_InitCommandLine(gArgc, gArgv); NS_ENSURE_SUCCESS(rv, 1); diff --git a/tools/trace-malloc/Makefile.in b/tools/trace-malloc/Makefile.in deleted file mode 100644 index 1f715db93d5f..000000000000 --- a/tools/trace-malloc/Makefile.in +++ /dev/null @@ -1,39 +0,0 @@ -# -# 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/. - -EXTRACSRCS = tmreader.c -EXTRACPPSRCS = adreader.cpp - -ifndef MOZ_PROFILE_GENERATE - -PROGCSRCS = \ - spacetrace.c \ - spacecategory.c \ - formdata.c \ - $(NULL) - -PROGOBJS = $(PROGCSRCS:.c=.$(OBJ_SUFFIX)) -endif - -CPPSRCS += $(EXTRACPPSRCS) - -include $(topsrcdir)/config/config.mk - -# This is the last use of EXTRA_LIBS, and it would be sad to not have an -# error if it's used in other Makefiles just because of it. So hack around -# the check. -_DEPRECATED_VARIABLES := $(filter-out EXTRA_LIBS,$(_DEPRECATED_VARIABLES)) -EXTRA_LIBS += \ - tmreader.$(OBJ_SUFFIX) \ - adreader.$(OBJ_SUFFIX) \ - $(NULL) - -EXTRA_DEPS = $(EXTRACSRCS:.c=.$(OBJ_SUFFIX)) $(EXTRACPPSRCS:.cpp=.$(OBJ_SUFFIX)) - -include $(topsrcdir)/config/rules.mk - -# install rules.txt along with spacetrace executable -libs:: rules.txt - $(INSTALL) $< $(DIST)/bin diff --git a/tools/trace-malloc/README b/tools/trace-malloc/README deleted file mode 100644 index ff2f00209e17..000000000000 --- a/tools/trace-malloc/README +++ /dev/null @@ -1,177 +0,0 @@ - Trace Malloc Tools - Chris Waterson - November 27, 2000 - -This is a short primer on how to use the `trace malloc' tools -contained in this directory. - - -WHAT IS TRACE MALLOC? -===================== - -Trace malloc is an optional facility that is built in to XPCOM. It -uses `weak linking' to intercept all calls to malloc(), calloc(), -realloc() and free(). It does two things: - -1. Writes information about allocations to a filehandle that you -specify. As each call to malloc(), et. al. is made, a record is logged -to the filehandle. - -2. Maintains a table of all `live objects' -- that is, objects that -have been allocated by malloc(), calloc() or realloc(), but have not -yet been free()'d. The contents of this table can be called by making -a `secret' call to JavaScript. - - -MAKING A TRACE MALLOC BUILD -=========================== - -As of this writing, trace malloc only works on Linux, but work is -underway to port it to Windows. - -On Linux, start with a clean tree, and configure your build with the -following flags: - - --enable-trace-malloc - --enable-cpp-rtti - -Be sure that `--enable-boehm' is *not* set. I don't think that the -values for `--enable-debug' and `--enable-optimize' matter, but I've -typically had debug on and optimize off. - - -COLLECTING LIVE OBJECT DATA -=========================== - -To collect `live object' data from `mozilla' using a build that has -trace malloc enabled, - - 1. Run `mozilla' as follows: - - % mozilla --trace-malloc /dev/null - - 2. Do whatever operations in mozilla you'd like to test. - - 3. Open the `live-bloat.html' file contained in this directory. - - 4. Press the button that says `Dump to /tmp/dump.log' - -An enormous file (typically 300MB) called `dump.log' will be dropped -in your `/tmp' directory. - -To collect live object data from `gtkEmbed' using a build that has -trace malloc enabled: - - 1. Run `gtkEmbed' as follows: - - % gtkEmbed --trace-malloc /dev/null - - 2. Do whatever operations in gtkEmbed that you'd like to test. - - 3. Press the `Dump Memory' button at the bottom of gtkEmbed. - -The enormous file will be dropped in the current directory, and is -called `allocations.log'. - - -About Live Object Logs ----------------------- - -A typical entry from the `live object' dump file will look like: - - Address Type Size - | | | - v v v - 0x40008080 16 - 0x00000001 <- Fields - 0x40008084 - 0x80004001 - 0x00000036 - __builtin_new[./libxpcom.so +0x10E9DC] <- Stack at allocation time - nsFooBar::CreateFooBar(nsFooBar **)[./libfoobar.so +0x408C] - main+C7E5AFB5[(null) +0xC7E5AFB5] - -One will be printed for each object that was allocated. - - -TOOLS TO PARSE LIVE OBJECT LOGS -=============================== - -This directory is meant to house the tools that you can use to parse -live-object logs. - -Object Histograms - histogram.pl --------------------------------- - -This program parses a `live object' dump and produces a histogram of -the objects, sorted from objects that take the most memory to objects -that take the least. The output of this program is rather spartan: on -each line, it prints the object type, the number of objects of that -type, and the total number of bytes that the objects consume. - -There are a two simple programs to `pretty print' the output from -histogram.pl: - - 1. histogram-pretty.sh takes a single histogram and produces a table - of objects. - - Type Count Bytes %Total - TOTAL 67348 4458127 100.00 - nsImageGTK 76 679092 15.23 - void* 8956 563572 12.64 - ... - PRLock 732 61488 1.38 - OTHER 24419 940235 21.09 - - 2. histogram-diff.sh takes two histograms and computes the difference - between them. - - ---- Base ---- ---- Incr ---- ----- Difference ---- - Type Count Bytes Count Bytes Count Bytes %Total - TOTAL 40241 1940945 73545 5315142 33304 3374197 100.00 - nsImageGTK 16 106824 151 832816 135 725992 21.52 - PresShell 16 51088 198 340706 182 289618 8.58 - ... - OTHER 27334 1147033 38623 1493385 11289 346352 10.26 - -Both of these scripts accept `-c' parameter that specifies how many -rows you'd like to see (by default, twenty). Any rows past the first -`n' rows are lumped into a single `OTHER' row. This allows you to keep -your reports short n' sweet. - -Stack-based Type Inference - types.dat --------------------------------------- - -Trace malloc uses `speculative RTTI' to determine the types of objects -as it dumps them. Unfortunately, RTTI can only deduce the type name -for C++ objects with a virtual destructor. - -This leaves: - - . C++ object without a virtual destructor - . array allocated C++ objects, and - . objects allocated with the C runtime function (malloc - and friends) - -out in the cold. Trace malloc reports objects allocated this was as -having type `void*'. - -The good news is that you can almost always determine the object's -type by looking at the stack trace that's taken at the time the object -is allocated. - -The file `types.dat' consists of rules to classify objects based on -stack trace. - - -Uncategorized Objects - uncategorized.pl ----------------------------------------- - -Categorizing objects in `types.dat' is sweaty work, and the -`uncategorized.pl' script is a tool that makes it a bit -easier. Specifically, it reads a `live object' dump file and sorts the -stack traces. Stack traces that account for the most uncategorized -objects are placed first. - -Using this tool, you can add the `most effective' rules to -`types.dat': rules that account for most of the uncategorized data. diff --git a/tools/trace-malloc/TraceMalloc.pm b/tools/trace-malloc/TraceMalloc.pm deleted file mode 100644 index 096ce71becf5..000000000000 --- a/tools/trace-malloc/TraceMalloc.pm +++ /dev/null @@ -1,156 +0,0 @@ -# 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/. -package TraceMalloc; - -use strict; - -# Read in the type inference file and construct a network that we can -# use to match stack prefixes to types. -sub init_type_inference($) { - my ($file) = @_; - - $::Fingerprints = { }; - - open(TYPES, "<$file") || die "unable to open $::opt_types, $!"; - - TYPE: while () { - next TYPE unless /<(.*)>/; - my $type = $1; - - my $link = \%::Fingerprints; - - FRAME: while () { - chomp; - last FRAME if /^$/; - - my $next = $link->{$_}; - if (! $next) { - $next = $link->{$_} = {}; - } - $link = $next; - } - - $link->{'#type#'} = $type; - - last TYPE if eof; - } -} - -# Infer the type, trying to find the most specific type possible. -sub infer_type($) { - my ($stack) = @_; - - my $link = \%::Fingerprints; - my $last; - my $type = 'void*'; - FRAME: foreach my $frame (@$stack) { - last FRAME unless $link; - - $frame =~ s/\[.*\]$//; # ignore exact addresses, as they'll drift - - $last = $link; - - # - # Remember this type, but keep going. We use the longest match - # we find, but substacks of longer matches will also match. - # - if ($last->{'#type#'}) { - $type = $last->{'#type#'}; - } - - $link = $link->{$frame}; - - if (! $link) { - CHILD: foreach my $child (keys %$last) { - next CHILD unless $child =~ /^~/; - - $child =~ s/^~//; - - if ($frame =~ $child) { - $link = $last->{'~' . $child}; - last CHILD; - } - } - } - } - - return $type; -} - - -#---------------------------------------------------------------------- -# -# Read in the output a trace malloc's dump. -# -sub read { - my ($callback, $noslop) = @_; - - OBJECT: while (<>) { - # e.g., 0x0832FBD0 (80) - next OBJECT unless /^0x(\S+) <(.*)> \((\d+)\)/; - my ($addr, $type, $size) = (hex $1, $2, $3); - - my $object = { 'type' => $type, 'size' => $size }; - - # Record the object's slots - my @slots; - - SLOT: while (<>) { - # e.g., 0x00000000 - last SLOT unless /^\t0x(\S+)/; - my $value = hex $1; - - # Ignore low bits, unless they've specified --noslop - $value &= ~0x7 unless $noslop; - - $slots[$#slots + 1] = $value; - } - - $object->{'slots'} = \@slots; - - # Record the stack by which the object was allocated - my @stack; - - while (/^(.*)\[(.*) \+0x(\S+)\]$/) { - # e.g., _dl_debug_message[/lib/ld-linux.so.2 +0x0000B858] - my ($func, $lib, $off) = ($1, $2, hex $3); - - chomp; - $stack[$#stack + 1] = $_; - - $_ = <>; - } - - $object->{'stack'} = \@stack; - - $object->{'type'} = infer_type(\@stack) - if $object->{'type'} eq 'void*'; - - &$callback($object) if $callback; - - # Gotta check EOF explicitly... - last OBJECT if eof; - } -} - -1; -__END__ - -=head1 NAME - -TraceMalloc - Perl routines to deal with output from ``trace malloc'' -and the Boehm GC - -=head1 SYNOPSIS - - use TraceMalloc; - - TraceMalloc::init_type_inference("types.dat"); - TraceMalloc::read(0); - -=head1 DESCRIPTION - -=head1 EXAMPLES - -=cut diff --git a/tools/trace-malloc/adreader.cpp b/tools/trace-malloc/adreader.cpp deleted file mode 100644 index 27cc7f495e00..000000000000 --- a/tools/trace-malloc/adreader.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* 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/. */ - -#include "adreader.h" - -#include -#include -#include - -ADLog::ADLog() - : mEntryCount(0) -{ - mEntries.mNext = static_cast(&mEntries); - mEntries.mPrev = static_cast(&mEntries); -} - -ADLog::~ADLog() -{ - for (const_iterator entry = begin(), entry_end = end(); - entry != entry_end; ++entry) { - free((void*) (*entry)->type); - free((char*) (*entry)->data); - free((char*) (*entry)->allocation_stack); - } - - for (EntryBlock *b = mEntries.mNext, *next; b != &mEntries; b = next) { - next = b->mNext; - delete b; - } -} - -bool -ADLog::Read(const char* aFileName) -{ - FILE *in = fopen(aFileName, "r"); - if (!in) { - return false; - } - - while (!feof(in)) { - unsigned int ptr; - char typebuf[256]; - int datasize; - int res = fscanf(in, "%x %s (%d)\n", &ptr, typebuf, &datasize); - if (res == EOF) - break; - if (res != 3) { - return false; - } - - size_t data_mem_size = ((datasize + sizeof(unsigned long) - 1) / - sizeof(unsigned long)) * sizeof(unsigned long); - char *data = (char*)malloc(data_mem_size); - - for (size_t *cur_data = (size_t*) data, - *cur_data_end = (size_t*) ((char*)data + data_mem_size); - cur_data != cur_data_end; ++cur_data) { - res = fscanf(in, " %zX\n", cur_data); - if (res != 1) { - return false; - } - } - - char stackbuf[100000]; - stackbuf[0] = '\0'; - - char *stack = stackbuf; - int len; - do { - fgets(stack, sizeof(stackbuf) - (stack - stackbuf), in); - len = strlen(stack); - stack += len; - } while (len > 1); - - if (mEntryCount % ADLOG_ENTRY_BLOCK_SIZE == 0) { - EntryBlock *new_block = new EntryBlock(); - new_block->mNext = static_cast(&mEntries); - new_block->mPrev = mEntries.mPrev; - mEntries.mPrev->mNext = new_block; - mEntries.mPrev = new_block; - } - - size_t typelen = strlen(typebuf); - char *type = (char*)malloc(typelen-1); - strncpy(type, typebuf+1, typelen-2); - type[typelen-2] = '\0'; - - Entry *entry = - &mEntries.mPrev->entries[mEntryCount % ADLOG_ENTRY_BLOCK_SIZE]; - entry->address = (Pointer) (uintptr_t) ptr; - entry->type = type; - entry->datasize = datasize; - entry->data = data; - entry->allocation_stack = strdup(stackbuf); - - ++mEntryCount; - } - - return true; -} - -ADLog::const_iterator::const_iterator(ADLog::EntryBlock *aBlock, - size_t aOffset) -{ - SetBlock(aBlock); - mCur = mBlockStart + aOffset; -} - -ADLog::const_iterator& -ADLog::const_iterator::operator++() -{ - ++mCur; - if (mCur == mBlockEnd) { - SetBlock(mBlock->mNext); - mCur = mBlockStart; - } - - return *this; -} - -ADLog::const_iterator& -ADLog::const_iterator::operator--() -{ - if (mCur == mBlockStart) { - SetBlock(mBlock->mPrev); - mCur = mBlockEnd; - } - --mCur; - - return *this; -} diff --git a/tools/trace-malloc/adreader.h b/tools/trace-malloc/adreader.h deleted file mode 100644 index a7f9b64de060..000000000000 --- a/tools/trace-malloc/adreader.h +++ /dev/null @@ -1,97 +0,0 @@ -/* 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/. */ - -#include - -#define ADLOG_ENTRY_BLOCK_SIZE 4096 - -class ADLog { - -public: - - // Use typedef in case somebody wants to process 64-bit output on a - // 32-bit machine someday. - typedef const char* Pointer; - - struct Entry { - Pointer address; - const char *type; - - const char *data; // The contents of the memory. - size_t datasize; - - const char *allocation_stack; - }; - - ADLog(); - ~ADLog(); - - /* - * Returns false on failure and true on success. - */ - bool Read(const char *aFilename); - -private: - // Link structure for a circularly linked list. - struct EntryBlock; - struct EntryBlockLink { - EntryBlock *mPrev; - EntryBlock *mNext; - }; - - struct EntryBlock : public EntryBlockLink { - Entry entries[ADLOG_ENTRY_BLOCK_SIZE]; - }; - - size_t mEntryCount; - EntryBlockLink mEntries; - -public: - - class const_iterator { - private: - // Only |ADLog| member functions can construct iterators. - friend class ADLog; - const_iterator(EntryBlock *aBlock, size_t aOffset); - - public: - const Entry* operator*() { return mCur; } - const Entry* operator->() { return mCur; } - - const_iterator& operator++(); - const_iterator& operator--(); - - bool operator==(const const_iterator& aOther) const { - return mCur == aOther.mCur; - } - - bool operator!=(const const_iterator& aOther) const { - return mCur != aOther.mCur; - } - - private: - void SetBlock(EntryBlock *aBlock) { - mBlock = aBlock; - mBlockStart = aBlock->entries; - mBlockEnd = aBlock->entries + ADLOG_ENTRY_BLOCK_SIZE; - } - - EntryBlock *mBlock; - Entry *mCur, *mBlockStart, *mBlockEnd; - - // Not to be implemented. - const_iterator operator++(int); - const_iterator operator--(int); - }; - - const_iterator begin() { - return const_iterator(mEntries.mNext, 0); - } - const_iterator end() { - return const_iterator(mEntries.mPrev, - mEntryCount % ADLOG_ENTRY_BLOCK_SIZE); - } - - size_t count() { return mEntryCount; } -}; diff --git a/tools/trace-malloc/allocation-stacks.c b/tools/trace-malloc/allocation-stacks.c deleted file mode 100644 index 7bbbf431424f..000000000000 --- a/tools/trace-malloc/allocation-stacks.c +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ -#include -#include -#include -#include -#ifdef HAVE_GETOPT_H -#include -#else -extern int getopt(int argc, char *const *argv, const char *shortopts); -extern char *optarg; -extern int optind; -#ifdef XP_WIN32 -int optind=1; -#endif -#endif -#include -#include "nsTraceMalloc.h" -#include "tmreader.h" - -static char *program; - -static void my_tmevent_handler(tmreader *tmr, tmevent *event) -{ - tmcallsite *callsite; - - switch (event->type) { - case TM_EVENT_REALLOC: - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - for (callsite = tmreader_callsite(tmr, event->serial); - callsite != &tmr->calltree_root; callsite = callsite->parent) { - fprintf(stdout, "%s +%08X (%s:%d)\n", - (const char*)callsite->method->graphnode.entry.value, - callsite->offset, - callsite->method->sourcefile, - callsite->method->linenumber); - } - fprintf(stdout, "\n"); - } -} - -int main(int argc, char **argv) -{ - int i, j, rv; - tmreader *tmr; - FILE *fp; - time_t start; - - program = *argv; - - tmr = tmreader_new(program, NULL); - if (!tmr) { - perror(program); - exit(1); - } - - start = time(NULL); - fprintf(stdout, "%s starting at %s", program, ctime(&start)); - fflush(stdout); - - argc -= optind; - argv += optind; - if (argc == 0) { - if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0) - exit(1); - } else { - for (i = j = 0; i < argc; i++) { - fp = fopen(argv[i], "r"); - if (!fp) { - fprintf(stderr, "%s: can't open %s: %s\n", - program, argv[i], strerror(errno)); - exit(1); - } - rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler); - if (rv < 0) - exit(1); - if (rv > 0) - j++; - fclose(fp); - } - if (j == 0) - exit(1); - } - - tmreader_destroy(tmr); - - exit(0); -} diff --git a/tools/trace-malloc/blame.css b/tools/trace-malloc/blame.css deleted file mode 100644 index 58339fb9b4ae..000000000000 --- a/tools/trace-malloc/blame.css +++ /dev/null @@ -1,14 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * - * 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/. */ - -td { - font: x-small sans-serif; - vertical-align: top; -} - -thead td { - font-weight: bold; -} diff --git a/tools/trace-malloc/blame.pl b/tools/trace-malloc/blame.pl deleted file mode 100755 index 36afcad4ebd1..000000000000 --- a/tools/trace-malloc/blame.pl +++ /dev/null @@ -1,219 +0,0 @@ -#!/usr/bin/perl -w -# -# 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/. - -# -# Process output of TraceMallocDumpAllocations() to produce a table -# that attributes memory to the allocators using call stack. -# - -use 5.004; -use strict; - -# A table of all ancestors. Key is function name, value is an -# array of ancestors, each attributed with a number of calls and -# the amount of memory allocated. -my %Ancestors; - -# Ibid, for descendants. -my %Descendants; - -# A table that keeps the total amount of memory allocated by each -# function -my %Totals; -$Totals{".root"} = { "#memory#" => 0, "#calls#" => 0 }; - -# A table that maps the long ugly function name to a unique number so -# that the HTML we generate isn't too fat -my %Ids; -my $NextId = 0; - -$Ids{".root"} = ++$NextId; - - -LINE: while (<>) { - # The line'll look like: - # - # 0x4000a008 16 PR_Malloc+16; nsMemoryImpl::Alloc(unsigned int)+12; ... - - # Ignore any lines that don't start with an address - next LINE unless /^0x/; - - # Parse it - my ($address, $size, $rest) = /^(0x\S*)\s*(\d+)\s*(.*)$/; - my @stack = reverse(split /; /, $rest); - - # Accumulate at the root - $Totals{".root"}->{"#memory#"} += $size; - ++$Totals{".root"}->{"#calls#"}; - - my $caller = ".root"; - foreach my $callee (@stack) { - # Strip the offset from the callsite information. I don't - # think we care. - $callee =~ s/\+\d+$//g; - - # Accumulate the total for the callee - if (! $Totals{$callee}) { - $Totals{$callee} = { "#memory#" => 0, "#calls#" => 0 }; - } - - $Totals{$callee}->{"#memory#"} += $size; - ++$Totals{$callee}->{"#calls#"}; - - # Descendants - my $descendants = $Descendants{$caller}; - if (! $descendants) { - $descendants = $Descendants{$caller} = [ ]; - } - - # Manage the list of descendants - { - my $wasInserted = 0; - DESCENDANT: foreach my $item (@$descendants) { - if ($item->{"#name#"} eq $callee) { - $item->{"#memory#"} += $size; - ++$item->{"#calls#"}; - $wasInserted = 1; - last DESCENDANT; - } - } - - if (! $wasInserted) { - $descendants->[@$descendants] = { - "#name#" => $callee, - "#memory#" => $size, - "#calls#" => 1 - }; - } - } - - # Ancestors - my $ancestors = $Ancestors{$callee}; - if (! $ancestors) { - $ancestors = $Ancestors{$callee} = [ ]; - } - - # Manage the list of ancestors - { - my $wasInserted = 0; - ANCESTOR: foreach my $item (@$ancestors) { - if ($item->{"#name#"} eq $caller) { - $item->{"#memory#"} += $size; - ++$item->{"#calls#"}; - $wasInserted = 1; - last ANCESTOR; - } - } - - if (! $wasInserted) { - $ancestors->[@$ancestors] = { - "#name#" => $caller, - "#memory#" => $size, - "#calls#" => 1 - }; - } - } - - # Make a new "id", if necessary - if (! $Ids{$callee}) { - $Ids{$callee} = ++$NextId; - } - - # On to the next one... - $caller = $callee; - } -} - - -# Change the manky looking callsite into a pretty function; strip argument -# types and offset information. -sub pretty($) { - $_ = $_[0]; - s/&/&/g; - s//>/g; - - if (/([^\(]*)(\(.*\))/) { - return $1 . "()"; - } - else { - return $_[0]; - } -} - -# Dump a web page! -print "\n"; -print "\n"; -print "Live Bloat Blame\n"; -print "\n"; -print "\n"; -print "\n"; - -# At most 100 rows per table so as not to kill the browser. -my $maxrows = 100; - -print "\n"; -print "\n"; - -foreach my $node (sort(keys(%Ids))) { - print "\n"; - - # Print the current node - { - my ($memory, $calls) = - ($Totals{$node}->{"#memory#"}, - $Totals{$node}->{"#calls#"}); - - my $pretty = pretty($node); - print " \n"; - } - - # Ancestors, sorted descending by amount of memory allocated - print " \n"; - - # Descendants, sorted descending by amount of memory allocated - print " \n"; - - if (--$maxrows == 0) { - print "
FunctionAncestorsDescendants
$pretty $memory ($calls)\n"; - my $ancestors = $Ancestors{$node}; - if ($ancestors) { - foreach my $ancestor (sort { $b->{"#memory#"} <=> $a->{"#memory#"} } @$ancestors) { - my ($name, $memory, $calls) = - ($ancestor->{"#name#"}, - $ancestor->{"#memory#"}, - $ancestor->{"#calls#"}); - - my $pretty = pretty($name); - - print " $pretty $memory ($calls)
\n"; - } - } - - print "
\n"; - my $descendants = $Descendants{$node}; - if ($descendants) { - foreach my $descendant (sort { $b->{"#memory#"} <=> $a->{"#memory#"} } @$descendants) { - my ($name, $memory, $calls) = - ($descendant->{"#name#"}, - $descendant->{"#memory#"}, - $descendant->{"#calls#"}); - - my $pretty = pretty($name); - - print " $pretty $memory ($calls)
\n"; - } - } - print "
\n"; - print "\n"; - print "\n"; - $maxrows = 100; - } -} - -# Footer -print "
FunctionAncestorsDescendants
\n"; -print "\n"; diff --git a/tools/trace-malloc/bloatblame.cpp b/tools/trace-malloc/bloatblame.cpp deleted file mode 100644 index 3772119dabfe..000000000000 --- a/tools/trace-malloc/bloatblame.cpp +++ /dev/null @@ -1,722 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ -#include -#include -#include -#include -#include -#ifdef HAVE_GETOPT_H -#include -#else -#ifdef XP_WIN -#include "getopt.c" -#else -extern int getopt(int argc, char *const *argv, const char *shortopts); -extern char *optarg; -extern int optind; -#endif -#endif -#include -#include -#include -#include "prlog.h" -#include "prprf.h" -#include "plhash.h" -#include "pldhash.h" -#include "nsTraceMalloc.h" -#include "tmreader.h" - -static char *program; -static int sort_by_direct = 0; -static int js_mode = 0; -static int do_tree_dump = 0; -static int unified_output = 0; -static char *function_dump = NULL; -static uint32_t min_subtotal = 0; - -static void compute_callsite_totals(tmcallsite *site) -{ - tmcallsite *kid; - - site->allocs.bytes.total += site->allocs.bytes.direct; - site->allocs.calls.total += site->allocs.calls.direct; - for (kid = site->kids; kid; kid = kid->siblings) { - compute_callsite_totals(kid); - site->allocs.bytes.total += kid->allocs.bytes.total; - site->allocs.calls.total += kid->allocs.calls.total; - } -} - -static void walk_callsite_tree(tmcallsite *site, int level, int kidnum, FILE *fp) -{ - tmcallsite *parent; - tmgraphnode *comp, *pcomp, *lib, *plib; - tmmethodnode *meth, *pmeth; - int old_meth_low, old_comp_low, old_lib_low, nkids; - tmcallsite *kid; - - parent = site->parent; - comp = lib = NULL; - meth = NULL; - if (parent) { - meth = site->method; - if (meth) { - pmeth = parent->method; - if (pmeth && pmeth != meth) { - if (!meth->graphnode.low) { - meth->graphnode.allocs.bytes.total += site->allocs.bytes.total; - meth->graphnode.allocs.calls.total += site->allocs.calls.total; - } - if (!tmgraphnode_connect(&(pmeth->graphnode), &(meth->graphnode), site)) - goto bad; - - comp = meth->graphnode.up; - if (comp) { - pcomp = pmeth->graphnode.up; - if (pcomp && pcomp != comp) { - if (!comp->low) { - comp->allocs.bytes.total - += site->allocs.bytes.total; - comp->allocs.calls.total - += site->allocs.calls.total; - } - if (!tmgraphnode_connect(pcomp, comp, site)) - goto bad; - - lib = comp->up; - if (lib) { - plib = pcomp->up; - if (plib && plib != lib) { - if (!lib->low) { - lib->allocs.bytes.total - += site->allocs.bytes.total; - lib->allocs.calls.total - += site->allocs.calls.total; - } - if (!tmgraphnode_connect(plib, lib, site)) - goto bad; - } - old_lib_low = lib->low; - if (!old_lib_low) - lib->low = level; - } - } - old_comp_low = comp->low; - if (!old_comp_low) - comp->low = level; - } - } - old_meth_low = meth->graphnode.low; - if (!old_meth_low) - meth->graphnode.low = level; - } - } - - if (do_tree_dump) { - fprintf(fp, "%c%*s%3d %3d %s %lu %ld\n", - site->kids ? '+' : '-', level, "", level, kidnum, - meth ? tmmethodnode_name(meth) : "???", - (unsigned long)site->allocs.bytes.direct, - (long)site->allocs.bytes.total); - } - nkids = 0; - level++; - for (kid = site->kids; kid; kid = kid->siblings) { - walk_callsite_tree(kid, level, nkids, fp); - nkids++; - } - - if (meth) { - if (!old_meth_low) - meth->graphnode.low = 0; - if (comp) { - if (!old_comp_low) - comp->low = 0; - if (lib) { - if (!old_lib_low) - lib->low = 0; - } - } - } - return; - -bad: - perror(program); - exit(1); -} - -/* - * Linked list bubble-sort (waterson and brendan went bald hacking this). - * - * Sort the list in non-increasing order, using the expression passed as the - * 'lessthan' formal macro parameter. This expression should use 'curr' as - * the pointer to the current node (of type nodetype) and 'next' as the next - * node pointer. It should return true if curr is less than next, and false - * otherwise. - */ -#define BUBBLE_SORT_LINKED_LIST(listp, nodetype, lessthan) \ - PR_BEGIN_MACRO \ - nodetype *curr, **currp, *next, **nextp, *tmp; \ - \ - currp = listp; \ - while ((curr = *currp) != NULL && curr->next) { \ - nextp = &curr->next; \ - while ((next = *nextp) != NULL) { \ - if (lessthan) { \ - tmp = curr->next; \ - *currp = tmp; \ - if (tmp == next) { \ - PR_ASSERT(nextp == &curr->next); \ - curr->next = next->next; \ - next->next = curr; \ - } else { \ - *nextp = next->next; \ - curr->next = next->next; \ - next->next = tmp; \ - *currp = next; \ - *nextp = curr; \ - nextp = &curr->next; \ - } \ - curr = next; \ - continue; \ - } \ - nextp = &next->next; \ - } \ - currp = &curr->next; \ - } \ - PR_END_MACRO - -static int tabulate_node(PLHashEntry *he, int i, void *arg) -{ - tmgraphnode *node = (tmgraphnode*) he; - tmgraphnode **table = (tmgraphnode**) arg; - - table[i] = node; - BUBBLE_SORT_LINKED_LIST(&node->down, tmgraphnode, - (curr->allocs.bytes.total < next->allocs.bytes.total)); - return HT_ENUMERATE_NEXT; -} - -/* Sort in reverse size order, so biggest node comes first. */ -static int node_table_compare(const void *p1, const void *p2) -{ - const tmgraphnode *node1, *node2; - uint32_t key1, key2; - - node1 = *(const tmgraphnode**) p1; - node2 = *(const tmgraphnode**) p2; - if (sort_by_direct) { - key1 = node1->allocs.bytes.direct; - key2 = node2->allocs.bytes.direct; - } else { - key1 = node1->allocs.bytes.total; - key2 = node2->allocs.bytes.total; - } - return (key2 < key1) ? -1 : (key2 > key1) ? 1 : 0; -} - -static int mean_size_compare(const void *p1, const void *p2) -{ - const tmgraphnode *node1, *node2; - double div1, div2, key1, key2; - - node1 = *(const tmgraphnode**) p1; - node2 = *(const tmgraphnode**) p2; - div1 = (double)node1->allocs.calls.direct; - div2 = (double)node2->allocs.calls.direct; - if (div1 == 0 || div2 == 0) - return (int)(div2 - div1); - key1 = (double)node1->allocs.bytes.direct / div1; - key2 = (double)node2->allocs.bytes.direct / div2; - if (key1 < key2) - return 1; - if (key1 > key2) - return -1; - return 0; -} - -static const char *prettybig(uint32_t num, char *buf, size_t limit) -{ - if (num >= 1000000000) - PR_snprintf(buf, limit, "%1.2fG", (double) num / 1e9); - else if (num >= 1000000) - PR_snprintf(buf, limit, "%1.2fM", (double) num / 1e6); - else if (num >= 1000) - PR_snprintf(buf, limit, "%1.2fK", (double) num / 1e3); - else - PR_snprintf(buf, limit, "%lu", (unsigned long) num); - return buf; -} - -static double percent(uint32_t num, uint32_t total) -{ - if (num == 0) - return 0.0; - return ((double) num * 100) / (double) total; -} - -static void sort_graphlink_list(tmgraphlink **listp, int which) -{ - BUBBLE_SORT_LINKED_LIST(listp, tmgraphlink, - (TM_LINK_TO_EDGE(curr, which)->allocs.bytes.total - < TM_LINK_TO_EDGE(next, which)->allocs.bytes.total)); -} - -static void dump_graphlink_list(tmgraphlink *list, int which, const char *name, - FILE *fp) -{ - tmcounts bytes; - tmgraphlink *link; - tmgraphedge *edge; - char buf[16]; - - bytes.direct = bytes.total = 0; - for (link = list; link; link = link->next) { - edge = TM_LINK_TO_EDGE(link, which); - bytes.direct += edge->allocs.bytes.direct; - bytes.total += edge->allocs.bytes.total; - } - - if (js_mode) { - fprintf(fp, - " %s:{dbytes:%ld, tbytes:%ld, edges:[\n", - name, (long) bytes.direct, (long) bytes.total); - for (link = list; link; link = link->next) { - edge = TM_LINK_TO_EDGE(link, which); - fprintf(fp, - " {node:%d, dbytes:%ld, tbytes:%ld},\n", - link->node->sort, - (long) edge->allocs.bytes.direct, - (long) edge->allocs.bytes.total); - } - fputs(" ]},\n", fp); - } else { - fputs("", fp); - for (link = list; link; link = link->next) { - edge = TM_LINK_TO_EDGE(link, which); - fprintf(fp, - "%s (%1.2f%%)\n", - tmgraphnode_name(link->node), - prettybig(edge->allocs.bytes.total, buf, sizeof buf), - percent(edge->allocs.bytes.total, bytes.total)); - } - fputs("", fp); - } -} - -static void dump_graph(tmreader *tmr, PLHashTable *hashtbl, const char *varname, - const char *title, FILE *fp) -{ - uint32_t i, count; - tmgraphnode **table, *node; - char *name; - size_t namelen; - char buf1[16], buf2[16], buf3[16], buf4[16]; - - count = hashtbl->nentries; - table = (tmgraphnode**) malloc(count * sizeof(tmgraphnode*)); - if (!table) { - perror(program); - exit(1); - } - PL_HashTableEnumerateEntries(hashtbl, tabulate_node, table); - qsort(table, count, sizeof(tmgraphnode*), node_table_compare); - for (i = 0; i < count; i++) - table[i]->sort = i; - - if (js_mode) { - fprintf(fp, - "var %s = {\n name:'%s', title:'%s', nodes:[\n", - varname, varname, title); - } else { - fprintf(fp, - "\n" - "" - "" - "" - "" - "" - "" - "" - "" - "\n", - title); - } - - for (i = 0; i < count; i++) { - /* Don't bother with truly puny nodes. */ - node = table[i]; - if (node->allocs.bytes.total < min_subtotal) - break; - - name = tmgraphnode_name(node); - if (js_mode) { - fprintf(fp, - " {name:'%s', dbytes:%ld, tbytes:%ld," - " dallocs:%ld, tallocs:%ld,\n", - name, - (long) node->allocs.bytes.direct, - (long) node->allocs.bytes.total, - (long) node->allocs.calls.direct, - (long) node->allocs.calls.total); - } else { - namelen = strlen(name); - fprintf(fp, - "" - "", - name, - (namelen > 40) ? 40 : (int)namelen, name, - (namelen > 40) ? "..." : ""); - if (node->down) { - fprintf(fp, - "", - tmgraphnode_name(node->down)); - } else { - fputs("", fp); - } - if (node->next) { - fprintf(fp, - "", - tmgraphnode_name(node->next)); - } else { - fputs("", fp); - } - fprintf(fp, - "" - "", - prettybig(node->allocs.bytes.total, buf1, sizeof buf1), - prettybig(node->allocs.bytes.direct, buf2, sizeof buf2), - percent(node->allocs.bytes.total, - tmr->calltree_root.allocs.bytes.total), - percent(node->allocs.bytes.direct, - tmr->calltree_root.allocs.bytes.total), - prettybig(node->allocs.calls.total, buf3, sizeof buf3), - prettybig(node->allocs.calls.direct, buf4, sizeof buf4), - percent(node->allocs.calls.total, - tmr->calltree_root.allocs.calls.total), - percent(node->allocs.calls.direct, - tmr->calltree_root.allocs.calls.total)); - } - - /* NB: we must use 'fin' because 'in' is a JS keyword! */ - sort_graphlink_list(&node->in, TM_EDGE_IN_LINK); - dump_graphlink_list(node->in, TM_EDGE_IN_LINK, "fin", fp); - sort_graphlink_list(&node->out, TM_EDGE_OUT_LINK); - dump_graphlink_list(node->out, TM_EDGE_OUT_LINK, "out", fp); - - if (js_mode) - fputs(" },\n", fp); - else - fputs("\n", fp); - } - - if (js_mode) { - fputs("]};\n", fp); - } else { - fputs("
%sDownNextTotal/Direct (percents)AllocationsFan-inFan-out
%.*s%sdownnext%s/%s (%1.2f%%/%1.2f%%)%s/%s (%1.2f%%/%1.2f%%)
\n
\n", fp); - - qsort(table, count, sizeof(tmgraphnode*), mean_size_compare); - - fprintf(fp, - "\n" - "\n" - "" - "" - "" - "" - "\n", - title); - - for (i = 0; i < count; i++) { - double allocs, bytes, mean, variance, sigma; - - node = table[i]; - allocs = (double)node->allocs.calls.direct; - if (!allocs) - continue; - - /* Compute direct-size mean and standard deviation. */ - bytes = (double)node->allocs.bytes.direct; - mean = bytes / allocs; - variance = allocs * node->sqsum - bytes * bytes; - if (variance < 0 || allocs == 1) - variance = 0; - else - variance /= allocs * (allocs - 1); - sigma = sqrt(variance); - - name = tmgraphnode_name(node); - namelen = strlen(name); - fprintf(fp, - "" - "" - "" - "" - "" - "\n", - (namelen > 65) ? 45 : (int)namelen, name, - (namelen > 65) ? "..." : "", - prettybig((uint32_t)mean, buf1, sizeof buf1), - prettybig((uint32_t)sigma, buf2, sizeof buf2), - prettybig(node->allocs.calls.direct, buf3, sizeof buf3)); - } - fputs("
Direct Allocators
%sMean SizeStdDevAllocations" - "
%.*s%s%s%s%s
\n", fp); - } - - free((void*) table); -} - -static void my_tmevent_handler(tmreader *tmr, tmevent *event) -{ - switch (event->type) { - case TM_EVENT_STATS: - if (js_mode) - break; - fprintf(stdout, - "

" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "
CounterValue
maximum actual stack depth%lu
maximum callsite tree depth%lu
number of parent callsites%lu
maximum kids per parent%lu
hits looking for a kid%lu
misses looking for a kid%lu
steps over other kids%lu
callsite recurrences%lu
number of stack backtraces%lu
backtrace failures%lu
backtrace malloc failures%lu
backtrace dladdr failures%lu
malloc calls%lu
malloc failures%lu
calloc calls%lu
calloc failures%lu
realloc calls%lu
realloc failures%lu
free calls%lu
free(null) calls%lu
", - (unsigned long) event->u.stats.tmstats.calltree_maxstack, - (unsigned long) event->u.stats.tmstats.calltree_maxdepth, - (unsigned long) event->u.stats.tmstats.calltree_parents, - (unsigned long) event->u.stats.tmstats.calltree_maxkids, - (unsigned long) event->u.stats.tmstats.calltree_kidhits, - (unsigned long) event->u.stats.tmstats.calltree_kidmisses, - (unsigned long) event->u.stats.tmstats.calltree_kidsteps, - (unsigned long) event->u.stats.tmstats.callsite_recurrences, - (unsigned long) event->u.stats.tmstats.backtrace_calls, - (unsigned long) event->u.stats.tmstats.backtrace_failures, - (unsigned long) event->u.stats.tmstats.btmalloc_failures, - (unsigned long) event->u.stats.tmstats.dladdr_failures, - (unsigned long) event->u.stats.tmstats.malloc_calls, - (unsigned long) event->u.stats.tmstats.malloc_failures, - (unsigned long) event->u.stats.tmstats.calloc_calls, - (unsigned long) event->u.stats.tmstats.calloc_failures, - (unsigned long) event->u.stats.tmstats.realloc_calls, - (unsigned long) event->u.stats.tmstats.realloc_failures, - (unsigned long) event->u.stats.tmstats.free_calls, - (unsigned long) event->u.stats.tmstats.null_free_calls); - - if (event->u.stats.calltree_maxkids_parent) { - tmcallsite *site = - tmreader_callsite(tmr, event->u.stats.calltree_maxkids_parent); - if (site && site->method) { - fprintf(stdout, "

callsite with the most kids: %s

", - tmmethodnode_name(site->method)); - } - } - - if (event->u.stats.calltree_maxstack_top) { - tmcallsite *site = - tmreader_callsite(tmr, event->u.stats.calltree_maxstack_top); - fputs("

deepest callsite tree path:\n" - "\n" - "\n", - stdout); - while (site) { - fprintf(stdout, - "\n", - site->method ? tmmethodnode_name(site->method) : "???", - (unsigned long) site->offset); - site = site->parent; - } - fputs("
MethodOffset
%s0x%08lX
\n


\n", stdout); - } - break; - } -} - -int main(int argc, char **argv) -{ - int c, i, j, rv; - tmreader *tmr; - FILE *fp; - - program = *argv; - tmr = tmreader_new(program, NULL); - if (!tmr) { - perror(program); - exit(1); - } - - while ((c = getopt(argc, argv, "djtuf:m:")) != EOF) { - switch (c) { - case 'd': - sort_by_direct = 1; - break; - case 'j': - js_mode = 1; - break; - case 't': - do_tree_dump = 1; - break; - case 'u': - unified_output = 1; - break; - case 'f': - function_dump = optarg; - break; - case 'm': - min_subtotal = atoi(optarg); - break; - default: - fprintf(stderr, - "usage: %s [-dtu] [-f function-dump-filename] [-m min] [output.html]\n", - program); - exit(2); - } - } - - if (!js_mode) { - time_t start = time(NULL); - - fprintf(stdout, - "\n"); - fprintf(stdout, "%s starting at %s", program, ctime(&start)); - fflush(stdout); - } - - argc -= optind; - argv += optind; - if (argc == 0) { - if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0) - exit(1); - } else { - for (i = j = 0; i < argc; i++) { - fp = fopen(argv[i], "r"); - if (!fp) { - fprintf(stderr, "%s: can't open %s: %s\n", - program, argv[i], strerror(errno)); - exit(1); - } - rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler); - if (rv < 0) - exit(1); - if (rv > 0) - j++; - fclose(fp); - } - if (j == 0) - exit(1); - } - - compute_callsite_totals(&tmr->calltree_root); - walk_callsite_tree(&tmr->calltree_root, 0, 0, stdout); - - if (js_mode) { - fprintf(stdout, - "\n" - "\n" - " \n" - " \n" - "\n", - stdout); - } - } - - exit(0); -} diff --git a/tools/trace-malloc/diffbloatdump.pl b/tools/trace-malloc/diffbloatdump.pl deleted file mode 100755 index 06759b3a10a0..000000000000 --- a/tools/trace-malloc/diffbloatdump.pl +++ /dev/null @@ -1,207 +0,0 @@ -#!/usr/bin/perl -w -# vim:cindent:ts=8:et:sw=4: -# 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/. - -# This script produces a diff between two files that are the result of -# calling NS_TraceMallocDumpAllocations. Such files can be created -# through the command-line option --shutdown-leaks= or through -# the DOM function window.TraceMallocDumpAllocations(). Both -# methods will work only if --trace-malloc= is also given on -# the command line. - -use 5.004; -use strict; -use Getopt::Long; - -$::opt_help = 0; -$::opt_depth = 6; -$::opt_include_zero = 0; -$::opt_allocation_count = 0; -$::opt_use_address = 0; - -# XXX Change --use-address to be the default and remove the option -# once tinderbox is no longer using it without --use-address. - -Getopt::Long::Configure("pass_through"); -Getopt::Long::GetOptions("help", "allocation-count", "depth=i", - "include-zero", "use-address"); - -if ($::opt_help) { - die "usage: diffbloatdump.pl [options] - --help Display this message - - --allocation-count Use allocation count rather than size (i.e., treat - all sizes as 1). - --depth= Only display frames at top of allocation stack. - --include-zero Display subtrees totalling zero. - --use-address Don't ignore the address part of the stack trace - (can make comparison more accurate when comparing - results from the same build) - - The input files ( and above) are either trace-malloc - memory dumps OR this script's output. (If this script's output, - --allocation-count and --use-address are ignored.) If the input files - have .gz or .bz2 extension, they are uncompressed. -"; -} - -my $calltree = { count => 0 }; # leave children undefined - -sub get_child($$) { - my ($node, $frame) = @_; - if (!defined($node->{children})) { - $node->{children} = {}; - } - if (!defined($node->{children}->{$frame})) { - $node->{children}->{$frame} = { count => 0 }; - } - return $node->{children}->{$frame}; -} - -sub add_tree_file($$$) { - my ($infile, $firstline, $factor) = @_; - - my @nodestack; - $nodestack[1] = $calltree; - $firstline =~ /^(-?\d+) malloc$/; - $calltree->{count} += $1 * $factor; - - my $lineno = 1; - while (!eof($infile)) { - my $line = <$infile>; - ++$lineno; - $line =~ /^( *)(-?\d+) (.*)$/ || die "malformed input, line $lineno"; - my $depth = length($1); - my $count = $2; - my $frame = $3; - die "malformed input, line $lineno" if ($depth % 2 != 0); - $depth /= 2; - die "malformed input, line $lineno" if ($depth > $#nodestack); - $#nodestack = $depth; - my $node = get_child($nodestack[$depth], $frame); - push @nodestack, $node; - $node->{count} += $count * $factor; - } -} - -sub add_file($$) { - # Takes (1) a reference to a file descriptor for input and (2) the - # factor to multiply the stacks by (generally +1 or -1). - # Returns a reference to an array representing the stack, allocation - # site in array[0]. - sub read_stack($) { - my ($infile) = @_; - my $line; - my @stack; - - # read the data at the memory location - while ( defined($infile) && ($line = <$infile>) && substr($line,0,1) eq "\t" ) { - # do nothing - } - - # read the stack - do { - chomp($line); - if ( ! $::opt_use_address && - $line =~ /(.*)\[(.*)\]/) { - $line = $1; - } - $stack[$#stack+1] = $line; - } while ( defined($infile) && ($line = <$infile>) && $line ne "\n" && $line ne "\r\n" ); - - return \@stack; - } - - # adds the stack given as a parameter (reference to array, $stack[0] is - # allocator) to $calltree, with the call count multiplied by $factor - # (typically +1 or -1). - sub add_stack($$) { - my @stack = @{$_[0]}; - my $factor = $_[1]; - - my $i = 0; - my $node = $calltree; - while ($i < $#stack && $i < $::opt_depth) { - $node->{count} += $factor; - $node = get_child($node, $stack[$i]); - ++$i; - } - $node->{count} += $factor; - } - - my ($infile, $factor) = @_; - - if ($infile =~ /\.bz2$/) { - # XXX This doesn't propagate errors from bzip2. - open (INFILE, "bzip2 -cd '$infile' |") || die "Can't open input \"$infile\""; - } elsif ($infile =~ /\.gz$/) { - # XXX This doesn't propagate errors from gzip. - open (INFILE, "gzip -cd '$infile' |") || die "Can't open input \"$infile\""; - } else { - open (INFILE, "<$infile") || die "Can't open input \"$infile\""; - } - my $first = 1; - while ( ! eof(INFILE) ) { - # read the type and address - my $line = ; - if ($first) { - $first = 0; - if ($line =~ /^-?\d+ malloc$/) { - # We're capable of reading in our own output as well. - add_tree_file(\*INFILE, $line, $factor); - close INFILE; - return; - } - } - unless ($line =~ /.*\((\d*)\)[\r|\n]/) { - die "badly formed allocation header in $infile"; - } - my $size; - if ($::opt_allocation_count) { - $size = 1; - } else { - $size = $1; - } - - add_stack(read_stack(\*INFILE), $size * $factor); - } - close INFILE; -} - -sub print_node_indent($$$); - -sub print_calltree() { - sub print_indent($) { - my ($i) = @_; - while (--$i >= 0) { - print " "; - } - } - - sub print_node_indent($$$) { - my ($nodename, $node, $indent) = @_; - - if (!$::opt_include_zero && $node->{count} == 0) { - return; - } - - print_indent($indent); - print "$node->{count} $nodename\n"; - if (defined($node->{children})) { - my %kids = %{$node->{children}}; - ++$indent; - foreach my $kid (sort { $kids{$b}->{count} <=> $kids{$a}->{count} } - keys (%kids)) { - print_node_indent($kid, $kids{$kid}, $indent); - } - } - } - - print_node_indent("malloc", $calltree, 0); -} - -add_file($ARGV[0], -1); -add_file($ARGV[1], 1); -print_calltree(); diff --git a/tools/trace-malloc/formdata.c b/tools/trace-malloc/formdata.c deleted file mode 100644 index f4660d0db185..000000000000 --- a/tools/trace-malloc/formdata.c +++ /dev/null @@ -1,204 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -/* -** formdata.c -** -** Play utility to parse up form get data into name value pairs. -*/ - -#include "formdata.h" - -#include -#include -#include - - -static void unhexcape(char* inPlace) -/* -** Real low tech unhexcaper.... -** -** inPlace string to decode, in place as it were. -*/ -{ - if(NULL != inPlace) - { - int index1 = 0; - int index2 = 0; - int theLen = strlen(inPlace); - - for(; index1 <= theLen; index1++) - { - if('%' == inPlace[index1] && '\0' != inPlace[index1 + 1] && '\0' != inPlace[index1 + 2]) - { - int unhex = 0; - - if('9' >= inPlace[index1 + 1]) - { - unhex |= ((inPlace[index1 + 1] - '0') << 4); - } - else - { - unhex |= ((toupper(inPlace[index1 + 1]) - 'A' + 10) << 4); - } - - if('9' >= inPlace[index1 + 2]) - { - unhex |= (inPlace[index1 + 2] - '0'); - } - else - { - unhex |= (toupper(inPlace[index1 + 2]) - 'A' + 10); - } - - index1 += 2; - inPlace[index1] = unhex; - } - - inPlace[index2++] = inPlace[index1]; - } - } -} - - -FormData* FormData_Create(const char* inFormData) -{ - FormData* retval = NULL; - - if(NULL != inFormData) - { - FormData* container = NULL; - - /* - ** Allocate form data container. - */ - container = (FormData*)calloc(1, sizeof(FormData)); - if(NULL != container) - { - /* - ** Dup the incoming form data. - */ - container->mStorage = strdup(inFormData); - if(NULL != container->mStorage) - { - char* traverse = NULL; - unsigned nvpairs = 1; - unsigned storeLen = 0; - - /* - ** Count the number of pairs we are going to have. - ** We do this by counting '&' + 1. - */ - for(traverse = container->mStorage; '\0' != *traverse; traverse++) - { - if('&' == *traverse) - { - nvpairs++; - } - } - storeLen = (unsigned)(traverse - container->mStorage); - - /* - ** Allocate space for our names and values. - */ - container->mNArray = (char**)calloc(nvpairs * 2, sizeof(char*)); - if(NULL != container->mNArray) - { - char* amp = NULL; - char* equ = NULL; - - container->mVArray = &container->mNArray[nvpairs]; - - /* - ** Go back over the storage. - ** Fill in the names and values as we go. - ** Terminate on dividing '=' and '&' characters. - ** Increase the count of items as we go. - */ - for(traverse = container->mStorage; NULL != traverse; container->mNVCount++) - { - container->mNArray[container->mNVCount] = traverse; - - amp = strchr(traverse, '&'); - equ = strchr(traverse, '='); - traverse = NULL; - - if(NULL != equ && (NULL == amp || equ < amp)) - { - *equ++ = '\0'; - - container->mVArray[container->mNVCount] = equ; - } - else - { - container->mVArray[container->mNVCount] = (container->mStorage + storeLen); - } - - if(NULL != amp) - { - *amp++ = '\0'; - - traverse = amp; - } - - unhexcape(container->mNArray[container->mNVCount]); - unhexcape(container->mVArray[container->mNVCount]); - } - - retval = container; - } - } - } - - /* - ** If we failed, cleanup. - */ - if(NULL == retval) - { - FormData_Destroy(container); - } - } - - return retval; -} - - -void FormData_Destroy(FormData* inDestroy) -{ - if(NULL != inDestroy) - { - unsigned traverse = 0; - - for(traverse = 0; traverse < inDestroy->mNVCount; traverse++) - { - if(NULL != inDestroy->mNArray) - { - inDestroy->mNArray[traverse] = NULL; - } - if(NULL != inDestroy->mVArray) - { - inDestroy->mVArray[traverse] = NULL; - } - } - inDestroy->mNVCount = 0; - - if(NULL != inDestroy->mStorage) - { - free(inDestroy->mStorage); - inDestroy->mStorage = NULL; - } - - if(NULL != inDestroy->mNArray) - { - free(inDestroy->mNArray); - inDestroy->mNArray = NULL; - inDestroy->mVArray = NULL; - } - - free(inDestroy); - inDestroy = NULL; - } -} diff --git a/tools/trace-malloc/formdata.h b/tools/trace-malloc/formdata.h deleted file mode 100644 index 0ef937b73a40..000000000000 --- a/tools/trace-malloc/formdata.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -#if !defined(__formdata_H__) -#define __formdata_H__ - -/* -** formdata.h -** -** Play (quick and dirty) utility API to parse up form get data into -** name value pairs. -*/ - -typedef struct __struct_FormData -/* -** Structure to hold the breakdown of any form data. -** -** mNArray Each form datum is a name value pair. -** This array holds the names. -** You can find the corresponding value at the same index in -** mVArray. -** Never NULL, but perhpas an empty string. -** mVArray Each form datum is a name value pair. -** This array holds the values. -** You can find the corresponding name at the same index in -** mNArray. -** Never NULL, but perhpas an empty string. -** mNVCount Count of array items in both mNArray and mVArray. -** mStorage Should be ignored by users of this API. -** In reality holds the duped and decoded form data. -*/ -{ - char** mNArray; - char** mVArray; - unsigned mNVCount; - char* mStorage; -} -FormData; - -FormData* FormData_Create(const char* inFormData) -/* -** Take a contiguous string of form data, possibly hex encoded, and return -** the name value pairs parsed up and decoded. -** A caller of this routine should call FormData_Destroy at some point. -** -** inFormData The form data to parse up and decode. -** returns FormData* The result of our effort. -** This should be passed to FormData_Destroy at some -** point of the memory will be leaked. -*/ -; - -void FormData_Destroy(FormData* inDestroy) -/* -** Release to the heap the structure previously created via FormData_Create. -** -** inDestroy The object to free off. -*/ -; - -#endif /* __formdata_H__ */ diff --git a/tools/trace-malloc/getopt.c b/tools/trace-malloc/getopt.c deleted file mode 100644 index a7619e9c7b72..000000000000 --- a/tools/trace-malloc/getopt.c +++ /dev/null @@ -1,107 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ -/* - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that: (1) source distributions retain this entire copyright - * notice and comment, and (2) distributions including binaries display - * the following acknowledgement: ``This product includes software - * developed by the University of California, Berkeley and its contributors'' - * in the documentation or other materials provided with the distribution - * and in all advertising materials mentioning features or use of this - * software. Neither the name of the University nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getopt.c 4.12 (Berkeley) 6/1/90"; -#endif /* LIBC_SCCS and not lint */ - -#include -#include -#define index strchr -#define rindex strrchr - -/* - * get option letter from argument vector - */ -int opterr = 1, /* if error message should be printed */ - optind = 1, /* index into parent argv vector */ - optopt; /* character checked for validity */ -char *optarg; /* argument associated with option */ - -#define BADCH (int)'?' -#define EMSG "" - -int getopt(int nargc, char **nargv, char *ostr) -{ - static char *place = EMSG; /* option letter processing */ - register char *oli; /* option letter list index */ - char *p; - - if (!*place) { /* update scanning pointer */ - if (optind >= nargc || *(place = nargv[optind]) != '-') { - place = EMSG; - return(EOF); - } - if (place[1] && *++place == '-') { /* found "--" */ - ++optind; - place = EMSG; - return(EOF); - } - } /* option letter okay? */ - if ((optopt = (int)*place++) == (int)':' || - !(oli = index(ostr, optopt))) { - /* - * if the user didn't specify '-' as an option, - * assume it means EOF. - */ - if (optopt == (int)'-') - return(EOF); - if (!*place) - ++optind; - if (opterr) { - if (!(p = rindex(*nargv, '/'))) - p = *nargv; - else - ++p; - (void)fprintf(stderr, "%s: illegal option -- %c\n", - p, optopt); - } - return(BADCH); - } - if (*++oli != ':') { /* don't need argument */ - optarg = NULL; - if (!*place) - ++optind; - } - else { /* need an argument */ - if (*place) /* no white space */ - optarg = place; - else if (nargc <= ++optind) { /* no arg */ - place = EMSG; - if (!(p = rindex(*nargv, '/'))) - p = *nargv; - else - ++p; - if (opterr) - (void)fprintf(stderr, - "%s: option requires an argument -- %c\n", - p, optopt); - return(BADCH); - } - else /* white space */ - optarg = nargv[optind]; - place = EMSG; - ++optind; - } - return(optopt); /* dump back option letter */ -} diff --git a/tools/trace-malloc/histogram-diff.sh b/tools/trace-malloc/histogram-diff.sh deleted file mode 100755 index 275de2a9844e..000000000000 --- a/tools/trace-malloc/histogram-diff.sh +++ /dev/null @@ -1,76 +0,0 @@ -#!/bin/sh -# -# 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/. - -# histogram-diff.sh [-c ] -# -# Compute incremental memory growth from histogram in file to -# histogram in file , displaying at most rows. - -# How many rows are we gonna show? -COUNT=20 - -# Read arguments -while [ $# -gt 0 ]; do - case "$1" in - -c) COUNT=$2 - shift 2 - ;; - *) break - ;; - esac -done - -BASE=$1 -INCR=$2 - -# Sort the base and incremental files so that we can `join' them on -# the type name -sort $BASE > /tmp/$$.left -sort $INCR > /tmp/$$.right - -# Do the join. The `awk' script computes the difference between -# the base and the incremental files. -join /tmp/$$.left /tmp/$$.right \ - | awk '{ print $1, $2, $3, $4, $5, $4 - $2, $5 - $3; }' \ - > /tmp/$$.joined - -rm -f /tmp/$$.left /tmp/$$.right - -# Now compute a `TOTAL' row. -awk '{ tobj1 += $2; tbytes1 += $3; tobj2 += $4; tbytes2 += $5; tdobj += $6; tdbytes += $7; } END { print "TOTAL", tobj1, tbytes1, tobj2, tbytes2, tdobj, tdbytes; }' /tmp/$$.joined \ - > /tmp/$$.sorted - -# Then, we sort by the largest delta in bytes. -sort -nr +6 /tmp/$$.joined >> /tmp/$$.sorted - -rm -f /tmp/$$.joined - -# Pretty-print, including percentages -cat < /tmp/$$.awk -BEGIN { - print " ---- Base ---- ---- Incr ---- ----- Difference ----"; - print "Type Count Bytes Count Bytes Count Bytes %Total"; - } -\$1 == "TOTAL" { - tbytes = \$7; - } -NR <= $COUNT { - printf "%-22s %6d %8d %6d %8d %6d %8d %6.2lf\n", \$1, \$2, \$3, \$4, \$5, \$6, \$7, 100.0 * \$7 / tbytes; - } -NR > $COUNT { - oobjs1 += \$2; obytes1 += \$3; - oobjs2 += \$4; obytes2 += \$5; - odobjs += \$6; odbytes += \$7; - } -END { - printf "%-22s %6d %8d %6d %8d %6d %8d %6.2lf\n", "OTHER", oobjs1, obytes1, oobjs2, obytes2, odobjs, odbytes, odbytes * 100.0 / tbytes; - } -EOF - -# Now pretty print the file, and spit it out on stdout. -awk -f /tmp/$$.awk /tmp/$$.sorted - -rm -f /tmp/$$.awk /tmp/$$.sorted diff --git a/tools/trace-malloc/histogram-pretty.sh b/tools/trace-malloc/histogram-pretty.sh deleted file mode 100755 index 36e90151033b..000000000000 --- a/tools/trace-malloc/histogram-pretty.sh +++ /dev/null @@ -1,63 +0,0 @@ -#!/bin/sh -# -# 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/. - -# histogram-pretty.sh [-c ] [-w ] -# -# Pretty-print the histogram in file , displaying at most -# rows. - -# How many rows are we gonna show? -COUNT=20 -WIDTH=22 - -# Read arguments -while [ $# -gt 0 ]; do - case "$1" in - -c) COUNT=$2 - shift 2 - ;; - -w) WIDTH=$2 - shift 2 - ;; - *) break - ;; - esac -done - -FILE=$1 - -# The first `awk' script computes a `TOTAL' row. Then, we sort by the -# larges delta in bytes. -awk '{ tobj += $2; tbytes += $3; } END { print "TOTAL", tobj, tbytes; }' ${FILE} > /tmp/$$.sorted - -sort -nr +2 ${FILE} >> /tmp/$$.sorted - -# Pretty-print, including percentages -cat < /tmp/$$.awk -BEGIN { - printf "%-${WIDTH}s Count Bytes %Total %Cov\n", "Type"; - } -\$1 == "TOTAL" { - tbytes = \$3; - } -NR <= $COUNT { - if (\$1 != "TOTAL") { - covered += \$3; - } - printf "%-${WIDTH}s %6d %8d %6.2lf %6.2lf\n", \$1, \$2, \$3, 100.0 * \$3 / tbytes, 100.0 * covered / tbytes; - } -NR > $COUNT { - oobjs += \$2; obytes += \$3; covered += \$3; - } -END { - printf "%-${WIDTH}s %6d %8d %6.2lf %6.2lf\n", "OTHER", oobjs, obytes, obytes * 100.0 / tbytes, covered * 100.0 / tbytes; - } -EOF - -# Now pretty print the file, and spit it out on stdout. -awk -f /tmp/$$.awk /tmp/$$.sorted - -rm -f /tmp/$$.awk /tmp/$$.sorted diff --git a/tools/trace-malloc/histogram.pl b/tools/trace-malloc/histogram.pl deleted file mode 100755 index 9cdb8bcc5995..000000000000 --- a/tools/trace-malloc/histogram.pl +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/perl -w -# -# 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/. - -# This program produces a ``class histogram'' of the live objects, one -# line per class, with the total number of objects allocated, and -# total number of bytes attributed to those objects. - -use 5.004; -use strict; -use Getopt::Long; - -# So we can find TraceMalloc.pm -use FindBin; -use lib "$FindBin::Bin"; - -use TraceMalloc; - -# Collect program options -$::opt_help = 0; -$::opt_types = "${FindBin::Bin}/types.dat"; - -GetOptions("help", "types=s"); - -if ($::opt_help) { - die "usage: histogram.pl [options] - --help Display this message - --types= Read type heuristics from "; -} - -# Initialize type inference juju from the type file specified by -# ``--types''. -if ($::opt_types) { - TraceMalloc::init_type_inference($::opt_types); -} - -# Read the dump file, collecting count and size information for each -# object that's detected. - -# This'll hold a record for each class that we detect -$::Classes = { }; - -sub collect_objects($) { - my ($object) = @_; - my $type = $object->{'type'}; - - my $entry = $::Classes{$type}; - if (! $entry) { - $entry = $::Classes{$type} = { '#count#' => 0, '#bytes#' => 0 }; - } - - $entry->{'#count#'} += 1; - $entry->{'#bytes#'} += $object->{'size'}; -} - -TraceMalloc::read(\&collect_objects); - -# Print one line per class, sorted with the classes that accumulated -# the most bytes first. -foreach my $class (sort { $::Classes{$b}->{'#bytes#'} <=> $::Classes{$a}->{'#bytes#'} } keys %::Classes) { - print "$class $::Classes{$class}->{'#count#'} $::Classes{$class}->{'#bytes#'}\n"; -} diff --git a/tools/trace-malloc/leak-soup.pl b/tools/trace-malloc/leak-soup.pl deleted file mode 100755 index b6e20d0aef49..000000000000 --- a/tools/trace-malloc/leak-soup.pl +++ /dev/null @@ -1,1180 +0,0 @@ -#!/usr/bin/perl -w -# -# 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/. - -# A perl version of Patrick Beard's ``Leak Soup'', which processes the -# stack crawls from the Boehm GC into a graph. - -use 5.004; -use strict; -use Getopt::Long; -use FileHandle; -use IPC::Open2; - -# Collect program options -$::opt_help = 0; -$::opt_detail = 0; -$::opt_fragment = 1.0; # Default to no fragment analysis -$::opt_nostacks = 0; -$::opt_nochildstacks = 0; -$::opt_depth = 9999; -$::opt_noentrained = 0; -$::opt_noslop = 0; -$::opt_showtype = -1; # default to listing all types -$::opt_stackrefine = "C"; -@::opt_stackretype = (); -@::opt_stackskipclass = (); -@::opt_stackskipfunc = (); -@::opt_typedivide = (); - -GetOptions("help", "detail", "format=s", "fragment=f", "nostacks", - "nochildstacks", "depth=i", "noentrained", "noslop", "showtype=i", - "stackrefine=s", "stackretype=s@", "stackskipclass=s@", "stackskipfunc=s@", - "typedivide=s@" - ); - -if ($::opt_help) { - die "usage: leak-soup.pl [options] - --help Display this message - --detail Provide details of memory sweeping from child to parents - --fragment=ratio Histogram bucket ratio for fragmentation analysis -# --nostacks Do not compute stack traces -# --nochildstacks Do not compute stack traces for entrained objects -# --depth= Only compute stack traces to depth of -# --noentrained Do not compute amount of memory entrained by root objects - --noslop Don't ignore low bits when searching for pointers - --showtype= Show memory usage histogram for most-significant types - --stackrefine={F|C} During stack based refinement, use 'F'ull name name or just 'C'lass - --stackretype=type Use allocation stack to refine vague types like void* - --stackskipclass=class When refining types, ignore stack frames from 'class' - --stackskipfunc=func When refining types, ignore stack frames for 'func' - --typedivide=type Subdivide 'type' based on objects pointing to each instance -"; -} - -# This is the table that keeps a graph of objects. It's indexed by the -# object's address (as an integer), and refers to a simple hash that -# has information about the object's type, size, slots, and allocation -# stack. -%::Objects = %{0}; - -# This will be a list of keys to (addresses in) Objects, that is sorted -# It gets used to evaluate overlaps, calculate fragmentation, and chase -# parent->child (interior) pointers. -@::SortedAddresses = []; - -# This is the table that keeps track of memory usage on a per-type basis. -# It is indexed by the type name (string), and keeps a tally of the -# total number of such objects, and the memory usage of such objects. -%::Types = %{0}; -$::TotalSize = 0; # sum of sizes of all objects included $::Types{} - -# This is an array of leaf node addresses. A leaf node has no children -# with memory allocations. We traverse them sweeping memory -# tallies into parents. Note that after all children have -# been swept into a parent, that parent may also become a leaf node. -@::Leafs = @{0}; - - - - -#---------------------------------------------------------------------- -# -# Decode arguments to override default values for doing call-stack-based -# refinement of typename based on contents of the stack at allocation time. -# - -# List the types that we need to refine (if any) based on allocation stack -$::VagueType = { - 'void*' => 1, -}; - -# With regard to the stack, ignore stack frames in the following -# overly vague classes. -$::VagueClasses = { -# 'nsStr' => 1, - 'nsVoidArray' => 1, -}; - -# With regard to stack, ignore stack frames with the following vague -# function names -$::VagueFunctions = { - 'PL_ArenaAllocate' => 1, - 'PL_HashTableFinalize(PLHashTable *)' => 1, - 'PL_HashTableInit__FP11PLHashTableUiPFPCv_UiPFPCvPCv_iT3PC14PLHashAllocOpsPv' => 1, - 'PL_HashTableRawAdd' => 1, - '__builtin_vec_new' => 1, - '_init' => 1, - 'il_get_container(_IL_GroupContext *, ImgCachePolicy, char const *, _NI_IRGB *, IL_DitherMode, int, int, int)' => 1, - 'nsCStringKey::Clone(void) const' => 1, - 'nsCppSharedAllocator::allocate(unsigned int, void const *)' => 1, - 'nsHashtable::Put(nsHashKey *, void *)' => 1, - 'nsHashtable::nsHashtable(unsigned int, int)' => 1, - 'nsMemory::Alloc(unsigned int)' => 1, - 'nsMemoryImpl::Alloc(unsigned int)' => 1, -}; - -sub init_stack_based_type_refinement() { - # Move across stackretype options, or use default values - if ($#::opt_stackretype < 0) { - print "Default --stackretype options will be used (since none were specified)\n"; - print " use --stackretype='nothing' to disable re-typing activity\n"; - } else { - foreach my $type (keys %{$::VagueType}) { - delete ($::VagueType->{$type}); - } - if ($#::opt_stackretype == 0 && $::opt_stackretype[0] eq 'nothing') { - print "Types will not be refined based on call stack\n"; - } else { - foreach my $type (@::opt_stackretype) { - $::VagueType->{$type} = 1; - } - } - } - - - if (keys %{$::VagueType}) { - print "The following type(s) will be refined based on call stacks:\n"; - foreach my $type (sort keys %{$::VagueType}) { - print " $type\n"; - } - print "Equivalent command line argument(s):\n"; - foreach my $type (sort keys %{$::VagueType}) { - print " --stackretype='$type'"; - } - print "\n\n"; - - if ($#::opt_stackskipclass < 0) { - print "Default --stackskipclass options will be used (since none were specified)\n"; - print " use --stackskipclass='nothing' to disable skipping stack frames based on class names\n"; - } else { - foreach my $type (keys %{$::VagueClasses}) { - delete ($::VagueClasses->{$type}); - } - if ($#::opt_stackskipclass == 0 && $::opt_stackskipclass[0] eq 'nothing') { - print "Types will not be refined based on call stack\n"; - } else { - foreach my $type (@::opt_stackskipclass) { - $::VagueClasses->{$type} = 1; - } - } - } - - if (keys %{$::VagueClasses}) { - print "Stack frames from the following class(es) will not be used to refine types:\n"; - foreach my $class (sort keys %{$::VagueClasses}) { - print " $class\n"; - } - print "Equivalent command line argument(s):\n"; - foreach my $class (sort keys %{$::VagueClasses}) { - print " --stackskipclass='$class'"; - } - print "\n\n"; - } - - - if ($#::opt_stackskipfunc < 0) { - print "Default --stackskipfunc options will be used (since none were specified)\n"; - print " use --stackskipfunc='nothing' to disable skipping stack frames based on function names\n"; - } else { - foreach my $type (keys %{$::VagueFunctions}) { - delete ($::VagueFunctions->{$type}); - } - if ($#::opt_stackskipfunc == 0 && $::opt_stackskipfunc[0] eq 'nothing') { - print "Types will not be refined based on call stack\n"; - } else { - foreach my $type (@::opt_stackskipfunc) { - $::VagueFunctions->{$type} = 1; - } - } - } - - if (keys %{$::VagueFunctions}) { - print "Stack frames from the following function(s) will not be used to refine types:\n"; - foreach my $func (sort keys %{$::VagueFunctions}) { - print " $func\n"; - } - print "Equivalent command line argument(s):\n"; - foreach my $func (sort keys %{$::VagueFunctions}) { - print " --stackskipfunc='$func'"; - } - print "\n\n"; - } - } -} - - -#---------------------------------------------------------------------- -# -# Read in the output from the Boehm GC or Trace-malloc. -# -sub read_boehm() { - OBJECT: while (<>) { - # e.g., 0x0832FBD0 (80) - next OBJECT unless /^0x(\S+) <(.*)> \((\d+)\)/; - my ($addr, $type, $size) = (hex $1, $2, $3); - - my $object = $::Objects{$addr}; - if (! $object) { - # Found a new object entry. Record its type and size - $::Objects{$addr} = - $object = - { 'type' => $type, 'size' => $size }; - } else { - print "Duplicate address $addr contains $object->{'type'} and $type\n"; - $object->{'dup_addr_count'}++; - } - - # Record the object's slots - my @slots; - - SLOT: while (<>) { - # e.g., 0x00000000 - last SLOT unless /^\t0x(\S+)/; - my $value = hex $1; - - # Ignore low bits, unless they've specified --noslop - $value &= ~0x7 unless $::opt_noslop; - - $slots[$#slots + 1] = $value; - } - - $object->{'slots'} = \@slots; - - if (@::opt_stackretype && (defined $::VagueType->{$type})) { - # Change the value of type of the object based on stack - # if we can find an interesting calling function - VAGUEFRAME: while (<>) { - # e.g., _dl_debug_message[/lib/ld-linux.so.2 +0x0000B858] - last VAGUEFRAMEFRAME unless /^(.*)\[(.*) \+0x(\S+)\]$/; - my ($func, $lib, $off) = ($1, $2, hex $3); - chomp; - - my ($class,,$fname) = split(/:/, $func); - next VAGUEFRAME if (defined $::VagueFunctions->{$func} || - defined $::VagueClasses->{$class}); - - # Refine typename and exit stack scan - $object->{'type'} = $type . ":" . - (('C' eq $::opt_stackrefine) ? - $class : - $func); - last VAGUEFRAME; - } - } else { - # Save all stack info if requested - if (! $::opt_nostacks) { - # Record the stack by which the object was allocated - my @stack; - - FRAME: while (<>) { - # e.g., _dl_debug_message[/lib/ld-linux.so.2 +0x0000B858] - last FRAME unless /^(.*)\[(.*) \+0x(\S+)\]$/; - my ($func, $lib, $off) = ($1, $2, hex $3); - chomp; - - $stack[$#stack + 1] = $_; - } - - $object->{'stack'} = \@stack; - } - } - - # Gotta check EOF explicitly... - last OBJECT if eof; - } -} - - -#---------------------------------------------------------------------- -# -# Read input -# -init_stack_based_type_refinement(); -read_boehm; - - - -#---------------------------------------------------------------------- -# -# Do basic initialization of the type hash table. Accumulate -# total counts, and basic memory usage (not including children) -sub load_type_table() { - # Reset global counter and hash table - $::TotalSize = 0; - %::Types = %{0}; - - OBJECT: foreach my $addr (keys %::Objects) { - my $obj = $::Objects{$addr}; - my ($type, $size, $swept_in, $overlap_count, $dup_addr_count) = - ($obj->{'type'}, $obj->{'size'}, - $obj->{'swept_in'}, - $obj->{'overlap_count'},$obj->{'dup_addr_count'}); - - my $type_data = $::Types{$type}; - if (! defined $type_data) { - $::Types{$type} = - $type_data = {'count' => 0, 'size' => 0, - 'max' => $size, 'min' => $size, - 'swept_in' => 0, 'swept' => 0, - 'overlap_count' => 0, - 'dup_addr_count' => 0}; - } - - if (!$size) { - $type_data->{'swept'}++; - next OBJECT; - } - $::TotalSize += $size; - - $type_data->{'count'}++; - $type_data->{'size'} += $size; - if (defined $swept_in) { - $type_data->{'swept_in'} += $swept_in; - - if ($::opt_detail) { - my $type_detail_sizes = $type_data->{'sweep_details_size'}; - my $type_detail_counts; - if (!defined $type_detail_sizes) { - $type_detail_sizes = $type_data->{'sweep_details_size'} = {}; - $type_detail_counts = $type_data->{'sweep_details_count'} = {}; - } else { - $type_detail_counts = $type_data->{'sweep_details_count'}; - } - - my $sweep_details = $obj->{'sweep_details'}; - for my $swept_addr (keys (%{$sweep_details})) { - my $swept_obj = $::Objects{$swept_addr}; - my $swept_type = $swept_obj->{'type'}; - $type_detail_sizes->{$swept_type} += $sweep_details->{$swept_addr}; - $type_detail_counts->{$swept_type}++; - } - } - } - if (defined $overlap_count) { - $type_data->{'overlap_count'} += $overlap_count; - } - - if (defined $dup_addr_count) { - $type_data->{'dup_addr_count'} += $dup_addr_count; - } - - if ($type_data->{'max'} < $size) { - $type_data->{'max'} = $size; - } - # Watch out for case where min is produced by a swept object - if (!$type_data->{'min'} || $type_data->{'min'} > $size) { - $type_data->{'min'} = $size; - } - } -} - - -#---------------------------------------------------------------------- -sub print_type_table(){ - if (!$::opt_showtype) { - return; - } - my $line_count = 0; - my $bytes_printed_tally = 0; - - # Display type summary information - my @sorted_types = keys (%::Types); - print "There are ", 1 + $#sorted_types, " types containing ", $::TotalSize, " bytes\n"; - @sorted_types = sort {$::Types{$b}->{'size'} - <=> $::Types{$a}->{'size'} } @sorted_types; - - foreach my $type (@sorted_types) { - last if ($line_count++ == $::opt_showtype); - - my $type_data = $::Types{$type}; - $bytes_printed_tally += $type_data->{'size'}; - - if ($type_data->{'count'}) { - printf "%.2f%% ", $type_data->{'size'} * 100.0/$::TotalSize; - print $type_data->{'size'}, - "\t(", - $type_data->{'min'}, "/", - int($type_data->{'size'} / $type_data->{'count'}),"/", - $type_data->{'max'}, ")"; - print "\t", $type_data->{'count'}, - " x "; - } - print $type; - - if ($type_data->{'swept_in'}) { - print ", $type_data->{'swept_in'} sub-objs absorbed"; - } - if ($type_data->{'swept'}) { - print ", $type_data->{'swept'} swept away"; - } - if ($type_data->{'overlap_count'}) { - print ", $type_data->{'overlap_count'} range overlaps"; - } - if ($type_data->{'dup_addr_count'}) { - print ", $type_data->{'dup_addr_count'} duplicated addresses"; - } - - print "\n" ; - if (defined $type_data->{'sweep_details_size'}) { - my $sizes = $type_data->{'sweep_details_size'}; - my $counts = $type_data->{'sweep_details_count'}; - my @swept_types = sort {$sizes->{$b} <=> $sizes->{$a}} keys (%{$sizes}); - - for my $type (@swept_types) { - printf " %.2f%% ", $sizes->{$type} * 100.0/$::TotalSize; - print "$sizes->{$type} (", int($sizes->{$type}/$counts->{$type}) , ") $counts->{$type} x $type\n"; - } - print " ---------------\n"; - } - } - if ($bytes_printed_tally != $::TotalSize) { - printf "%.2f%% ", ($::TotalSize- $bytes_printed_tally) * 100.0/$::TotalSize; - print $::TotalSize - $bytes_printed_tally, "\t not shown due to truncation of type list\n"; - print "Currently only data on $::opt_showtype types are displayed, due to command \n", - "line argument '--showtype=$::opt_showtype'\n\n"; - } - -} - -#---------------------------------------------------------------------- -# -# Check for duplicate address ranges is Objects table, and -# create list of sorted addresses for doing pointer-chasing - -sub validate_address_ranges() { - # Build sorted list of address for validating interior pointers - @::SortedAddresses = sort {$a <=> $b} keys %::Objects; - - # Validate non-overlap of memory - my $prev_addr_end = -1; - my $prev_addr = -1; - my $index = 0; - my $overlap_tally = 0; # overlapping object memory - my $unused_tally = 0; # unused memory between blocks - while ($index <= $#::SortedAddresses) { - my $address = $::SortedAddresses[$index]; - if ($prev_addr_end > $address) { - print "Object overlap from $::Objects{$prev_addr}->{'type'}:$prev_addr-$prev_addr_end into"; - my $test_index = $index; - my $prev_addr_overlap_tally = 0; - - while ($test_index <= $#::SortedAddresses) { - my $test_address = $::SortedAddresses[$test_index]; - last if ($prev_addr_end < $test_address); - print " $::Objects{$test_address}->{'type'}:$test_address"; - - $::Objects{$prev_addr}->{'overlap_count'}++; - $::Objects{$test_address}->{'overlap_count'}++; - my $overlap = $prev_addr_end - $test_address; - if ($overlap > $::Objects{$test_address}->{'size'}) { - $overlap = $::Objects{$test_address}->{'size'}; - } - print "($overlap bytes)"; - $prev_addr_overlap_tally += $overlap; - - $test_index++; - } - print " [total $prev_addr_overlap_tally bytes]"; - $overlap_tally += $prev_addr_overlap_tally; - print "\n"; - } - - $prev_addr = $address; - $prev_addr_end = $prev_addr + $::Objects{$prev_addr}->{'size'} - 1; - $index++; - } #end while - if ($overlap_tally) { - print "Total overlap of $overlap_tally bytes\n"; - } -} - -#---------------------------------------------------------------------- -# -# Evaluate sizes of interobject spacing (fragmentation loss?) -# Gather the sizes into histograms for analysis -# This function assumes a sorted list of addresses is present globally - -sub generate_and_print_unused_memory_histogram() { - print "\nInterobject spacing (fragmentation waste) Statistics\n"; - if ($::opt_fragment <= 1) { - print "Statistics are not being gathered. Use '--fragment=10' to get stats\n"; - return; - } - print "Ratio of histogram buckets will be a factor of $::opt_fragment\n"; - - my $prev_addr_end = -1; - my $prev_addr = -1; - my $index = 0; - - my @fragment_count; - my @fragment_tally; - my $power; - my $bucket_size; - - my $max_power = 0; - - my $tally_sizes = 0; - - while ($index <= $#::SortedAddresses) { - my $address = $::SortedAddresses[$index]; - - my $unused = $address - $prev_addr_end; - - # handle overlaps gracefully - if ($unused < 0) { - $unused = 0; - } - - $power = 0; - $bucket_size = 1; - while ($bucket_size < $unused) { - $bucket_size *= $::opt_fragment; - $power++; - } - $fragment_count[$power]++; - $fragment_tally[$power] += $unused; - if ($power > $max_power) { - $max_power = $power; - } - my $size = $::Objects{$address}->{'size'}; - $tally_sizes += $size; - $prev_addr_end = $address + $size - 1; - $index++; - } - - - $power = 0; - $bucket_size = 1; - print "Basic gap histogram is (max_size:count):\n"; - while ($power <= $max_power) { - if (! defined $fragment_count[$power]) { - $fragment_count[$power] = $fragment_tally[$power] = 0; - } - printf " %.1f:", $bucket_size; - print $fragment_count[$power]; - $power++; - $bucket_size *= $::opt_fragment; - } - print "\n"; - - print "Summary gap analysis:\n"; - - $power = 0; - $bucket_size = 1; - my $tally = 0; - my $count = 0; - while ($power <= $max_power) { - $count += $fragment_count[$power]; - $tally += $fragment_tally[$power]; - print "$count gaps, totaling $tally bytes, were under "; - printf "%.1f bytes each", $bucket_size; - if ($count) { - printf ", for an average of %.1f bytes per gap", $tally/$count, ; - } - print "\n"; - $power++; - $bucket_size *= $::opt_fragment; - } - - print "Total allocation was $tally_sizes bytes, or "; - printf "%.0f bytes per allocation block\n\n", $tally_sizes/($count+1); - -} - -#---------------------------------------------------------------------- -# -# Now thread the parents and children together by looking through the -# slots for each object. -# -sub create_parent_links(){ - my $min_addr = $::SortedAddresses[0]; - my $max_addr = $::SortedAddresses[ $#::SortedAddresses]; #allow one beyond each object - $max_addr += $::Objects{$max_addr}->{'size'}; - - print "Viable addresses range from $min_addr to $max_addr for a total of ", - $max_addr-$min_addr, " bytes\n\n"; - - # Gather stats as we try to convert slots to children - my $slot_count = 0; # total slots examined - my $fixed_addr_count = 0; # slots into interiors that were adjusted - my $parent_child_count = 0; # Number of parent-child links - my $child_count = 0; # valid slots, discounting sibling twins - my $child_dup_count = 0; # number of duplicate child pointers - my $self_pointer_count = 0; # count of discarded self-pointers - - foreach my $parent (keys %::Objects) { - # We'll collect a list of this parent object's children - # by iterating through its slots. - my @children; - my %children_hash; - my $self_pointer = 0; - - my @slots = @{$::Objects{$parent}->{'slots'}}; - $slot_count += $#slots + 1; - SLOT: foreach my $child (@slots) { - - # We only care about pointers that refer to other objects - if (! defined $::Objects{$child}) { - # check to see if we are an interior pointer - - # Punt if we are completely out of range - next SLOT unless ($max_addr >= $child && - $child >= $min_addr); - - # Do binary search to find object below this address - my ($min_index, $beyond_index) = (0, $#::SortedAddresses + 1); - my $test_index; - while ($min_index != - ($test_index = int (($beyond_index+$min_index)/2))) { - if ($child >= $::SortedAddresses[$test_index]) { - $min_index = $test_index; - } else { - $beyond_index = $test_index; - } - } - # See if pointer is within extent of this object - my $address = $::SortedAddresses[$test_index]; - next SLOT unless ($child < - $address + $::Objects{$address}->{'size'}); - - # Make adjustment so we point to the actual child precisely - $child = $address; - $fixed_addr_count++; - } - - if ($child == $parent) { - $self_pointer_count++; - next SLOT; # Discard self-pointers - } - - # Avoid creating duplicate child-parent links - if (! defined $children_hash{$child}) { - $parent_child_count++; - # Add the parent to the child's list of parents - my $parents = $::Objects{$child}->{'parents'}; - if (! $parents) { - $parents = $::Objects{$child}->{'parents'} = []; - } - - $parents->[scalar(@$parents)] = $parent; - - # Add the child to the parent's list of children - $children_hash{$child} = 1; - } else { - $child_dup_count++; - } - } - @children = keys %children_hash; - # Track tally of unique children linked - $child_count += $#children + 1; - - $::Objects{$parent}->{'children'} = \@children; - - if (! @children) { - $::Leafs[$#::Leafs + 1] = $parent; - } - } - print "Scanning $#::SortedAddresses objects, we found $parent_child_count parents-to-child connections by chasing $slot_count pointers.\n", - "This required $fixed_addr_count interior pointer fixups, skipping $child_dup_count duplicate pointers, ", - "and $self_pointer_count self pointers\nAlso discarded ", - $slot_count - $parent_child_count -$self_pointer_count - $child_dup_count, - " out-of-range pointers\n\n"; -} - - -#---------------------------------------------------------------------- -# For every leaf, if a leaf has only one parent, then sweep the memory -# cost into the parent from the leaf -sub sweep_leaf_memory () { - my $sweep_count = 0; - my $leaf_counter = 0; - LEAF: while ($leaf_counter <= $#::Leafs) { - my $leaf_addr = $::Leafs[$leaf_counter++]; - my $leaf_obj = $::Objects{$leaf_addr}; - my $parents = $leaf_obj->{'parents'}; - - next LEAF if (! defined($parents) || 1 != scalar(@$parents)); - - # We have only one parent, so we'll try to sweep upwards - my $parent_addr = @$parents[0]; - my $parent_obj = $::Objects{$parent_addr}; - - # watch out for self-pointers - next LEAF if ($parent_addr == $leaf_addr); - - if ($::opt_detail) { - foreach my $obj ($parent_obj, $leaf_obj) { - if (!defined $obj->{'original_size'}) { - $obj->{'original_size'} = $obj->{'size'}; - } - } - if (defined $leaf_obj->{'sweep_details'}) { - if (defined $parent_obj->{'sweep_details'}) { # merge details - foreach my $swept_obj (keys (%{$leaf_obj->{'sweep_details'}})) { - %{$parent_obj->{'sweep_details'}}->{$swept_obj} = - %{$leaf_obj->{'sweep_details'}}->{$swept_obj}; - } - } else { # No parent info - $parent_obj->{'sweep_details'} = \%{$leaf_obj->{'sweep_details'}}; - } - delete $leaf_obj->{'sweep_details'}; - } else { # no leaf detail - if (!defined $parent_obj->{'sweep_details'}) { - $parent_obj->{'sweep_details'} = {}; - } - } - %{$parent_obj->{'sweep_details'}}->{$leaf_addr} = $leaf_obj->{'original_size'}; - } - - $parent_obj->{'size'} += $leaf_obj->{'size'}; - $leaf_obj->{'size'} = 0; - - if (defined ($leaf_obj->{'swept_in'})) { - $parent_obj->{'swept_in'} += $leaf_obj->{'swept_in'}; - $leaf_obj->{'swept_in'} = 0; # sweep has been handed off to parent - } - $parent_obj->{'swept_in'} ++; # tally swept in leaf_obj - - $sweep_count++; - - # See if we created another leaf - my $consumed_children = $parent_obj->{'consumed'}++; - my @children = $parent_obj->{'children'}; - if ($consumed_children == $#children) { - $::Leafs[$#::Leafs + 1] = @$parents[0]; - } - } - print "Processed ", $leaf_counter, " leaves sweeping memory to parents in ", $sweep_count, " objects\n"; -} - - -#---------------------------------------------------------------------- -# -# Subdivide the types of objects that are in our "expand" list -# List types that should be sub-divided based on parents, and possibly -# children -# The argument supplied is a hash table with keys selecting types that -# need to be "refined" by including the types of the parent objects, -# and (when we are desparate) the types of the children objects. - -sub expand_type_names($) { - my %TypeExpand = %{$_[0]}; - - my @retype; # array of addrs that get extended type names - foreach my $child (keys %::Objects) { - my $child_obj = $::Objects{$child}; - next unless (defined ($TypeExpand{$child_obj->{'type'}})); - - foreach my $relation ('parents','children') { - my $relatives = $child_obj->{$relation}; - next unless defined @$relatives; - - # Sort out the names of the types of the relatives - my %names; - foreach my $relative (@$relatives) { - %names->{$::Objects{$relative}->{'type'}} = 1; - } - my $related_type_names = join(',' , sort(keys(%names))); - - - $child_obj->{'name' . $relation} = $related_type_names; - - # Don't bother with children if we have significant parent types - last if (!defined ($TypeExpand{$related_type_names})); - } - $retype[$#retype + 1] = $child; - } - - # Revisit all addresses we've marked - foreach my $child (@retype) { - my $child_obj = $::Objects{$child}; - $child_obj->{'type'} = $TypeExpand{$child_obj->{'type'}}; - my $extended_type = $child_obj->{'namechildren'}; - if (defined $extended_type) { - $child_obj->{'type'}.= "->(" . $extended_type . ")"; - delete ($child_obj->{'namechildren'}); - } - $extended_type = $child_obj->{'nameparents'}; - if (defined $extended_type) { - $child_obj->{'type'} = "(" . $extended_type . ")->" . $::Objects{$child}->{'type'}; - delete ($child_obj->{'nameparents'}); - } - } -} - -#---------------------------------------------------------------------- -# -# Print out a type histogram - -sub print_type_histogram() { - load_type_table(); - print_type_table(); - print "\n\n"; -} - - -#---------------------------------------------------------------------- -# Provide a nice summary of the types during the process -validate_address_ranges(); -create_parent_links(); - -print "\nBasic memory use histogram is:\n"; -print_type_histogram(); - -generate_and_print_unused_memory_histogram(); - -sweep_leaf_memory (); -print "After doing basic leaf-sweep processing of instances:\n"; -print_type_histogram(); - -{ - foreach my $typename (@::opt_typedivide) { - my %expansion_table; - $expansion_table{$typename} = $typename; - expand_type_names(\%expansion_table); - print "After subdividing <$typename> based on inbound (and somtimes outbound) pointers:\n"; - print_type_histogram(); - } -} - -exit(); # Don't bother with SCCs yet. - - -#---------------------------------------------------------------------- -# -# Determine objects that entrain equivalent sets, using the strongly -# connected component algorithm from Cormen, Leiserson, and Rivest, -# ``An Introduction to Algorithms'', MIT Press 1990, pp. 488-493. -# -sub compute_post_order($$$) { -# This routine produces a post-order of the call graph (what CLR call -# ``ordering the nodes by f[u]'') - my ($parent, $visited, $finish) = @_; - - # Bail if we've already seen this node - return if $visited->{$parent}; - - # We have now! - $visited->{$parent} = 1; - - # Walk the children - my $children = $::Objects{$parent}->{'children'}; - - foreach my $child (@$children) { - compute_post_order($child, $visited, $finish); - } - - # Now that we've walked all the kids, we can append the parent to - # the post-order - @$finish[scalar(@$finish)] = $parent; -} - -sub compute_equivalencies($$$) { -# This routine recursively computes equivalencies by walking the -# transpose of the callgraph. - my ($child, $table, $equivalencies) = @_; - - # Bail if we've already seen this node - return if $table->{$child}; - - # Otherwise, append ourself to the list of equivalencies... - @$equivalencies[scalar(@$equivalencies)] = $child; - - # ...and note our other equivalents in the table - $table->{$child} = $equivalencies; - - my $parents = $::Objects{$child}->{'parents'}; - - foreach my $parent (@$parents) { - compute_equivalencies($parent, $table, $equivalencies); - } -} - -sub compute_equivalents() { -# Here's the strongly connected components algorithm. (Step 2 has been -# done implictly by our object graph construction.) - my %visited; - my @finish; - - # Step 1. Compute a post-ordering of the object graph - foreach my $parent (keys %::Objects) { - compute_post_order($parent, \%visited, \@finish); - } - - # Step 3. Traverse the transpose of the object graph in reverse - # post-order, collecting vertices into %equivalents - my %equivalents; - foreach my $child (reverse @finish) { - compute_equivalencies($child, \%equivalents, []); - } - - # Now, we'll trim the %equivalents table, arbitrarily removing - # ``redundant'' entries. - EQUIVALENT: foreach my $node (keys %equivalents) { - my $equivalencies = $equivalents{$node}; - next EQUIVALENT unless $equivalencies; - - foreach my $equivalent (@$equivalencies) { - delete $equivalents{$equivalent} unless $equivalent == $node; - } - } - - # Note the equivalent objects in a way that will yield the most - # interesting order as we do depth-first traversal later to - # output them. - ROOT: foreach my $equivalent (reverse @finish) { - next ROOT unless $equivalents{$equivalent}; - $::Equivalents[$#::Equivalents + 1] = $equivalent; - - # XXX Lame! Should figure out function refs. - $::Objects{$equivalent}->{'entrained-size'} = 0; - } -} - -# Do it! -compute_equivalents(); - - -#---------------------------------------------------------------------- -# -# Compute the size of each node's transitive closure. -# -sub compute_entrained($$) { - my ($parent, $visited) = @_; - - $visited->{$parent} = 1; - - $::Objects{$parent}->{'entrained-size'} = $::Objects{$parent}->{'size'}; - - my $children = $::Objects{$parent}->{'children'}; - CHILD: foreach my $child (@$children) { - next CHILD if $visited->{$child}; - - compute_entrained($child, $visited); - $::Objects{$parent}->{'entrained-size'} += $::Objects{$child}->{'entrained-size'}; - } -} - -if (! $::opt_noentrained) { - my %visited; - - PARENT: foreach my $parent (@::Equivalents) { - next PARENT if $visited{$parent}; - compute_entrained($parent, \%visited); - } -} - - -#---------------------------------------------------------------------- -# -# Converts a shared library and an address into a file and line number -# using a bunch of addr2line processes. -# -sub addr2line($$) { - my ($dso, $addr) = @_; - - # $::Addr2Lines is a global table that maps a DSO's name to a pair - # of filehandles that are talking to an addr2line process. - my $fhs = $::Addr2Lines{$dso}; - if (! $fhs) { - if (!(-r $dso)) { - # bogus filename (that happens sometimes), so bail - return { 'dso' => $dso, 'addr' => $addr }; - } - my ($in, $out) = (new FileHandle, new FileHandle); - open2($in, $out, "addr2line --exe=$dso") || die "unable to open addr2line --exe=$dso"; - $::Addr2Lines{$dso} = $fhs = { 'in' => $in, 'out' => $out }; - } - - # addr2line takes a hex address as input... - $fhs->{'out'}->print($addr . "\n"); - - # ...and'll return file:lineno as output - if ($fhs->{'in'}->getline() =~ /([^:]+):(.+)/) { - return { 'file' => $1, 'line' => $2 }; - } - else { - return { 'dso' => $dso, 'addr' => $addr }; - } -} - - -#---------------------------------------------------------------------- -# -# Dump the objects, using a depth-first traversal. -# -sub dump_objects($$$) { - my ($parent, $visited, $depth) = @_; - - # Have we already seen this? - my $already_visited = $visited->{$parent}; - return if ($depth == 0 && $already_visited); - - if (! $already_visited) { - $visited->{$parent} = 1; - $::Total += $::Objects{$parent}->{'size'}; - } - - my $parententry = $::Objects{$parent}; - - # Make an ``object'' div, which'll contain an ``object'' span, two - # ``toggle'' spans, an invisible ``stack'' div, and the invisible - # ``children'' div. - print "
"; - - if ($already_visited) { - print ""; - } - else { - print ""; - } - - printf "0x%x<%s>[%d]", $parent, $parententry->{'type'}, $parententry->{'size'}; - - if ($already_visited) { - print ""; - goto DONE; - } - - if ($depth == 0) { - print "($parententry->{'entrained-size'})" - if $parententry->{'entrained-size'}; - - print " Children" - if @{$parententry->{'children'}} > 0; - } - - if (($depth == 0 || !$::opt_nochildstacks) && !$::opt_nostacks) { - print " Stack"; - } - - print ""; - - # Print stack traces - print "
\n"; - - if (($depth == 0 || !$::opt_nochildstacks) && !$::opt_nostacks) { - my $depth = $::opt_depth; - - FRAME: foreach my $frame (@{$parententry->{'stack'}}) { - # Only go as deep as they've asked us to. - last FRAME unless --$depth >= 0; - - # Stack frames look like ``mangled_name[dso address]'' - $frame =~ /([^\]]+)\[(.*) \+0x([0-9A-Fa-f]+)\]/; - - # Convert address to file and line number - my $mangled = $1; - my $result = addr2line($2, $3); - - if ($result->{'file'}) { - # It's mozilla source! Clean up refs to dist/include - if (($result->{'file'} =~ s/.*\.\.\/\.\.\/dist\/include\//http:\/\/bonsai.mozilla.org\/cvsguess.cgi\?file=/) || - ($result->{'file'} =~ s/.*\/mozilla/http:\/\/bonsai.mozilla.org\/cvsblame.cgi\?file=mozilla/)) { - my $prevline = $result->{'line'} - 10; - print "{'file'}\&mark=$result->{'line'}#$prevline\">$mangled
\n"; - } - else { - print "$mangled ($result->{'file'}, line $result->{'line'})
\n"; - } - } - else { - print "$result->{'dso'} ($result->{'addr'})
\n"; - } - } - - } - - print "
"; - - # Recurse to children - if (@{$parententry->{'children'}} >= 0) { - print "
\n" if $depth == 0; - - foreach my $child (@{$parententry->{'children'}}) { - dump_objects($child, $visited, $depth + 1); - } - - print "
" if $depth == 0; - } - - DONE: - print "
\n"; -} - - -#---------------------------------------------------------------------- -# -# Do the output. -# - -# Force flush on STDOUT. We get funky output unless we do this. -$| = 1; - -# Header -print " - -Object Graph - - - - -"; - -{ -# Body. Display ``roots'', sorted by the amount of memory they -# entrain. Because of the way we've sorted @::Equivalents, we should -# get a nice ordering that sorts things with a lot of kids early -# on. This should yield a fairly "deep" depth-first traversal, with -# most of the objects appearing as children. -# -# XXX I sure hope that Perl implements a stable sort! - my %visited; - - foreach my $parent (sort { $::Objects{$b}->{'entrained-size'} - <=> $::Objects{$a}->{'entrained-size'} } - @::Equivalents) { - dump_objects($parent, \%visited, 0); - print "\n"; - } -} - -# Footer -print "
$::Total total bytes\n" if $::Total; -print " - -"; - diff --git a/tools/trace-malloc/leaksoup.cpp b/tools/trace-malloc/leaksoup.cpp deleted file mode 100644 index c555bd585152..000000000000 --- a/tools/trace-malloc/leaksoup.cpp +++ /dev/null @@ -1,416 +0,0 @@ -/* 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/. */ - -#include "adreader.h" - -#include -#include "plhash.h" - -#include "nsTArray.h" -#include "nsQuickSort.h" -#include "nsXPCOM.h" - -const uint32_t kPointersDefaultSize = 8; - -/* - * Read in an allocation dump, presumably one taken at shutdown (using - * the --shutdown-leaks=file option, which must be used along with - * --trace-malloc=tmlog), and treat the memory in the dump as leaks. - * Find the leak roots, including cycles that are roots, by finding the - * strongly connected components in the graph. Print output to stdout - * as HTML. - */ - -struct AllocationNode { - const ADLog::Entry *entry; - - // Other |AllocationNode| objects whose memory has a pointer to - // this object. - nsAutoTArray pointers_to; - - // The reverse. - nsAutoTArray pointers_from; - - // Early on in the algorithm, the pre-order index from a DFS. - // Later on, set to the index of the strongly connected component to - // which this node belongs. - uint32_t index; - - bool reached; - bool is_root; -}; - -static PLHashNumber hash_pointer(const void *key) -{ - return (PLHashNumber) NS_PTR_TO_INT32(key); -} - -static int sort_by_index(const void* e1, const void* e2, void*) -{ - const AllocationNode *n1 = *static_cast(e1); - const AllocationNode *n2 = *static_cast(e2); - return n1->index - n2->index; -} - -static int sort_by_reverse_index(const void* e1, const void* e2, void*) -{ - const AllocationNode *n1 = *static_cast(e1); - const AllocationNode *n2 = *static_cast(e2); - return n2->index - n1->index; -} - -static void print_escaped(FILE *aStream, const char* aData) -{ - char c; - char buf[1000]; - char *p = buf; - while ((c = *aData++)) { - switch (c) { -#define CH(char) *p++ = char - case '<': - CH('&'); CH('l'); CH('t'); CH(';'); - break; - case '>': - CH('&'); CH('g'); CH('t'); CH(';'); - break; - case '&': - CH('&'); CH('a'); CH('m'); CH('p'); CH(';'); - break; - default: - CH(c); - break; -#undef CH - } - if (p + 10 > buf + sizeof(buf)) { - *p = '\0'; - fputs(buf, aStream); - p = buf; - } - } - *p = '\0'; - fputs(buf, aStream); -} - -static const char *allocation_format = - (sizeof(ADLog::Pointer) == 4) ? "0x%08zX" : - (sizeof(ADLog::Pointer) == 8) ? "0x%016zX" : - "UNEXPECTED sizeof(void*)"; - -int main(int argc, char **argv) -{ - if (argc != 2) { - fprintf(stderr, - "Expected usage: %s \n" - " sd-leak-file: Output of --shutdown-leaks= option.\n", - argv[0]); - return 1; - } - - NS_InitXPCOM2(nullptr, nullptr, nullptr); - - ADLog log; - if (!log.Read(argv[1])) { - fprintf(stderr, - "%s: Error reading input file %s.\n", argv[0], argv[1]); - } - - const size_t count = log.count(); - - PLHashTable *memory_map = - PL_NewHashTable(count * 8, hash_pointer, PL_CompareValues, - PL_CompareValues, 0, 0); - if (!memory_map) { - fprintf(stderr, "%s: Out of memory.\n", argv[0]); - return 1; - } - - // Create one |AllocationNode| object for each log entry, and create - // entries in the hashtable pointing to it for each byte it occupies. - AllocationNode *nodes = new AllocationNode[count]; - if (!nodes) { - fprintf(stderr, "%s: Out of memory.\n", argv[0]); - return 1; - } - - { - AllocationNode *cur_node = nodes; - for (ADLog::const_iterator entry = log.begin(), entry_end = log.end(); - entry != entry_end; ++entry, ++cur_node) { - const ADLog::Entry *e = cur_node->entry = *entry; - cur_node->reached = false; - - for (ADLog::Pointer p = e->address, - p_end = e->address + e->datasize; - p != p_end; ++p) { - PLHashEntry *he = PL_HashTableAdd(memory_map, p, cur_node); - if (!he) { - fprintf(stderr, "%s: Out of memory.\n", argv[0]); - return 1; - } - } - } - } - - // Construct graph based on pointers. - for (AllocationNode *node = nodes, *node_end = nodes + count; - node != node_end; ++node) { - const ADLog::Entry *e = node->entry; - for (const char *d = e->data, *d_end = e->data + e->datasize - - e->datasize % sizeof(ADLog::Pointer); - d != d_end; d += sizeof(ADLog::Pointer)) { - AllocationNode *target = (AllocationNode*) - PL_HashTableLookup(memory_map, *(void**)d); - if (target) { - target->pointers_from.AppendElement(node); - node->pointers_to.AppendElement(target); - } - } - } - - // Do a depth-first search on the graph (i.e., by following - // |pointers_to|) and assign the post-order index to |index|. - { - uint32_t dfs_index = 0; - nsTArray stack; - - for (AllocationNode *n = nodes, *n_end = nodes+count; n != n_end; ++n) { - if (n->reached) { - continue; - } - stack.AppendElement(n); - - do { - uint32_t pos = stack.Length() - 1; - AllocationNode *n = stack[pos]; - if (n->reached) { - n->index = dfs_index++; - stack.RemoveElementAt(pos); - } else { - n->reached = true; - - // When doing post-order processing, we have to be - // careful not to put reached nodes into the stack. - for (int32_t i = n->pointers_to.Length() - 1; i >= 0; --i) { - AllocationNode* e = n->pointers_to[i]; - if (!e->reached) { - stack.AppendElement(e); - } - } - } - } while (stack.Length() > 0); - } - } - - // Sort the nodes by their DFS index, in reverse, so that the first - // node is guaranteed to be in a root SCC. - AllocationNode **sorted_nodes = new AllocationNode*[count]; - if (!sorted_nodes) { - fprintf(stderr, "%s: Out of memory.\n", argv[0]); - return 1; - } - - { - for (size_t i = 0; i < count; ++i) { - sorted_nodes[i] = nodes + i; - } - NS_QuickSort(sorted_nodes, count, sizeof(AllocationNode*), - sort_by_reverse_index, 0); - } - - // Put the nodes into their strongly-connected components. - uint32_t num_sccs = 0; - { - for (size_t i = 0; i < count; ++i) { - nodes[i].reached = false; - } - nsTArray stack; - for (AllocationNode **sn = sorted_nodes, - **sn_end = sorted_nodes + count; sn != sn_end; ++sn) { - if ((*sn)->reached) { - continue; - } - - // We found a new strongly connected index. - stack.AppendElement(*sn); - do { - uint32_t pos = stack.Length() - 1; - AllocationNode *n = stack[pos]; - stack.RemoveElementAt(pos); - - if (!n->reached) { - n->reached = true; - n->index = num_sccs; - stack.AppendElements(n->pointers_from); - } - } while (stack.Length() > 0); - ++num_sccs; - } - } - - // Identify which nodes are leak roots by using DFS, and watching - // for component transitions. - uint32_t num_root_nodes = count; - { - for (size_t i = 0; i < count; ++i) { - nodes[i].is_root = true; - } - - nsTArray stack; - for (AllocationNode *n = nodes, *n_end = nodes+count; n != n_end; ++n) { - if (!n->is_root) { - continue; - } - - // Loop through pointers_to, and add any that are in a - // different SCC to stack: - for (int i = n->pointers_to.Length() - 1; i >= 0; --i) { - AllocationNode *target = n->pointers_to[i]; - if (n->index != target->index) { - stack.AppendElement(target); - } - } - - while (stack.Length() > 0) { - uint32_t pos = stack.Length() - 1; - AllocationNode *n = stack[pos]; - stack.RemoveElementAt(pos); - - if (n->is_root) { - n->is_root = false; - --num_root_nodes; - stack.AppendElements(n->pointers_to); - } - } - } - } - - // Sort the nodes by their SCC index. - NS_QuickSort(sorted_nodes, count, sizeof(AllocationNode*), - sort_by_index, 0); - - // Print output. - { - printf("\n" - "\n" - "\n" - "Leak analysis\n" - "\n" - "\n"); - printf("\n\n" - "

Generated %zd entries (%d in root SCCs) and %d SCCs.

\n\n", - count, num_root_nodes, num_sccs); - - for (size_t i = 0; i < count; ++i) { - nodes[i].reached = false; - } - - // Loop over the sorted nodes twice, first printing the roots - // and then the non-roots. - for (int32_t root_type = true; - root_type == true || root_type == false; --root_type) { - if (root_type) { - printf("\n\n" - "
\n" - "

Root components

\n"); - } else { - printf("\n\n" - "
\n" - "

Non-root components

\n"); - } - uint32_t component = (uint32_t)-1; - bool one_object_component; - for (const AllocationNode *const* sn = sorted_nodes, - *const* sn_end = sorted_nodes + count; - sn != sn_end; ++sn) { - const AllocationNode *n = *sn; - if (n->is_root != root_type) - continue; - const ADLog::Entry *e = n->entry; - - if (n->index != component) { - component = n->index; - one_object_component = - sn + 1 == sn_end || (*(sn+1))->index != component; - if (!one_object_component) - printf("\n\n

Component %d

\n", - component, component); - } - - if (one_object_component) { - printf("\n\n
\n", component); - printf("

Object %td " - "(single-object component %d)

\n", - n-nodes, n-nodes, component); - } else { - printf("\n\n

Object %td

\n", - n-nodes, n-nodes); - } - printf("
\n");
-                printf("%p <%s> (%zd)\n",
-                       e->address, e->type, e->datasize);
-                for (size_t d = 0; d < e->datasize;
-                     d += sizeof(ADLog::Pointer)) {
-                    AllocationNode *target = (AllocationNode*)
-                        PL_HashTableLookup(memory_map, *(void**)(e->data + d));
-                    if (target) {
-                        printf("        ",
-                               target - nodes);
-                        printf(allocation_format,
-                               *(size_t*)(e->data + d));
-                        printf(" <%s>",
-                               target->entry->type);
-                        if (target->index != n->index) {
-                            printf(", component %d", target->index);
-                        }
-                        printf("\n");
-                    } else {
-                        printf("        ");
-                        printf(allocation_format,
-                               *(size_t*)(e->data + d));
-                        printf("\n");
-                    }
-                }
-
-                if (n->pointers_from.Length()) {
-                    printf("\nPointers from:\n");
-                    for (uint32_t i = 0, i_end = n->pointers_from.Length();
-                         i != i_end; ++i) {
-                        AllocationNode *t = n->pointers_from[i];
-                        const ADLog::Entry *te = t->entry;
-                        printf("    %s (Object %td, ",
-                               t - nodes, te->type, t - nodes);
-                        if (t->index != n->index) {
-                            printf("component %d, ", t->index);
-                        }
-                        if (t == n) {
-                            printf("self)\n");
-                        } else {
-                            printf("%p)\n", te->address);
-                        }
-                    }
-                }
-
-                print_escaped(stdout, e->allocation_stack);
-
-                printf("
\n"); - if (one_object_component) { - printf("
\n"); - } - } - printf("
\n"); - } - printf("\n" - "\n"); - } - - delete [] sorted_nodes; - delete [] nodes; - - NS_ShutdownXPCOM(nullptr); - - return 0; -} diff --git a/tools/trace-malloc/leakstats.c b/tools/trace-malloc/leakstats.c deleted file mode 100644 index 4291e104e066..000000000000 --- a/tools/trace-malloc/leakstats.c +++ /dev/null @@ -1,161 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ -#include -#include -#include -#include -#ifdef HAVE_GETOPT_H -#include -#else -extern int getopt(int argc, char *const *argv, const char *shortopts); -extern char *optarg; -extern int optind; -#ifdef XP_WIN32 -int optind=1; -#endif -#endif -#include -#include "nsTraceMalloc.h" -#include "tmreader.h" -#include "prlog.h" - -static char *program; - -typedef struct handler_data { - uint32_t current_heapsize; - uint32_t max_heapsize; - uint32_t bytes_allocated; - uint32_t current_allocations; - uint32_t total_allocations; - uint32_t unmatched_frees; - int finished; -} handler_data; - -static void handler_data_init(handler_data *data) -{ - data->current_heapsize = 0; - data->max_heapsize = 0; - data->bytes_allocated = 0; - data->current_allocations = 0; - data->total_allocations = 0; - data->unmatched_frees = 0; - data->finished = 0; -} - -static void handler_data_finish(handler_data *data) -{ -} - -static void my_tmevent_handler(tmreader *tmr, tmevent *event) -{ - handler_data *data = (handler_data*) tmr->data; - - switch (event->type) { - case TM_EVENT_REALLOC: - /* On Windows, original allocation could be before we overrode malloc */ - if (event->u.alloc.oldserial != 0) { - data->current_heapsize -= event->u.alloc.oldsize; - --data->current_allocations; - } else { - ++data->unmatched_frees; - PR_ASSERT(event->u.alloc.oldsize == 0); - } - /* fall-through intentional */ - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - ++data->current_allocations; - ++data->total_allocations; - data->bytes_allocated += event->u.alloc.size; - data->current_heapsize += event->u.alloc.size; - if (data->current_heapsize > data->max_heapsize) - data->max_heapsize = data->current_heapsize; - break; - case TM_EVENT_FREE: - /* On Windows, original allocation could be before we overrode malloc */ - if (event->serial != 0) { - --data->current_allocations; - data->current_heapsize -= event->u.alloc.size; - } else { - ++data->unmatched_frees; - PR_ASSERT(event->u.alloc.size == 0); - } - break; - case TM_EVENT_STATS: - data->finished = 1; - break; - } -} - - -int main(int argc, char **argv) -{ - int i, j, rv; - tmreader *tmr; - FILE *fp; - time_t start; - handler_data data; - - program = *argv; - - handler_data_init(&data); - tmr = tmreader_new(program, &data); - if (!tmr) { - perror(program); - exit(1); - } - - start = time(NULL); - fprintf(stdout, "%s starting at %s", program, ctime(&start)); - fflush(stdout); - - argc -= optind; - argv += optind; - if (argc == 0) { - if (tmreader_eventloop(tmr, "-", my_tmevent_handler) <= 0) - exit(1); - } else { - for (i = j = 0; i < argc; i++) { - fp = fopen(argv[i], "r"); - if (!fp) { - fprintf(stderr, - "TEST-UNEXPECTED-FAIL | leakstats | can't open %s: %s\n", - argv[i], strerror(errno)); - exit(1); - } - rv = tmreader_eventloop(tmr, argv[i], my_tmevent_handler); - if (rv < 0) - exit(1); - if (rv > 0) - j++; - fclose(fp); - } - if (j == 0) - exit(1); - } - - if (!data.finished) { - fprintf(stderr, "TEST-UNEXPECTED-FAIL | leakstats | log file incomplete\n"); - exit(1); - } - - fprintf(stdout, - "Leaks: %u bytes, %u allocations\n" - "Maximum Heap Size: %u bytes\n" - "%u bytes were allocated in %u allocations.\n", - data.current_heapsize, data.current_allocations, - data.max_heapsize, - data.bytes_allocated, data.total_allocations); - if (data.unmatched_frees != 0) - fprintf(stdout, - "Logged %u free (or realloc) calls for which we missed the " - "original malloc.\n", - data.unmatched_frees); - - handler_data_finish(&data); - tmreader_destroy(tmr); - - exit(0); -} diff --git a/tools/trace-malloc/lib/moz.build b/tools/trace-malloc/lib/moz.build deleted file mode 100644 index 281c9beb39f1..000000000000 --- a/tools/trace-malloc/lib/moz.build +++ /dev/null @@ -1,34 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -EXPORTS += [ - 'nsTraceMalloc.h', -] - -SOURCES += [ - 'nsTraceMalloc.c', -] - -SOURCES += [ - 'nsTypeInfo.cpp', -] - -if CONFIG['OS_ARCH'] == 'WINNT': - SOURCES += [ - 'nsDebugHelpWin32.cpp', - 'nsWinTraceMalloc.cpp', - ] - -FINAL_LIBRARY = 'xul' - -if CONFIG['WRAP_SYSTEM_INCLUDES']: - DEFINES['WRAP_SYSTEM_INCLUDES'] = True - -DEFINES['MOZ_NO_MOZALLOC'] = True - -DEFFILE = SRCDIR + '/tm.def' - -DISABLE_STL_WRAPPING = True diff --git a/tools/trace-malloc/lib/nsDebugHelpWin32.cpp b/tools/trace-malloc/lib/nsDebugHelpWin32.cpp deleted file mode 100644 index 5aa11920ccf9..000000000000 --- a/tools/trace-malloc/lib/nsDebugHelpWin32.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - - -#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) -// This is the .cpp file where the globals live -#define DHW_IMPLEMENT_GLOBALS -#include -#include "prprf.h" -#include "prlog.h" -#include "plstr.h" -#include "prlock.h" -#include "nscore.h" -#include "nsDebugHelpWin32.h" -#else -#error "nsDebugHelpWin32.cpp should only be built in Win32 x86/x64 builds" -#endif - - - -/***************************************************************************/ - - -PRLock* DHWImportHooker::gLock = nullptr; -DHWImportHooker* DHWImportHooker::gHooks = nullptr; -decltype(GetProcAddress)* DHWImportHooker::gRealGetProcAddress = nullptr; - - -static bool -dhwEnsureImageHlpInitialized() -{ - static bool gInitialized = false; - static bool gTried = false; - - if (!gInitialized && !gTried) { - gTried = true; - HMODULE module = ::LoadLibrary("DBGHELP.DLL"); - if (!module) { - DWORD dw = GetLastError(); - printf("DumpStack Error: DBGHELP.DLL wasn't found. GetLastError() returned 0x%8.8X\n" - " This DLL is needed for succeessfully implementing trace-malloc.\n" - " This dll ships by default on Win2k. Disabling trace-malloc functionality.\n" - , dw); - return false; - } - -#define INIT_PROC(typename_, name_) \ - dhw##name_ = (decltype(name_)*) ::GetProcAddress(module, #name_); \ - if(!dhw##name_) return false; - -#ifdef _WIN64 - INIT_PROC(ENUMERATELOADEDMODULES64, EnumerateLoadedModules64); -#else - INIT_PROC(ENUMERATELOADEDMODULES, EnumerateLoadedModules); -#endif - INIT_PROC(IMAGEDIRECTORYENTRYTODATA, ImageDirectoryEntryToData); - -#undef INIT_PROC - - gInitialized = true; - } - - return gInitialized; -} - - -DHWImportHooker& -DHWImportHooker::getGetProcAddressHooker() -{ - static DHWImportHooker gGetProcAddress("Kernel32.dll", "GetProcAddress", - (PROC)DHWImportHooker::GetProcAddress); - return gGetProcAddress; -} - - -DHWImportHooker& -DHWImportHooker::getLoadLibraryWHooker() -{ - static DHWImportHooker gLoadLibraryW("Kernel32.dll", "LoadLibraryW", - (PROC)DHWImportHooker::LoadLibraryW); - return gLoadLibraryW; -} - -DHWImportHooker& -DHWImportHooker::getLoadLibraryExWHooker() -{ - static DHWImportHooker gLoadLibraryExW("Kernel32.dll", "LoadLibraryExW", - (PROC)DHWImportHooker::LoadLibraryExW); - return gLoadLibraryExW; -} - -DHWImportHooker& -DHWImportHooker::getLoadLibraryAHooker() -{ - static DHWImportHooker gLoadLibraryA("Kernel32.dll", "LoadLibraryA", - (PROC)DHWImportHooker::LoadLibraryA); - return gLoadLibraryA; -} - -DHWImportHooker& -DHWImportHooker::getLoadLibraryExAHooker() -{ - static DHWImportHooker gLoadLibraryExA("Kernel32.dll", "LoadLibraryExA", - (PROC)DHWImportHooker::LoadLibraryExA); - return gLoadLibraryExA; -} - - -static HMODULE ThisModule() -{ - MEMORY_BASIC_INFORMATION info; - return VirtualQuery(ThisModule, &info, sizeof(info)) ? - (HMODULE) info.AllocationBase : nullptr; -} - -DHWImportHooker::DHWImportHooker(const char* aModuleName, - const char* aFunctionName, - PROC aHook, - bool aExcludeOurModule /* = false */) - : mNext(nullptr), - mModuleName(aModuleName), - mFunctionName(aFunctionName), - mOriginal(nullptr), - mHook(aHook), - mIgnoreModule(aExcludeOurModule ? ThisModule() : nullptr), - mHooking(true) -{ - //printf("DHWImportHooker hooking %s, function %s\n",aModuleName, aFunctionName); - - if(!gLock) - gLock = PR_NewLock(); - PR_Lock(gLock); - - dhwEnsureImageHlpInitialized(); // for the extra ones we care about. - - if(!gRealGetProcAddress) - gRealGetProcAddress = ::GetProcAddress; - - mOriginal = gRealGetProcAddress(::GetModuleHandleA(aModuleName), - aFunctionName), - - mNext = gHooks; - gHooks = this; - - PatchAllModules(); - - PR_Unlock(gLock); -} - -DHWImportHooker::~DHWImportHooker() -{ - PR_Lock(gLock); - - mHooking = false; - PatchAllModules(); - - for (DHWImportHooker **cur = &gHooks; - (PR_ASSERT(*cur), *cur); /* assert that we find this */ - cur = &(*cur)->mNext) - { - if (*cur == this) - { - *cur = mNext; - break; - } - } - - if(!gHooks) - { - PRLock* theLock = gLock; - gLock = nullptr; - PR_Unlock(theLock); - PR_DestroyLock(theLock); - } - if (gLock) - PR_Unlock(gLock); -} - -#ifdef _WIN64 -static BOOL CALLBACK ModuleEnumCallback(PCSTR ModuleName, - DWORD64 ModuleBase, - ULONG ModuleSize, - PVOID UserContext) -#else -static BOOL CALLBACK ModuleEnumCallback(PCSTR ModuleName, - ULONG ModuleBase, - ULONG ModuleSize, - PVOID UserContext) -#endif -{ - //printf("Module Name %s\n",ModuleName); - DHWImportHooker* self = (DHWImportHooker*) UserContext; - HMODULE aModule = (HMODULE) ModuleBase; - return self->PatchOneModule(aModule, ModuleName); -} - -bool -DHWImportHooker::PatchAllModules() -{ - // Need to cast to PENUMLOADED_MODULES_CALLBACK because the - // constness of the first parameter of PENUMLOADED_MODULES_CALLBACK - // varies over SDK versions (from non-const to const over time). - // See bug 391848 and bug 415426. -#ifdef _WIN64 - return dhwEnumerateLoadedModules64(::GetCurrentProcess(), - (PENUMLOADED_MODULES_CALLBACK64)ModuleEnumCallback, this); -#else - return dhwEnumerateLoadedModules(::GetCurrentProcess(), - (PENUMLOADED_MODULES_CALLBACK)ModuleEnumCallback, this); -#endif -} - -bool -DHWImportHooker::PatchOneModule(HMODULE aModule, const char* name) -{ - if(aModule == mIgnoreModule) - { - return true; - } - - // do the fun stuff... - - PIMAGE_IMPORT_DESCRIPTOR desc; - ULONG size; - - desc = (PIMAGE_IMPORT_DESCRIPTOR) - dhwImageDirectoryEntryToData(aModule, true, - IMAGE_DIRECTORY_ENTRY_IMPORT, &size); - - if(!desc) - { - return true; - } - - for(; desc->Name; desc++) - { - const char* entryModuleName = (const char*) - ((char*)aModule + desc->Name); - if(!lstrcmpi(entryModuleName, mModuleName)) - break; - } - - if(!desc->Name) - { - return true; - } - - PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA) - ((char*) aModule + desc->FirstThunk); - - for(; thunk->u1.Function; thunk++) - { - PROC original; - PROC replacement; - - if(mHooking) - { - original = mOriginal; - replacement = mHook; - } - else - { - original = mHook; - replacement = mOriginal; - } - - PROC* ppfn = (PROC*) &thunk->u1.Function; - if(*ppfn == original) - { - DWORD dwDummy; - VirtualProtect(ppfn, sizeof(ppfn), PAGE_EXECUTE_READWRITE, &dwDummy); - BOOL result = WriteProcessMemory(GetCurrentProcess(), - ppfn, &replacement, sizeof(replacement), nullptr); - if (!result) //failure - { - printf("failure name %s func %x\n",name,*ppfn); - DWORD error = GetLastError(); - return true; - } - else - { - // printf("success name %s func %x\n",name,*ppfn); - DWORD filler = result+1; - return result; - } - } - - } - return true; -} - -bool -DHWImportHooker::ModuleLoaded(HMODULE aModule, DWORD flags) -{ - //printf("ModuleLoaded\n"); - if(aModule && !(flags & LOAD_LIBRARY_AS_DATAFILE)) - { - PR_Lock(gLock); - // We don't know that the newly loaded module didn't drag in implicitly - // linked modules, so we patch everything in sight. - for(DHWImportHooker* cur = gHooks; cur; cur = cur->mNext) - cur->PatchAllModules(); - PR_Unlock(gLock); - } - return true; -} - -// static -HMODULE WINAPI -DHWImportHooker::LoadLibraryW(PCWSTR path) -{ - //wprintf(L"LoadLibraryW %s\n",path); - HMODULE hmod = DHW_ORIGINAL(::LoadLibraryW, getLoadLibraryWHooker())(path); - ModuleLoaded(hmod, 0); - return hmod; -} - - -// static -HMODULE WINAPI -DHWImportHooker::LoadLibraryExW(PCWSTR path, HANDLE file, DWORD flags) -{ - //wprintf(L"LoadLibraryExW %s\n",path); - HMODULE hmod = DHW_ORIGINAL(::LoadLibraryExW, getLoadLibraryExWHooker())(path, file, flags); - ModuleLoaded(hmod, flags); - return hmod; -} - -// static -HMODULE WINAPI -DHWImportHooker::LoadLibraryA(PCSTR path) -{ - //printf("LoadLibraryA %s\n",path); - HMODULE hmod = DHW_ORIGINAL(::LoadLibraryA, getLoadLibraryAHooker())(path); - ModuleLoaded(hmod, 0); - return hmod; -} - -// static -HMODULE WINAPI -DHWImportHooker::LoadLibraryExA(PCSTR path, HANDLE file, DWORD flags) -{ - //printf("LoadLibraryExA %s\n",path); - HMODULE hmod = DHW_ORIGINAL(::LoadLibraryExA, getLoadLibraryExAHooker())(path, file, flags); - ModuleLoaded(hmod, flags); - return hmod; -} -// static -FARPROC WINAPI -DHWImportHooker::GetProcAddress(HMODULE aModule, PCSTR aFunctionName) -{ - FARPROC pfn = gRealGetProcAddress(aModule, aFunctionName); - - if(pfn) - { - PR_Lock(gLock); - for(DHWImportHooker* cur = gHooks; cur; cur = cur->mNext) - { - if(pfn == cur->mOriginal) - { - pfn = cur->mHook; - break; - } - } - PR_Unlock(gLock); - } - return pfn; -} - - diff --git a/tools/trace-malloc/lib/nsDebugHelpWin32.h b/tools/trace-malloc/lib/nsDebugHelpWin32.h deleted file mode 100644 index eef1597b2034..000000000000 --- a/tools/trace-malloc/lib/nsDebugHelpWin32.h +++ /dev/null @@ -1,133 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* 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/. */ - -/* Win32 x86/x64 code for stack walking, symbol resolution, and function hooking */ - -#ifndef __nsDebugHelpWin32_h__ -#define __nsDebugHelpWin32_h__ - -#if defined(_WIN32) && (defined(_M_IX86) || defined(_M_X64)) - #ifndef WIN32_LEAN_AND_MEAN - #define WIN32_LEAN_AND_MEAN - #endif - #include - #include - #include -#else - #error "nsDebugHelpWin32.h should only be included in Win32 x86/x64 builds" -#endif - -// XXX temporary hack... -//#include "hacky_defines.h" - - -/***************************************************************************/ -// useful macros... - -#ifdef DHW_IMPLEMENT_GLOBALS -#define DHW_DECLARE_FUN_GLOBAL(name_) decltype(name_)* dhw##name_ -#else -#define DHW_DECLARE_FUN_GLOBAL(name_) extern decltype(name_)* dhw##name_ -#endif - - -/**********************************************************/ -// This is used to get 'original' function addresses from DHWImportHooker. - -#define DHW_ORIGINAL(name_, hooker_) \ - ((decltype(name_)*) hooker_ . GetOriginalFunction()) - -/***************************************************************************/ -// Global declarations of entry points into ImgHelp functions - -#ifndef _WIN64 -DHW_DECLARE_FUN_GLOBAL(EnumerateLoadedModules); -#else -DHW_DECLARE_FUN_GLOBAL(EnumerateLoadedModules64); -#endif - -DHW_DECLARE_FUN_GLOBAL(ImageDirectoryEntryToData); - -/***************************************************************************/ - -extern bool -dhwEnsureImageHlpInitialized(); - -/***************************************************************************/ - -class DHWImportHooker -{ -public: - - DHWImportHooker(const char* aModuleName, - const char* aFunctionName, - PROC aHook, - bool aExcludeOurModule = false); - - ~DHWImportHooker(); - - PROC GetOriginalFunction() {return mOriginal;} - - bool PatchAllModules(); - bool PatchOneModule(HMODULE aModule, const char* name); - static bool ModuleLoaded(HMODULE aModule, DWORD flags); - - - // I think that these should be made not static members, but allocated - // things created in an explicit static 'init' method and cleaned up in - // an explicit static 'finish' method. This would allow the application - // to have proper lifetime control over all the hooks. - - static DHWImportHooker &getLoadLibraryWHooker(); - static DHWImportHooker &getLoadLibraryExWHooker(); - static DHWImportHooker &getLoadLibraryAHooker(); - static DHWImportHooker &getLoadLibraryExAHooker(); - static DHWImportHooker &getGetProcAddressHooker(); - - static HMODULE WINAPI LoadLibraryA(PCSTR path); - -private: - DHWImportHooker* mNext; - const char* mModuleName; - const char* mFunctionName; - PROC mOriginal; - PROC mHook; - HMODULE mIgnoreModule; - bool mHooking; - -private: - static PRLock* gLock; - static DHWImportHooker* gHooks; - static decltype(GetProcAddress)* gRealGetProcAddress; - - static HMODULE WINAPI LoadLibraryW(PCWSTR path); - static HMODULE WINAPI LoadLibraryExW(PCWSTR path, HANDLE file, DWORD flags); - static HMODULE WINAPI LoadLibraryExA(PCSTR path, HANDLE file, DWORD flags); - - static FARPROC WINAPI GetProcAddress(HMODULE aModule, PCSTR aFunctionName); -}; - -/***************************************************************************/ -// This supports the _CrtSetAllocHook based hooking. -// This system sucks because you don't get to see the allocated pointer. I -// don't think it appropriate for nsTraceMalloc, but is useful as a means to make -// malloc fail for testing purposes. -#if 0 //comment out this stuff. not necessary - -class DHWAllocationSizeDebugHook -{ -public: - virtual bool AllocHook(size_t size) = 0; - virtual bool ReallocHook(size_t size, size_t sizeOld) = 0; - virtual bool FreeHook(size_t size) = 0; -}; - -extern bool dhwSetAllocationSizeDebugHook(DHWAllocationSizeDebugHook* hook); -extern bool dhwClearAllocationSizeDebugHook(); - -/***************************************************************************/ -#endif //0 - -#endif /* __nsDebugHelpWin32_h__ */ diff --git a/tools/trace-malloc/lib/nsTraceMalloc.c b/tools/trace-malloc/lib/nsTraceMalloc.c deleted file mode 100644 index 459b56d7d3e8..000000000000 --- a/tools/trace-malloc/lib/nsTraceMalloc.c +++ /dev/null @@ -1,2063 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * vim:cindent:ts=8:et:sw=4: - * - * 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/. */ -#ifdef NS_TRACE_MALLOC - /* - * TODO: - * - FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=392008 - * - extend logfile so 'F' record tells free stack - */ -#include -#include -#include -#include -#ifdef XP_UNIX -#include -#include -#include -#endif -#include "plhash.h" -#include "pratom.h" -#include "prlog.h" -#include "prlock.h" -#include "prmon.h" -#include "prprf.h" -#include "prenv.h" -#include "prnetdb.h" -#include "nsTraceMalloc.h" -#include "nscore.h" -#include "prinit.h" -#include "prthread.h" -#include "plstr.h" -#include "nsStackWalk.h" -#include "nsTraceMallocCallbacks.h" -#include "nsTypeInfo.h" -#include "mozilla/PoisonIOInterposer.h" - -#if defined(XP_MACOSX) - -#include - -#define WRITE_FLAGS "w" - -#define __libc_malloc(x) malloc(x) -#define __libc_realloc(x, y) realloc(x, y) -#define __libc_free(x) free(x) - -#elif defined(XP_UNIX) - -#include - -#define WRITE_FLAGS "w" - -#ifdef WRAP_SYSTEM_INCLUDES -#pragma GCC visibility push(default) -#endif -extern __ptr_t __libc_malloc(size_t); -extern __ptr_t __libc_calloc(size_t, size_t); -extern __ptr_t __libc_realloc(__ptr_t, size_t); -extern void __libc_free(__ptr_t); -extern __ptr_t __libc_memalign(size_t, size_t); -extern __ptr_t __libc_valloc(size_t); -#ifdef WRAP_SYSTEM_INCLUDES -#pragma GCC visibility pop -#endif - -#elif defined(XP_WIN32) - -#include /* for timeb */ -#include /* for fstat */ - -#include /*for write*/ - -#define WRITE_FLAGS "w" - -#define __libc_malloc(x) dhw_orig_malloc(x) -#define __libc_realloc(x, y) dhw_orig_realloc(x,y) -#define __libc_free(x) dhw_orig_free(x) - -#else /* not XP_MACOSX, XP_UNIX, or XP_WIN32 */ - -# error "Unknown build configuration!" - -#endif - -typedef struct logfile logfile; - -#define STARTUP_TMBUFSIZE (64 * 1024) -#define LOGFILE_TMBUFSIZE (16 * 1024) - -struct logfile { - int fd; - int lfd; /* logical fd, dense among all logfiles */ - char *buf; - int bufsize; - int pos; - uint32_t size; - uint32_t simsize; - logfile *next; - logfile **prevp; -}; - -static char default_buf[STARTUP_TMBUFSIZE]; -static logfile default_logfile = - {-1, 0, default_buf, STARTUP_TMBUFSIZE, 0, 0, 0, NULL, NULL}; -static logfile *logfile_list = NULL; -static logfile **logfile_tail = &logfile_list; -static logfile *logfp = &default_logfile; -static PRLock *tmlock = NULL; -#ifndef PATH_MAX -#define PATH_MAX 4096 -#endif -static char sdlogname[PATH_MAX] = ""; /* filename for shutdown leak log */ - -/* - * This enables/disables trace-malloc logging. - * - * It is separate from suppress_tracing so that we do not have to pay - * the performance cost of repeated TM_TLS_GET_DATA calls when - * trace-malloc is disabled (which is not as bad as the locking we used - * to have). - * - * It must default to zero, since it can be tested by the Linux malloc - * hooks before NS_TraceMallocStartup sets it. - */ -static uint32_t tracing_enabled = 0; - -/* - * Control whether we should log stacks - */ -static uint32_t stacks_enabled = 1; - -/* - * This lock must be held while manipulating the calltree, the - * allocations table, the log, or the tmstats. - * - * Callers should not *enter* the lock without checking suppress_tracing - * first; otherwise they risk trying to re-enter on the same thread. - */ -#define TM_ENTER_LOCK(t) \ - PR_BEGIN_MACRO \ - PR_ASSERT(t->suppress_tracing != 0); \ - if (tmlock) \ - PR_Lock(tmlock); \ - PR_END_MACRO - -#define TM_EXIT_LOCK(t) \ - PR_BEGIN_MACRO \ - PR_ASSERT(t->suppress_tracing != 0); \ - if (tmlock) \ - PR_Unlock(tmlock); \ - PR_END_MACRO - -#define TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t) \ - PR_BEGIN_MACRO \ - t->suppress_tracing++; \ - TM_ENTER_LOCK(t); \ - PR_END_MACRO - -#define TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t) \ - PR_BEGIN_MACRO \ - TM_EXIT_LOCK(t); \ - t->suppress_tracing--; \ - PR_END_MACRO - - -/* - * Thread-local storage. - * - * We can't use NSPR thread-local storage for this because it mallocs - * within PR_GetThreadPrivate (the first time) and PR_SetThreadPrivate - * (which can be worked around by protecting all uses of those functions - * with a monitor, ugh) and because it calls malloc/free when the - * thread-local storage is in an inconsistent state within - * PR_SetThreadPrivate (when expanding the thread-local storage array) - * and _PRI_DetachThread (when and after deleting the thread-local - * storage array). - */ - -#ifdef XP_WIN32 - -#include - -#define TM_TLS_INDEX_TYPE DWORD -#define TM_CREATE_TLS_INDEX(i_) PR_BEGIN_MACRO \ - (i_) = TlsAlloc(); \ - PR_END_MACRO -#define TM_DESTROY_TLS_INDEX(i_) TlsFree((i_)) -#define TM_GET_TLS_DATA(i_) TlsGetValue((i_)) -#define TM_SET_TLS_DATA(i_, v_) TlsSetValue((i_), (v_)) - -#else - -#include - -#define TM_TLS_INDEX_TYPE pthread_key_t -#define TM_CREATE_TLS_INDEX(i_) pthread_key_create(&(i_), NULL) -#define TM_DESTROY_TLS_INDEX(i_) pthread_key_delete((i_)) -#define TM_GET_TLS_DATA(i_) pthread_getspecific((i_)) -#define TM_SET_TLS_DATA(i_, v_) pthread_setspecific((i_), (v_)) - -#endif - -static TM_TLS_INDEX_TYPE tls_index; -static PRBool tls_index_initialized = PR_FALSE; - -/* FIXME (maybe): This is currently unused; we leak the thread-local data. */ -#if 0 -static void -free_tm_thread(void *priv) -{ - tm_thread *t = (tm_thread*) priv; - - PR_ASSERT(t->suppress_tracing == 0); - - if (t->in_heap) { - t->suppress_tracing = 1; - if (t->backtrace_buf.buffer) - __libc_free(t->backtrace_buf.buffer); - - __libc_free(t); - } -} -#endif - -tm_thread * -tm_get_thread(void) -{ - tm_thread *t; - tm_thread stack_tm_thread; - - if (!tls_index_initialized) { - /** - * Assume that the first call to |malloc| will occur before - * there are multiple threads. (If that's not the case, we - * probably need to do the necessary synchronization without - * using NSPR primitives. See discussion in - * https://bugzilla.mozilla.org/show_bug.cgi?id=442192 - */ - TM_CREATE_TLS_INDEX(tls_index); - tls_index_initialized = PR_TRUE; - } - - t = TM_GET_TLS_DATA(tls_index); - - if (!t) { - /* - * First, store a tm_thread on the stack to suppress for the - * malloc below - */ - stack_tm_thread.suppress_tracing = 1; - stack_tm_thread.backtrace_buf.buffer = NULL; - stack_tm_thread.backtrace_buf.size = 0; - stack_tm_thread.backtrace_buf.entries = 0; - TM_SET_TLS_DATA(tls_index, &stack_tm_thread); - - t = (tm_thread*) __libc_malloc(sizeof(tm_thread)); - t->suppress_tracing = 0; - t->backtrace_buf = stack_tm_thread.backtrace_buf; - TM_SET_TLS_DATA(tls_index, t); - - PR_ASSERT(stack_tm_thread.suppress_tracing == 1); /* balanced */ - } - - return t; -} - -/* We don't want more than 32 logfiles open at once, ok? */ -typedef uint32_t lfd_set; - -#define LFD_SET_STATIC_INITIALIZER 0 -#define LFD_SET_SIZE 32 - -#define LFD_ZERO(s) (*(s) = 0) -#define LFD_BIT(i) ((uint32_t)1 << (i)) -#define LFD_TEST(i,s) (LFD_BIT(i) & *(s)) -#define LFD_SET(i,s) (*(s) |= LFD_BIT(i)) -#define LFD_CLR(i,s) (*(s) &= ~LFD_BIT(i)) - -static logfile *get_logfile(int fd) -{ - logfile *fp; - int lfd; - - for (fp = logfile_list; fp; fp = fp->next) { - if (fp->fd == fd) - return fp; - } - lfd = 0; -retry: - for (fp = logfile_list; fp; fp = fp->next) { - if (fp->fd == lfd) { - if (++lfd >= LFD_SET_SIZE) - return NULL; - goto retry; - } - } - fp = __libc_malloc(sizeof(logfile) + LOGFILE_TMBUFSIZE); - if (!fp) - return NULL; - fp->fd = fd; - fp->lfd = lfd; - fp->buf = (char*) (fp + 1); - fp->bufsize = LOGFILE_TMBUFSIZE; - fp->pos = 0; - fp->size = fp->simsize = 0; - fp->next = NULL; - fp->prevp = logfile_tail; - *logfile_tail = fp; - logfile_tail = &fp->next; - return fp; -} - -static void flush_logfile(logfile *fp) -{ - int len, cnt, fd; - char *bp; - - len = fp->pos; - if (len == 0) - return; - fp->pos = 0; - fd = fp->fd; - if (fd >= 0) { - fp->size += len; - bp = fp->buf; - do { - cnt = write(fd, bp, len); - if (cnt <= 0) { - printf("### nsTraceMalloc: write failed or wrote 0 bytes!\n"); - return; - } - bp += cnt; - len -= cnt; - } while (len > 0); - } - fp->simsize += len; -} - -static void log_byte(logfile *fp, char byte) -{ - if (fp->pos == fp->bufsize) - flush_logfile(fp); - fp->buf[fp->pos++] = byte; -} - -static void log_string(logfile *fp, const char *str) -{ - int len, rem, cnt; - - len = strlen(str) + 1; /* include null terminator */ - while ((rem = fp->pos + len - fp->bufsize) > 0) { - cnt = len - rem; - memcpy(&fp->buf[fp->pos], str, cnt); - str += cnt; - fp->pos += cnt; - flush_logfile(fp); - len = rem; - } - memcpy(&fp->buf[fp->pos], str, len); - fp->pos += len; -} - -static void log_filename(logfile* fp, const char* filename) -{ - if (strlen(filename) < 512) { - char *bp, *cp, buf[512]; - - bp = strstr(strcpy(buf, filename), "mozilla"); - if (!bp) - bp = buf; - - for (cp = bp; *cp; cp++) { - if (*cp == '\\') - *cp = '/'; - } - - filename = bp; - } - log_string(fp, filename); -} - -static void log_uint32(logfile *fp, uint32_t ival) -{ - if (ival < 0x80) { - /* 0xxx xxxx */ - log_byte(fp, (char) ival); - } else if (ival < 0x4000) { - /* 10xx xxxx xxxx xxxx */ - log_byte(fp, (char) ((ival >> 8) | 0x80)); - log_byte(fp, (char) (ival & 0xff)); - } else if (ival < 0x200000) { - /* 110x xxxx xxxx xxxx xxxx xxxx */ - log_byte(fp, (char) ((ival >> 16) | 0xc0)); - log_byte(fp, (char) ((ival >> 8) & 0xff)); - log_byte(fp, (char) (ival & 0xff)); - } else if (ival < 0x10000000) { - /* 1110 xxxx xxxx xxxx xxxx xxxx xxxx xxxx */ - log_byte(fp, (char) ((ival >> 24) | 0xe0)); - log_byte(fp, (char) ((ival >> 16) & 0xff)); - log_byte(fp, (char) ((ival >> 8) & 0xff)); - log_byte(fp, (char) (ival & 0xff)); - } else { - /* 1111 0000 xxxx xxxx xxxx xxxx xxxx xxxx xxxx xxxx */ - log_byte(fp, (char) 0xf0); - log_byte(fp, (char) ((ival >> 24) & 0xff)); - log_byte(fp, (char) ((ival >> 16) & 0xff)); - log_byte(fp, (char) ((ival >> 8) & 0xff)); - log_byte(fp, (char) (ival & 0xff)); - } -} - -static void log_event1(logfile *fp, char event, uint32_t serial) -{ - log_byte(fp, event); - log_uint32(fp, (uint32_t) serial); -} - -static void log_event2(logfile *fp, char event, uint32_t serial, size_t size) -{ - log_event1(fp, event, serial); - log_uint32(fp, (uint32_t) size); -} - -static void log_event3(logfile *fp, char event, uint32_t serial, size_t oldsize, - size_t size) -{ - log_event2(fp, event, serial, oldsize); - log_uint32(fp, (uint32_t) size); -} - -static void log_event4(logfile *fp, char event, uint32_t serial, uint32_t ui2, - uint32_t ui3, uint32_t ui4) -{ - log_event3(fp, event, serial, ui2, ui3); - log_uint32(fp, ui4); -} - -static void log_event5(logfile *fp, char event, uint32_t serial, uint32_t ui2, - uint32_t ui3, uint32_t ui4, uint32_t ui5) -{ - log_event4(fp, event, serial, ui2, ui3, ui4); - log_uint32(fp, ui5); -} - -static void log_event6(logfile *fp, char event, uint32_t serial, uint32_t ui2, - uint32_t ui3, uint32_t ui4, uint32_t ui5, uint32_t ui6) -{ - log_event5(fp, event, serial, ui2, ui3, ui4, ui5); - log_uint32(fp, ui6); -} - -static void log_event7(logfile *fp, char event, uint32_t serial, uint32_t ui2, - uint32_t ui3, uint32_t ui4, uint32_t ui5, uint32_t ui6, - uint32_t ui7) -{ - log_event6(fp, event, serial, ui2, ui3, ui4, ui5, ui6); - log_uint32(fp, ui7); -} - -static void log_event8(logfile *fp, char event, uint32_t serial, uint32_t ui2, - uint32_t ui3, uint32_t ui4, uint32_t ui5, uint32_t ui6, - uint32_t ui7, uint32_t ui8) -{ - log_event7(fp, event, serial, ui2, ui3, ui4, ui5, ui6, ui7); - log_uint32(fp, ui8); -} - -typedef struct callsite callsite; - -struct callsite { - void* pc; - uint32_t serial; - lfd_set lfdset; - const char *name; /* pointer to string owned by methods table */ - const char *library; /* pointer to string owned by libraries table */ - int offset; - callsite *parent; - callsite *siblings; - callsite *kids; -}; - -/* NB: these counters are incremented and decremented only within tmlock. */ -static uint32_t library_serial_generator = 0; -static uint32_t method_serial_generator = 0; -static uint32_t callsite_serial_generator = 0; -static uint32_t tmstats_serial_generator = 0; -static uint32_t filename_serial_generator = 0; - -/* Root of the tree of callsites, the sum of all (cycle-compressed) stacks. */ -static callsite calltree_root = - {0, 0, LFD_SET_STATIC_INITIALIZER, NULL, NULL, 0, NULL, NULL, NULL}; - -/* a fake pc for when stacks are disabled; must be different from the - pc in calltree_root */ -#define STACK_DISABLED_PC ((void*)1) - -/* Basic instrumentation. */ -static nsTMStats tmstats = NS_TMSTATS_STATIC_INITIALIZER; - -/* Parent with the most kids (tmstats.calltree_maxkids). */ -static callsite *calltree_maxkids_parent; - -/* Calltree leaf for path with deepest stack backtrace. */ -static callsite *calltree_maxstack_top; - -/* Last site (i.e., calling pc) that recurred during a backtrace. */ -static callsite *last_callsite_recurrence; - -static void log_tmstats(logfile *fp) -{ - log_event1(fp, TM_EVENT_STATS, ++tmstats_serial_generator); - log_uint32(fp, tmstats.calltree_maxstack); - log_uint32(fp, tmstats.calltree_maxdepth); - log_uint32(fp, tmstats.calltree_parents); - log_uint32(fp, tmstats.calltree_maxkids); - log_uint32(fp, tmstats.calltree_kidhits); - log_uint32(fp, tmstats.calltree_kidmisses); - log_uint32(fp, tmstats.calltree_kidsteps); - log_uint32(fp, tmstats.callsite_recurrences); - log_uint32(fp, tmstats.backtrace_calls); - log_uint32(fp, tmstats.backtrace_failures); - log_uint32(fp, tmstats.btmalloc_failures); - log_uint32(fp, tmstats.dladdr_failures); - log_uint32(fp, tmstats.malloc_calls); - log_uint32(fp, tmstats.malloc_failures); - log_uint32(fp, tmstats.calloc_calls); - log_uint32(fp, tmstats.calloc_failures); - log_uint32(fp, tmstats.realloc_calls); - log_uint32(fp, tmstats.realloc_failures); - log_uint32(fp, tmstats.free_calls); - log_uint32(fp, tmstats.null_free_calls); - log_uint32(fp, calltree_maxkids_parent ? calltree_maxkids_parent->serial - : 0); - log_uint32(fp, calltree_maxstack_top ? calltree_maxstack_top->serial : 0); -} - -static void *generic_alloctable(void *pool, size_t size) -{ - return __libc_malloc(size); -} - -static void generic_freetable(void *pool, void *item) -{ - __libc_free(item); -} - -typedef struct lfdset_entry { - PLHashEntry base; - lfd_set lfdset; -} lfdset_entry; - -static PLHashEntry *lfdset_allocentry(void *pool, const void *key) -{ - lfdset_entry *le = __libc_malloc(sizeof *le); - if (le) - LFD_ZERO(&le->lfdset); - return &le->base; -} - -static void lfdset_freeentry(void *pool, PLHashEntry *he, unsigned flag) -{ - lfdset_entry *le; - - if (flag != HT_FREE_ENTRY) - return; - le = (lfdset_entry*) he; - __libc_free((void*) le); -} - -static PLHashAllocOps lfdset_hashallocops = { - generic_alloctable, generic_freetable, - lfdset_allocentry, lfdset_freeentry -}; - -/* Table of library pathnames mapped to to logged 'L' record serial numbers. */ -static PLHashTable *libraries = NULL; - -/* Table of filename pathnames mapped to logged 'G' record serial numbers. */ -static PLHashTable *filenames = NULL; - -/* Table mapping method names to logged 'N' record serial numbers. */ -static PLHashTable *methods = NULL; - -/* - * Presumes that its caller is holding tmlock, but may temporarily exit - * the lock. - */ -static callsite * -calltree(void **stack, size_t num_stack_entries, tm_thread *t) -{ - logfile *fp = logfp; - void *pc; - uint32_t nkids; - callsite *parent, *site, **csp, *tmp; - int maxstack; - uint32_t library_serial, method_serial, filename_serial; - const char *library, *method, *filename; - char *slash; - PLHashNumber hash; - PLHashEntry **hep, *he; - lfdset_entry *le; - size_t stack_index; - nsCodeAddressDetails details; - nsresult rv; - - maxstack = (num_stack_entries > tmstats.calltree_maxstack); - if (maxstack) { - /* these two are the same, although that used to be less clear */ - tmstats.calltree_maxstack = num_stack_entries; - tmstats.calltree_maxdepth = num_stack_entries; - } - - /* Reverse the stack again, finding and building a path in the tree. */ - parent = &calltree_root; - stack_index = num_stack_entries; - do { - --stack_index; - pc = stack[stack_index]; - - csp = &parent->kids; - while ((site = *csp) != NULL) { - if (site->pc == pc) { - tmstats.calltree_kidhits++; - - /* Put the most recently used site at the front of siblings. */ - *csp = site->siblings; - site->siblings = parent->kids; - parent->kids = site; - - /* Check whether we've logged for this site and logfile yet. */ - if (!LFD_TEST(fp->lfd, &site->lfdset)) { - /* - * Some other logfile put this site in the calltree. We - * must log an event for site, and possibly first for its - * method and/or library. Note the code after the while - * loop that tests if (!site). - */ - break; - } - - /* Site already built and logged to fp -- go up the stack. */ - goto upward; - } - tmstats.calltree_kidsteps++; - csp = &site->siblings; - } - - if (!site) { - tmstats.calltree_kidmisses++; - - /* Check for recursion: see if pc is on our ancestor line. */ - for (site = parent; site; site = site->parent) { - if (site->pc == pc) { - tmstats.callsite_recurrences++; - last_callsite_recurrence = site; - goto upward; - } - } - } - - /* - * Not in tree at all, or not logged to fp: let's find our symbolic - * callsite info. - */ - - if (!stacks_enabled) { - /* - * Fake the necessary information for our single fake stack - * frame. - */ - PL_strncpyz(details.library, "stacks_disabled", - sizeof(details.library)); - details.loffset = 0; - details.filename[0] = '\0'; - details.lineno = 0; - details.function[0] = '\0'; - details.foffset = 0; - } else { - /* - * NS_DescribeCodeAddress can (on Linux) acquire a lock inside - * the shared library loader. Another thread might call malloc - * while holding that lock (when loading a shared library). So - * we have to exit tmlock around this call. For details, see - * https://bugzilla.mozilla.org/show_bug.cgi?id=363334#c3 - * - * We could be more efficient by building the nodes in the - * calltree, exiting the monitor once to describe all of them, - * and then filling in the descriptions for any that hadn't been - * described already. But this is easier for now. - */ - TM_EXIT_LOCK(t); - rv = NS_DescribeCodeAddress(pc, &details); - TM_ENTER_LOCK(t); - if (NS_FAILED(rv)) { - tmstats.dladdr_failures++; - goto fail; - } - } - - /* Check whether we need to emit a library trace record. */ - library_serial = 0; - library = NULL; - if (details.library[0]) { - if (!libraries) { - libraries = PL_NewHashTable(100, PL_HashString, - PL_CompareStrings, PL_CompareValues, - &lfdset_hashallocops, NULL); - if (!libraries) { - tmstats.btmalloc_failures++; - goto fail; - } - } - hash = PL_HashString(details.library); - hep = PL_HashTableRawLookup(libraries, hash, details.library); - he = *hep; - if (he) { - library = (char*) he->key; - library_serial = (uint32_t) NS_PTR_TO_INT32(he->value); - le = (lfdset_entry *) he; - if (LFD_TEST(fp->lfd, &le->lfdset)) { - /* We already logged an event on fp for this library. */ - le = NULL; - } - } else { - library = strdup(details.library); - if (library) { - library_serial = ++library_serial_generator; - he = PL_HashTableRawAdd(libraries, hep, hash, library, - NS_INT32_TO_PTR(library_serial)); - } - if (!he) { - tmstats.btmalloc_failures++; - goto fail; - } - le = (lfdset_entry *) he; - } - if (le) { - /* Need to log an event to fp for this lib. */ - slash = strrchr(library, '/'); - log_event1(fp, TM_EVENT_LIBRARY, library_serial); - log_string(fp, slash ? slash + 1 : library); - LFD_SET(fp->lfd, &le->lfdset); - } - } - - /* For compatibility with current log format, always emit a - * filename trace record, using "noname" / 0 when no file name - * is available. */ - filename_serial = 0; - filename = details.filename[0] ? details.filename : "noname"; - if (!filenames) { - filenames = PL_NewHashTable(100, PL_HashString, - PL_CompareStrings, PL_CompareValues, - &lfdset_hashallocops, NULL); - if (!filenames) { - tmstats.btmalloc_failures++; - return NULL; - } - } - hash = PL_HashString(filename); - hep = PL_HashTableRawLookup(filenames, hash, filename); - he = *hep; - if (he) { - filename = (char*) he->key; - filename_serial = (uint32_t) NS_PTR_TO_INT32(he->value); - le = (lfdset_entry *) he; - if (LFD_TEST(fp->lfd, &le->lfdset)) { - /* We already logged an event on fp for this filename. */ - le = NULL; - } - } else { - filename = strdup(filename); - if (filename) { - filename_serial = ++filename_serial_generator; - he = PL_HashTableRawAdd(filenames, hep, hash, filename, - NS_INT32_TO_PTR(filename_serial)); - } - if (!he) { - tmstats.btmalloc_failures++; - return NULL; - } - le = (lfdset_entry *) he; - } - if (le) { - /* Need to log an event to fp for this filename. */ - log_event1(fp, TM_EVENT_FILENAME, filename_serial); - log_filename(fp, filename); - LFD_SET(fp->lfd, &le->lfdset); - } - - if (!details.function[0]) { - PR_snprintf(details.function, sizeof(details.function), - "%s+%X", library ? library : "main", details.loffset); - } - - /* Emit an 'N' (for New method, 'M' is for malloc!) event if needed. */ - method_serial = 0; - if (!methods) { - methods = PL_NewHashTable(10000, PL_HashString, - PL_CompareStrings, PL_CompareValues, - &lfdset_hashallocops, NULL); - if (!methods) { - tmstats.btmalloc_failures++; - goto fail; - } - } - hash = PL_HashString(details.function); - hep = PL_HashTableRawLookup(methods, hash, details.function); - he = *hep; - if (he) { - method = (char*) he->key; - method_serial = (uint32_t) NS_PTR_TO_INT32(he->value); - le = (lfdset_entry *) he; - if (LFD_TEST(fp->lfd, &le->lfdset)) { - /* We already logged an event on fp for this method. */ - le = NULL; - } - } else { - method = strdup(details.function); - if (method) { - method_serial = ++method_serial_generator; - he = PL_HashTableRawAdd(methods, hep, hash, method, - NS_INT32_TO_PTR(method_serial)); - } - if (!he) { - tmstats.btmalloc_failures++; - return NULL; - } - le = (lfdset_entry *) he; - } - if (le) { - log_event4(fp, TM_EVENT_METHOD, method_serial, library_serial, - filename_serial, details.lineno); - log_string(fp, method); - LFD_SET(fp->lfd, &le->lfdset); - } - - /* Create a new callsite record. */ - if (!site) { - site = __libc_malloc(sizeof(callsite)); - if (!site) { - tmstats.btmalloc_failures++; - goto fail; - } - - /* Update parent and max-kids-per-parent stats. */ - if (!parent->kids) - tmstats.calltree_parents++; - nkids = 1; - for (tmp = parent->kids; tmp; tmp = tmp->siblings) - nkids++; - if (nkids > tmstats.calltree_maxkids) { - tmstats.calltree_maxkids = nkids; - calltree_maxkids_parent = parent; - } - - /* Insert the new site into the tree. */ - site->pc = pc; - site->serial = ++callsite_serial_generator; - LFD_ZERO(&site->lfdset); - site->name = method; - site->library = library; - site->offset = details.loffset; - site->parent = parent; - site->siblings = parent->kids; - parent->kids = site; - site->kids = NULL; - } - - /* Log the site with its parent, method, and offset. */ - log_event4(fp, TM_EVENT_CALLSITE, site->serial, parent->serial, - method_serial, details.foffset); - LFD_SET(fp->lfd, &site->lfdset); - - upward: - parent = site; - } while (stack_index > 0); - - if (maxstack) - calltree_maxstack_top = site; - - return site; - - fail: - return NULL; -} - -/* - * Buffer the stack from top at low index to bottom at high, so that we can - * reverse it in calltree. - */ -static void -stack_callback(uint32_t frameNumber, void *pc, void *sp, void *closure) -{ - stack_buffer_info *info = (stack_buffer_info*) closure; - - /* - * If we run out of buffer, keep incrementing entries so that - * backtrace can call us again with a bigger buffer. - */ - if (info->entries < info->size) - info->buffer[info->entries] = pc; - ++info->entries; -} - -/* - * The caller MUST NOT be holding tmlock when calling backtrace. - * On return, if *immediate_abort is set, then the return value is NULL - * and the thread is in a very dangerous situation (e.g. holding - * sem_pool_lock in Mac OS X pthreads); the caller should bail out - * without doing anything (such as acquiring locks). - */ -static callsite * -backtrace(tm_thread *t, int skipFrames, int *immediate_abort) -{ - callsite *site; - stack_buffer_info *info = &t->backtrace_buf; - void ** new_stack_buffer; - size_t new_stack_buffer_size; - nsresult rv; - - t->suppress_tracing++; - - if (!stacks_enabled) { -#if defined(XP_MACOSX) - /* Walk the stack, even if stacks_enabled is false. We do this to - check if we must set immediate_abort. */ - info->entries = 0; - rv = NS_StackWalk(stack_callback, skipFrames, /* maxFrames */ 0, info, - 0, NULL); - *immediate_abort = rv == NS_ERROR_UNEXPECTED; - if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) { - t->suppress_tracing--; - return NULL; - } -#endif - - /* - * Create a single fake stack frame so that all the tools get - * data in the correct format. - */ - *immediate_abort = 0; - if (info->size < 1) { - PR_ASSERT(!info->buffer); /* !info->size == !info->buffer */ - info->buffer = __libc_malloc(1 * sizeof(void*)); - if (!info->buffer) - return NULL; - info->size = 1; - } - - info->entries = 1; - info->buffer[0] = STACK_DISABLED_PC; - } else { - /* - * NS_StackWalk can (on Windows) acquire a lock the shared library - * loader. Another thread might call malloc while holding that lock - * (when loading a shared library). So we can't be in tmlock during - * this call. For details, see - * https://bugzilla.mozilla.org/show_bug.cgi?id=374829#c8 - */ - - /* - * skipFrames == 0 means |backtrace| should show up, so don't use - * skipFrames + 1. - * NB: this call is repeated below if the buffer is too small. - */ - info->entries = 0; - rv = NS_StackWalk(stack_callback, skipFrames, /* maxFrames */ 0, info, - 0, NULL); - *immediate_abort = rv == NS_ERROR_UNEXPECTED; - if (rv == NS_ERROR_UNEXPECTED || info->entries == 0) { - t->suppress_tracing--; - return NULL; - } - - /* - * To avoid allocating in stack_callback (which, on Windows, is - * called on a different thread from the one we're running on here), - * reallocate here if it didn't have a big enough buffer (which - * includes the first call on any thread), and call it again. - */ - if (info->entries > info->size) { - new_stack_buffer_size = 2 * info->entries; - new_stack_buffer = __libc_realloc(info->buffer, - new_stack_buffer_size * sizeof(void*)); - if (!new_stack_buffer) - return NULL; - info->buffer = new_stack_buffer; - info->size = new_stack_buffer_size; - - /* and call NS_StackWalk again */ - info->entries = 0; - NS_StackWalk(stack_callback, skipFrames, /* maxFrames */ 0, info, - 0, NULL); - - /* same stack */ - PR_ASSERT(info->entries * 2 == new_stack_buffer_size); - } - } - - TM_ENTER_LOCK(t); - - site = calltree(info->buffer, info->entries, t); - - tmstats.backtrace_calls++; - if (!site) { - tmstats.backtrace_failures++; - PR_ASSERT(tmstats.backtrace_failures < 100); - } - TM_EXIT_LOCK(t); - - t->suppress_tracing--; - return site; -} - -typedef struct allocation { - PLHashEntry entry; - size_t size; - FILE *trackfp; /* for allocation tracking */ -} allocation; - -#define ALLOC_HEAP_SIZE 150000 - -static allocation alloc_heap[ALLOC_HEAP_SIZE]; -static allocation *alloc_freelist = NULL; -static int alloc_heap_initialized = 0; - -static PLHashEntry *alloc_allocentry(void *pool, const void *key) -{ - allocation **listp, *alloc; - int n; - - if (!alloc_heap_initialized) { - n = ALLOC_HEAP_SIZE; - listp = &alloc_freelist; - for (alloc = alloc_heap; --n >= 0; alloc++) { - *listp = alloc; - listp = (allocation**) &alloc->entry.next; - } - *listp = NULL; - alloc_heap_initialized = 1; - } - - listp = &alloc_freelist; - alloc = *listp; - if (!alloc) - return __libc_malloc(sizeof(allocation)); - *listp = (allocation*) alloc->entry.next; - return &alloc->entry; -} - -static void alloc_freeentry(void *pool, PLHashEntry *he, unsigned flag) -{ - allocation *alloc; - - if (flag != HT_FREE_ENTRY) - return; - alloc = (allocation*) he; - if ((ptrdiff_t)(alloc - alloc_heap) < (ptrdiff_t)ALLOC_HEAP_SIZE) { - alloc->entry.next = &alloc_freelist->entry; - alloc_freelist = alloc; - } else { - __libc_free((void*) alloc); - } -} - -static PLHashAllocOps alloc_hashallocops = { - generic_alloctable, generic_freetable, - alloc_allocentry, alloc_freeentry -}; - -static PLHashNumber hash_pointer(const void *key) -{ - return (PLHashNumber) key; -} - -static PLHashTable *allocations = NULL; - -static PLHashTable *new_allocations(void) -{ - allocations = PL_NewHashTable(200000, hash_pointer, - PL_CompareValues, PL_CompareValues, - &alloc_hashallocops, NULL); - return allocations; -} - -#define get_allocations() (allocations ? allocations : new_allocations()) - -#if defined(XP_MACOSX) - -/* from malloc.c in Libc */ -typedef void -malloc_logger_t(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, - uintptr_t result, uint32_t num_hot_frames_to_skip); - -extern malloc_logger_t *malloc_logger; - -#define MALLOC_LOG_TYPE_ALLOCATE 2 -#define MALLOC_LOG_TYPE_DEALLOCATE 4 -#define MALLOC_LOG_TYPE_HAS_ZONE 8 -#define MALLOC_LOG_TYPE_CLEARED 64 - -static void -my_malloc_logger(uint32_t type, uintptr_t arg1, uintptr_t arg2, uintptr_t arg3, - uintptr_t result, uint32_t num_hot_frames_to_skip) -{ - uintptr_t all_args[3] = { arg1, arg2, arg3 }; - uintptr_t *args = all_args + ((type & MALLOC_LOG_TYPE_HAS_ZONE) ? 1 : 0); - - uint32_t alloc_type = - type & (MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_DEALLOCATE); - tm_thread *t = tm_get_thread(); - - if (alloc_type == (MALLOC_LOG_TYPE_ALLOCATE | MALLOC_LOG_TYPE_DEALLOCATE)) { - ReallocCallback((void*)args[0], (void*)result, args[1], 0, 0, t); - } else if (alloc_type == MALLOC_LOG_TYPE_ALLOCATE) { - /* - * We don't get size/count information for calloc, so just use - * MallocCallback. - */ - MallocCallback((void*)result, args[0], 0, 0, t); - } else if (alloc_type == MALLOC_LOG_TYPE_DEALLOCATE) { - FreeCallback((void*)args[0], 0, 0, t); - } -} - -static void -StartupHooker(void) -{ - PR_ASSERT(!malloc_logger); - malloc_logger = my_malloc_logger; -} - -static void -ShutdownHooker(void) -{ - PR_ASSERT(malloc_logger == my_malloc_logger); - malloc_logger = NULL; -} - -#elif defined(XP_UNIX) - -/* - * We can't use glibc's malloc hooks because they can't be used in a - * threadsafe manner. They require unsetting the hooks to call into the - * original malloc implementation, and then resetting them when the - * original implementation returns. If another thread calls the same - * allocation function while the hooks are unset, we have no chance to - * intercept the call. - */ - -NS_EXTERNAL_VIS_(__ptr_t) -malloc(size_t size) -{ - uint32_t start, end; - __ptr_t ptr; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_malloc(size); - } - - t->suppress_tracing++; - start = PR_IntervalNow(); - ptr = __libc_malloc(size); - end = PR_IntervalNow(); - t->suppress_tracing--; - - MallocCallback(ptr, size, start, end, t); - - return ptr; -} - -NS_EXTERNAL_VIS_(__ptr_t) -calloc(size_t count, size_t size) -{ - uint32_t start, end; - __ptr_t ptr; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_calloc(count, size); - } - - t->suppress_tracing++; - start = PR_IntervalNow(); - ptr = __libc_calloc(count, size); - end = PR_IntervalNow(); - t->suppress_tracing--; - - CallocCallback(ptr, count, size, start, end, t); - - return ptr; -} - -NS_EXTERNAL_VIS_(__ptr_t) -realloc(__ptr_t oldptr, size_t size) -{ - uint32_t start, end; - __ptr_t ptr; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_realloc(oldptr, size); - } - - t->suppress_tracing++; - start = PR_IntervalNow(); - ptr = __libc_realloc(oldptr, size); - end = PR_IntervalNow(); - t->suppress_tracing--; - - /* FIXME bug 392008: We could race with reallocation of oldptr. */ - ReallocCallback(oldptr, ptr, size, start, end, t); - - return ptr; -} - -NS_EXTERNAL_VIS_(void*) -valloc(size_t size) -{ - uint32_t start, end; - __ptr_t ptr; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_valloc(size); - } - - t->suppress_tracing++; - start = PR_IntervalNow(); - ptr = __libc_valloc(size); - end = PR_IntervalNow(); - t->suppress_tracing--; - - MallocCallback(ptr, size, start, end, t); - - return ptr; -} - -NS_EXTERNAL_VIS_(void*) -memalign(size_t boundary, size_t size) -{ - uint32_t start, end; - __ptr_t ptr; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - return __libc_memalign(boundary, size); - } - - t->suppress_tracing++; - start = PR_IntervalNow(); - ptr = __libc_memalign(boundary, size); - end = PR_IntervalNow(); - t->suppress_tracing--; - - MallocCallback(ptr, size, start, end, t); - - return ptr; -} - -NS_EXTERNAL_VIS_(int) -posix_memalign(void **memptr, size_t alignment, size_t size) -{ - __ptr_t ptr = memalign(alignment, size); - if (!ptr) - return ENOMEM; - *memptr = ptr; - return 0; -} - -NS_EXTERNAL_VIS_(void) -free(__ptr_t ptr) -{ - uint32_t start, end; - tm_thread *t; - - if (!tracing_enabled || !PR_Initialized() || - (t = tm_get_thread())->suppress_tracing != 0) { - __libc_free(ptr); - return; - } - - t->suppress_tracing++; - start = PR_IntervalNow(); - __libc_free(ptr); - end = PR_IntervalNow(); - t->suppress_tracing--; - - /* FIXME bug 392008: We could race with reallocation of ptr. */ - - FreeCallback(ptr, start, end, t); -} - -NS_EXTERNAL_VIS_(void) -cfree(void *ptr) -{ - free(ptr); -} - -#define StartupHooker() PR_BEGIN_MACRO PR_END_MACRO -#define ShutdownHooker() PR_BEGIN_MACRO PR_END_MACRO - -#elif defined(XP_WIN32) - -/* See nsWinTraceMalloc.cpp. */ - -#endif - -static const char magic[] = NS_TRACE_MALLOC_MAGIC; - -static void -log_header(int logfd) -{ - uint32_t ticksPerSec = PR_htonl(PR_TicksPerSecond()); - (void) write(logfd, magic, NS_TRACE_MALLOC_MAGIC_SIZE); - (void) write(logfd, &ticksPerSec, sizeof ticksPerSec); -} - -PR_IMPLEMENT(void) -NS_TraceMallocStartup(int logfd) -{ - const char* stack_disable_env; - - /* We must be running on the primordial thread. */ - PR_ASSERT(tracing_enabled == 0); - PR_ASSERT(logfp == &default_logfile); - tracing_enabled = (logfd >= 0); - - if (logfd >= 3) - MozillaRegisterDebugFD(logfd); - - /* stacks are disabled if this env var is set to a non-empty value */ - stack_disable_env = PR_GetEnv("NS_TRACE_MALLOC_DISABLE_STACKS"); - stacks_enabled = !stack_disable_env || !*stack_disable_env; - - if (tracing_enabled) { - PR_ASSERT(logfp->simsize == 0); /* didn't overflow startup buffer */ - - /* Log everything in logfp (aka default_logfile)'s buffer to logfd. */ - logfp->fd = logfd; - logfile_list = &default_logfile; - logfp->prevp = &logfile_list; - logfile_tail = &logfp->next; - log_header(logfd); - } - - RegisterTraceMallocShutdown(); - - tmlock = PR_NewLock(); - (void) tm_get_thread(); /* ensure index initialization while it's easy */ - - if (tracing_enabled) - StartupHooker(); -} - -/* - * Options for log files, with the log file name either as the next option - * or separated by '=' (e.g. "./mozilla --trace-malloc * malloc.log" or - * "./mozilla --trace-malloc=malloc.log"). - */ -static const char TMLOG_OPTION[] = "--trace-malloc"; -static const char SDLOG_OPTION[] = "--shutdown-leaks"; - -#define SHOULD_PARSE_ARG(name_, log_, arg_) \ - (0 == strncmp(arg_, name_, sizeof(name_) - 1)) - -#define PARSE_ARG(name_, log_, argv_, i_, consumed_) \ - PR_BEGIN_MACRO \ - char _nextchar = argv_[i_][sizeof(name_) - 1]; \ - if (_nextchar == '=') { \ - log_ = argv_[i_] + sizeof(name_); \ - consumed_ = 1; \ - } else if (_nextchar == '\0') { \ - log_ = argv_[i_+1]; \ - consumed_ = 2; \ - } \ - PR_END_MACRO - -PR_IMPLEMENT(int) -NS_TraceMallocStartupArgs(int argc, char **argv) -{ - int i, logfd = -1, consumed, logflags; - char *tmlogname = NULL, *sdlogname_local = NULL; - - /* - * Look for the --trace-malloc option early, to avoid missing - * early mallocs (we miss static constructors whose output overflows the - * log file's static 16K output buffer). - */ - for (i = 1; i < argc; i += consumed) { - consumed = 0; - if (SHOULD_PARSE_ARG(TMLOG_OPTION, tmlogname, argv[i])) - PARSE_ARG(TMLOG_OPTION, tmlogname, argv, i, consumed); - else if (SHOULD_PARSE_ARG(SDLOG_OPTION, sdlogname_local, argv[i])) - PARSE_ARG(SDLOG_OPTION, sdlogname_local, argv, i, consumed); - - if (consumed) { -#ifndef XP_WIN32 /* If we don't comment this out, it will crash Windows. */ - int j; - /* Now remove --trace-malloc and its argument from argv. */ - argc -= consumed; - for (j = i; j < argc; ++j) - argv[j] = argv[j+consumed]; - argv[argc] = NULL; - consumed = 0; /* don't advance next iteration */ -#endif - } else { - consumed = 1; - } - } - - if (tmlogname) { -#ifdef XP_UNIX - int pipefds[2]; -#endif - - switch (*tmlogname) { -#ifdef XP_UNIX - case '|': - if (pipe(pipefds) == 0) { - pid_t pid = fork(); - if (pid == 0) { - /* In child: set up stdin, parse args, and exec. */ - int maxargc, nargc; - char **nargv, *token; - - if (pipefds[0] != 0) { - dup2(pipefds[0], 0); - close(pipefds[0]); - } - close(pipefds[1]); - - tmlogname = strtok(tmlogname + 1, " \t"); - maxargc = 3; - nargv = (char **) malloc((maxargc+1) * sizeof(char *)); - if (!nargv) exit(1); - nargc = 0; - nargv[nargc++] = tmlogname; - while ((token = strtok(NULL, " \t")) != NULL) { - if (nargc == maxargc) { - maxargc *= 2; - nargv = (char**) - realloc(nargv, (maxargc+1) * sizeof(char*)); - if (!nargv) exit(1); - } - nargv[nargc++] = token; - } - nargv[nargc] = NULL; - - (void) setsid(); - execvp(tmlogname, nargv); - exit(127); - } - - if (pid > 0) { - /* In parent: set logfd to the pipe's write side. */ - close(pipefds[0]); - logfd = pipefds[1]; - } - } - if (logfd < 0) { - fprintf(stderr, - "%s: can't pipe to trace-malloc child process %s: %s\n", - argv[0], tmlogname, strerror(errno)); - exit(1); - } - break; -#endif /*XP_UNIX*/ - case '-': - /* Don't log from startup, but do prepare to log later. */ - /* XXX traditional meaning of '-' as option argument is "stdin" or "stdout" */ - if (tmlogname[1] == '\0') - break; - /* FALL THROUGH */ - - default: - logflags = O_CREAT | O_WRONLY | O_TRUNC; -#if defined(XP_WIN32) - /* - * Avoid translations on WIN32. - */ - logflags |= O_BINARY; -#endif - logfd = open(tmlogname, logflags, 0644); - if (logfd < 0) { - fprintf(stderr, - "%s: can't create trace-malloc log named %s: %s\n", - argv[0], tmlogname, strerror(errno)); - exit(1); - } - break; - } - } - - if (sdlogname_local) { - strncpy(sdlogname, sdlogname_local, sizeof(sdlogname)); - sdlogname[sizeof(sdlogname) - 1] = '\0'; - } - - NS_TraceMallocStartup(logfd); - return argc; -} - -PR_IMPLEMENT(PRBool) -NS_TraceMallocHasStarted(void) -{ - return tmlock ? PR_TRUE : PR_FALSE; -} - -PR_IMPLEMENT(void) -NS_TraceMallocShutdown(void) -{ - logfile *fp; - - if (sdlogname[0]) - NS_TraceMallocDumpAllocations(sdlogname); - - if (tmstats.backtrace_failures) { - fprintf(stderr, - "TraceMalloc backtrace failures: %lu (malloc %lu dladdr %lu)\n", - (unsigned long) tmstats.backtrace_failures, - (unsigned long) tmstats.btmalloc_failures, - (unsigned long) tmstats.dladdr_failures); - } - while ((fp = logfile_list) != NULL) { - logfile_list = fp->next; - log_tmstats(fp); - flush_logfile(fp); - if (fp->fd >= 0) { - MozillaUnRegisterDebugFD(fp->fd); - close(fp->fd); - fp->fd = -1; - } - if (fp != &default_logfile) { - if (fp == logfp) - logfp = &default_logfile; - free((void*) fp); - } - } - if (tmlock) { - PRLock *lock = tmlock; - tmlock = NULL; - PR_DestroyLock(lock); - } - if (tracing_enabled) { - tracing_enabled = 0; - ShutdownHooker(); - } -} - -PR_IMPLEMENT(void) -NS_TraceMallocDisable(void) -{ - tm_thread *t = tm_get_thread(); - logfile *fp; - uint32_t sample; - - /* Robustify in case of duplicate call. */ - PR_ASSERT(tracing_enabled); - if (tracing_enabled == 0) - return; - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - for (fp = logfile_list; fp; fp = fp->next) - flush_logfile(fp); - sample = --tracing_enabled; - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); - if (sample == 0) - ShutdownHooker(); -} - -PR_IMPLEMENT(void) -NS_TraceMallocEnable(void) -{ - tm_thread *t = tm_get_thread(); - uint32_t sample; - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - sample = ++tracing_enabled; - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); - if (sample == 1) - StartupHooker(); -} - -PR_IMPLEMENT(int) -NS_TraceMallocChangeLogFD(int fd) -{ - logfile *oldfp, *fp; - struct stat sb; - tm_thread *t = tm_get_thread(); - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - oldfp = logfp; - if (oldfp->fd != fd) { - flush_logfile(oldfp); - fp = get_logfile(fd); - if (!fp) { - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); - return -2; - } - if (fd >= 0 && fstat(fd, &sb) == 0 && sb.st_size == 0) - log_header(fd); - logfp = fp; - } - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); - return oldfp->fd; -} - -static int -lfd_clr_enumerator(PLHashEntry *he, int i, void *arg) -{ - lfdset_entry *le = (lfdset_entry*) he; - logfile *fp = (logfile*) arg; - - LFD_CLR(fp->lfd, &le->lfdset); - return HT_ENUMERATE_NEXT; -} - -static void -lfd_clr_walk(callsite *site, logfile *fp) -{ - callsite *kid; - - LFD_CLR(fp->lfd, &site->lfdset); - for (kid = site->kids; kid; kid = kid->siblings) - lfd_clr_walk(kid, fp); -} - -PR_IMPLEMENT(void) -NS_TraceMallocCloseLogFD(int fd) -{ - logfile *fp; - tm_thread *t = tm_get_thread(); - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - - fp = get_logfile(fd); - if (fp) { - flush_logfile(fp); - if (fp == &default_logfile) { - /* Leave default_logfile in logfile_list with an fd of -1. */ - fp->fd = -1; - - /* NB: we can never free lfd 0, it belongs to default_logfile. */ - PR_ASSERT(fp->lfd == 0); - } else { - /* Clear fp->lfd in all possible lfdsets. */ - PL_HashTableEnumerateEntries(libraries, lfd_clr_enumerator, fp); - PL_HashTableEnumerateEntries(methods, lfd_clr_enumerator, fp); - lfd_clr_walk(&calltree_root, fp); - - /* Unlink fp from logfile_list, freeing lfd for reallocation. */ - *fp->prevp = fp->next; - if (!fp->next) { - PR_ASSERT(logfile_tail == &fp->next); - logfile_tail = fp->prevp; - } - - /* Reset logfp if we must, then free fp. */ - if (fp == logfp) - logfp = &default_logfile; - free((void*) fp); - } - } - - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); - MozillaUnRegisterDebugFD(fd); - close(fd); -} - -PR_IMPLEMENT(void) -NS_TraceMallocLogTimestamp(const char *caption) -{ - logfile *fp; -#ifdef XP_UNIX - struct timeval tv; -#endif -#ifdef XP_WIN32 - struct _timeb tb; -#endif - tm_thread *t = tm_get_thread(); - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - - fp = logfp; - log_byte(fp, TM_EVENT_TIMESTAMP); - -#ifdef XP_UNIX - gettimeofday(&tv, NULL); - log_uint32(fp, (uint32_t) tv.tv_sec); - log_uint32(fp, (uint32_t) tv.tv_usec); -#endif -#ifdef XP_WIN32 - _ftime(&tb); - log_uint32(fp, (uint32_t) tb.time); - log_uint32(fp, (uint32_t) tb.millitm); -#endif - log_string(fp, caption); - - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -static void -print_stack(FILE *ofp, callsite *site) -{ - while (site) { - if (site->name || site->parent) { - fprintf(ofp, "%s[%s +0x%X]\n", - site->name, site->library, site->offset); - } - site = site->parent; - } -} - -static const char *allocation_format = - (sizeof(void*) == 4) ? "\t0x%08zX\n" : - (sizeof(void*) == 8) ? "\t0x%016zX\n" : - "UNEXPECTED sizeof(void*)"; - -static int -allocation_enumerator(PLHashEntry *he, int i, void *arg) -{ - allocation *alloc = (allocation*) he; - FILE *ofp = (FILE*) arg; - callsite *site = (callsite*) he->value; - - size_t *p, *end; - - fprintf(ofp, "%p <%s> (%lu)\n", - he->key, - nsGetTypeName(he->key), - (unsigned long) alloc->size); - - for (p = (size_t*) he->key, - end = (size_t*) ((char*)he->key + alloc->size); - p < end; ++p) { - fprintf(ofp, allocation_format, *p); - } - - print_stack(ofp, site); - fputc('\n', ofp); - return HT_ENUMERATE_NEXT; -} - -PR_IMPLEMENT(void) -NS_TraceStack(int skip, FILE *ofp) -{ - callsite *site; - tm_thread *t = tm_get_thread(); - int immediate_abort; - - site = backtrace(t, skip + 1, &immediate_abort); - while (site) { - if (site->name || site->parent) { - fprintf(ofp, "%s[%s +0x%X]\n", - site->name, site->library, site->offset); - } - site = site->parent; - } -} - -PR_IMPLEMENT(int) -NS_TraceMallocDumpAllocations(const char *pathname) -{ - FILE *ofp; - int rv; - int fd; - - tm_thread *t = tm_get_thread(); - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - - ofp = fopen(pathname, WRITE_FLAGS); - if (ofp) { - MozillaRegisterDebugFD(fileno(ofp)); - if (allocations) { - PL_HashTableEnumerateEntries(allocations, allocation_enumerator, - ofp); - } - rv = ferror(ofp) ? -1 : 0; - MozillaUnRegisterDebugFILE(ofp); - fclose(ofp); - } else { - rv = -1; - } - - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); - - return rv; -} - -PR_IMPLEMENT(void) -NS_TraceMallocFlushLogfiles(void) -{ - logfile *fp; - tm_thread *t = tm_get_thread(); - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - - for (fp = logfile_list; fp; fp = fp->next) - flush_logfile(fp); - - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -PR_IMPLEMENT(void) -NS_TrackAllocation(void* ptr, FILE *ofp) -{ - allocation *alloc; - tm_thread *t = tm_get_thread(); - - fprintf(ofp, "Trying to track %p\n", (void*) ptr); - setlinebuf(ofp); - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - if (get_allocations()) { - alloc = (allocation*) - *PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr); - if (alloc) { - fprintf(ofp, "Tracking %p\n", (void*) ptr); - alloc->trackfp = ofp; - } else { - fprintf(ofp, "Not tracking %p\n", (void*) ptr); - } - } - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -PR_IMPLEMENT(void) -MallocCallback(void *ptr, size_t size, uint32_t start, uint32_t end, tm_thread *t) -{ - callsite *site; - PLHashEntry *he; - allocation *alloc; - int immediate_abort; - - if (!tracing_enabled || t->suppress_tracing != 0) - return; - - site = backtrace(t, 2, &immediate_abort); - if (immediate_abort) - return; - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - tmstats.malloc_calls++; - if (!ptr) { - tmstats.malloc_failures++; - } else { - if (site) { - log_event5(logfp, TM_EVENT_MALLOC, - site->serial, start, end - start, - (uint32_t)NS_PTR_TO_INT32(ptr), size); - } - if (get_allocations()) { - he = PL_HashTableAdd(allocations, ptr, site); - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = NULL; - } - } - } - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -PR_IMPLEMENT(void) -CallocCallback(void *ptr, size_t count, size_t size, uint32_t start, uint32_t end, tm_thread *t) -{ - callsite *site; - PLHashEntry *he; - allocation *alloc; - int immediate_abort; - - if (!tracing_enabled || t->suppress_tracing != 0) - return; - - site = backtrace(t, 2, &immediate_abort); - if (immediate_abort) - return; - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - tmstats.calloc_calls++; - if (!ptr) { - tmstats.calloc_failures++; - } else { - size *= count; - if (site) { - log_event5(logfp, TM_EVENT_CALLOC, - site->serial, start, end - start, - (uint32_t)NS_PTR_TO_INT32(ptr), size); - } - if (get_allocations()) { - he = PL_HashTableAdd(allocations, ptr, site); - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = NULL; - } - } - } - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -PR_IMPLEMENT(void) -ReallocCallback(void * oldptr, void *ptr, size_t size, - uint32_t start, uint32_t end, tm_thread *t) -{ - callsite *oldsite, *site; - size_t oldsize; - PLHashNumber hash; - PLHashEntry **hep, *he; - allocation *alloc; - FILE *trackfp = NULL; - int immediate_abort; - - if (!tracing_enabled || t->suppress_tracing != 0) - return; - - site = backtrace(t, 2, &immediate_abort); - if (immediate_abort) - return; - - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - tmstats.realloc_calls++; - oldsite = NULL; - oldsize = 0; - hep = NULL; - he = NULL; - if (oldptr && get_allocations()) { - hash = hash_pointer(oldptr); - hep = PL_HashTableRawLookup(allocations, hash, oldptr); - he = *hep; - if (he) { - oldsite = (callsite*) he->value; - alloc = (allocation*) he; - oldsize = alloc->size; - trackfp = alloc->trackfp; - if (trackfp) { - fprintf(alloc->trackfp, - "\nrealloc(%p, %lu), oldsize %lu, alloc site %p\n", - (void*) ptr, (unsigned long) size, - (unsigned long) oldsize, (void*) oldsite); - NS_TraceStack(1, trackfp); - } - } - } - if (!ptr && size) { - /* - * When realloc() fails, the original block is not freed or moved, so - * we'll leave the allocation entry untouched. - */ - tmstats.realloc_failures++; - } else { - if (site) { - log_event8(logfp, TM_EVENT_REALLOC, - site->serial, start, end - start, - (uint32_t)NS_PTR_TO_INT32(ptr), size, - oldsite ? oldsite->serial : 0, - (uint32_t)NS_PTR_TO_INT32(oldptr), oldsize); - } - if (ptr && allocations) { - if (ptr != oldptr) { - /* - * If we're reallocating (not allocating new space by passing - * null to realloc) and realloc moved the block, free oldptr. - */ - if (he) - PL_HashTableRawRemove(allocations, hep, he); - - /* Record the new allocation now, setting he. */ - he = PL_HashTableAdd(allocations, ptr, site); - } else { - /* - * If we haven't yet recorded an allocation (possibly due to a - * temporary memory shortage), do it now. - */ - if (!he) - he = PL_HashTableAdd(allocations, ptr, site); - } - if (he) { - alloc = (allocation*) he; - alloc->size = size; - alloc->trackfp = trackfp; - } - } - } - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -PR_IMPLEMENT(void) -FreeCallback(void * ptr, uint32_t start, uint32_t end, tm_thread *t) -{ - PLHashEntry **hep, *he; - callsite *site; - allocation *alloc; - - if (!tracing_enabled || t->suppress_tracing != 0) - return; - - /* - * FIXME: Perhaps we should call backtrace() so we can check for - * immediate_abort. However, the only current contexts where - * immediate_abort will be true do not call free(), so for now, - * let's avoid the cost of backtrace(). See bug 478195. - */ - TM_SUPPRESS_TRACING_AND_ENTER_LOCK(t); - tmstats.free_calls++; - if (!ptr) { - tmstats.null_free_calls++; - } else { - if (get_allocations()) { - hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr); - he = *hep; - if (he) { - site = (callsite*) he->value; - if (site) { - alloc = (allocation*) he; - if (alloc->trackfp) { - fprintf(alloc->trackfp, "\nfree(%p), alloc site %p\n", - (void*) ptr, (void*) site); - NS_TraceStack(1, alloc->trackfp); - } - log_event5(logfp, TM_EVENT_FREE, - site->serial, start, end - start, - (uint32_t)NS_PTR_TO_INT32(ptr), alloc->size); - } - PL_HashTableRawRemove(allocations, hep, he); - } - } - } - TM_EXIT_LOCK_AND_UNSUPPRESS_TRACING(t); -} - -PR_IMPLEMENT(nsTMStackTraceID) -NS_TraceMallocGetStackTrace(void) -{ - callsite *site; - int dummy; - tm_thread *t = tm_get_thread(); - - PR_ASSERT(t->suppress_tracing == 0); - - site = backtrace(t, 2, &dummy); - return (nsTMStackTraceID) site; -} - -PR_IMPLEMENT(void) -NS_TraceMallocPrintStackTrace(FILE *ofp, nsTMStackTraceID id) -{ - print_stack(ofp, (callsite *)id); -} - -#endif /* NS_TRACE_MALLOC */ diff --git a/tools/trace-malloc/lib/nsTraceMalloc.h b/tools/trace-malloc/lib/nsTraceMalloc.h deleted file mode 100644 index 4d1a89214a91..000000000000 --- a/tools/trace-malloc/lib/nsTraceMalloc.h +++ /dev/null @@ -1,226 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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 nsTraceMalloc_h___ -#define nsTraceMalloc_h___ - -#include -#include /* for FILE */ -#include "prtypes.h" - -#ifdef XP_WIN -#define setlinebuf(stream) setvbuf((stream), (char *)NULL, _IOLBF, 0) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Magic "number" at start of a trace-malloc log file. Inspired by the PNG - * magic string, which inspired XPCOM's typelib (.xpt) file magic. See the - * NS_TraceMallocStartup comment (below) for magic number differences in log - * file structure. - */ -#define NS_TRACE_MALLOC_MAGIC "XPCOM\nTMLog08\r\n\032" -#define NS_TRACE_MALLOC_MAGIC_SIZE 16 - -/** - * Trace-malloc stats, traced via the 'Z' event at the end of a log file. - */ -typedef struct nsTMStats { - uint32_t calltree_maxstack; - uint32_t calltree_maxdepth; - uint32_t calltree_parents; - uint32_t calltree_maxkids; - uint32_t calltree_kidhits; - uint32_t calltree_kidmisses; - uint32_t calltree_kidsteps; - uint32_t callsite_recurrences; - uint32_t backtrace_calls; - uint32_t backtrace_failures; - uint32_t btmalloc_failures; - uint32_t dladdr_failures; - uint32_t malloc_calls; - uint32_t malloc_failures; - uint32_t calloc_calls; - uint32_t calloc_failures; - uint32_t realloc_calls; - uint32_t realloc_failures; - uint32_t free_calls; - uint32_t null_free_calls; -} nsTMStats; - -#define NS_TMSTATS_STATIC_INITIALIZER {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} - -/** - * Call NS_TraceMallocStartup with a valid file descriptor to enable logging - * of compressed malloc traces, including callsite chains. Integers may be - * unsigned serial numbers, sizes, or offsets, and require at most 32 bits. - * They're encoded as follows: - * 0-127 0xxxxxxx (binary, one byte) - * 128-16383 10xxxxxx xxxxxxxx - * 16384-0x1fffff 110xxxxx xxxxxxxx xxxxxxxx - * 0x200000-0xfffffff 1110xxxx xxxxxxxx xxxxxxxx xxxxxxxx - * 0x10000000-0xffffffff 11110000 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx - * Strings are NUL-terminated ASCII. - * - * Event Operands (magic TMLog01) - * 'L' library serial, shared object filename string - * 'N' method serial, library serial, demangled name string - * 'S' site serial, parent serial, method serial, calling pc offset - * 'M' site serial, malloc size - * 'C' site serial, calloc size - * 'R' site serial, realloc oldsize, realloc size - * 'F' site serial, free size - * - * Event Operands (magic TMLog02) - * 'Z' serialized struct tmstats (20 unsigned integers), - * maxkids parent callsite serial, - * maxstack top callsite serial - * - * Event Operands (magic TMLog03) - * 'T' seconds, microseconds, caption - * - * Event Operands (magic TMLog04) - * 'R' site serial, realloc size, old site serial, realloc oldsize - * - * Event Operands (magic TMLog05) - * 'M' site serial, address, malloc size - * 'C' site serial, address, calloc size - * 'R' site serial, address, realloc size, old site serial, - * old address, old size - * 'F' site serial, address, free size - * - * Event Operands (magic TMLog06) - * 'M' site serial, interval time (end), address, malloc size - * 'C' site serial, interval time (end), address, calloc size - * 'R' site serial, interval time (end), address, realloc size, - * old site serial, old address, old size - * 'F' site serial, interval time (end), address, free size - * - * Event Operands (magic TMLog07) - * 'M' site serial, interval time (start), duration, address, malloc size - * 'C' site serial, interval time (start), duration, address, calloc size - * 'R' site serial, interval time (start), duration, address, realloc size, - * old site serial, old address, old size - * 'F' site serial, interval time (start), duration, address, free size - * - * Event Operands (magic TMLog08) - * 'G' filename serial, source filename string. - * 'N' method serial, library serial, source filename serial, - * source file linenumber, demangled name string - * - * See tools/trace-malloc/bloatblame.c for an example log-file reader. - */ -#define TM_EVENT_LIBRARY 'L' -#define TM_EVENT_FILENAME 'G' -#define TM_EVENT_METHOD 'N' -#define TM_EVENT_CALLSITE 'S' -#define TM_EVENT_MALLOC 'M' -#define TM_EVENT_CALLOC 'C' -#define TM_EVENT_REALLOC 'R' -#define TM_EVENT_FREE 'F' -#define TM_EVENT_STATS 'Z' -#define TM_EVENT_TIMESTAMP 'T' - -PR_EXTERN(void) NS_TraceMallocStartup(int logfd); - -/** - * Initialize malloc tracing, using the ``standard'' startup arguments. - */ -PR_EXTERN(int) NS_TraceMallocStartupArgs(int argc, char* argv[]); - -/** - * Return PR_TRUE iff |NS_TraceMallocStartup[Args]| has been successfully called. - */ -PR_EXTERN(PRBool) NS_TraceMallocHasStarted(void); - -/** - * Stop all malloc tracing, flushing any buffered events to the logfile. - */ -PR_EXTERN(void) NS_TraceMallocShutdown(void); - -/** - * Disable malloc tracing. - */ -PR_EXTERN(void) NS_TraceMallocDisable(void); - -/** - * Enable malloc tracing. - */ -PR_EXTERN(void) NS_TraceMallocEnable(void); - -/** - * Change the log file descriptor, flushing any buffered output to the old - * fd, and writing NS_TRACE_MALLOC_MAGIC to the new file if it is zero length. - * Return the old fd, so the caller can swap open fds. Return -2 on failure, - * which means malloc failure. - */ -PR_EXTERN(int) NS_TraceMallocChangeLogFD(int fd); - -/** - * Close the file descriptor fd and forget any bookkeeping associated with it. - * Do nothing if fd is -1. - */ -PR_EXTERN(void) NS_TraceMallocCloseLogFD(int fd); - -/** - * Emit a timestamp event with the given caption to the current log file. - */ -PR_EXTERN(void) NS_TraceMallocLogTimestamp(const char *caption); - -/** - * Walk the stack, dumping frames in standard form to ofp. If skip is 0, - * exclude the frames for NS_TraceStack and anything it calls to do the walk. - * If skip is less than 0, include -skip such frames. If skip is positive, - * exclude that many frames leading to the call to NS_TraceStack. - */ -PR_EXTERN(void) -NS_TraceStack(int skip, FILE *ofp); - -/** - * Dump a human-readable listing of current allocations and their compressed - * stack backtraces to the file named by pathname. Beware this file may have - * very long lines. - * - * Return -1 on error with errno set by the system, 0 on success. - */ -PR_EXTERN(int) -NS_TraceMallocDumpAllocations(const char *pathname); - -/** - * Flush all logfile buffers. - */ -PR_EXTERN(void) -NS_TraceMallocFlushLogfiles(void); - -/** - * Track all realloc and free calls operating on a given allocation. - */ -PR_EXTERN(void) -NS_TrackAllocation(void* ptr, FILE *ofp); - -/* opaque type for API */ -typedef struct nsTMStackTraceIDStruct *nsTMStackTraceID; - -/** - * Get an identifier for the stack trace of the current thread (to this - * function's callsite) that can be used to print that stack trace later. - */ -PR_EXTERN(nsTMStackTraceID) -NS_TraceMallocGetStackTrace(void); - -/** - * Print the stack trace identified. - */ -PR_EXTERN(void) -NS_TraceMallocPrintStackTrace(FILE *ofp, nsTMStackTraceID id); - -#ifdef __cplusplus -} -#endif - -#endif /* nsTraceMalloc_h___ */ diff --git a/tools/trace-malloc/lib/nsTraceMallocCallbacks.h b/tools/trace-malloc/lib/nsTraceMallocCallbacks.h deleted file mode 100644 index 7e97cb273c0d..000000000000 --- a/tools/trace-malloc/lib/nsTraceMallocCallbacks.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -/* declarations needed by both nsTraceMalloc.c and nsWinTraceMalloc.cpp */ - -#ifndef NSTRACEMALLOCCALLBACKS_H -#define NSTRACEMALLOCCALLBACKS_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* Used by backtrace. */ -typedef struct stack_buffer_info { - void **buffer; - size_t size; - size_t entries; -} stack_buffer_info; - -typedef struct tm_thread tm_thread; -struct tm_thread { - /* - * This counter suppresses tracing, in case any tracing code needs - * to malloc. - */ - uint32_t suppress_tracing; - - /* buffer for backtrace, below */ - stack_buffer_info backtrace_buf; -}; - -/* implemented in nsTraceMalloc.c */ -tm_thread * tm_get_thread(void); - -/* implemented in nsTraceMalloc.c */ -PR_EXTERN(void) MallocCallback(void *aPtr, size_t aSize, uint32_t start, uint32_t end, tm_thread *t); -PR_EXTERN(void) CallocCallback(void *aPtr, size_t aCount, size_t aSize, uint32_t start, uint32_t end, tm_thread *t); -PR_EXTERN(void) ReallocCallback(void *aPin, void* aPout, size_t aSize, uint32_t start, uint32_t end, tm_thread *t); -PR_EXTERN(void) FreeCallback(void *aPtr, uint32_t start, uint32_t end, tm_thread *t); - -#ifdef XP_WIN32 -/* implemented in nsTraceMalloc.c */ -PR_EXTERN(void) StartupHooker(); -PR_EXTERN(void) ShutdownHooker(); - -/* implemented in nsWinTraceMalloc.cpp */ -void* dhw_orig_malloc(size_t); -void* dhw_orig_calloc(size_t, size_t); -void* dhw_orig_realloc(void*, size_t); -void dhw_orig_free(void*); - -#endif /* defined(XP_WIN32) */ - -#ifdef __cplusplus -} -#endif - -#endif /* !defined(NSTRACEMALLOCCALLBACKS_H) */ diff --git a/tools/trace-malloc/lib/nsTypeInfo.cpp b/tools/trace-malloc/lib/nsTypeInfo.cpp deleted file mode 100644 index 2a4ae4bb7ef1..000000000000 --- a/tools/trace-malloc/lib/nsTypeInfo.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -/* - typeinfo.cpp - - Speculatively use RTTI on a random object. If it contains a pointer at offset 0 - that is in the current process' address space, and that so on, then attempt to - use C++ RTTI's typeid operation to obtain the name of the type. - - by Patrick C. Beard. - */ - -#include /* Needed for MSVC2010 due to bug 1055675 */ -#include -#include - -#include "nsTypeInfo.h" - -extern "C" void NS_TraceMallocShutdown(); - -struct TraceMallocShutdown { - TraceMallocShutdown() {} - ~TraceMallocShutdown() { - NS_TraceMallocShutdown(); - } -}; - -extern "C" void RegisterTraceMallocShutdown() { - // This instanciates the dummy class above, and will trigger the class - // destructor when libxul is unloaded. This is equivalent to atexit(), - // but gracefully handles dlclose(). - static TraceMallocShutdown t; -} - -class IUnknown { -public: - virtual long QueryInterface() = 0; - virtual long AddRef() = 0; - virtual long Release() = 0; -}; - -#if defined(MACOS) - -#include - -class AddressSpace { -public: - AddressSpace(); - Boolean contains(void* ptr); -private: - ProcessInfoRec mInfo; -}; - -AddressSpace::AddressSpace() -{ - ProcessSerialNumber psn = { 0, kCurrentProcess }; - mInfo.processInfoLength = sizeof(mInfo); - ::GetProcessInformation(&psn, &mInfo); -} - -Boolean AddressSpace::contains(void* ptr) -{ - UInt32 start = UInt32(mInfo.processLocation); - return (UInt32(ptr) >= start && UInt32(ptr) < (start + mInfo.processSize)); -} - -const char* nsGetTypeName(void* ptr) -{ - // construct only one of these per process. - static AddressSpace space; - - // sanity check the vtable pointer, before trying to use RTTI on the object. - void** vt = *(void***)ptr; - if (vt && !(unsigned(vt) & 0x3) && space.contains(vt) && space.contains(*vt)) { - IUnknown* u = static_cast(ptr); - const char* type = typeid(*u).name(); - // make sure it looks like a C++ identifier. - if (type && (isalnum(type[0]) || type[0] == '_')) - return type; - } - return "void*"; -} - -#endif - -// New, more "portable" Linux code is below, but this might be a useful -// model for other platforms, so keeping. -//#if defined(linux) -#if 0 - -#include -#include - -static jmp_buf context; - -static void handler(int signum) -{ - longjmp(context, signum); -} - -#define attempt() setjmp(context) - -class Signaller { -public: - Signaller(int signum); - ~Signaller(); - -private: - typedef void (*handler_t) (int signum); - int mSignal; - handler_t mOldHandler; -}; - -Signaller::Signaller(int signum) - : mSignal(signum), mOldHandler(signal(signum, &handler)) -{ -} - -Signaller::~Signaller() -{ - signal(mSignal, mOldHandler); -} - -// The following are pointers that bamboozle our otherwise feeble -// attempts to "safely" collect type names. -// -// XXX this kind of sucks because it means that anyone trying to use -// this without NSPR will get unresolved symbols when this library -// loads. It's also not very extensible. Oh well: FIX ME! -extern "C" { - // from nsprpub/pr/src/io/priometh.c (libnspr4.so) - extern void* _pr_faulty_methods; -}; - -static inline int -sanity_check_vtable_i386(void** vt) -{ - // Now that we're "safe" inside the signal handler, we can - // start poking around. If we're really an object with - // RTTI, then the second entry in the vtable should point - // to a function. - // - // Let's see if the second entry: - // - // 1) looks like a 4-byte aligned pointer - // - // 2) points to something that looks like the following - // i386 instructions: - // - // 55 push %ebp - // 89e5 mov %esp,%ebp - // 53 push %ebx - // - // or - // - // 55 push %ebp - // 89e5 mov %esp,%ebp - // 56 push %esi - // - // (which is the standard function prologue generated - // by egcs, plus a ``signature'' instruction that appears - // in the typeid() function's implementation). - unsigned char** fp1 = reinterpret_cast(vt) + 1; - - // Does it look like an address? - unsigned char* ip = *fp1; - if ((unsigned(ip) & 3) != 0) - return 0; - - // Does it look like it refers to the standard prologue? - static unsigned char prologue[] = { 0x55, 0x89, 0xE5 }; - for (unsigned i = 0; i < sizeof(prologue); ++i) - if (*ip++ != prologue[i]) - return 0; - - // Is the next instruction a `push %ebx' or `push %esi'? - if (*ip == 0x53 || *ip == 0x56) { - return 1; - } - - // Nope. There's another variant that has a `sub' instruction, - // followed by a `cmpl' and a `jne'. Check for that. - if (ip[0] == 0x83 && ip[1] == 0xec // sub - && ip[3] == 0x83 && ip[4] == 0x3d // cmpl - && ip[10] == 0x75 // jne - ) { - return 1; - } - - return 0; -} - -static inline int -sanity_check_vtable_ppc(void** vt) -{ - // XXX write me! - return 1; -} - -#if defined(__i386) -# define SANITY_CHECK_VTABLE(vt) (sanity_check_vtable_i386(vt)) -#elif defined(PPC) -# define SANITY_CHECK_VTABLE(vt) (sanity_check_vtable_ppc(vt)) -#else -# define SANITY_CHECK_VTABLE(vt) (1) -#endif - -const char* nsGetTypeName(void* ptr) -{ - // sanity check the vtable pointer, before trying to use RTTI on the object. - void** vt = *(void***)ptr; - if (vt && !(unsigned(vt) & 3) && (vt != &_pr_faulty_methods)) { - Signaller s1(SIGSEGV); - if (attempt() == 0) { - if (SANITY_CHECK_VTABLE(vt)) { - // Looks like a function: what the hell, let's call it. - IUnknown* u = static_cast(ptr); - const char* type = typeid(*u).name(); - // EGCS seems to prefix a length string. - while (isdigit(*type)) ++type; - return type; - } - } - } - return "void*"; -} - -#endif - -#if defined(linux) || defined(XP_MACOSX) - -#define __USE_GNU -#include -#include -#include - -const char* nsGetTypeName(void* ptr) -{ -#if defined(__GXX_ABI_VERSION) && __GXX_ABI_VERSION >= 100 /* G++ V3 ABI */ - const int expected_offset = 8; - const char vtable_sym_start[] = "_ZTV"; - const int vtable_sym_start_length = sizeof(vtable_sym_start) - 1; -#else - const int expected_offset = 0; - const char vtable_sym_start[] = "__vt_"; - const int vtable_sym_start_length = sizeof(vtable_sym_start) - 1; -#endif - void* vt = *(void**)ptr; - Dl_info info; - // If dladdr fails, if we're not at the expected offset in the vtable, - // or if the symbol name isn't a vtable symbol name, return "void*". - if ( !dladdr(vt, &info) || - ((char*)info.dli_saddr) + expected_offset != vt || - !info.dli_sname || - strncmp(info.dli_sname, vtable_sym_start, vtable_sym_start_length)) - return "void*"; - - // skip the garbage at the beginning of things like - // __vt_14nsRootBoxFrame (gcc 2.96) or _ZTV14nsRootBoxFrame (gcc 3.0) - const char* rv = info.dli_sname + vtable_sym_start_length; - while (*rv && isdigit(*rv)) - ++rv; - return rv; -} - -#endif - -#ifdef XP_WIN32 -const char* nsGetTypeName(void* ptr) -{ - //TODO: COMPLETE THIS - return "void*"; -} - -#endif //XP_WIN32 diff --git a/tools/trace-malloc/lib/nsTypeInfo.h b/tools/trace-malloc/lib/nsTypeInfo.h deleted file mode 100644 index 55af69f03273..000000000000 --- a/tools/trace-malloc/lib/nsTypeInfo.h +++ /dev/null @@ -1,22 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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 trace_malloc_nsTypeInfo_h_ -#define trace_malloc_nsTypeInfo_h_ - -#ifdef __cplusplus -extern "C" { -#endif - -extern const char* nsGetTypeName(void* ptr); - -extern void RegisterTraceMallocShutdown(); - -#ifdef __cplusplus -} -#endif - -#endif /* trace_malloc_nsTypeInfo_h_ */ diff --git a/tools/trace-malloc/lib/nsWinTraceMalloc.cpp b/tools/trace-malloc/lib/nsWinTraceMalloc.cpp deleted file mode 100644 index 84a42ffbbcf7..000000000000 --- a/tools/trace-malloc/lib/nsWinTraceMalloc.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -#include -#include - -#include "prinrval.h" -#include "prlock.h" -#include "nscore.h" - -#include "nsDebugHelpWin32.h" -#include "nsTraceMallocCallbacks.h" - -/***************************************************************************/ -// shows how to use the dhw stuff to hook imported functions - -#if _MSC_VER == 1600 -#define NS_DEBUG_CRT "msvcr100d.dll" -#elif _MSC_VER == 1700 -#define NS_DEBUG_CRT "msvcr110d.dll" -#elif _MSC_VER == 1800 -#define NS_DEBUG_CRT "msvcr120d.dll" -#else -#error "Don't know filename of MSVC debug library." -#endif - -decltype(malloc) dhw_malloc; - -DHWImportHooker &getMallocHooker() -{ - static DHWImportHooker gMallocHooker(NS_DEBUG_CRT, "malloc", (PROC) dhw_malloc); - return gMallocHooker; -} - -void * __cdecl dhw_malloc( size_t size ) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - void* result = DHW_ORIGINAL(malloc, getMallocHooker())(size); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - MallocCallback(result, size, start, end, t); - return result; -} - -decltype(calloc) dhw_calloc; - -DHWImportHooker &getCallocHooker() -{ - static DHWImportHooker gCallocHooker(NS_DEBUG_CRT, "calloc", (PROC) dhw_calloc); - return gCallocHooker; -} - -void * __cdecl dhw_calloc( size_t count, size_t size ) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - void* result = DHW_ORIGINAL(calloc, getCallocHooker())(count,size); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - CallocCallback(result, count, size, start, end, t); - return result; -} - -decltype(free) dhw_free; -DHWImportHooker &getFreeHooker() -{ - static DHWImportHooker gFreeHooker(NS_DEBUG_CRT, "free", (PROC) dhw_free); - return gFreeHooker; -} - -void __cdecl dhw_free( void* p ) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - DHW_ORIGINAL(free, getFreeHooker())(p); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - /* FIXME bug 392008: We could race with reallocation of p. */ - FreeCallback(p, start, end, t); -} - - -decltype(realloc) dhw_realloc; -DHWImportHooker &getReallocHooker() -{ - static DHWImportHooker gReallocHooker(NS_DEBUG_CRT, "realloc", (PROC) dhw_realloc); - return gReallocHooker; -} - -void * __cdecl dhw_realloc(void * pin, size_t size) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - void* pout = DHW_ORIGINAL(realloc, getReallocHooker())(pin, size); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - /* FIXME bug 392008: We could race with reallocation of pin. */ - ReallocCallback(pin, pout, size, start, end, t); - return pout; -} - -// Note the mangled name! -void * __cdecl dhw_new(size_t size); -DHWImportHooker &getNewHooker() -{ - static DHWImportHooker gNewHooker(NS_DEBUG_CRT, "??2@YAPAXI@Z", (PROC) dhw_new); - return gNewHooker; -} - -void * __cdecl dhw_new(size_t size) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - void* result = DHW_ORIGINAL(dhw_new, getNewHooker())(size); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - MallocCallback(result, size, start, end, t);//do we need a different one for new? - return result; -} - -// Note the mangled name! -void __cdecl dhw_delete(void* p); -DHWImportHooker &getDeleteHooker() -{ - static DHWImportHooker gDeleteHooker(NS_DEBUG_CRT, "??3@YAXPAX@Z", (PROC) dhw_delete); - return gDeleteHooker; -} - -void __cdecl dhw_delete(void* p) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - DHW_ORIGINAL(dhw_delete, getDeleteHooker())(p); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - FreeCallback(p, start, end, t); -} - -// Note the mangled name! -void * __cdecl dhw_vec_new(size_t size); -DHWImportHooker &getVecNewHooker() -{ - static DHWImportHooker gVecNewHooker(NS_DEBUG_CRT, "??_U@YAPAXI@Z", (PROC) dhw_vec_new); - return gVecNewHooker; -} - -void * __cdecl dhw_vec_new(size_t size) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; // need to suppress since new[] calls new - uint32_t start = PR_IntervalNow(); - void* result = DHW_ORIGINAL(dhw_vec_new, getVecNewHooker())(size); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - MallocCallback(result, size, start, end, t);//do we need a different one for new[]? - return result; -} - -// Note the mangled name! -void __cdecl dhw_vec_delete(void* p); -DHWImportHooker &getVecDeleteHooker() -{ - static DHWImportHooker gVecDeleteHooker(NS_DEBUG_CRT, "??_V@YAXPAX@Z", (PROC) dhw_vec_delete); - return gVecDeleteHooker; -} - -void __cdecl dhw_vec_delete(void* p) -{ - tm_thread *t = tm_get_thread(); - ++t->suppress_tracing; - uint32_t start = PR_IntervalNow(); - DHW_ORIGINAL(dhw_vec_delete, getVecDeleteHooker())(p); - uint32_t end = PR_IntervalNow(); - --t->suppress_tracing; - FreeCallback(p, start, end, t); -} - -/*C Callbacks*/ -PR_IMPLEMENT(void) -StartupHooker() -{ - //run through get all hookers - DHWImportHooker &loadlibraryW = DHWImportHooker::getLoadLibraryWHooker(); - DHWImportHooker &loadlibraryExW = DHWImportHooker::getLoadLibraryExWHooker(); - DHWImportHooker &loadlibraryA = DHWImportHooker::getLoadLibraryAHooker(); - DHWImportHooker &loadlibraryExA = DHWImportHooker::getLoadLibraryExAHooker(); - DHWImportHooker &mallochooker = getMallocHooker(); - DHWImportHooker &reallochooker = getReallocHooker(); - DHWImportHooker &callochooker = getCallocHooker(); - DHWImportHooker &freehooker = getFreeHooker(); - DHWImportHooker &newhooker = getNewHooker(); - DHWImportHooker &deletehooker = getDeleteHooker(); - DHWImportHooker &vecnewhooker = getVecNewHooker(); - DHWImportHooker &vecdeletehooker = getVecDeleteHooker(); - printf("Startup Hooker\n"); -} - -PR_IMPLEMENT(void) -ShutdownHooker() -{ -} - -extern "C" { - void* dhw_orig_malloc(size_t); - void* dhw_orig_calloc(size_t, size_t); - void* dhw_orig_realloc(void*, size_t); - void dhw_orig_free(void*); -} - -void* -dhw_orig_malloc(size_t size) -{ - return DHW_ORIGINAL(malloc, getMallocHooker())(size); -} - -void* -dhw_orig_calloc(size_t count, size_t size) -{ - return DHW_ORIGINAL(calloc, getCallocHooker())(count,size); -} - -void* -dhw_orig_realloc(void* pin, size_t size) -{ - return DHW_ORIGINAL(realloc, getReallocHooker())(pin, size); -} - -void -dhw_orig_free(void* p) -{ - DHW_ORIGINAL(free, getFreeHooker())(p); -} diff --git a/tools/trace-malloc/lib/tm.def b/tools/trace-malloc/lib/tm.def deleted file mode 100644 index 9bd3b8cc61a9..000000000000 --- a/tools/trace-malloc/lib/tm.def +++ /dev/null @@ -1,19 +0,0 @@ -; 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/. - -LIBRARY tracemalloc.dll - -EXPORTS - -NS_TraceMallocStartup -NS_TraceMallocStartupArgs -NS_TraceMallocShutdown -NS_TraceMallocDisable -NS_TraceMallocEnable -NS_TraceMallocChangeLogFD -NS_TraceMallocCloseLogFD -NS_TraceMallocLogTimestamp -NS_TraceStack -NS_TraceMallocDumpAllocations -NS_TraceMallocFlushLogfiles diff --git a/tools/trace-malloc/live-bloat.html b/tools/trace-malloc/live-bloat.html deleted file mode 100644 index 73a881f806df..000000000000 --- a/tools/trace-malloc/live-bloat.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - -Live Bloat Dump - - - - - \ No newline at end of file diff --git a/tools/trace-malloc/merge.pl b/tools/trace-malloc/merge.pl deleted file mode 100755 index 4efef18ff54f..000000000000 --- a/tools/trace-malloc/merge.pl +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/perl -# 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/. - - -$argv = $ARGV[0]; -open( bloatFile, $argv ) or die "Can't open $argv: $!\n"; -while () { - if (/name=/) { - ($td,$name,$func,$a,$ntd) = split(/>/, $_); - ($fname, $memSize) = split( / /, $func ); - ($trash, $linkName) = split( /"/, $name ); - $namesLinks{$fname} = $linkName; - if ($namesSizes{$fname}) { - $namesSizes{$fname} = $namesSizes{$fname} + $memSize; - } - else { - $namesSizes{$fname} = $memSize; - } - } -} - -$argv = $ARGV[1]; -if ($argv) -{ - open( bloatFile, $argv ) or die "Can't open $argv: $!\n"; - while () { - if (/name=/) { - ($td,$name,$func,$a,$ntd) = split(/>/, $_); - ($fname, $memSize) = split( / /, $func ); - $namesSizes{$fname} = $namesSizes{$fname} - $memSize; - } - } -} - -sub byvalue { $namesSizes{$b} <=> $namesSizes{$a} } - - -print ''; -print "\n\n"; -print "Bloat Blame Delta\n"; -print ''; -print "\n\n\n\n"; -print "\n"; - -foreach $key (sort byvalue keys %namesSizes) { - if ($namesSizes{$key}) - { - print "\n"; - print ' \n"; - print " \n"; - print "\n" - } -} - -print "
Memory AllocatedFunction NameLink
', $namesSizes{$key}," ", $key, "
\n"; diff --git a/tools/trace-malloc/moz.build b/tools/trace-malloc/moz.build deleted file mode 100644 index cc3f78dc0317..000000000000 --- a/tools/trace-malloc/moz.build +++ /dev/null @@ -1,34 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -if not CONFIG['MOZ_PROFILE_GENERATE']: - Program('spacetrace') - SOURCES += [ - 'formdata.c', - 'spacecategory.c', - 'spacetrace.c', - ] - -bin_suffix = CONFIG['BIN_SUFFIX'] - - -SOURCES += [ - 'tmreader.c', -] - -SimplePrograms([ - 'leakstats', - 'tmstats', -], ext='.c') - -GeckoSimplePrograms([ - 'bloatblame', - 'leaksoup', -]) - -RESOURCE_FILES += [ - 'spacetrace.css' -] diff --git a/tools/trace-malloc/rules.txt b/tools/trace-malloc/rules.txt deleted file mode 100644 index 95e55119ae4c..000000000000 --- a/tools/trace-malloc/rules.txt +++ /dev/null @@ -1,442 +0,0 @@ -# Categorization rules for spacetrace -# -# This file defines the stack frame rules that will categorize -# allocations that spacetrace processes. The format of this file is -# -# -# initial string match for stack frame n -# initial string match for stack frame n+1 -# initial string match for stack frame n+2 -# -# The key in the matching rule is that for every rule, we provide a -# snippet of the stack frame - contiguous substring matches. -# categorynames and rules substring matches are case sensitive -# -# Predefined Categories -# "All" - All allocations [default] -# "uncategorized" - All allocations that don't match any category -# -# -# Suresh Duddi -########################################################################### -# NOTE: This is still under definition -########################################################################### -# General principle of categorization: -# -# - Each category, in general, denotes a module or feature. -# -# - We assign each allocation to the module/feature that directly -# caused the allocation irrespective of which higher level module -# caused the allocation. There are very few exceptions usually when -# an allocation belongs both to a feature-category and to a -# module-category. -# -# bookmarks -# Bookmarks. Mainly initialization. Does not include menu cost. -# css -# Cascading style sheets -# dom -# Memory held by DOM. -# font -# All font stuff -# global-history -# html -# html parsing and layout -# layout -# reflow, frames, line, view -# images -# All images. -# jar -# jar, zip -# js -# javascript -# necko -# All protocol and uri stuff. All urls created accounted here -# preferences -# Preferences stuff. All js cost for preferences is included here. -## rdf -# Most of the rdf allocations. rdf cost from xul, chromeregistry, -# is assigned to xul. -# -# wallet -# Form cache. -# -# xbl -# xbl stuff. Includes js in xbl. -# xpcom -# xpcom, xpt. Allocations for creations of objects are assigned -# onto the respective modules -# xul -# XUL parsing and layout. Includes rdf overhead from xul like -# nsChromeRegistry -# - - -# - -# =========================================================================== -# Leaf rules. We categorize them out first. -# All allocations matching these rules DO belong to the category. -# =========================================================================== - - -nsXULPrototypeScript::Deserialize - - -XSupportsLocale - - -/usr/X11R6/lib/libX11.so - - -JS_Init - - -NS_NewPermanentAtom - - -gif_write - - -imgRequest::OnDataAvailable - - -imgLoader:: - - -jinit_master_decompress - - -jinit_marker_reader - - -jinit_marker_decompress - - -nsJPEGDecoder:: - - -nsGIFDecoder2:: - - -nsZipArchive::BuildFileList - - -nsZipArchive::ReadInit - - -nsJARChannel::Open - - -NS_InitXPCOM2 - -# xpt file loads - -xptiInterfaceInfoManager::LoadFile - - -nsGenericModule::Initialize - - -nsStringBundle - - -nsLocale:: - - -nsCharsetConverterManager:: - - -nsDiskCacheDevice::Init - - -nsCacheEntryDescriptor::nsTransportWrapper::OpenOutputStream - - -nsSocketTransport:: - - -nsCacheService:: - - -nsDiskCacheStreamIO:: - - -nsHttpResponseHead:: - - -WLLT - - -nsXULElement::Create - - -nsXULAttribute::Create - - -nsXULDocument::AddElementToMap - - -XULContentSinkImpl::AddAttributes - - -XULContentSinkImpl::CreateElement - - -nsXULElement::SetAttr - - -nsXULDocument::InsertElement - - -NS_NewXULContentBuilder - - -nsXULElement::AppendChildTo - - -nsXBLPrototypeHandler::AppendHandlerText( - - -FrameArena::AllocateFrame - - -nsGlobalHistory::OpenDB - - -nsFontCache:: - - -nsFont::nsFont - - -gtk_init - - -RDFServiceImpl::GetResource - - -RDFContentSinkImpl::AddProperties - - -RDFContainerImpl::AppendElement - - -RDFXMLDataSourceImpl::Assert - - -NS_NewRDFInMemoryDataSource - - -CSSLoaderImpl::ParseSheet - - -CSSParserImpl::Parse( - - -NS_NewCSS - - -RuleHash::AppendRule - - -nsRuleNode::GetStyleData - - -SelectorList:: - - -CSSRuleProcessor::RulesMatching - - -CSSStyleSheetImpl::Clone - - -nsHttpHeaderArray:: - - -nsScanner::Append - - -nsHTMLTokenizer:: - - -NS_NewHTMLTokenizer - - -nsSlidingString:: - - -nsParser:: - - -nsIParserService:: - - -nsCParserNode:: - - -CNavDTD::CNavDTD - - -nsHTMLDocument:: - - -IncrementalReflow::AddCommand - - -nsBlockFrame:: - - -nsBoxFrame:: - - -nsImageFrame:: - - -nsInlineFrame:: - - -nsLeafFrame:: - - -nsLineLayout:: - - -nsReflowPath::EnsureSubtreeFor - - -nsSliderFrame:: - - -nsScrollBoxFrame:: - - -nsTextFrame:: - - -nsTableRowFrame:: - - -nsTableRowGroupFrame:: - - -nsViewManager:: - - -PresShell::ProcessReflowCommands - - -# ====================================================================== -# Rules that match higher up on the stack -# These go later. -# ====================================================================== - - -PREF_ - - -nsBookmarksService:: - - -nsXBLService::LoadBindings - - -nsXBLBinding::ExecuteAttachedHandler - - -nsXULDocument::LoadScript - - -nsXULDocument::ExecuteScript - - -XULContentSinkImpl::Open - - -RDFContentSinkImpl::HandleEndElement - - -HTMLContentSink::AddAttributes - - -HTMLContentSink::OpenContainer - - -HTMLContentSink::CloseContainer - -# XXX whom to account LoadImage to? I am going with images. - -imgLoader::LoadImage - - -StackArena:: - -# ====================================================================== -# Even more genralized rules. There could be lots of activity that -# happens below them in the stack. But we are sure we have categorized -# a lot of them by using the rules above and know the category of the -# most of the rest. -# ====================================================================== - - -RDFContentSinkImpl:: - - -nsGenericDOMDataNode:: - - -nsDOMClassInfo:: - - -nsDOMSOFactory:: - - -nsXULTemplateBuilder:: - - -XULContentSinkImpl::HandleEndElement - - -nsChromeRegistry:: - - -nsJSContext::EvaluateString - -# Almost all of what is left with XULContentSink belongs to xul -# Also, this was roughly 0.3% of startup memory - -XULContentSinkImpl:: - -# XXX this is a wild guess -> html What remains here is about -# XXX 1.5% of startup footprint - -HTMLContentSink:: - - -nsXBLContentSink:: - - -nsXBLStreamListener::OnDataAvailable - - -nsIOService::NewURI - - -nsIOService::NewChannelFromURI - - -nsSegmentedBuffer::AppendNewSegment - - -nsHttpChannel:: - -# Catchalls to help categorize -# ---------------------------------------------------------------------- - -js_ - -# Everything else -# ---------------------------------------------------------------------- -# -# This is a predefined category. Don't create it yourself. diff --git a/tools/trace-malloc/spacecategory.c b/tools/trace-malloc/spacecategory.c deleted file mode 100644 index f3b518cec8ce..000000000000 --- a/tools/trace-malloc/spacecategory.c +++ /dev/null @@ -1,959 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -/* -** spacecategory.c -** -** Cagtegorizes each allocation using a predefined set of rules -** and presents a tree of categories for browsing. -*/ - -/* -** Required include files. -*/ -#include "spacetrace.h" -#include -#include - -#include "nsQuickSort.h" - -#if defined(HAVE_BOUTELL_GD) -/* -** See http://www.boutell.com/gd for the GD graphics library. -** Ports for many platorms exist. -** Your box may already have the lib (mine did, redhat 7.1 workstation). -*/ -#include -#include -#include -#include -#endif /* HAVE_BOUTELL_GD */ - -/* -** AddRule -** -** Add a rule into the list of rules maintainted in global -*/ -int -AddRule(STGlobals * g, STCategoryRule * rule) -{ - if (g->mNRules % ST_ALLOC_STEP == 0) { - /* Need more space */ - STCategoryRule **newrules; - - newrules = (STCategoryRule **) realloc(g->mCategoryRules, - (g->mNRules + - ST_ALLOC_STEP) * - sizeof(STCategoryRule *)); - if (!newrules) { - REPORT_ERROR(__LINE__, AddRule_No_Memory); - return -1; - } - g->mCategoryRules = newrules; - } - g->mCategoryRules[g->mNRules++] = rule; - return 0; -} - -/* -** AddChild -** -** Add the node as a child of the parent node -*/ -int -AddChild(STCategoryNode * parent, STCategoryNode * child) -{ - if (parent->nchildren % ST_ALLOC_STEP == 0) { - /* need more space */ - STCategoryNode **newnodes; - - newnodes = (STCategoryNode **) realloc(parent->children, - (parent->nchildren + - ST_ALLOC_STEP) * - sizeof(STCategoryNode *)); - if (!newnodes) { - REPORT_ERROR(__LINE__, AddChild_No_Memory); - return -1; - } - parent->children = newnodes; - } - parent->children[parent->nchildren++] = child; - return 0; -} - -int -Reparent(STCategoryNode * parent, STCategoryNode * child) -{ - uint32_t i; - - if (child->parent == parent) - return 0; - - /* Remove child from old parent */ - if (child->parent) { - for (i = 0; i < child->parent->nchildren; i++) { - if (child->parent->children[i] == child) { - /* Remove child from list */ - if (i + 1 < child->parent->nchildren) - memmove(&child->parent->children[i], - &child->parent->children[i + 1], - (child->parent->nchildren - i - - 1) * sizeof(STCategoryNode *)); - child->parent->nchildren--; - break; - } - } - } - - /* Add child into new parent */ - AddChild(parent, child); - - return 0; -} - -/* -** findCategoryNode -** -** Given a category name, finds the Node corresponding to the category -*/ -STCategoryNode * -findCategoryNode(const char *catName, STGlobals * g) -{ - uint32_t i; - - for (i = 0; i < g->mNCategoryMap; i++) { - if (!strcmp(g->mCategoryMap[i]->categoryName, catName)) - return g->mCategoryMap[i]->node; - } - - /* Check if we are looking for the root node */ - if (!strcmp(catName, ST_ROOT_CATEGORY_NAME)) - return &g->mCategoryRoot; - - return NULL; -} - -/* -** AddCategoryNode -** -** Adds a mapping between a category and its Node into the categoryMap -*/ -int -AddCategoryNode(STCategoryNode * node, STGlobals * g) -{ - if (g->mNCategoryMap % ST_ALLOC_STEP == 0) { - /* Need more space */ - STCategoryMapEntry **newmap = - (STCategoryMapEntry **) realloc(g->mCategoryMap, - (g->mNCategoryMap + - ST_ALLOC_STEP) * - sizeof(STCategoryMapEntry *)); - if (!newmap) { - REPORT_ERROR(__LINE__, AddCategoryNode_No_Memory); - return -1; - } - g->mCategoryMap = newmap; - - } - g->mCategoryMap[g->mNCategoryMap] = - (STCategoryMapEntry *) calloc(1, sizeof(STCategoryMapEntry)); - if (!g->mCategoryMap[g->mNCategoryMap]) { - REPORT_ERROR(__LINE__, AddCategoryNode_No_Memory); - return -1; - } - g->mCategoryMap[g->mNCategoryMap]->categoryName = node->categoryName; - g->mCategoryMap[g->mNCategoryMap]->node = node; - g->mNCategoryMap++; - return 0; -} - -/* -** NewCategoryNode -** -** Creates a new category node for category name 'catname' and makes -** 'parent' its parent. -*/ -STCategoryNode * -NewCategoryNode(const char *catName, STCategoryNode * parent, STGlobals * g) -{ - STCategoryNode *node; - - node = (STCategoryNode *) calloc(1, sizeof(STCategoryNode)); - if (!node) - return NULL; - - node->runs = - (STRun **) calloc(g->mCommandLineOptions.mContexts, sizeof(STRun *)); - if (NULL == node->runs) { - free(node); - return NULL; - } - - node->categoryName = catName; - - /* Set parent of child */ - node->parent = parent; - - /* Set child in parent */ - AddChild(parent, node); - - /* Add node into mapping table */ - AddCategoryNode(node, g); - - return node; -} - -/* -** ProcessCategoryLeafRule -** -** Add this into the tree as a leaf node. It doesn't know who its parent is. For now we make -** root as its parent -*/ -int -ProcessCategoryLeafRule(STCategoryRule * leafRule, STCategoryNode * root, - STGlobals * g) -{ - STCategoryRule *rule; - STCategoryNode *node; - - rule = (STCategoryRule *) calloc(1, sizeof(STCategoryRule)); - if (!rule) - return -1; - - /* Take ownership of all elements of rule */ - *rule = *leafRule; - - /* Find/Make a STCategoryNode and add it into the tree */ - node = findCategoryNode(rule->categoryName, g); - if (!node) - node = NewCategoryNode(rule->categoryName, root, g); - - /* Make sure rule knows which node to access */ - rule->node = node; - - /* Add rule into rulelist */ - AddRule(g, rule); - - return 0; -} - -/* -** ProcessCategoryParentRule -** -** Rule has all the children of category as patterns. Sets up the tree so that -** the parent child relationship is honored. -*/ -int -ProcessCategoryParentRule(STCategoryRule * parentRule, STCategoryNode * root, - STGlobals * g) -{ - STCategoryNode *node; - STCategoryNode *child; - uint32_t i; - - /* Find the parent node in the tree. If not make one and add it into the tree */ - node = findCategoryNode(parentRule->categoryName, g); - if (!node) { - node = NewCategoryNode(parentRule->categoryName, root, g); - if (!node) - return -1; - } - - /* For every child node, Find/Create it and make it the child of this node */ - for (i = 0; i < parentRule->npats; i++) { - child = findCategoryNode(parentRule->pats[i], g); - if (!child) { - child = NewCategoryNode(parentRule->pats[i], node, g); - if (!child) - return -1; - } - else { - /* Reparent child to node. This is because when we created the node - ** we would have created it as the child of root. Now we need to - ** remove it from root's child list and add it into this node - */ - Reparent(node, child); - } - } - - return 0; -} - -/* -** initCategories -** -** Initialize all categories. This reads in a file that says how to categorize -** each callsite, creates a tree of these categories and makes a list of these -** patterns in order for matching -*/ -int -initCategories(STGlobals * g) -{ - FILE *fp; - char buf[1024], *in; - int n; - PRBool inrule, leaf; - STCategoryRule rule; - - fp = fopen(g->mCommandLineOptions.mCategoryFile, "r"); - if (!fp) { - /* It isn't an error to not have a categories file */ - REPORT_INFO("No categories file."); - return -1; - } - - inrule = PR_FALSE; - leaf = PR_FALSE; - - memset(&rule, 0, sizeof(rule)); - - while (fgets(buf, sizeof(buf), fp) != NULL) { - /* Lose the \n */ - n = strlen(buf); - if (buf[n - 1] == '\n') - buf[--n] = '\0'; - in = buf; - - /* skip comments */ - if (*in == '#') - continue; - - /* skip empty lines. If we are in a rule, end the rule. */ - while (*in && isspace(*in)) - in++; - if (*in == '\0') { - if (inrule) { - /* End the rule : leaf or non-leaf */ - if (leaf) - ProcessCategoryLeafRule(&rule, &g->mCategoryRoot, g); - else - /* non-leaf */ - ProcessCategoryParentRule(&rule, &g->mCategoryRoot, g); - inrule = PR_FALSE; - memset(&rule, 0, sizeof(rule)); - } - continue; - } - - /* if we are in a rule acculumate */ - if (inrule) { - rule.pats[rule.npats] = strdup(in); - rule.patlen[rule.npats++] = strlen(in); - } - else if (*in == '<') { - /* Start a category */ - inrule = PR_TRUE; - leaf = PR_TRUE; - - /* Get the category name */ - in++; - n = strlen(in); - if (in[n - 1] == '>') - in[n - 1] = '\0'; - rule.categoryName = strdup(in); - } - else { - /* this is a non-leaf category. Should be of the form CategoryName - ** followed by list of child category names one per line - */ - inrule = PR_TRUE; - leaf = PR_FALSE; - rule.categoryName = strdup(in); - } - } - - /* If we were in a rule when processing the last line, end the rule */ - if (inrule) { - /* End the rule : leaf or non-leaf */ - if (leaf) - ProcessCategoryLeafRule(&rule, &g->mCategoryRoot, g); - else - /* non-leaf */ - ProcessCategoryParentRule(&rule, &g->mCategoryRoot, g); - } - - /* Add the final "uncategorized" category. We make new memory locations - ** for all these to conform to the general principle of all strings are allocated - ** so it makes release logic very simple. - */ - memset(&rule, 0, sizeof(rule)); - rule.categoryName = strdup("uncategorized"); - rule.pats[0] = strdup(""); - rule.patlen[0] = 0; - rule.npats = 1; - ProcessCategoryLeafRule(&rule, &g->mCategoryRoot, g); - - return 0; -} - -/* -** callsiteMatchesRule -** -** Returns the corresponding node if callsite matches the rule. Rule is a sequence -** of patterns that must match contiguously the callsite. -*/ -int -callsiteMatchesRule(tmcallsite * aCallsite, STCategoryRule * aRule) -{ - uint32_t patnum = 0; - const char *methodName = NULL; - - while (patnum < aRule->npats && aCallsite && aCallsite->method) { - methodName = tmmethodnode_name(aCallsite->method); - if (!methodName) - return 0; - if (!*aRule->pats[patnum] - || !strncmp(methodName, aRule->pats[patnum], - aRule->patlen[patnum])) { - /* We have matched so far. Proceed up the stack and to the next pattern */ - patnum++; - aCallsite = aCallsite->parent; - } - else { - /* Deal with mismatch */ - if (patnum > 0) { - /* contiguous mismatch. Stop */ - return 0; - } - /* We still haven't matched the first pattern. Proceed up the stack without - ** moving to the next pattern. - */ - aCallsite = aCallsite->parent; - } - } - - if (patnum == aRule->npats) { - /* all patterns matched. We have a winner. */ -#if defined(DEBUG_dp) && 0 - fprintf(stderr, "[%s] match\n", aRule->categoryName); -#endif - return 1; - } - - return 0; -} - -#ifdef DEBUG_dp -PRIntervalTime _gMatchTime = 0; -uint32_t _gMatchCount = 0; -uint32_t _gMatchRules = 0; -#endif - -/* -** matchAllocation -** -** Runs through all rules and returns the node corresponding to -** a match of the allocation. -*/ -STCategoryNode * -matchAllocation(STGlobals * g, STAllocation * aAllocation) -{ -#ifdef DEBUG_dp - PRIntervalTime start = PR_IntervalNow(); -#endif - uint32_t rulenum; - STCategoryNode *node = NULL; - STCategoryRule *rule; - - for (rulenum = 0; rulenum < g->mNRules; rulenum++) { -#ifdef DEBUG_dp - _gMatchRules++; -#endif - rule = g->mCategoryRules[rulenum]; - if (callsiteMatchesRule(aAllocation->mEvents[0].mCallsite, rule)) { - node = rule->node; - break; - } - } -#ifdef DEBUG_dp - _gMatchCount++; - _gMatchTime += PR_IntervalNow() - start; -#endif - return node; -} - -/* -** categorizeAllocation -** -** Given an allocation, it adds it into the category tree at the right spot -** by comparing the allocation to the rules and adding into the right node. -** Also, does propogation of cost upwards in the tree. -** The root of the tree is in the globls as the tree is dependent on the -** category file (options) rather than the run. -*/ -int -categorizeAllocation(STOptions * inOptions, STContext * inContext, - STAllocation * aAllocation, STGlobals * g) -{ - /* Run through the rules in order to see if this allcation matches - ** any of them. - */ - STCategoryNode *node; - - node = matchAllocation(g, aAllocation); - if (!node) { - /* ugh! it should atleast go into the "uncategorized" node. wierd! - */ - REPORT_ERROR(__LINE__, categorizeAllocation); - return -1; - } - - /* Create run for node if not already */ - if (!node->runs[inContext->mIndex]) { - /* - ** Create run with positive timestamp as we can harvest it later - ** for callsite details summarization - */ - node->runs[inContext->mIndex] = - createRun(inContext, PR_IntervalNow()); - if (!node->runs[inContext->mIndex]) { - REPORT_ERROR(__LINE__, categorizeAllocation_No_Memory); - return -1; - } - } - - /* Add allocation into node. We expand the table of allocations in steps */ - if (node->runs[inContext->mIndex]->mAllocationCount % ST_ALLOC_STEP == 0) { - /* Need more space */ - STAllocation **allocs; - - allocs = - (STAllocation **) realloc(node->runs[inContext->mIndex]-> - mAllocations, - (node->runs[inContext->mIndex]-> - mAllocationCount + - ST_ALLOC_STEP) * - sizeof(STAllocation *)); - if (!allocs) { - REPORT_ERROR(__LINE__, categorizeAllocation_No_Memory); - return -1; - } - node->runs[inContext->mIndex]->mAllocations = allocs; - } - node->runs[inContext->mIndex]->mAllocations[node-> - runs[inContext->mIndex]-> - mAllocationCount++] = - aAllocation; - - /* - ** Make sure run's stats are calculated. We don't go update the parents of allocation - ** at this time. That will happen when we focus on this category. This updating of - ** stats will provide us fast categoryreports. - */ - recalculateAllocationCost(inOptions, inContext, - node->runs[inContext->mIndex], aAllocation, - PR_FALSE); - - /* Propagate upwards the statistics */ - /* XXX */ -#if defined(DEBUG_dp) && 0 - fprintf(stderr, "DEBUG: [%s] match\n", node->categoryName); -#endif - return 0; -} - -typedef PRBool STCategoryNodeProcessor(STRequest * inRequest, - STOptions * inOptions, - STContext * inContext, - void *clientData, - STCategoryNode * node); - -PRBool -freeNodeRunProcessor(STRequest * inRequest, STOptions * inOptions, - STContext * inContext, void *clientData, - STCategoryNode * node) -{ - if (node->runs && node->runs[inContext->mIndex]) { - freeRun(node->runs[inContext->mIndex]); - node->runs[inContext->mIndex] = NULL; - } - return PR_TRUE; -} - -PRBool -freeNodeRunsProcessor(STRequest * inRequest, STOptions * inOptions, - STContext * inContext, void *clientData, - STCategoryNode * node) -{ - if (node->runs) { - uint32_t loop = 0; - - for (loop = 0; loop < globals.mCommandLineOptions.mContexts; loop++) { - if (node->runs[loop]) { - freeRun(node->runs[loop]); - node->runs[loop] = NULL; - } - } - - free(node->runs); - node->runs = NULL; - } - - return PR_TRUE; -} - -#if defined(DEBUG_dp) -PRBool -printNodeProcessor(STRequest * inRequest, STOptions * inOptions, - STContext * inContext, void *clientData, - STCategoryNode * node) -{ - STCategoryNode *root = (STCategoryNode *) clientData; - - fprintf(stderr, "%-25s [ %9s size", node->categoryName, - FormatNumber(node->run ? node->run->mStats[inContext->mIndex]. - mSize : 0)); - fprintf(stderr, ", %5.1f%%", - node->run ? ((double) node->run->mStats[inContext->mIndex].mSize / - root->run->mStats[inContext->mIndex].mSize * - 100) : 0); - fprintf(stderr, ", %7s allocations ]\n", - FormatNumber(node->run ? node->run->mStats[inContext->mIndex]. - mCompositeCount : 0)); - return PR_TRUE; -} - -#endif - -typedef struct __struct_optcon -{ - STOptions *mOptions; - STContext *mContext; -} -optcon; - -/* -** compareNode -** -** qsort callback. -** Compare the nodes as specified by the options. -*/ -int -compareNode(const void *aNode1, const void *aNode2, void *aContext) -{ - int retval = 0; - STCategoryNode *node1, *node2; - uint32_t a, b; - optcon *oc = (optcon *) aContext; - - if (!aNode1 || !aNode2 || !oc->mOptions || !oc->mContext) - return 0; - - node1 = *((STCategoryNode **) aNode1); - node2 = *((STCategoryNode **) aNode2); - - if (node1 && node2) { - if (oc->mOptions->mOrderBy == ST_COUNT) { - a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc-> - mContext-> - mIndex]-> - mStats[oc->mContext->mIndex].mCompositeCount : 0; - b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc-> - mContext-> - mIndex]-> - mStats[oc->mContext->mIndex].mCompositeCount : 0; - } - else { - /* Default is by size */ - a = (node1->runs[oc->mContext->mIndex]) ? node1->runs[oc-> - mContext-> - mIndex]-> - mStats[oc->mContext->mIndex].mSize : 0; - b = (node2->runs[oc->mContext->mIndex]) ? node2->runs[oc-> - mContext-> - mIndex]-> - mStats[oc->mContext->mIndex].mSize : 0; - } - if (a < b) - retval = __LINE__; - else - retval = -__LINE__; - } - return retval; -} - -PRBool -sortNodeProcessor(STRequest * inRequest, STOptions * inOptions, - STContext * inContext, void *clientData, - STCategoryNode * node) -{ - if (node->nchildren) { - optcon context; - - context.mOptions = inOptions; - context.mContext = inContext; - - NS_QuickSort(node->children, node->nchildren, - sizeof(STCategoryNode *), compareNode, &context); - } - - return PR_TRUE; -} - - -/* -** walkTree -** -** General purpose tree walker. Issues callback for each node. -** If 'maxdepth' > 0, then stops after processing that depth. Root is -** depth 0, the nodes below it are depth 1 etc... -*/ -#define MODINC(n, mod) ((n+1) % mod) - -void -walkTree(STCategoryNode * root, STCategoryNodeProcessor func, - STRequest * inRequest, STOptions * inOptions, STContext * inContext, - void *clientData, int maxdepth) -{ - STCategoryNode *nodes[1024], *node; - uint32_t begin, end, i; - int ret = 0; - int curdepth = 0, ncurdepth = 0; - - nodes[0] = root; - begin = 0; - end = 1; - ncurdepth = 1; - while (begin != end) { - node = nodes[begin]; - ret = (*func) (inRequest, inOptions, inContext, clientData, node); - if (!ret) { - /* Abort */ - break; - } - begin = MODINC(begin, 1024); - for (i = 0; i < node->nchildren; i++) { - nodes[end] = node->children[i]; - end = MODINC(end, 1024); - } - /* Depth tracking. Do it only if walkTree is contrained by a maxdepth */ - if (maxdepth > 0 && --ncurdepth == 0) { - /* - ** No more children in current depth. The rest of the nodes - ** we have in our list should be nodes in the depth below us. - */ - ncurdepth = (begin < end) ? (end - begin) : (1024 - begin + end); - if (++curdepth > maxdepth) { - /* - ** Gone too deep. Stop. - */ - break; - } - } - } - return; -} - -int -freeRule(STCategoryRule * rule) -{ - uint32_t i; - char *p = (char *) rule->categoryName; - - PR_FREEIF(p); - - for (i = 0; i < rule->npats; i++) - free(rule->pats[i]); - - free(rule); - return 0; -} - -void -freeNodeRuns(STCategoryNode * root) -{ - walkTree(root, freeNodeRunsProcessor, NULL, NULL, NULL, NULL, 0); -} - -void -freeNodeMap(STGlobals * g) -{ - uint32_t i; - - /* all nodes are in the map table. Just delete all of those. */ - for (i = 0; i < g->mNCategoryMap; i++) { - free(g->mCategoryMap[i]->node); - free(g->mCategoryMap[i]); - } - free(g->mCategoryMap); -} - -int -freeCategories(STGlobals * g) -{ - uint32_t i; - - /* - ** walk the tree and free runs held in nodes - */ - freeNodeRuns(&g->mCategoryRoot); - - /* - ** delete nodemap. This is the where nodes get deleted. - */ - freeNodeMap(g); - - /* - ** delete rule stuff - */ - for (i = 0; i < g->mNRules; i++) { - freeRule(g->mCategoryRules[i]); - } - free(g->mCategoryRules); - - return 0; -} - - -/* -** categorizeRun -** -** categorize all the allocations of the run using the rules into -** a tree rooted at globls.mCategoryRoot -*/ -int -categorizeRun(STOptions * inOptions, STContext * inContext, - const STRun * aRun, STGlobals * g) -{ - uint32_t i; - -#if defined(DEBUG_dp) - PRIntervalTime start = PR_IntervalNow(); - - fprintf(stderr, "DEBUG: categorizing run...\n"); -#endif - - /* - ** First, cleanup our tree - */ - walkTree(&g->mCategoryRoot, freeNodeRunProcessor, NULL, inOptions, - inContext, NULL, 0); - - if (g->mNCategoryMap > 0) { - for (i = 0; i < aRun->mAllocationCount; i++) { - categorizeAllocation(inOptions, inContext, aRun->mAllocations[i], - g); - } - } - - /* - ** the run is always going to be the one corresponding to the root node - */ - g->mCategoryRoot.runs[inContext->mIndex] = (STRun *) aRun; - g->mCategoryRoot.categoryName = ST_ROOT_CATEGORY_NAME; - -#if defined(DEBUG_dp) - fprintf(stderr, - "DEBUG: categorizing ends: %dms [%d rules, %d allocations]\n", - PR_IntervalToMilliseconds(PR_IntervalNow() - start), g->mNRules, - aRun->mAllocationCount); - fprintf(stderr, "DEBUG: match : %dms [%d calls, %d rule-compares]\n", - PR_IntervalToMilliseconds(_gMatchTime), _gMatchCount, - _gMatchRules); -#endif - - /* - ** sort the tree based on our sort criterion - */ - walkTree(&g->mCategoryRoot, sortNodeProcessor, NULL, inOptions, inContext, - NULL, 0); - -#if defined(DEBUG_dp) - walkTree(&g->mCategoryRoot, printNodeProcessor, NULL, inOptions, - inContext, &g->mCategoryRoot, 0); -#endif - - return 0; -} - - -/* -** displayCategoryReport -** -** Generate the category report - a list of all categories and details about each -** depth parameter controls how deep we traverse the category tree. -*/ -PRBool -displayCategoryNodeProcessor(STRequest * inRequest, STOptions * inOptions, - STContext * inContext, void *clientData, - STCategoryNode * node) -{ - STCategoryNode *root = (STCategoryNode *) clientData; - uint32_t byteSize = 0, heapCost = 0, count = 0; - double percent = 0; - STOptions customOps; - - if (node->runs[inContext->mIndex]) { - /* - ** Byte size - */ - byteSize = - node->runs[inContext->mIndex]->mStats[inContext->mIndex].mSize; - - /* - ** Composite count - */ - count = - node->runs[inContext->mIndex]->mStats[inContext->mIndex]. - mCompositeCount; - - /* - ** Heap operation cost - **/ - heapCost = - node->runs[inContext->mIndex]->mStats[inContext->mIndex]. - mHeapRuntimeCost; - - /* - ** % of total size - */ - if (root->runs[inContext->mIndex]) { - percent = - ((double) byteSize) / - root->runs[inContext->mIndex]->mStats[inContext->mIndex]. - mSize * 100; - } - } - - PR_fprintf(inRequest->mFD, " \n" " "); - - /* a link to topcallsites report with focus on category */ - memcpy(&customOps, inOptions, sizeof(customOps)); - PR_snprintf(customOps.mCategoryName, sizeof(customOps.mCategoryName), - "%s", node->categoryName); - - htmlAnchor(inRequest, "top_callsites.html", node->categoryName, NULL, - "category-callsites", &customOps); - PR_fprintf(inRequest->mFD, - "\n" " %u\n" - " %4.1f%%\n" - " %u\n" " " - ST_MICROVAL_FORMAT "\n" " \n", byteSize, percent, - count, ST_MICROVAL_PRINTABLE(heapCost)); - - return PR_TRUE; -} - - -int -displayCategoryReport(STRequest * inRequest, STCategoryNode * root, int depth) -{ - PR_fprintf(inRequest->mFD, - "\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" " \n"); - - walkTree(root, displayCategoryNodeProcessor, inRequest, - &inRequest->mOptions, inRequest->mContext, root, depth); - - PR_fprintf(inRequest->mFD, "
CategoryComposite Byte Size%% of Total SizeHeap Object CountComposite Heap Operations Seconds
\n"); - - return 0; -} diff --git a/tools/trace-malloc/spacetrace.c b/tools/trace-malloc/spacetrace.c deleted file mode 100644 index f101ce9ce9e6..000000000000 --- a/tools/trace-malloc/spacetrace.c +++ /dev/null @@ -1,6352 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -/* -** spacetrace.c -** -** SpaceTrace is meant to take the output of trace-malloc and present -** a picture of allocations over the run of the application. -*/ - -/* -** Required include files. -*/ -#include "spacetrace.h" - -#include -#include -#include -#include -#if defined(XP_WIN32) -#include /* _heapMin */ -#endif - -#if defined(HAVE_BOUTELL_GD) -/* -** See http://www.boutell.com/gd for the GD graphics library. -** Ports for many platorms exist. -** Your box may already have the lib (mine did, redhat 7.1 workstation). -*/ -#include -#include -#include -#include -#endif /* HAVE_BOUTELL_GD */ - -#include "nsQuickSort.h" -/* -** strcasecmp API please. -*/ -#if defined(_MSC_VER) -#define strcasecmp _stricmp -#define strncasecmp _strnicmp -#endif - -/* -** the globals variables. happy joy. -*/ -STGlobals globals; - -/* -** have the heap cleanup at opportune times, if possible. -*/ -void -heapCompact(void) -{ -#if defined(XP_WIN32) - _heapmin(); -#endif -} - -#define ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) \ - PR_fprintf(PR_STDOUT, "--%s\nDisabled by default.\n%s\n", #option_name, option_help); -#define ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - PR_fprintf(PR_STDOUT, "--%s=\nDefault value is \"%s\".\n%s\n", #option_name, default_value, option_help); -#define ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - PR_fprintf(PR_STDOUT, "--%s=\nUp to %u occurrences allowed.\n%s\n", #option_name, array_size, option_help); -#define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) \ - PR_fprintf(PR_STDOUT, "--%s=\nUnlimited occurrences allowed.\n%s\n", #option_name, option_help); -#define ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - PR_fprintf(PR_STDOUT, "--%s=\nDefault value is %u.\n%s\n", #option_name, default_value, option_help); -#define ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - PR_fprintf(PR_STDOUT, "--%s=\nDefault value is %llu.\n%s\n", #option_name, default_value, option_help); - -/* -** showHelp -** -** Give simple command line help. -** Returns !0 if the help was showed. -*/ -int -showHelp(void) -{ - int retval = 0; - - if (PR_FALSE != globals.mCommandLineOptions.mHelp) { - PR_fprintf(PR_STDOUT, "Usage:\t%s [OPTION]... [-|filename]\n\n", - globals.mProgramName); - - -#include "stoptions.h" - - /* - ** Showed something. - */ - retval = __LINE__; - } - - return retval; -} - -/* -** ticks2xsec -** -** Convert platform specific ticks to second units -** Returns 0 on success. -*/ -uint32_t -ticks2xsec(tmreader * aReader, uint32_t aTicks, uint32_t aResolution) -{ - return (uint32_t)((aResolution * aTicks)/aReader->ticksPerSec); -} - -#define ticks2msec(reader, ticks) ticks2xsec((reader), (ticks), 1000) -#define ticks2usec(reader, ticks) ticks2xsec((reader), (ticks), 1000000) - -/* -** initOptions -** -** Determine global settings for the application. -** Returns 0 on success. -*/ -int -initOptions(int aArgCount, char **aArgArray) -{ - int retval = 0; - int traverse = 0; - - /* - ** Set the initial global default options. - */ -#define ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) globals.mCommandLineOptions.m##option_name = PR_FALSE; -#define ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) PR_snprintf(globals.mCommandLineOptions.m##option_name, sizeof(globals.mCommandLineOptions.m##option_name), "%s", default_value); -#define ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) { int loop; for(loop = 0; loop < array_size; loop++) { globals.mCommandLineOptions.m##option_name[loop][0] = '\0'; } } -#define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) globals.mCommandLineOptions.m##option_name = NULL; globals.mCommandLineOptions.m##option_name##Count = 0; -#define ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) globals.mCommandLineOptions.m##option_name = default_value * multiplier; -#define ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) { uint64_t def64 = default_value; uint64_t mul64 = multiplier; globals.mCommandLineOptions.m##option_name##64 = def64 * mul64; } - -#include "stoptions.h" - - /* - ** Go through all arguments. - ** Two dashes lead off an option. - ** Any single dash leads off help, unless it is a lone dash (stdin). - ** Anything else will be attempted as a file to be processed. - */ - for (traverse = 1; traverse < aArgCount; traverse++) { - if ('-' == aArgArray[traverse][0] && '-' == aArgArray[traverse][1]) { - const char *option = &aArgArray[traverse][2]; - - /* - ** Initial if(0) needed to make "else if"s valid. - */ - if (0) { - } - -#define ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) \ - else if(0 == strcasecmp(option, #option_name)) \ - { \ - globals.mCommandLineOptions.m##option_name = PR_TRUE; \ - } -#define ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - else if(0 == strncasecmp(option, #option_name "=", strlen(#option_name "="))) \ - { \ - PR_snprintf(globals.mCommandLineOptions.m##option_name, sizeof(globals.mCommandLineOptions.m##option_name), "%s", option + strlen(#option_name "=")); \ - } -#define ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - else if(0 == strncasecmp(option, #option_name "=", strlen(#option_name "="))) \ - { \ - int arrLoop = 0; \ - \ - for(arrLoop = 0; arrLoop < array_size; arrLoop++) \ - { \ - if('\0' == globals.mCommandLineOptions.m##option_name[arrLoop][0]) \ - { \ - break; \ - } \ - }\ - \ - if(arrLoop != array_size) \ - { \ - PR_snprintf(globals.mCommandLineOptions.m##option_name[arrLoop], sizeof(globals.mCommandLineOptions.m##option_name[arrLoop]), "%s", option + strlen(#option_name "=")); \ - } \ - else \ - { \ - REPORT_ERROR_MSG(__LINE__, option); \ - retval = __LINE__; \ - globals.mCommandLineOptions.mHelp = PR_TRUE; \ - } \ - } -#define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) \ - else if(0 == strncasecmp(option, #option_name "=", strlen(#option_name "="))) \ - { \ - const char** expand = NULL; \ - \ - expand = (const char**)realloc((void*)globals.mCommandLineOptions.m##option_name, sizeof(const char*) * (globals.mCommandLineOptions.m##option_name##Count + 1)); \ - if(NULL != expand) \ - { \ - globals.mCommandLineOptions.m##option_name = expand; \ - globals.mCommandLineOptions.m##option_name[globals.mCommandLineOptions.m##option_name##Count] = option + strlen(#option_name "="); \ - globals.mCommandLineOptions.m##option_name##Count++; \ - } \ - else \ - { \ - retval = __LINE__; \ - globals.mCommandLineOptions.mHelp = PR_TRUE; \ - } \ - } -#define ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - else if(0 == strncasecmp(option, #option_name "=", strlen(#option_name "="))) \ - { \ - int32_t scanRes = 0; \ - \ - scanRes = PR_sscanf(option + strlen(#option_name "="), "%u", &globals.mCommandLineOptions.m##option_name); \ - if(1 != scanRes) \ - { \ - REPORT_ERROR_MSG(__LINE__, option); \ - retval = __LINE__; \ - globals.mCommandLineOptions.mHelp = PR_TRUE; \ - } \ - } -#define ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - else if(0 == strncasecmp(option, #option_name "=", strlen(#option_name "="))) \ - { \ - int32_t scanRes = 0; \ - \ - scanRes = PR_sscanf(option + strlen(#option_name "="), "%llu", &globals.mCommandLineOptions.m##option_name##64); \ - if(1 != scanRes) \ - { \ - REPORT_ERROR_MSG(__LINE__, option); \ - retval = __LINE__; \ - globals.mCommandLineOptions.mHelp = PR_TRUE; \ - } \ - } - -#include "stoptions.h" - - /* - ** If no match on options, this else will get hit. - */ - else { - REPORT_ERROR_MSG(__LINE__, option); - retval = __LINE__; - globals.mCommandLineOptions.mHelp = PR_TRUE; - } - } - else if ('-' == aArgArray[traverse][0] - && '\0' != aArgArray[traverse][1]) { - /* - ** Show help, bad/legacy option. - */ - REPORT_ERROR_MSG(__LINE__, aArgArray[traverse]); - retval = __LINE__; - globals.mCommandLineOptions.mHelp = PR_TRUE; - } - else { - /* - ** Default is same as FileName option, the file to process. - */ - PR_snprintf(globals.mCommandLineOptions.mFileName, - sizeof(globals.mCommandLineOptions.mFileName), "%s", - aArgArray[traverse]); - } - } - - /* - ** initialize the categories - */ - initCategories(&globals); - - return retval; -} - -#if ST_WANT_GRAPHS -/* -** createGraph -** -** Create a GD image with the common properties of a graph. -** Upon return, you normally allocate legend colors, -** draw your graph inside the region -** STGD_MARGIN,STGD_MARGIN,STGD_WIDTH-STGD_MARGIN,STGD_HEIGH-STGD_MARGIN, -** and then call drawGraph to format the surrounding information. -** -** You should use the normal GD image release function, gdImageDestroy -** when done with it. -** -** Image attributes: -** STGD_WIDTHxSTGD_HEIGHT -** trasparent (white) background -** incremental display -*/ -gdImagePtr -createGraph(int *aTransparencyColor) -{ - gdImagePtr retval = NULL; - - if (NULL != aTransparencyColor) { - *aTransparencyColor = -1; - - retval = gdImageCreate(STGD_WIDTH, STGD_HEIGHT); - if (NULL != retval) { - /* - ** Background color (first one). - */ - *aTransparencyColor = gdImageColorAllocate(retval, 255, 255, 255); - if (-1 != *aTransparencyColor) { - /* - ** As transparency. - */ - gdImageColorTransparent(retval, *aTransparencyColor); - } - - /* - ** And to set interlacing. - */ - gdImageInterlace(retval, 1); - } - else { - REPORT_ERROR(__LINE__, gdImageCreate); - } - } - else { - REPORT_ERROR(__LINE__, createGraph); - } - - return retval; -} -#endif /* ST_WANT_GRAPHS */ - -#if ST_WANT_GRAPHS -/* -** drawGraph -** -** This function mainly exists to simplify putitng all the pretty lace -** around a home made graph. -*/ -void -drawGraph(gdImagePtr aImage, int aColor, - const char *aGraphTitle, - const char *aXAxisTitle, - const char *aYAxisTitle, - uint32_t aXMarkCount, - uint32_t * aXMarkPercents, - const char **aXMarkTexts, - uint32_t aYMarkCount, - uint32_t * aYMarkPercents, - const char **aYMarkTexts, - uint32_t aLegendCount, - int *aLegendColors, const char **aLegendTexts) -{ - if (NULL != aImage && NULL != aGraphTitle && - NULL != aXAxisTitle && NULL != aYAxisTitle && - (0 == aXMarkCount || (NULL != aXMarkPercents && NULL != aXMarkTexts)) - && (0 == aYMarkCount - || (NULL != aYMarkPercents && NULL != aYMarkTexts)) - && (0 == aLegendCount - || (NULL != aLegendColors && NULL != aLegendTexts))) { - int margin = 1; - uint32_t traverse = 0; - uint32_t target = 0; - const int markSize = 2; - int x1 = 0; - int y1 = 0; - int x2 = 0; - int y2 = 0; - time_t theTimeT = time(NULL); - char *theTime = ctime(&theTimeT); - const char *logo = "SpaceTrace"; - gdFontPtr titleFont = gdFontMediumBold; - gdFontPtr markFont = gdFontTiny; - gdFontPtr dateFont = gdFontTiny; - gdFontPtr axisFont = gdFontSmall; - gdFontPtr legendFont = gdFontTiny; - gdFontPtr logoFont = gdFontTiny; - - /* - ** Fixup the color. - ** Black by default. - */ - if (-1 == aColor) { - aColor = gdImageColorAllocate(aImage, 0, 0, 0); - } - if (-1 == aColor) { - aColor = gdImageColorClosest(aImage, 0, 0, 0); - } - - /* - ** Output the box. - */ - x1 = STGD_MARGIN - margin; - y1 = STGD_MARGIN - margin; - x2 = STGD_WIDTH - x1; - y2 = STGD_HEIGHT - y1; - gdImageRectangle(aImage, x1, y1, x2, y2, aColor); - margin++; - - /* - ** Need to make small markings on the graph to indicate where the - ** labels line up exactly. - ** While we're at it, draw the label text. - */ - for (traverse = 0; traverse < aXMarkCount; traverse++) { - target = - ((STGD_WIDTH - - (STGD_MARGIN * 2)) * aXMarkPercents[traverse]) / 100; - - x1 = STGD_MARGIN + target; - y1 = STGD_MARGIN - margin; - x2 = x1; - y2 = y1 - markSize; - gdImageLine(aImage, x1, y1, x2, y2, aColor); - - y1 = STGD_HEIGHT - y1; - y2 = STGD_HEIGHT - y2; - gdImageLine(aImage, x1, y1, x2, y2, aColor); - - if (NULL != aXMarkTexts[traverse]) { - x1 = STGD_MARGIN + target - (markFont->h / 2); - y1 = STGD_HEIGHT - STGD_MARGIN + margin + markSize + - (strlen(aXMarkTexts[traverse]) * markFont->w); - gdImageStringUp(aImage, markFont, x1, y1, - (unsigned char *) aXMarkTexts[traverse], - aColor); - } - } - for (traverse = 0; traverse < aYMarkCount; traverse++) { - target = - ((STGD_HEIGHT - (STGD_MARGIN * 2)) * (100 - - aYMarkPercents - [traverse])) / 100; - - x1 = STGD_MARGIN - margin; - y1 = STGD_MARGIN + target; - x2 = x1 - markSize; - y2 = y1; - gdImageLine(aImage, x1, y1, x2, y2, aColor); - - x1 = STGD_WIDTH - x1; - x2 = STGD_WIDTH - x2; - gdImageLine(aImage, x1, y1, x2, y2, aColor); - - if (NULL != aYMarkTexts[traverse]) { - x1 = STGD_MARGIN - margin - markSize - - (strlen(aYMarkTexts[traverse]) * markFont->w); - y1 = STGD_MARGIN + target - (markFont->h / 2); - gdImageString(aImage, markFont, x1, y1, - (unsigned char *) aYMarkTexts[traverse], - aColor); - } - } - margin += markSize; - - /* - ** Title will be centered above the image. - */ - x1 = (STGD_WIDTH / 2) - ((strlen(aGraphTitle) * titleFont->w) / 2); - y1 = ((STGD_MARGIN - margin) / 2) - (titleFont->h / 2); - gdImageString(aImage, titleFont, x1, y1, - (unsigned char *) aGraphTitle, aColor); - - /* - ** Upper left will be the date. - */ - x1 = 0; - y1 = 0; - traverse = strlen(theTime) - 1; - if (isspace(theTime[traverse])) { - theTime[traverse] = '\0'; - } - gdImageString(aImage, dateFont, x1, y1, (unsigned char *) theTime, - aColor); - - /* - ** Lower right will be the logo. - */ - x1 = STGD_WIDTH - (strlen(logo) * logoFont->w); - y1 = STGD_HEIGHT - logoFont->h; - gdImageString(aImage, logoFont, x1, y1, (unsigned char *) logo, - aColor); - - /* - ** X and Y axis titles - */ - x1 = (STGD_WIDTH / 2) - ((strlen(aXAxisTitle) * axisFont->w) / 2); - y1 = STGD_HEIGHT - axisFont->h; - gdImageString(aImage, axisFont, x1, y1, (unsigned char *) aXAxisTitle, - aColor); - x1 = 0; - y1 = (STGD_HEIGHT / 2) + ((strlen(aYAxisTitle) * axisFont->w) / 2); - gdImageStringUp(aImage, axisFont, x1, y1, - (unsigned char *) aYAxisTitle, aColor); - - /* - ** The legend. - ** Centered on the right hand side, going up. - */ - x1 = STGD_WIDTH - STGD_MARGIN + margin + - (aLegendCount * legendFont->h) / 2; - x2 = STGD_WIDTH - (aLegendCount * legendFont->h); - if (x1 > x2) { - x1 = x2; - } - - y1 = 0; - for (traverse = 0; traverse < aLegendCount; traverse++) { - y2 = (STGD_HEIGHT / 2) + - ((strlen(aLegendTexts[traverse]) * legendFont->w) / 2); - if (y2 > y1) { - y1 = y2; - } - } - for (traverse = 0; traverse < aLegendCount; traverse++) { - gdImageStringUp(aImage, legendFont, x1, y1, - (unsigned char *) aLegendTexts[traverse], - aLegendColors[traverse]); - x1 += legendFont->h; - } - } -} - -#endif /* ST_WANT_GRAPHS */ - -#if defined(HAVE_BOUTELL_GD) -/* -** pngSink -** -** GD callback, used to write out the png. -*/ -int -pngSink(void *aContext, const char *aBuffer, int aLen) -{ - return PR_Write((PRFileDesc *) aContext, aBuffer, aLen); -} -#endif /* HAVE_BOUTELL_GD */ - -/* -** FormatNumber -** -** Formats a number with thousands separator. Don't free the result. Returns -** static data. -*/ -char * -FormatNumber(int32_t num) -{ - static char buf[64]; - char tmpbuf[64]; - int len = 0; - int bufindex = sizeof(buf) - 1; - int mod3; - - PR_snprintf(tmpbuf, sizeof(tmpbuf), "%d", num); - - /* now insert the thousands separator */ - mod3 = 0; - len = strlen(tmpbuf); - while (len >= 0) { - if (tmpbuf[len] >= '0' && tmpbuf[len] <= '9') { - if (mod3 == 3) { - buf[bufindex--] = ','; - mod3 = 0; - } - mod3++; - } - buf[bufindex--] = tmpbuf[len--]; - } - return buf + bufindex + 1; -} - -/* -** actualByteSize -** -** Apply alignment and overhead to size to figure out actual byte size -*/ -uint32_t -actualByteSize(STOptions * inOptions, uint32_t retval) -{ - /* - ** Need to bump the result by our alignment and overhead. - ** The idea here is that an allocation actually costs you more than you - ** thought. - ** - ** The msvcrt malloc has an alignment of 16 with an overhead of 8. - ** The win32 HeapAlloc has an alignment of 8 with an overhead of 8. - */ - if (0 != retval) { - uint32_t eval = 0; - uint32_t over = 0; - - eval = retval - 1; - if (0 != inOptions->mAlignBy) { - over = eval % inOptions->mAlignBy; - } - retval = eval + inOptions->mOverhead + inOptions->mAlignBy - over; - } - - return retval; -} - -/* -** byteSize -** -** Figuring the byte size of an allocation. -** Might expand in the future to report size at a given time. -** For now, just use last relevant event. -*/ -uint32_t -byteSize(STOptions * inOptions, STAllocation * aAlloc) -{ - uint32_t retval = 0; - - if (NULL != aAlloc && 0 != aAlloc->mEventCount) { - uint32_t index = aAlloc->mEventCount; - - /* - ** Generally, the size is the last event's size. - */ - do { - index--; - retval = aAlloc->mEvents[index].mHeapSize; - } - while (0 == retval && 0 != index); - } - return actualByteSize(inOptions, retval); -} - - -/* -** recalculateAllocationCost -** -** Given an allocation, does a recalculation of Cost - weight, heapcount etc. -** and does the right thing to propagate the cost upwards. -*/ -int -recalculateAllocationCost(STOptions * inOptions, STContext * inContext, - STRun * aRun, STAllocation * aAllocation, - PRBool updateParent) -{ - /* - ** Now, see if they desire a callsite update. - ** As mentioned previously, we decide if the run desires us to - ** manipulate the callsite data only if its stamp is set. - ** We change all callsites and parent callsites to have that - ** stamp as well, so as to mark them as being relevant to - ** the current run in question. - */ - if (NULL != inContext && 0 != aRun->mStats[inContext->mIndex].mStamp) { - uint32_t timeval = - aAllocation->mMaxTimeval - aAllocation->mMinTimeval; - uint32_t size = byteSize(inOptions, aAllocation); - uint32_t heapCost = aAllocation->mHeapRuntimeCost; - uint64_t timeval64 = timeval; - uint64_t size64 = size; - uint64_t weight64 = timeval64 * size64; - - /* - ** First, update this run. - */ - aRun->mStats[inContext->mIndex].mCompositeCount++; - aRun->mStats[inContext->mIndex].mHeapRuntimeCost += heapCost; - aRun->mStats[inContext->mIndex].mSize += size; - aRun->mStats[inContext->mIndex].mTimeval64 += timeval64; - aRun->mStats[inContext->mIndex].mWeight64 += weight64; - - /* - ** Use the first event of the allocation to update the parent - ** callsites. - ** This has positive effect of not updating realloc callsites - ** with the same data over and over again. - */ - if (updateParent && 0 < aAllocation->mEventCount) { - tmcallsite *callsite = aAllocation->mEvents[0].mCallsite; - STRun *callsiteRun = NULL; - - /* - ** Go up parents till we drop. - */ - while (NULL != callsite && NULL != callsite->method) { - callsiteRun = CALLSITE_RUN(callsite); - if (NULL != callsiteRun) { - /* - ** Do we init it? - */ - if (callsiteRun->mStats[inContext->mIndex].mStamp != - aRun->mStats[inContext->mIndex].mStamp) { - memset(&callsiteRun->mStats[inContext->mIndex], 0, - sizeof(STCallsiteStats)); - callsiteRun->mStats[inContext->mIndex].mStamp = - aRun->mStats[inContext->mIndex].mStamp; - } - - /* - ** Add the values. - ** Note that if the allocation was ever realloced, - ** we are actually recording the final size. - ** Also, the composite count does not include - ** calls to realloc (or free for that matter), - ** but rather is simply a count of actual heap - ** allocation objects, from which someone will - ** draw conclusions regarding number of malloc - ** and free calls. - ** It is possible to generate the exact number - ** of calls to free/malloc/realloc should the - ** absolute need arise to count them individually, - ** but I fear it will take mucho memory and this - ** is perhaps good enough for now. - */ - callsiteRun->mStats[inContext->mIndex].mCompositeCount++; - callsiteRun->mStats[inContext->mIndex].mHeapRuntimeCost += - heapCost; - callsiteRun->mStats[inContext->mIndex].mSize += size; - callsiteRun->mStats[inContext->mIndex].mTimeval64 += - timeval64; - callsiteRun->mStats[inContext->mIndex].mWeight64 += - weight64; - } - - callsite = callsite->parent; - } - } - } - - return 0; -} - - -/* -** appendAllocation -** -** Given a run, append the allocation to it. -** No DUP checks are done. -** Also, we might want to update the parent callsites with stats. -** We decide to do this heavy duty work only if the run we are appending -** to has a non ZERO mStats[].mStamp, meaning that it is asking to track -** such information when it was created. -** Returns !0 on success. -*/ -int -appendAllocation(STOptions * inOptions, STContext * inContext, - STRun * aRun, STAllocation * aAllocation) -{ - int retval = 0; - - if (NULL != aRun && NULL != aAllocation && NULL != inOptions) { - STAllocation **expand = NULL; - - /* - ** Expand the size of the array if needed. - */ - expand = (STAllocation **) realloc(aRun->mAllocations, - sizeof(STAllocation *) * - (aRun->mAllocationCount + 1)); - if (NULL != expand) { - /* - ** Reassign in case of pointer move. - */ - aRun->mAllocations = expand; - - /* - ** Stick the allocation in. - */ - aRun->mAllocations[aRun->mAllocationCount] = aAllocation; - - /* - ** If this is the global run, we need to let the allocation - ** track the index back to us. - */ - if (&globals.mRun == aRun) { - aAllocation->mRunIndex = aRun->mAllocationCount; - } - - /* - ** Increase the count. - */ - aRun->mAllocationCount++; - - /* - ** We're good. - */ - retval = __LINE__; - - /* - ** update allocation cost - */ - recalculateAllocationCost(inOptions, inContext, aRun, aAllocation, - PR_TRUE); - } - else { - REPORT_ERROR(__LINE__, appendAllocation); - } - } - else { - REPORT_ERROR(__LINE__, appendAllocation); - } - - return retval; -} - -/* -** hasCallsiteMatch -** -** Determine if the callsite or the other callsites has the matching text. -** -** Returns 0 if there is no match. -*/ -int -hasCallsiteMatch(tmcallsite * aCallsite, const char *aMatch, int aDirection) -{ - int retval = 0; - - if (NULL != aCallsite && NULL != aCallsite->method && - NULL != aMatch && '\0' != *aMatch) { - const char *methodName = NULL; - - do { - methodName = tmmethodnode_name(aCallsite->method); - if (NULL != methodName && NULL != strstr(methodName, aMatch)) { - /* - ** Contains the text. - */ - retval = __LINE__; - break; - } - else { - switch (aDirection) { - case ST_FOLLOW_SIBLINGS: - aCallsite = aCallsite->siblings; - break; - case ST_FOLLOW_PARENTS: - aCallsite = aCallsite->parent; - break; - default: - aCallsite = NULL; - REPORT_ERROR(__LINE__, hasCallsiteMatch); - break; - } - } - } - while (NULL != aCallsite && NULL != aCallsite->method); - } - else { - REPORT_ERROR(__LINE__, hasCallsiteMatch); - } - - return retval; -} - -/* -** harvestRun -** -** Provide a simply way to go over a run, and yield the relevant allocations. -** The restrictions are easily set via the options page or the command -** line switches. -** -** On any match, add the allocation to the provided run. -** -** This makes it much easier for all the code to respect the options in -** force. -** -** Returns !0 on error, though aOutRun may contain a partial data set. -*/ -int -harvestRun(const STRun * aInRun, STRun * aOutRun, - STOptions * aOptions, STContext * inContext) -{ - int retval = 0; - -#if defined(DEBUG_dp) - PRIntervalTime start = PR_IntervalNow(); - - fprintf(stderr, "DEBUG: harvesting run...\n"); -#endif - - if (NULL != aInRun && NULL != aOutRun && aInRun != aOutRun - && NULL != aOptions && NULL != inContext) { - uint32_t traverse = 0; - STAllocation *current = NULL; - - for (traverse = 0; - 0 == retval && traverse < aInRun->mAllocationCount; traverse++) { - current = aInRun->mAllocations[traverse]; - if (NULL != current) { - uint32_t lifetime = 0; - uint32_t bytesize = 0; - uint64_t weight64 = 0; - uint64_t bytesize64 = 0; - uint64_t lifetime64 = 0; - int appendRes = 0; - int looper = 0; - PRBool matched = PR_FALSE; - - /* - ** Use this as an opportune time to fixup a memory - ** leaked timeval, so as to not completely skew - ** the weights. - */ - if (ST_TIMEVAL_MAX == current->mMaxTimeval) { - current->mMaxTimeval = globals.mMaxTimeval; - } - - /* - ** Check allocation timeval restrictions. - ** We have to slide the recorded timevals to be zero - ** based, so that the comparisons make sense. - */ - if ((aOptions->mAllocationTimevalMin > - (current->mMinTimeval - globals.mMinTimeval)) || - (aOptions->mAllocationTimevalMax < - (current->mMinTimeval - globals.mMinTimeval))) { - continue; - } - - /* - ** Check timeval restrictions. - ** We have to slide the recorded timevals to be zero - ** based, so that the comparisons make sense. - */ - if ((aOptions->mTimevalMin > - (current->mMinTimeval - globals.mMinTimeval)) || - (aOptions->mTimevalMax < - (current->mMinTimeval - globals.mMinTimeval))) { - continue; - } - - /* - ** Check lifetime restrictions. - */ - lifetime = current->mMaxTimeval - current->mMinTimeval; - if ((lifetime < aOptions->mLifetimeMin) || - (lifetime > aOptions->mLifetimeMax)) { - continue; - } - - /* - ** Check byte size restrictions. - */ - bytesize = byteSize(aOptions, current); - if ((bytesize < aOptions->mSizeMin) || - (bytesize > aOptions->mSizeMax)) { - continue; - } - - /* - ** Check weight restrictions. - */ - weight64 = (uint64_t)(bytesize * lifetime); - if (weight64 < aOptions->mWeightMin64 || - weight64 > aOptions->mWeightMax64) { - continue; - } - - /* - ** Possibly restrict the callsite by text. - ** Do this last, as it is a heavier check. - ** - ** One day, we may need to expand the logic to check for - ** events beyond the initial allocation event. - */ - for (looper = 0; ST_SUBSTRING_MATCH_MAX > looper; looper++) { - if ('\0' != aOptions->mRestrictText[looper][0]) { - if (0 == - hasCallsiteMatch(current->mEvents[0].mCallsite, - aOptions->mRestrictText[looper], - ST_FOLLOW_PARENTS)) { - break; - } - } - else { - matched = PR_TRUE; - break; - } - } - if (ST_SUBSTRING_MATCH_MAX == looper) { - matched = PR_TRUE; - } - if (PR_FALSE == matched) { - continue; - } - - /* - ** You get here, we add to the run. - */ - appendRes = - appendAllocation(aOptions, inContext, aOutRun, current); - if (0 == appendRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, appendAllocation); - } - } - } - } - -#if defined(DEBUG_dp) - fprintf(stderr, "DEBUG: harvesting ends: %dms [%d allocations]\n", - PR_IntervalToMilliseconds(PR_IntervalNow() - start), - aInRun->mAllocationCount); -#endif - return retval; -} - -/* -** recalculateRunCost -** -** Goes over all allocations of a run and recalculates and propagates -** the allocation costs - weight, heapcount, size -*/ -int -recalculateRunCost(STOptions * inOptions, STContext * inContext, STRun * aRun) -{ - uint32_t traverse = 0; - STAllocation *current = NULL; - -#if defined(DEBUG_dp) - PRIntervalTime start = PR_IntervalNow(); - - fprintf(stderr, "DEBUG: recalculateRunCost...\n"); -#endif - - if (NULL == aRun) - return -1; - - /* reset stats of this run to 0 to begin recalculation */ - memset(&aRun->mStats[inContext->mIndex], 0, sizeof(STCallsiteStats)); - - /* reset timestamp to force propogation of cost */ - aRun->mStats[inContext->mIndex].mStamp = PR_IntervalNow(); - - for (traverse = 0; traverse < aRun->mAllocationCount; traverse++) { - current = aRun->mAllocations[traverse]; - if (NULL != current) { - recalculateAllocationCost(inOptions, inContext, aRun, current, - PR_TRUE); - } - } - -#if defined(DEBUG_dp) - fprintf(stderr, "DEBUG: recalculateRunCost ends: %dms [%d allocations]\n", - PR_IntervalToMilliseconds(PR_IntervalNow() - start), - aRun->mAllocationCount); -#endif - - return 0; -} - - -/* -** compareAllocations -** -** qsort callback. -** Compare the allocations as specified by the options. -*/ -int -compareAllocations(const void *aAlloc1, const void *aAlloc2, void *aContext) -{ - int retval = 0; - STOptions *inOptions = (STOptions *) aContext; - - if (NULL != aAlloc1 && NULL != aAlloc2 && NULL != inOptions) { - STAllocation *alloc1 = *((STAllocation **) aAlloc1); - STAllocation *alloc2 = *((STAllocation **) aAlloc2); - - if (NULL != alloc1 && NULL != alloc2) { - /* - ** Logic determined by pref/option. - */ - switch (inOptions->mOrderBy) { - case ST_COUNT: - /* - ** "By count" on a single allocation means nothing, - ** fall through to weight. - */ - case ST_WEIGHT: - { - uint64_t weight164 = 0; - uint64_t weight264 = 0; - uint64_t bytesize164 = 0; - uint64_t bytesize264 = 0; - uint64_t timeval164 = 0; - uint64_t timeval264 = 0; - - bytesize164 = byteSize(inOptions, alloc1); - timeval164 = alloc1->mMaxTimeval - alloc1->mMinTimeval; - weight164 = bytesize164 * timeval164; - bytesize264 = byteSize(inOptions, alloc2); - timeval264 = alloc2->mMaxTimeval - alloc2->mMinTimeval; - weight264 = bytesize264 * timeval264; - - if (weight164 < weight264) { - retval = __LINE__; - } - else if (weight164 > weight264) { - retval = -__LINE__; - } - } - break; - - case ST_SIZE: - { - uint32_t size1 = byteSize(inOptions, alloc1); - uint32_t size2 = byteSize(inOptions, alloc2); - - if (size1 < size2) { - retval = __LINE__; - } - else if (size1 > size2) { - retval = -__LINE__; - } - } - break; - - case ST_TIMEVAL: - { - uint32_t timeval1 = - (alloc1->mMaxTimeval - alloc1->mMinTimeval); - uint32_t timeval2 = - (alloc2->mMaxTimeval - alloc2->mMinTimeval); - - if (timeval1 < timeval2) { - retval = __LINE__; - } - else if (timeval1 > timeval2) { - retval = -__LINE__; - } - } - break; - - case ST_HEAPCOST: - { - uint32_t cost1 = alloc1->mHeapRuntimeCost; - uint32_t cost2 = alloc2->mHeapRuntimeCost; - - if (cost1 < cost2) { - retval = __LINE__; - } - else if (cost1 > cost2) { - retval = -__LINE__; - } - } - break; - - default: - { - REPORT_ERROR(__LINE__, compareAllocations); - } - break; - } - } - } - - return retval; -} - -/* -** sortRun -** -** Given a run, sort it in the manner specified by the options. -** Returns !0 on failure. -*/ -int -sortRun(STOptions * inOptions, STRun * aRun) -{ - int retval = 0; - - if (NULL != aRun && NULL != inOptions) { - if (NULL != aRun->mAllocations && 0 < aRun->mAllocationCount) { - NS_QuickSort(aRun->mAllocations, aRun->mAllocationCount, - sizeof(STAllocation *), compareAllocations, - inOptions); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, sortRun); - } - - return retval; -} - -/* -** createRun -** -** Returns a newly allocated run, properly initialized. -** Must call freeRun() with the new STRun. -** -** ONLY PASS IN A NON_ZERO STAMP IF YOU KNOW WHAT YOU ARE DOING!!! -** A non zero stamp in a run has side effects all over the -** callsites of the allocations added to the run and their -** parents. -** -** Returns NULL on failure. -*/ -STRun * -createRun(STContext * inContext, uint32_t aStamp) -{ - STRun *retval = NULL; - - retval = (STRun *) calloc(1, sizeof(STRun)); - if (NULL != retval) { - retval->mStats = - (STCallsiteStats *) calloc(globals.mCommandLineOptions.mContexts, - sizeof(STCallsiteStats)); - if (NULL != retval->mStats) { - if (NULL != inContext) { - retval->mStats[inContext->mIndex].mStamp = aStamp; - } - } - else { - free(retval); - retval = NULL; - } - } - - return retval; -} - -/* -** freeRun -** -** Free off the run and the associated data. -*/ -void -freeRun(STRun * aRun) -{ - if (NULL != aRun) { - if (NULL != aRun->mAllocations) { - /* - ** We do not free the allocations themselves. - ** They are likely pointed to by at least 2 other existing - ** runs. - */ - free(aRun->mAllocations); - aRun->mAllocations = NULL; - } - - if (NULL != aRun->mStats) { - free(aRun->mStats); - aRun->mStats = NULL; - } - - free(aRun); - aRun = NULL; - } -} - -/* -** createRunFromGlobal -** -** Harvest the global run, then sort it. -** Returns NULL on failure. -** Must call freeRun() with the new STRun. -*/ -STRun * -createRunFromGlobal(STOptions * inOptions, STContext * inContext) -{ - STRun *retval = NULL; - - if (NULL != inOptions && NULL != inContext) { - /* - ** We stamp the run. - ** As things are appended to it, it realizes that it should stamp the - ** callsite backtrace with the information as well. - ** In this manner, we can provide meaningful callsite data. - */ - retval = createRun(inContext, PR_IntervalNow()); - - if (NULL != retval) { - STCategoryNode *node = NULL; - int failure = 0; - int harvestRes = - harvestRun(&globals.mRun, retval, inOptions, inContext); - if (0 == harvestRes) { - int sortRes = sortRun(inOptions, retval); - - if (0 != sortRes) { - failure = __LINE__; - } - } - else { - failure = __LINE__; - } - - - if (0 != failure) { - freeRun(retval); - retval = NULL; - - REPORT_ERROR(failure, createRunFromGlobal); - } - - /* - ** Categorize the run. - */ - failure = categorizeRun(inOptions, inContext, retval, &globals); - if (0 != failure) { - REPORT_ERROR(__LINE__, categorizeRun); - } - - /* - ** if we are focussing on a category, return that run instead of - ** the harvested run. Make sure to recalculate cost. - */ - node = findCategoryNode(inOptions->mCategoryName, &globals); - if (node) { - /* Recalculate cost of run */ - recalculateRunCost(inOptions, inContext, - node->runs[inContext->mIndex]); - - retval = node->runs[inContext->mIndex]; - } - } - } - else { - REPORT_ERROR(__LINE__, createRunFromGlobal); - } - - return retval; -} - -/* -** getLiveAllocationByHeapID -** -** Go through a run and find the right heap ID. -** At the time of the call to this function, the allocation must be LIVE, -** meaning that it can not be freed. -** Go through the run backwards, in hopes of finding it near the end. -** -** Returns the allocation on success, otherwise NULL. -*/ -STAllocation * -getLiveAllocationByHeapID(STRun * aRun, uint32_t aHeapID) -{ - STAllocation *retval = NULL; - - if (NULL != aRun && 0 != aHeapID) { - uint32_t traverse = aRun->mAllocationCount; - STAllocation *eval = NULL; - - /* - ** Go through in reverse order. - ** Stop when we have a return value. - */ - while (0 < traverse && NULL == retval) { - /* - ** Back up one to align with zero based index. - */ - traverse--; - - /* - ** Take the pointer math out of further operations. - */ - eval = aRun->mAllocations[traverse]; - - /* - ** Take a look at the events in reverse order. - ** Basically the last event must NOT be a free. - ** The last event must NOT be a realloc of size zero (free). - ** Otherwise, try to match up the heapID of the event. - */ - if (0 != eval->mEventCount) { - STAllocEvent *event = eval->mEvents + (eval->mEventCount - 1); - - switch (event->mEventType) { - case TM_EVENT_FREE: - { - /* - ** No freed allocation can match. - */ - } - break; - - case TM_EVENT_REALLOC: - case TM_EVENT_CALLOC: - case TM_EVENT_MALLOC: - { - /* - ** Heap IDs must match. - */ - if (aHeapID == event->mHeapID) { - retval = eval; - } - } - break; - - default: - { - REPORT_ERROR(__LINE__, getAllocationByHeapID); - } - break; - } - } - } - } - else { - REPORT_ERROR(__LINE__, getAllocationByHeapID); - } - - return retval; -} - -/* -** appendEvent -** -** Given an allocation, append a new event to its lifetime. -** Returns the new event on success, otherwise NULL. -*/ -STAllocEvent * -appendEvent(STAllocation * aAllocation, uint32_t aTimeval, char aEventType, - uint32_t aHeapID, uint32_t aHeapSize, tmcallsite * aCallsite) -{ - STAllocEvent *retval = NULL; - - if (NULL != aAllocation && NULL != aCallsite) { - STAllocEvent *expand = NULL; - - /* - ** Expand the allocation's event array. - */ - expand = - (STAllocEvent *) realloc(aAllocation->mEvents, - sizeof(STAllocEvent) * - (aAllocation->mEventCount + 1)); - if (NULL != expand) { - /* - ** Reassign in case of pointer move. - */ - aAllocation->mEvents = expand; - - /* - ** Remove the pointer math from rest of code. - */ - retval = aAllocation->mEvents + aAllocation->mEventCount; - - /* - ** Increase event array count. - */ - aAllocation->mEventCount++; - - /* - ** Fill in the event. - */ - retval->mTimeval = aTimeval; - retval->mEventType = aEventType; - retval->mHeapID = aHeapID; - retval->mHeapSize = aHeapSize; - retval->mCallsite = aCallsite; - - /* - ** Allocation may need to update idea of lifetime. - ** See allocationTracker to see mMinTimeval inited to ST_TIMEVAL_MAX. - */ - if (aAllocation->mMinTimeval > aTimeval) { - aAllocation->mMinTimeval = aTimeval; - } - - /* - ** This a free event? - ** Can only set max timeval on a free. - ** Otherwise, mMaxTimeval remains ST_TIMEVAL_MAX. - ** Set in allocationTracker. - */ - if (TM_EVENT_FREE == aEventType) { - aAllocation->mMaxTimeval = aTimeval; - } - } - else { - REPORT_ERROR(__LINE__, appendEvent); - } - } - else { - REPORT_ERROR(__LINE__, appendEvent); - } - - return retval; -} - -/* -** hasAllocation -** -** Determine if a given run has an allocation. -** This is really nothing more than a pointer comparison loop. -** Returns !0 if the run has the allocation. -*/ -int -hasAllocation(STRun * aRun, STAllocation * aTestFor) -{ - int retval = 0; - - if (NULL != aRun && NULL != aTestFor) { - uint32_t traverse = aRun->mAllocationCount; - - /* - ** Go through reverse, in the hopes it exists nearer the end. - */ - while (0 < traverse) { - /* - ** Back up. - */ - traverse--; - - if (aTestFor == aRun->mAllocations[traverse]) { - retval = __LINE__; - break; - } - } - } - else { - REPORT_ERROR(__LINE__, hasAllocation); - } - - return retval; -} - -/* -** allocationTracker -** -** Important to keep track of all allocations unique so as to determine -** their lifetimes. -** -** Returns a pointer to the allocation on success. -** Return NULL on failure. -*/ -STAllocation * -allocationTracker(uint32_t aTimeval, char aType, uint32_t aHeapRuntimeCost, - tmcallsite * aCallsite, uint32_t aHeapID, uint32_t aSize, - tmcallsite * aOldCallsite, uint32_t aOldHeapID, - uint32_t aOldSize) -{ - STAllocation *retval = NULL; - static int compactor = 1; - const int frequency = 10000; - uint32_t actualSize, actualOldSize = 0; - - actualSize = actualByteSize(&globals.mCommandLineOptions, aSize); - if (aOldSize) - actualOldSize = - actualByteSize(&globals.mCommandLineOptions, aOldSize); - - if (NULL != aCallsite) { - int newAllocation = 0; - tmcallsite *searchCallsite = NULL; - uint32_t searchHeapID = 0; - STAllocation *allocation = NULL; - - /* - ** Global operation ID increases. - */ - globals.mOperationCount++; - - /* - ** Fix up the timevals if needed. - */ - if (aTimeval < globals.mMinTimeval) { - globals.mMinTimeval = aTimeval; - } - if (aTimeval > globals.mMaxTimeval) { - globals.mMaxTimeval = aTimeval; - } - - switch (aType) { - case TM_EVENT_FREE: - { - /* - ** Update the global counter. - */ - globals.mFreeCount++; - - /* - ** Update our peak memory used counter - */ - globals.mMemoryUsed -= actualSize; - - /* - ** Not a new allocation, will need to search passed in site - ** for the original allocation. - */ - searchCallsite = aCallsite; - searchHeapID = aHeapID; - } - break; - - case TM_EVENT_MALLOC: - { - /* - ** Update the global counter. - */ - globals.mMallocCount++; - - /* - ** Update our peak memory used counter - */ - globals.mMemoryUsed += actualSize; - if (globals.mMemoryUsed > globals.mPeakMemoryUsed) { - globals.mPeakMemoryUsed = globals.mMemoryUsed; - } - - /* - ** This will be a new allocation. - */ - newAllocation = __LINE__; - } - break; - - case TM_EVENT_CALLOC: - { - /* - ** Update the global counter. - */ - globals.mCallocCount++; - - /* - ** Update our peak memory used counter - */ - globals.mMemoryUsed += actualSize; - if (globals.mMemoryUsed > globals.mPeakMemoryUsed) { - globals.mPeakMemoryUsed = globals.mMemoryUsed; - } - - /* - ** This will be a new allocation. - */ - newAllocation = __LINE__; - } - break; - - case TM_EVENT_REALLOC: - { - /* - ** Update the global counter. - */ - globals.mReallocCount++; - - /* - ** Update our peak memory used counter - */ - globals.mMemoryUsed += actualSize - actualOldSize; - if (globals.mMemoryUsed > globals.mPeakMemoryUsed) { - globals.mPeakMemoryUsed = globals.mMemoryUsed; - } - - /* - ** This might be a new allocation. - */ - if (NULL == aOldCallsite) { - newAllocation = __LINE__; - } - else { - /* - ** Need to search for the original callsite for the - ** index to the allocation. - */ - searchCallsite = aOldCallsite; - searchHeapID = aOldHeapID; - } - } - break; - - default: - { - REPORT_ERROR(__LINE__, allocationTracker); - } - break; - } - - /* - ** We are either modifying an existing allocation or we are creating - ** a new one. - */ - if (0 != newAllocation) { - allocation = (STAllocation *) calloc(1, sizeof(STAllocation)); - if (NULL != allocation) { - /* - ** Fixup the min timeval so if logic later will just work. - */ - allocation->mMinTimeval = ST_TIMEVAL_MAX; - allocation->mMaxTimeval = ST_TIMEVAL_MAX; - } - } - else if (NULL != searchCallsite - && NULL != CALLSITE_RUN(searchCallsite) - && 0 != searchHeapID) { - /* - ** We know what to search for, and we reduce what we search - ** by only looking for those allocations at a known callsite. - */ - allocation = - getLiveAllocationByHeapID(CALLSITE_RUN(searchCallsite), - searchHeapID); - } - else { - REPORT_ERROR(__LINE__, allocationTracker); - } - - if (NULL != allocation) { - STAllocEvent *appendResult = NULL; - - /* - ** Record the amount of time this allocation event took. - */ - allocation->mHeapRuntimeCost += aHeapRuntimeCost; - - /* - ** Now that we have an allocation, we need to make sure it has - ** the proper event. - */ - appendResult = - appendEvent(allocation, aTimeval, aType, aHeapID, aSize, - aCallsite); - if (NULL != appendResult) { - if (0 != newAllocation) { - int runAppendResult = 0; - int callsiteAppendResult = 0; - - /* - ** A new allocation needs to be added to the global run. - ** A new allocation needs to be added to the callsite. - */ - runAppendResult = - appendAllocation(&globals.mCommandLineOptions, NULL, - &globals.mRun, allocation); - callsiteAppendResult = - appendAllocation(&globals.mCommandLineOptions, NULL, - CALLSITE_RUN(aCallsite), allocation); - if (0 != runAppendResult && 0 != callsiteAppendResult) { - /* - ** Success. - */ - retval = allocation; - } - else { - REPORT_ERROR(__LINE__, appendAllocation); - } - } - else { - /* - ** An existing allocation, if a realloc situation, - ** may need to be added to the new callsite. - ** This can only occur if the new and old callsites - ** differ. - ** Even then, a brute force check will need to be made - ** to ensure the allocation was not added twice; - ** consider a realloc scenario where two different - ** call stacks bump the allocation back and forth. - */ - if (aCallsite != searchCallsite) { - int found = 0; - - found = - hasAllocation(CALLSITE_RUN(aCallsite), - allocation); - if (0 == found) { - int appendResult = 0; - - appendResult = - appendAllocation(&globals.mCommandLineOptions, - NULL, - CALLSITE_RUN(aCallsite), - allocation); - if (0 != appendResult) { - /* - ** Success. - */ - retval = allocation; - } - else { - REPORT_ERROR(__LINE__, appendAllocation); - } - } - else { - /* - ** Already there. - */ - retval = allocation; - } - } - else { - /* - ** Success. - */ - retval = allocation; - } - } - } - else { - REPORT_ERROR(__LINE__, appendEvent); - } - } - else { - REPORT_ERROR(__LINE__, allocationTracker); - } - } - else { - REPORT_ERROR(__LINE__, allocationTracker); - } - - /* - ** Compact the heap a bit if you can. - */ - compactor++; - if (0 == (compactor % frequency)) { - heapCompact(); - } - - return retval; -} - -/* -** trackEvent -** -** An allocation event has dropped in on us. -** We need to do the right thing and track it. -*/ -void -trackEvent(uint32_t aTimeval, char aType, uint32_t aHeapRuntimeCost, - tmcallsite * aCallsite, uint32_t aHeapID, uint32_t aSize, - tmcallsite * aOldCallsite, uint32_t aOldHeapID, uint32_t aOldSize) -{ - if (NULL != aCallsite) { - /* - ** Verify the old callsite just in case. - */ - if (NULL != CALLSITE_RUN(aCallsite) - && (NULL == aOldCallsite || NULL != CALLSITE_RUN(aOldCallsite))) { - STAllocation *allocation = NULL; - - /* - ** Add to the allocation tracking code. - */ - allocation = - allocationTracker(aTimeval, aType, aHeapRuntimeCost, - aCallsite, aHeapID, aSize, aOldCallsite, - aOldHeapID, aOldSize); - - if (NULL == allocation) { - REPORT_ERROR(__LINE__, allocationTracker); - } - } - else { - REPORT_ERROR(__LINE__, trackEvent); - } - } - else { - REPORT_ERROR(__LINE__, trackEvent); - } -} - -/* -** tmEventHandler -** -** Callback from the tmreader_eventloop function. -** Simply tries to sort out what we desire to know. -*/ - -static const char spinner_chars[] = { '/', '-', '\\', '|' }; - -#define SPINNER_UPDATE_FREQUENCY 4096 -#define SPINNER_CHAR_COUNT (sizeof(spinner_chars) / sizeof(spinner_chars[0])) -#define SPINNER_CHAR(_x) spinner_chars[(_x / SPINNER_UPDATE_FREQUENCY) % SPINNER_CHAR_COUNT] - -void -tmEventHandler(tmreader * aReader, tmevent * aEvent) -{ - static int event_count = 0; /* for spinner */ - if ((event_count++ % SPINNER_UPDATE_FREQUENCY) == 0) - printf("\rReading... %c", SPINNER_CHAR(event_count)); - - if (NULL != aReader && NULL != aEvent) { - switch (aEvent->type) { - /* - ** Events we ignore. - */ - case TM_EVENT_LIBRARY: - case TM_EVENT_METHOD: - case TM_EVENT_STATS: - case TM_EVENT_TIMESTAMP: - case TM_EVENT_FILENAME: - break; - - /* - ** Allocation events need to be tracked. - */ - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - case TM_EVENT_REALLOC: - case TM_EVENT_FREE: - { - uint32_t oldptr = 0; - uint32_t oldsize = 0; - tmcallsite *callsite = NULL; - tmcallsite *oldcallsite = NULL; - - if (TM_EVENT_REALLOC == aEvent->type) { - /* - ** Only care about old arguments if there were any. - */ - if (0 != aEvent->u.alloc.oldserial) { - oldptr = aEvent->u.alloc.oldptr; - oldsize = aEvent->u.alloc.oldsize; - oldcallsite = - tmreader_callsite(aReader, - aEvent->u.alloc.oldserial); - if (NULL == oldcallsite) { - REPORT_ERROR(__LINE__, tmreader_callsite); - } - } - } - - callsite = tmreader_callsite(aReader, aEvent->serial); - if (NULL != callsite) { - /* - ** Verify a callsite run is there. - ** If not, we are ignoring this callsite. - */ - if (NULL != CALLSITE_RUN(callsite)) { - char eventType = aEvent->type; - uint32_t eventSize = aEvent->u.alloc.size; - - /* - ** Play a nasty trick on reallocs of size zero. - ** They are to become free events, adjust the size accordingly. - ** This allows me to avoid all types of special case code. - */ - if (0 == aEvent->u.alloc.size - && TM_EVENT_REALLOC == aEvent->type) { - eventType = TM_EVENT_FREE; - if (0 != aEvent->u.alloc.oldserial) { - eventSize = aEvent->u.alloc.oldsize; - } - } - trackEvent(ticks2msec - (aReader, aEvent->u.alloc.interval), - eventType, ticks2usec(aReader, - aEvent->u.alloc. - cost), callsite, - aEvent->u.alloc.ptr, eventSize, - oldcallsite, oldptr, oldsize); - } - } - else { - REPORT_ERROR(__LINE__, tmreader_callsite); - } - } - break; - - /* - ** Callsite, set up the callsite run if it does not exist. - */ - case TM_EVENT_CALLSITE: - { - tmcallsite *callsite = - tmreader_callsite(aReader, aEvent->serial); - - if (NULL != callsite) { - if (NULL == CALLSITE_RUN(callsite)) { - int createrun = __LINE__; - -#if defined(MOZILLA_CLIENT) - /* - ** For a mozilla spacetrace, ignore this particular - ** callsite as it is just noise, and causes us to - ** use a lot of memory. - ** - ** This callsite is present on the linux build, - ** not sure if the other platforms have it. - */ - if (0 != - hasCallsiteMatch(callsite, "g_main_is_running", - ST_FOLLOW_PARENTS)) { - createrun = 0; - } -#endif /* MOZILLA_CLIENT */ - - if (0 != createrun) { - callsite->data = createRun(NULL, 0); - } - } - } - else { - REPORT_ERROR(__LINE__, tmreader_callsite); - } - } - break; - - /* - ** Unhandled events should not be allowed. - */ - default: - { - REPORT_ERROR(__LINE__, tmEventHandler); - } - break; - } - } -} - -/* -** optionGetDataOut -** -** Output option get data. -*/ -void -optionGetDataOut(PRFileDesc * inFD, STOptions * inOptions) -{ - if (NULL != inFD && NULL != inOptions) { - int mark = 0; - -#define ST_WEB_OPTION_BOOL(option_name, option_genre, option_help) \ - PR_fprintf(inFD, "%s%s=%d", (0 == mark++) ? "?" : "&", #option_name, inOptions->m##option_name); -#define ST_WEB_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - PR_fprintf(inFD, "%s%s=%s", (0 == mark++) ? "?" : "&", #option_name, inOptions->m##option_name); -#define ST_WEB_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - { \ - uint32_t loop = 0; \ - \ - for(loop = 0; loop < array_size; loop++) \ - { \ - PR_fprintf(inFD, "%s%s=%s", (0 == mark++) ? "?" : "&", #option_name, inOptions->m##option_name[loop]); \ - } \ - } -#define ST_WEB_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) /* no implementation */ -#define ST_WEB_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - PR_fprintf(inFD, "%s%s=%u", (0 == mark++) ? "?" : "&", #option_name, inOptions->m##option_name / multiplier); -#define ST_WEB_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - { \ - uint64_t def64 = default_value; \ - uint64_t mul64 = multiplier; \ - uint64_t div64; \ - \ - div64 = inOptions->m##option_name##64 / mul64; \ - PR_fprintf(inFD, "%s%s=%llu", (0 == mark++) ? "?" : "&", #option_name, div64); \ - } - -#include "stoptions.h" - } -} - -/* -** htmlAnchor -** -** Output an HTML anchor, or just the text depending on the mode. -*/ -void -htmlAnchor(STRequest * inRequest, - const char *aHref, - const char *aText, - const char *aTarget, const char *aClass, STOptions * inOptions) -{ - if (NULL != aHref && '\0' != *aHref && NULL != aText && '\0' != *aText) { - int anchorLive = 1; - - /* - ** In batch mode, we need to verify the anchor is live. - */ - if (0 != inRequest->mOptions.mBatchRequestCount) { - uint32_t loop = 0; - int comparison = 1; - - for (loop = 0; loop < inRequest->mOptions.mBatchRequestCount; - loop++) { - comparison = - strcmp(aHref, inRequest->mOptions.mBatchRequest[loop]); - if (0 == comparison) { - break; - } - } - - /* - ** Did we find it? - */ - if (0 == comparison) { - anchorLive = 0; - } - } - - /* - ** In any mode, don't make an href to the current page. - */ - if (0 != anchorLive && NULL != inRequest->mGetFileName) { - if (0 == strcmp(aHref, inRequest->mGetFileName)) { - anchorLive = 0; - } - } - - /* - ** Do the right thing. - */ - if (0 != anchorLive) { - PR_fprintf(inRequest->mFD, "mFD, "target=\"%s\" ", aTarget); - } - PR_fprintf(inRequest->mFD, "href=\"./%s", aHref); - - /* - ** The options, if desired, get appended as form data. - */ - optionGetDataOut(inRequest->mFD, inOptions); - - PR_fprintf(inRequest->mFD, "\">%s\n", aText); - } - else { - PR_fprintf(inRequest->mFD, "%s\n", - aClass, aText); - } - } - else { - REPORT_ERROR(__LINE__, htmlAnchor); - } -} - -/* -** htmlAllocationAnchor -** -** Output an html achor that will resolve to the allocation in question. -*/ -void -htmlAllocationAnchor(STRequest * inRequest, STAllocation * aAllocation, - const char *aText) -{ - if (NULL != aAllocation && NULL != aText && '\0' != *aText) { - char buffer[128]; - - /* - ** This is a total hack. - ** The filename contains the index of the allocation in globals.mRun. - ** Safer than using the raw pointer value.... - */ - PR_snprintf(buffer, sizeof(buffer), "allocation_%u.html", - aAllocation->mRunIndex); - - htmlAnchor(inRequest, buffer, aText, NULL, "allocation", - &inRequest->mOptions); - } - else { - REPORT_ERROR(__LINE__, htmlAllocationAnchor); - } -} - -/* -** resolveSourceFile -** -** Easy way to get a readable/short name. -** NULL if not present, not resolvable. -*/ -const char * -resolveSourceFile(tmmethodnode * aMethod) -{ - const char *retval = NULL; - - if (NULL != aMethod) { - const char *methodSays = NULL; - - methodSays = aMethod->sourcefile; - - if (NULL != methodSays && '\0' != methodSays[0] - && 0 != strcmp("noname", methodSays)) { - retval = strrchr(methodSays, '/'); - if (NULL != retval) { - retval++; - } - else { - retval = methodSays; - } - } - } - - return retval; -} - -/* -** htmlCallsiteAnchor -** -** Output an html anchor that will resolve to the callsite in question. -** If no text is provided, we provide our own. -** -** RealName determines whether or not we crawl our parents until the point -** we no longer match stats. -*/ -void -htmlCallsiteAnchor(STRequest * inRequest, tmcallsite * aCallsite, - const char *aText, int aRealName) -{ - if (NULL != aCallsite) { - char textBuf[512]; - char hrefBuf[128]; - tmcallsite *namesite = aCallsite; - - /* - ** Should we use a different name? - */ - if (0 == aRealName && NULL != namesite->parent - && NULL != namesite->parent->method) { - STRun *myRun = NULL; - STRun *upRun = NULL; - - do { - myRun = CALLSITE_RUN(namesite); - upRun = CALLSITE_RUN(namesite->parent); - - if (0 != - memcmp(&myRun->mStats[inRequest->mContext->mIndex], - &upRun->mStats[inRequest->mContext->mIndex], - sizeof(STCallsiteStats))) { - /* - ** Doesn't match, stop. - */ - break; - } - else { - /* - ** Matches, keep going up. - */ - namesite = namesite->parent; - } - } - while (NULL != namesite->parent - && NULL != namesite->parent->method); - } - - /* - ** If no text, provide our own. - */ - if (NULL == aText || '\0' == *aText) { - const char *methodName = NULL; - const char *sourceFile = NULL; - - if (NULL != namesite->method) { - methodName = tmmethodnode_name(namesite->method); - } - else { - methodName = "==NONAME=="; - } - - /* - ** Decide which format to use to identify the callsite. - ** If we can detect availability, hook up the filename with lxr information. - */ - sourceFile = resolveSourceFile(namesite->method); - if (NULL != sourceFile - && 0 == strncmp("mozilla/", namesite->method->sourcefile, - 8)) { - char lxrHREFBuf[512]; - - PR_snprintf(lxrHREFBuf, sizeof(lxrHREFBuf), - " [%s:%u]", - namesite->method->sourcefile + 8, - namesite->method->linenumber, sourceFile, - namesite->method->linenumber); - PR_snprintf(textBuf, sizeof(textBuf), - "%s%s", - methodName, lxrHREFBuf); - } - else if (NULL != sourceFile) { - PR_snprintf(textBuf, sizeof(textBuf), - "%s [%s:%u]", - methodName, sourceFile, - namesite->method->linenumber); - } - else { - PR_snprintf(textBuf, sizeof(textBuf), - "%s [+%u(%u)]", - methodName, namesite->offset, - (uint32_t) namesite->entry.key); - } - - aText = textBuf; - } - - PR_snprintf(hrefBuf, sizeof(hrefBuf), "callsite_%u.html", - (uint32_t) aCallsite->entry.key); - - htmlAnchor(inRequest, hrefBuf, aText, NULL, "callsite", - &inRequest->mOptions); - } - else { - REPORT_ERROR(__LINE__, htmlCallsiteAnchor); - } -} - -/* -** htmlHeader -** -** Output a standard header in the report files. -*/ -void -htmlHeader(STRequest * inRequest, const char *aTitle) -{ - PR_fprintf(inRequest->mFD, - "\n" - "\n" - "%s\n" - "\n" - "\n" - "
\n" - "Spacetrace" - "\n" - "Category:\n" - "%s\n", - aTitle, inRequest->mOptions.mCategoryName); - - PR_fprintf(inRequest->mFD, ""); - htmlAnchor(inRequest, "index.html", "Index", NULL, "header-menuitem", - &inRequest->mOptions); - PR_fprintf(inRequest->mFD, "\n"); - - PR_fprintf(inRequest->mFD, ""); - htmlAnchor(inRequest, "options.html", "Options", NULL, "header-menuitem", - &inRequest->mOptions); - PR_fprintf(inRequest->mFD, "\n"); - - PR_fprintf(inRequest->mFD, "\n"); /* class=navigate */ - - PR_fprintf(inRequest->mFD, - "
\n\n
\n\n"); -} - -/* -** htmlFooter -** -** Output a standard footer in the report file. -*/ -void -htmlFooter(STRequest * inRequest) -{ - PR_fprintf(inRequest->mFD, - "
\n\n" - "
\n" - "SpaceTrace\n" - "
\n\n" "\n" "\n"); -} - -/* -** htmlNotFound -** -** Not found message. -*/ -void -htmlNotFound(STRequest * inRequest) -{ - htmlHeader(inRequest, "File Not Found"); - PR_fprintf(inRequest->mFD, "File Not Found\n"); - htmlFooter(inRequest); -} - -void -htmlStartTable(STRequest* inRequest, - const char* table_class, - const char* id, - const char* caption, - const char * const headers[], uint32_t header_length) -{ - uint32_t i; - - PR_fprintf(inRequest->mFD, - "
\n" - " " - " \n" - " \n", id, - table_class ? table_class : "", - caption); - - for (i=0; i< header_length; i++) - PR_fprintf(inRequest->mFD, - " \n", headers[i]); - - PR_fprintf(inRequest->mFD, " \n"); -} - -/* -** callsiteArrayFromCallsite -** -** Simply return an array of the callsites divulged from the site passed in, -** including the site passed in. -** Do not worry about dups, or the order of the items. -** -** Returns the number of items in the array. -** If the same as aExistingCount, then nothing happened. -*/ -uint32_t -callsiteArrayFromCallsite(tmcallsite *** aArray, uint32_t aExistingCount, - tmcallsite * aSite, int aFollow) -{ - uint32_t retval = 0; - - if (NULL != aArray && NULL != aSite) { - tmcallsite **expand = NULL; - - /* - ** If we have an existing count, we just keep expanding this. - */ - retval = aExistingCount; - - /* - ** Go through every allocation. - */ - do { - /* - ** expand the array. - */ - expand = - (tmcallsite **) realloc(*aArray, - sizeof(tmcallsite *) * (retval + 1)); - if (NULL != expand) { - /* - ** Set the callsite in case of pointer move. - */ - *aArray = expand; - - /* - ** Assign the value. - */ - (*aArray)[retval] = aSite; - retval++; - } - else { - REPORT_ERROR(__LINE__, realloc); - break; - } - - - /* - ** What do we follow? - */ - switch (aFollow) { - case ST_FOLLOW_SIBLINGS: - aSite = aSite->siblings; - break; - case ST_FOLLOW_PARENTS: - aSite = aSite->parent; - break; - default: - aSite = NULL; - REPORT_ERROR(__LINE__, callsiteArrayFromCallsite); - break; - } - } - while (NULL != aSite && NULL != aSite->method); - } - - return retval; -} - -/* -** callsiteArrayFromRun -** -** Simply return an array of the callsites from the run allocations. -** We only pay attention to callsites that were not free callsites. -** Do not worry about dups, or the order of the items. -** -** Returns the number of items in the array. -** If the same as aExistingCount, then nothing happened. -*/ -uint32_t -callsiteArrayFromRun(tmcallsite *** aArray, uint32_t aExistingCount, - STRun * aRun) -{ - uint32_t retval = 0; - - if (NULL != aArray && NULL != aRun && 0 < aRun->mAllocationCount) { - uint32_t allocLoop = 0; - uint32_t eventLoop = 0; - int stopLoops = 0; - - /* - ** If we have an existing count, we just keep expanding this. - */ - retval = aExistingCount; - - /* - ** Go through every allocation. - */ - for (allocLoop = 0; - 0 == stopLoops && allocLoop < aRun->mAllocationCount; - allocLoop++) { - /* - ** Go through every event. - */ - for (eventLoop = 0; - 0 == stopLoops - && eventLoop < aRun->mAllocations[allocLoop]->mEventCount; - eventLoop++) { - /* - ** Skip the free events. - */ - if (TM_EVENT_FREE != - aRun->mAllocations[allocLoop]->mEvents[eventLoop]. - mEventType) { - tmcallsite **expand = NULL; - - /* - ** expand the array. - */ - expand = - (tmcallsite **) realloc(*aArray, - sizeof(tmcallsite *) * - (retval + 1)); - if (NULL != expand) { - /* - ** Set the callsite in case of pointer move. - */ - *aArray = expand; - - /* - ** Assign the value. - */ - (*aArray)[retval] = - aRun->mAllocations[allocLoop]->mEvents[eventLoop]. - mCallsite; - retval++; - } - else { - REPORT_ERROR(__LINE__, realloc); - stopLoops = __LINE__; - } - } - } - } - } - - return retval; -} - -/* -** getDataPRUint* -** -** Helper to avoid cut and paste code. -** Failure to find aCheckFor does not mean failure. -** In case of dups, specify an index on non "1" to get others. -** Do not touch storage space unless a find is made. -** Returns !0 on failure. -*/ -int -getDataPRUint32Base(const FormData * aGetData, const char *aCheckFor, - int inIndex, void *aStoreResult, uint32_t aBits) -{ - int retval = 0; - - if (NULL != aGetData && NULL != aCheckFor && 0 != inIndex - && NULL != aStoreResult) { - unsigned finder = 0; - - /* - ** Loop over the names, looking for an exact string match. - ** Skip over initial finds, decrementing inIndex, until "1". - */ - for (finder = 0; finder < aGetData->mNVCount; finder++) { - if (0 == strcmp(aCheckFor, aGetData->mNArray[finder])) { - inIndex--; - - if (0 == inIndex) { - int32_t scanRes = 0; - - if (64 == aBits) { - scanRes = - PR_sscanf(aGetData->mVArray[finder], "%llu", - aStoreResult); - } - else { - scanRes = - PR_sscanf(aGetData->mVArray[finder], "%u", - aStoreResult); - } - if (1 != scanRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_sscanf); - } - break; - } - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, getDataPRUint32Base); - } - - return retval; -} - -int -getDataPRUint32(const FormData * aGetData, const char *aCheckFor, int inIndex, - uint32_t * aStoreResult, uint32_t aConversion) -{ - int retval = 0; - - retval = - getDataPRUint32Base(aGetData, aCheckFor, inIndex, aStoreResult, 32); - *aStoreResult *= aConversion; - - return retval; -} - -int -getDataPRUint64(const FormData * aGetData, const char *aCheckFor, int inIndex, - uint64_t * aStoreResult64, uint64_t aConversion64) -{ - int retval = 0; - uint64_t value64 = 0; - - retval = getDataPRUint32Base(aGetData, aCheckFor, inIndex, &value64, 64); - *aStoreResult64 = value64 * aConversion64; - - return retval; -} - -/* -** getDataString -** -** Pull out the string data, if specified. -** In case of dups, specify an index on non "1" to get others. -** Do not touch storage space unless a find is made. -** Return !0 on failure. -*/ -int -getDataString(const FormData * aGetData, const char *aCheckFor, int inIndex, - char *aStoreResult, int inStoreResultLength) -{ - int retval = 0; - - if (NULL != aGetData && NULL != aCheckFor && 0 != inIndex - && NULL != aStoreResult && 0 != inStoreResultLength) { - unsigned finder = 0; - - /* - ** Loop over the names, looking for an exact string match. - ** Skip over initial finds, decrementing inIndex, until "1". - */ - for (finder = 0; finder < aGetData->mNVCount; finder++) { - if (0 == strcmp(aCheckFor, aGetData->mNArray[finder])) { - inIndex--; - - if (0 == inIndex) { - PR_snprintf(aStoreResult, inStoreResultLength, "%s", - aGetData->mVArray[finder]); - break; - } - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, getDataPRUint32); - } - - return retval; -} - -/* -** displayTopAllocations -** -** Present the top allocations. -** The run must be passed in, and it must be pre-sorted. -** -** Returns !0 on failure. -*/ -int -displayTopAllocations(STRequest * inRequest, STRun * aRun, - const char* id, - const char* caption, - int aWantCallsite) -{ - int retval = 0; - - if (NULL != aRun) { - if (0 < aRun->mAllocationCount) { - uint32_t loop = 0; - STAllocation *current = NULL; - - static const char* const headers[] = { - "Rank", "Index", "Byte Size", "Lifespan (sec)", - "Weight", "Heap Op (sec)" - }; - - static const char* const headers_callsite[] = { - "Rank", "Index", "Byte Size", "Lifespan (sec)", - "Weight", "Heap Op (sec)", "Origin Callsite" - }; - - if (aWantCallsite) - htmlStartTable(inRequest, NULL, id, - caption, - headers_callsite, - sizeof(headers_callsite) / sizeof(headers_callsite[0])); - else - htmlStartTable(inRequest, NULL, id, caption, - headers, - sizeof(headers) / sizeof(headers[0])); - /* - ** Loop over the items, up to some limit or until the end. - */ - for (loop = 0; - loop < inRequest->mOptions.mListItemMax - && loop < aRun->mAllocationCount; loop++) { - current = aRun->mAllocations[loop]; - if (NULL != current) { - uint32_t lifespan = - current->mMaxTimeval - current->mMinTimeval; - uint32_t size = byteSize(&inRequest->mOptions, current); - uint32_t heapCost = current->mHeapRuntimeCost; - uint64_t weight64 = 0; - char buffer[32]; - - weight64 =(uint64_t)(size * lifespan); - - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Rank. - */ - PR_fprintf(inRequest->mFD, "\n", - loop + 1); - - /* - ** Index. - */ - PR_snprintf(buffer, sizeof(buffer), "%u", - current->mRunIndex); - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Byte Size. - */ - PR_fprintf(inRequest->mFD, "\n", - size); - - /* - ** Lifespan. - */ - PR_fprintf(inRequest->mFD, - "\n", - ST_TIMEVAL_PRINTABLE(lifespan)); - - /* - ** Weight. - */ - PR_fprintf(inRequest->mFD, "\n", - weight64); - - /* - ** Heap operation cost. - */ - PR_fprintf(inRequest->mFD, - "\n", ST_MICROVAL_PRINTABLE(heapCost)); - - if (0 != aWantCallsite) { - /* - ** Callsite. - */ - PR_fprintf(inRequest->mFD, "\n"); - } - - PR_fprintf(inRequest->mFD, "\n"); - } - } - - PR_fprintf(inRequest->mFD, "\n
%s
%s
%u\n"); - htmlAllocationAnchor(inRequest, current, buffer); - PR_fprintf(inRequest->mFD, "%u" ST_TIMEVAL_FORMAT "%llu" ST_MICROVAL_FORMAT - ""); - htmlCallsiteAnchor(inRequest, - current->mEvents[0].mCallsite, - NULL, 0); - PR_fprintf(inRequest->mFD, "
\n\n"); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayTopAllocations); - } - - return retval; -} - -/* -** displayMemoryLeaks -** -** Present the top memory leaks. -** The run must be passed in, and it must be pre-sorted. -** -** Returns !0 on failure. -*/ -int -displayMemoryLeaks(STRequest * inRequest, STRun * aRun) -{ - int retval = 0; - - if (NULL != aRun) { - uint32_t loop = 0; - uint32_t displayed = 0; - STAllocation *current = NULL; - - static const char * headers[] = { - "Rank", "Index", "Byte Size", "Lifespan (sec)", - "Weight", "Heap Op (sec)", "Origin Callsite" - }; - - htmlStartTable(inRequest, NULL, "memory-leaks", "Memory Leaks", headers, - sizeof(headers) / sizeof(headers[0])); - - /* - ** Loop over all of the items, or until we've displayed enough. - */ - for (loop = 0; - displayed < inRequest->mOptions.mListItemMax - && loop < aRun->mAllocationCount; loop++) { - current = aRun->mAllocations[loop]; - if (NULL != current && 0 != current->mEventCount) { - /* - ** In order to be a leak, the last event of its life must - ** NOT be a free operation. - ** - ** A free operation is just that, a free. - */ - if (TM_EVENT_FREE != - current->mEvents[current->mEventCount - 1].mEventType) { - uint32_t lifespan = - current->mMaxTimeval - current->mMinTimeval; - uint32_t size = byteSize(&inRequest->mOptions, current); - uint32_t heapCost = current->mHeapRuntimeCost; - uint64_t weight64 = 0; - char buffer[32]; - - weight64 =(uint64_t)(size * lifespan); - - /* - ** One more shown. - */ - displayed++; - - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Rank. - */ - PR_fprintf(inRequest->mFD, "%u\n", - displayed); - - /* - ** Index. - */ - PR_snprintf(buffer, sizeof(buffer), "%u", - current->mRunIndex); - PR_fprintf(inRequest->mFD, "\n"); - htmlAllocationAnchor(inRequest, current, buffer); - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Byte Size. - */ - PR_fprintf(inRequest->mFD, "%u\n", - size); - - /* - ** Lifespan. - */ - PR_fprintf(inRequest->mFD, - "" ST_TIMEVAL_FORMAT "\n", - ST_TIMEVAL_PRINTABLE(lifespan)); - - /* - ** Weight. - */ - PR_fprintf(inRequest->mFD, "%llu\n", - weight64); - - /* - ** Heap Operation Seconds. - */ - PR_fprintf(inRequest->mFD, - "" ST_MICROVAL_FORMAT - "\n", ST_MICROVAL_PRINTABLE(heapCost)); - - /* - ** Callsite. - */ - PR_fprintf(inRequest->mFD, ""); - htmlCallsiteAnchor(inRequest, - current->mEvents[0].mCallsite, NULL, - 0); - PR_fprintf(inRequest->mFD, "\n"); - - PR_fprintf(inRequest->mFD, "\n"); - } - } - } - - PR_fprintf(inRequest->mFD, "
\n\n"); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayMemoryLeaks); - } - - return retval; -} - -/* -** displayCallsites -** -** Display a table of callsites. -** If the stamp is non zero, then must match that stamp. -** If the stamp is zero, then must match the global sorted run stamp. -** Return !0 on error. -*/ -int -displayCallsites(STRequest * inRequest, tmcallsite * aCallsite, int aFollow, - uint32_t aStamp, - const char* id, - const char* caption, - int aRealNames) -{ - int retval = 0; - - if (NULL != aCallsite && NULL != aCallsite->method) { - int headerDisplayed = 0; - STRun *run = NULL; - - /* - ** Correct the stamp if need be. - */ - if (0 == aStamp && NULL != inRequest->mContext->mSortedRun) { - aStamp = - inRequest->mContext->mSortedRun->mStats[inRequest->mContext-> - mIndex].mStamp; - } - - /* - ** Loop over the callsites looking for a stamp match. - ** A stamp guarantees there is something interesting to look at too. - ** If found, output it. - */ - while (NULL != aCallsite && NULL != aCallsite->method) { - run = CALLSITE_RUN(aCallsite); - if (NULL != run) { - if (aStamp == run->mStats[inRequest->mContext->mIndex].mStamp) { - /* - ** We got a header? - */ - if (0 == headerDisplayed) { - - static const char* const headers[] = { - "Callsite", - "C. Size", - "C. Seconds", - "C. Weight", - "H.O. Count", - "C.H. Operation (sec)" - }; - headerDisplayed = __LINE__; - htmlStartTable(inRequest, NULL, id, caption, headers, - sizeof(headers)/sizeof(headers[0])); - } - - /* - ** Output the information. - */ - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Method name. - */ - PR_fprintf(inRequest->mFD, ""); - htmlCallsiteAnchor(inRequest, aCallsite, NULL, - aRealNames); - PR_fprintf(inRequest->mFD, ""); - - /* - ** Byte Size. - */ - PR_fprintf(inRequest->mFD, - "%u\n", - run->mStats[inRequest->mContext->mIndex]. - mSize); - - /* - ** Seconds. - */ - PR_fprintf(inRequest->mFD, - "" ST_TIMEVAL_FORMAT - "\n", - ST_TIMEVAL_PRINTABLE64(run-> - mStats[inRequest-> - mContext-> - mIndex]. - mTimeval64)); - - /* - ** Weight. - */ - PR_fprintf(inRequest->mFD, - "%llu\n", - run->mStats[inRequest->mContext->mIndex]. - mWeight64); - - /* - ** Allocation object count. - */ - PR_fprintf(inRequest->mFD, - "%u\n", - run->mStats[inRequest->mContext->mIndex]. - mCompositeCount); - - /* - ** Heap Operation Seconds. - */ - PR_fprintf(inRequest->mFD, - "" - ST_MICROVAL_FORMAT "\n", - ST_MICROVAL_PRINTABLE(run-> - mStats[inRequest-> - mContext->mIndex]. - mHeapRuntimeCost)); - - PR_fprintf(inRequest->mFD, "\n"); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsites); - break; - } - - /* - ** What do we follow? - */ - switch (aFollow) { - case ST_FOLLOW_SIBLINGS: - aCallsite = aCallsite->siblings; - break; - case ST_FOLLOW_PARENTS: - aCallsite = aCallsite->parent; - break; - default: - aCallsite = NULL; - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsites); - break; - } - } - - /* - ** Terminate the table if we should. - */ - if (0 != headerDisplayed) { - PR_fprintf(inRequest->mFD, "\n\n"); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsites); - } - - return retval; -} - -/* -** displayAllocationDetails -** -** Report what we know about the allocation. -** -** Returns !0 on error. -*/ -int -displayAllocationDetails(STRequest * inRequest, STAllocation * aAllocation) -{ - int retval = 0; - - if (NULL != aAllocation) { - uint32_t traverse = 0; - uint32_t bytesize = byteSize(&inRequest->mOptions, aAllocation); - uint32_t timeval = - aAllocation->mMaxTimeval - aAllocation->mMinTimeval; - uint32_t heapCost = aAllocation->mHeapRuntimeCost; - uint64_t weight64 = 0; - uint32_t cacheval = 0; - int displayRes = 0; - - weight64 = (uint64_t)(bytesize * timeval); - - PR_fprintf(inRequest->mFD, "

Allocation %u Details:

\n", - aAllocation->mRunIndex); - - PR_fprintf(inRequest->mFD, "
\n"); - PR_fprintf(inRequest->mFD, - "\n", - bytesize); - PR_fprintf(inRequest->mFD, - "\n", - ST_TIMEVAL_PRINTABLE(timeval)); - PR_fprintf(inRequest->mFD, - "\n", - weight64); - PR_fprintf(inRequest->mFD, - "\n", - ST_MICROVAL_PRINTABLE(heapCost)); - PR_fprintf(inRequest->mFD, "
Final Size:%u
Lifespan Seconds:" - ST_TIMEVAL_FORMAT "
Weight:%llu
Heap Operation Seconds:" - ST_MICROVAL_FORMAT "
\n"); - - /* - ** The events. - */ - - { - static const char* const headers[] = { - "Operation", "Size", "Seconds", "" - }; - - char caption[100]; - PR_snprintf(caption, sizeof(caption), "%u Life Event(s)", - aAllocation->mEventCount); - htmlStartTable(inRequest, NULL, "allocation-details", caption, headers, - sizeof(headers) / sizeof(headers[0])); - } - - for (traverse = 0; - traverse < aAllocation->mEventCount - && traverse < inRequest->mOptions.mListItemMax; traverse++) { - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** count. - */ - PR_fprintf(inRequest->mFD, - "%u.\n", traverse + 1); - - /* - ** Operation. - */ - PR_fprintf(inRequest->mFD, ""); - switch (aAllocation->mEvents[traverse].mEventType) { - case TM_EVENT_CALLOC: - PR_fprintf(inRequest->mFD, "calloc"); - break; - case TM_EVENT_FREE: - PR_fprintf(inRequest->mFD, "free"); - break; - case TM_EVENT_MALLOC: - PR_fprintf(inRequest->mFD, "malloc"); - break; - case TM_EVENT_REALLOC: - PR_fprintf(inRequest->mFD, "realloc"); - break; - default: - retval = __LINE__; - REPORT_ERROR(__LINE__, displayAllocationDetails); - break; - } - PR_fprintf(inRequest->mFD, ""); - - /* - ** Size. - */ - PR_fprintf(inRequest->mFD, "%u\n", - aAllocation->mEvents[traverse].mHeapSize); - - /* - ** Timeval. - */ - cacheval = - aAllocation->mEvents[traverse].mTimeval - globals.mMinTimeval; - PR_fprintf(inRequest->mFD, - "" ST_TIMEVAL_FORMAT - "\n", ST_TIMEVAL_PRINTABLE(cacheval)); - - /* - ** Callsite backtrace. - ** Only relevant backtrace is for event 0 for now until - ** trace-malloc outputs proper callsites for all others. - */ - PR_fprintf(inRequest->mFD, "\n"); - if (0 == traverse) { - displayRes = - displayCallsites(inRequest, - aAllocation->mEvents[traverse].mCallsite, - ST_FOLLOW_PARENTS, 0, "event-stack", "", __LINE__); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsite); - } - } - PR_fprintf(inRequest->mFD, "\n"); - - PR_fprintf(inRequest->mFD, "\n"); - } - PR_fprintf(inRequest->mFD, "\n"); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayAllocationDetails); - } - - return retval; -} - -/* -** compareCallsites -** -** qsort callback. -** Compare the callsites as specified by the options. -** There must be NO equal callsites, unless they really are duplicates, -** this is so that a duplicate detector loop can -** simply skip sorted items until the callsite is different. -*/ -int -compareCallsites(const void *aSite1, const void *aSite2, void *aContext) -{ - int retval = 0; - STRequest *inRequest = (STRequest *) aContext; - - if (NULL != aSite1 && NULL != aSite2) { - tmcallsite *site1 = *((tmcallsite **) aSite1); - tmcallsite *site2 = *((tmcallsite **) aSite2); - - if (NULL != site1 && NULL != site2) { - STRun *run1 = CALLSITE_RUN(site1); - STRun *run2 = CALLSITE_RUN(site2); - - if (NULL != run1 && NULL != run2) { - STCallsiteStats *stats1 = - &(run1->mStats[inRequest->mContext->mIndex]); - STCallsiteStats *stats2 = - &(run2->mStats[inRequest->mContext->mIndex]); - - /* - ** Logic determined by pref/option. - */ - switch (inRequest->mOptions.mOrderBy) { - case ST_WEIGHT: - { - uint64_t weight164 = stats1->mWeight64; - uint64_t weight264 = stats2->mWeight64; - - if (weight164 < weight264) { - retval = __LINE__; - } - else if (weight164 > weight264) { - retval = -__LINE__; - } - } - break; - - case ST_SIZE: - { - uint32_t size1 = stats1->mSize; - uint32_t size2 = stats2->mSize; - - if (size1 < size2) { - retval = __LINE__; - } - else if (size1 > size2) { - retval = -__LINE__; - } - } - break; - - case ST_TIMEVAL: - { - uint64_t timeval164 = stats1->mTimeval64; - uint64_t timeval264 = stats2->mTimeval64; - - if (timeval164 < timeval264) { - retval = __LINE__; - } - else if (timeval164 > timeval264) { - retval = -__LINE__; - } - } - break; - - case ST_COUNT: - { - uint32_t count1 = stats1->mCompositeCount; - uint32_t count2 = stats2->mCompositeCount; - - if (count1 < count2) { - retval = __LINE__; - } - else if (count1 > count2) { - retval = -__LINE__; - } - } - break; - - case ST_HEAPCOST: - { - uint32_t cost1 = stats1->mHeapRuntimeCost; - uint32_t cost2 = stats2->mHeapRuntimeCost; - - if (cost1 < cost2) { - retval = __LINE__; - } - else if (cost1 > cost2) { - retval = -__LINE__; - } - } - break; - - default: - { - REPORT_ERROR(__LINE__, compareAllocations); - } - break; - } - - /* - ** If the return value is still zero, do a pointer compare. - ** This makes sure we return zero, only iff the same object. - */ - if (0 == retval) { - if (stats1 < stats2) { - retval = __LINE__; - } - else if (stats1 > stats2) { - retval = -__LINE__; - } - } - } - } - } - - return retval; -} - -/* -** displayTopCallsites -** -** Given a list of callsites, sort it, and output skipping dups. -** The passed in callsite array is side effected, as in that it will come -** back sorted. This function will not release the array. -** -** Note: If the stamp passed in is non zero, then all callsites must match. -** If the stamp is zero, all callsites must match global sorted run stamp. -** -** Returns !0 on error. -*/ -int -displayTopCallsites(STRequest * inRequest, tmcallsite ** aCallsites, - uint32_t aCallsiteCount, uint32_t aStamp, - const char* id, - const char* caption, - int aRealName) -{ - int retval = 0; - - if (NULL != aCallsites && 0 < aCallsiteCount) { - uint32_t traverse = 0; - STRun *run = NULL; - tmcallsite *site = NULL; - int headerDisplayed = 0; - uint32_t displayed = 0; - - /* - ** Fixup the stamp. - */ - if (0 == aStamp && NULL != inRequest->mContext->mSortedRun) { - aStamp = - inRequest->mContext->mSortedRun->mStats[inRequest->mContext-> - mIndex].mStamp; - } - - /* - ** Sort the things. - */ - NS_QuickSort(aCallsites, aCallsiteCount, sizeof(tmcallsite *), - compareCallsites, inRequest); - - /* - ** Time for output. - */ - for (traverse = 0; - traverse < aCallsiteCount - && inRequest->mOptions.mListItemMax > displayed; traverse++) { - site = aCallsites[traverse]; - run = CALLSITE_RUN(site); - - /* - ** Only if the same stamp.... - */ - if (aStamp == run->mStats[inRequest->mContext->mIndex].mStamp) { - /* - ** We got a header yet? - */ - if (0 == headerDisplayed) { - static const char* const headers[] = { - "Rank", - "Callsite", - "Size", - "Seconds", - "Weight", - "Object Count", - "C.H. Operation (sec)" - }; - headerDisplayed = __LINE__; - - htmlStartTable(inRequest, NULL, id, caption, headers, - sizeof(headers) / sizeof(headers[0])); - } - - displayed++; - - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Rank. - */ - PR_fprintf(inRequest->mFD, - "%u\n", displayed); - - /* - ** Method. - */ - PR_fprintf(inRequest->mFD, ""); - htmlCallsiteAnchor(inRequest, site, NULL, aRealName); - PR_fprintf(inRequest->mFD, "\n"); - - /* - ** Size. - */ - PR_fprintf(inRequest->mFD, - "%u\n", - run->mStats[inRequest->mContext->mIndex].mSize); - - /* - ** Timeval. - */ - PR_fprintf(inRequest->mFD, - "" ST_TIMEVAL_FORMAT - "\n", - ST_TIMEVAL_PRINTABLE64(run-> - mStats[inRequest->mContext-> - mIndex].mTimeval64)); - - /* - ** Weight. - */ - PR_fprintf(inRequest->mFD, - "%llu\n", - run->mStats[inRequest->mContext->mIndex]. - mWeight64); - - /* - ** Allocation object count. - */ - PR_fprintf(inRequest->mFD, - "%u\n", - run->mStats[inRequest->mContext->mIndex]. - mCompositeCount); - - /* - ** Heap operation seconds. - */ - PR_fprintf(inRequest->mFD, - "" ST_MICROVAL_FORMAT - "\n", - ST_MICROVAL_PRINTABLE(run-> - mStats[inRequest->mContext-> - mIndex]. - mHeapRuntimeCost)); - - PR_fprintf(inRequest->mFD, "\n"); - - - if (inRequest->mOptions.mListItemMax > displayed) { - /* - ** Skip any dups. - */ - while (((traverse + 1) < aCallsiteCount) - && (site == aCallsites[traverse + 1])) { - traverse++; - } - } - } - } - - /* - ** We need to terminate anything? - */ - if (0 != headerDisplayed) { - PR_fprintf(inRequest->mFD, "\n"); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayTopCallsites); - } - - return retval; -} - -/* -** displayCallsiteDetails -** -** The callsite specific report. -** Try to report what we know. -** This one hits a little harder than the rest. -** -** Returns !0 on error. -*/ -int -displayCallsiteDetails(STRequest * inRequest, tmcallsite * aCallsite) -{ - int retval = 0; - - if (NULL != aCallsite && NULL != aCallsite->method) { - STRun *sortedRun = NULL; - STRun *thisRun = CALLSITE_RUN(aCallsite); - const char *sourceFile = NULL; - - sourceFile = resolveSourceFile(aCallsite->method); - - PR_fprintf(inRequest->mFD, "
\n"); - if (sourceFile) { - PR_fprintf(inRequest->mFD, "%s", - tmmethodnode_name(aCallsite->method)); - PR_fprintf(inRequest->mFD, - " [%s:%u]", - aCallsite->method->sourcefile, - aCallsite->method->linenumber, sourceFile, - aCallsite->method->linenumber); - } - else { - PR_fprintf(inRequest->mFD, - "

%s+%u(%u) Callsite Details:

\n", - tmmethodnode_name(aCallsite->method), - aCallsite->offset, (uint32_t) aCallsite->entry.key); - } - - PR_fprintf(inRequest->mFD, "
\n\n"); - PR_fprintf(inRequest->mFD, "
\n"); - PR_fprintf(inRequest->mFD, - "\n", - thisRun->mStats[inRequest->mContext->mIndex].mSize); - PR_fprintf(inRequest->mFD, - "\n", - ST_TIMEVAL_PRINTABLE64(thisRun-> - mStats[inRequest->mContext->mIndex]. - mTimeval64)); - PR_fprintf(inRequest->mFD, - "\n", - thisRun->mStats[inRequest->mContext->mIndex].mWeight64); - PR_fprintf(inRequest->mFD, - "\n", - thisRun->mStats[inRequest->mContext->mIndex]. - mCompositeCount); - PR_fprintf(inRequest->mFD, - "\n", - ST_MICROVAL_PRINTABLE(thisRun-> - mStats[inRequest->mContext->mIndex]. - mHeapRuntimeCost)); - PR_fprintf(inRequest->mFD, "
Composite Byte Size:%u
Composite Seconds:" - ST_TIMEVAL_FORMAT "
Composite Weight:%llu
Heap Object Count:%u
Heap Operation Seconds:" - ST_MICROVAL_FORMAT "
\n\n"); - - /* - ** Kids (callsites we call): - */ - if (NULL != aCallsite->kids && NULL != aCallsite->kids->method) { - int displayRes = 0; - uint32_t siteCount = 0; - tmcallsite **sites = NULL; - - /* - ** Collect the kid sibling callsites. - ** Doing it this way sorts them for relevance. - */ - siteCount = - callsiteArrayFromCallsite(&sites, 0, aCallsite->kids, - ST_FOLLOW_SIBLINGS); - if (0 != siteCount && NULL != sites) { - /* - ** Got something to show. - */ - displayRes = - displayTopCallsites(inRequest, sites, siteCount, 0, - "callsites", - "Children Callsites", - __LINE__); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayTopCallsites); - } - - /* - ** Done with array. - */ - free(sites); - sites = NULL; - } - } - - /* - ** Parents (those who call us): - */ - if (NULL != aCallsite->parent && NULL != aCallsite->parent->method) { - int displayRes = 0; - - displayRes = - displayCallsites(inRequest, aCallsite->parent, - ST_FOLLOW_PARENTS, 0, "caller-stack", "Caller stack", - __LINE__); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsites); - } - } - - /* - ** Allocations we did. - ** Simply harvest our own run. - */ - sortedRun = createRun(inRequest->mContext, 0); - if (NULL != sortedRun) { - int harvestRes = 0; - - harvestRes = - harvestRun(CALLSITE_RUN(aCallsite), sortedRun, - &inRequest->mOptions, inRequest->mContext); - if (0 == harvestRes) { - if (0 != sortedRun->mAllocationCount) { - int sortRes = 0; - - sortRes = sortRun(&inRequest->mOptions, sortedRun); - if (0 == sortRes) { - int displayRes = 0; - - displayRes = - displayTopAllocations(inRequest, sortedRun, - "allocations", - "Allocations", - 0); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayTopAllocations); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, sortRun); - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, harvestRun); - } - - /* - ** Done with the run. - */ - freeRun(sortedRun); - sortedRun = NULL; - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, createRun); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsiteDetails); - } - - return retval; -} - -#if ST_WANT_GRAPHS -/* -** graphFootprint -** -** Output a PNG graph of the memory usage of the run. -** -** Draw the graph within these boundaries. -** STGD_MARGIN,STGD_MARGIN,STGD_WIDTH-STGD_MARGIN,STGD_HEIGHT-STGD_MARGIN -** -** Returns !0 on failure. -*/ -int -graphFootprint(STRequest * inRequest, STRun * aRun) -{ - int retval = 0; - - if (NULL != aRun) { - uint32_t *YData = NULL; - uint32_t YDataArray[STGD_SPACE_X]; - uint32_t traverse = 0; - uint32_t timeval = 0; - uint32_t loop = 0; - PRBool underLock = PR_FALSE; - - /* - ** Decide if this is custom or we should use the cache. - */ - if (aRun == inRequest->mContext->mSortedRun) { - YData = inRequest->mContext->mFootprintYData; - underLock = PR_TRUE; - } - else { - YData = YDataArray; - } - - /* - ** Protect the shared data so that only one client has access to it - ** at any given time. - */ - if (PR_FALSE != underLock) { - PR_Lock(inRequest->mContext->mImageLock); - } - - /* - ** Only do the computations if we aren't cached already. - */ - if (YData != inRequest->mContext->mFootprintYData - || PR_FALSE == inRequest->mContext->mFootprintCached) { - memset(YData, 0, sizeof(uint32_t) * STGD_SPACE_X); - - /* - ** Initialize our Y data. - ** Pretty brutal loop here.... - */ - for (traverse = 0; 0 == retval && traverse < STGD_SPACE_X; - traverse++) { - /* - ** Compute what timeval this Y data lands in. - */ - timeval = - ((traverse * - (globals.mMaxTimeval - - globals.mMinTimeval)) / STGD_SPACE_X) + - globals.mMinTimeval; - - /* - ** Loop over the run. - ** Should an allocation contain said Timeval, we're good. - */ - for (loop = 0; loop < aRun->mAllocationCount; loop++) { - if (timeval >= aRun->mAllocations[loop]->mMinTimeval - && timeval <= aRun->mAllocations[loop]->mMaxTimeval) { - YData[traverse] += - byteSize(&inRequest->mOptions, - aRun->mAllocations[loop]); - } - } - } - - /* - ** Did we cache this? - */ - if (YData == inRequest->mContext->mFootprintYData) { - inRequest->mContext->mFootprintCached = PR_TRUE; - } - } - - /* - ** Done with the lock. - */ - if (PR_FALSE != underLock) { - PR_Unlock(inRequest->mContext->mImageLock); - } - - if (0 == retval) { - uint32_t minMemory = (uint32_t) - 1; - uint32_t maxMemory = 0; - int transparent = 0; - gdImagePtr graph = NULL; - - /* - ** Go through and find the minimum and maximum sizes. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - if (YData[traverse] < minMemory) { - minMemory = YData[traverse]; - } - if (YData[traverse] > maxMemory) { - maxMemory = YData[traverse]; - } - } - - /* - ** We can now draw the graph. - */ - graph = createGraph(&transparent); - if (NULL != graph) { - gdSink theSink; - int red = 0; - int x1 = 0; - int y1 = 0; - int x2 = 0; - int y2 = 0; - uint32_t percents[11] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - char *timevals[11]; - char *bytes[11]; - char timevalSpace[11][32]; - char byteSpace[11][32]; - int legendColors[1]; - const char *legends[1] = { "Memory in Use" }; - uint32_t cached = 0; - - /* - ** Figure out what the labels will say. - */ - for (traverse = 0; traverse < 11; traverse++) { - timevals[traverse] = timevalSpace[traverse]; - bytes[traverse] = byteSpace[traverse]; - - cached = - ((globals.mMaxTimeval - - globals.mMinTimeval) * percents[traverse]) / 100; - PR_snprintf(timevals[traverse], 32, ST_TIMEVAL_FORMAT, - ST_TIMEVAL_PRINTABLE(cached)); - PR_snprintf(bytes[traverse], 32, "%u", - ((maxMemory - - minMemory) * percents[traverse]) / 100); - } - - red = gdImageColorAllocate(graph, 255, 0, 0); - legendColors[0] = red; - - drawGraph(graph, -1, "Memory Footprint Over Time", "Seconds", - "Bytes", 11, percents, (const char **) timevals, 11, - percents, (const char **) bytes, 1, legendColors, - legends); - - if (maxMemory != minMemory) { - int64_t in64 = 0; - int64_t ydata64 = 0; - int64_t spacey64 = 0; - int64_t mem64 = 0; - int32_t in32 = 0; - - /* - ** Go through our Y data and mark it up. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - x1 = traverse + STGD_MARGIN; - y1 = STGD_HEIGHT - STGD_MARGIN; - - /* - ** Need to do this math in 64 bits. - */ - ydata64 = (int64_t)YData[traverse]; - spacey64 = (int64_t)STGD_SPACE_Y; - mem64 = (int64_t)(maxMemory - minMemory); - - in64 = ydata64 * spacey64; - in64 /= mem64; - in32 = int32_t(in64); - - x2 = x1; - y2 = y1 - in32; - - gdImageLine(graph, x1, y1, x2, y2, red); - } - } - - - theSink.context = inRequest->mFD; - theSink.sink = pngSink; - gdImagePngToSink(graph, &theSink); - - gdImageDestroy(graph); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, createGraph); - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphFootprint); - } - - return retval; -} -#endif /* ST_WANT_GRAPHS */ - -#if ST_WANT_GRAPHS -/* -** graphTimeval -** -** Output a PNG graph of when the memory is allocated. -** -** Draw the graph within these boundaries. -** STGD_MARGIN,STGD_MARGIN,STGD_WIDTH-STGD_MARGIN,STGD_HEIGHT-STGD_MARGIN -** -** Returns !0 on failure. -*/ -int -graphTimeval(STRequest * inRequest, STRun * aRun) -{ - int retval = 0; - - if (NULL != aRun) { - uint32_t *YData = NULL; - uint32_t YDataArray[STGD_SPACE_X]; - uint32_t traverse = 0; - uint32_t timeval = globals.mMinTimeval; - uint32_t loop = 0; - PRBool underLock = PR_FALSE; - - /* - ** Decide if this is custom or we should use the global cache. - */ - if (aRun == inRequest->mContext->mSortedRun) { - YData = inRequest->mContext->mTimevalYData; - underLock = PR_TRUE; - } - else { - YData = YDataArray; - } - - /* - ** Protect the shared data so that only one client has access to it - ** at any given time. - */ - if (PR_FALSE != underLock) { - PR_Lock(inRequest->mContext->mImageLock); - } - - /* - ** Only do the computations if we aren't cached already. - */ - if (YData != inRequest->mContext->mTimevalYData - || PR_FALSE == inRequest->mContext->mTimevalCached) { - uint32_t prevTimeval = 0; - - memset(YData, 0, sizeof(uint32_t) * STGD_SPACE_X); - - /* - ** Initialize our Y data. - ** Pretty brutal loop here.... - */ - for (traverse = 0; 0 == retval && traverse < STGD_SPACE_X; - traverse++) { - /* - ** Compute what timeval this Y data lands in. - */ - prevTimeval = timeval; - timeval = - ((traverse * - (globals.mMaxTimeval - - globals.mMinTimeval)) / STGD_SPACE_X) + - globals.mMinTimeval; - - /* - ** Loop over the run. - ** Should an allocation have been allocated between - ** prevTimeval and timeval.... - */ - for (loop = 0; loop < aRun->mAllocationCount; loop++) { - if (prevTimeval < aRun->mAllocations[loop]->mMinTimeval - && timeval >= aRun->mAllocations[loop]->mMinTimeval) { - YData[traverse] += - byteSize(&inRequest->mOptions, - aRun->mAllocations[loop]); - } - } - } - - /* - ** Did we cache this? - */ - if (YData == inRequest->mContext->mTimevalYData) { - inRequest->mContext->mTimevalCached = PR_TRUE; - } - } - - /* - ** Done with the lock. - */ - if (PR_FALSE != underLock) { - PR_Unlock(inRequest->mContext->mImageLock); - } - - if (0 == retval) { - uint32_t minMemory = (uint32_t) - 1; - uint32_t maxMemory = 0; - int transparent = 0; - gdImagePtr graph = NULL; - - /* - ** Go through and find the minimum and maximum sizes. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - if (YData[traverse] < minMemory) { - minMemory = YData[traverse]; - } - if (YData[traverse] > maxMemory) { - maxMemory = YData[traverse]; - } - } - - /* - ** We can now draw the graph. - */ - graph = createGraph(&transparent); - if (NULL != graph) { - gdSink theSink; - int red = 0; - int x1 = 0; - int y1 = 0; - int x2 = 0; - int y2 = 0; - uint32_t percents[11] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - char *timevals[11]; - char *bytes[11]; - char timevalSpace[11][32]; - char byteSpace[11][32]; - int legendColors[1]; - const char *legends[1] = { "Memory Allocated" }; - uint32_t cached = 0; - - /* - ** Figure out what the labels will say. - */ - for (traverse = 0; traverse < 11; traverse++) { - timevals[traverse] = timevalSpace[traverse]; - bytes[traverse] = byteSpace[traverse]; - - cached = - ((globals.mMaxTimeval - - globals.mMinTimeval) * percents[traverse]) / 100; - PR_snprintf(timevals[traverse], 32, ST_TIMEVAL_FORMAT, - ST_TIMEVAL_PRINTABLE(cached)); - PR_snprintf(bytes[traverse], 32, "%u", - ((maxMemory - - minMemory) * percents[traverse]) / 100); - } - - red = gdImageColorAllocate(graph, 255, 0, 0); - legendColors[0] = red; - - drawGraph(graph, -1, "Allocation Times", "Seconds", "Bytes", - 11, percents, (const char **) timevals, 11, - percents, (const char **) bytes, 1, legendColors, - legends); - - if (maxMemory != minMemory) { - int64_t in64 = 0; - int64_t ydata64 = 0; - int64_t spacey64 = 0; - int64_t mem64 = 0; - int32_t in32 = 0; - - /* - ** Go through our Y data and mark it up. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - x1 = traverse + STGD_MARGIN; - y1 = STGD_HEIGHT - STGD_MARGIN; - - /* - ** Need to do this math in 64 bits. - */ - ydata64 = (int64_t)YData[traverse]; - spacey64 = (int64_t)STGD_SPACE_Y; - mem64 = (int64_t)(maxMemory - minMemory); - - in64 = ydata64 * spacey64; - in64 /= mem64; - in32 = int32_t(in64); - - x2 = x1; - y2 = y1 - in32; - - gdImageLine(graph, x1, y1, x2, y2, red); - } - } - - - theSink.context = inRequest->mFD; - theSink.sink = pngSink; - gdImagePngToSink(graph, &theSink); - - gdImageDestroy(graph); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, createGraph); - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphTimeval); - } - - return retval; -} -#endif /* ST_WANT_GRAPHS */ - -#if ST_WANT_GRAPHS -/* -** graphLifespan -** -** Output a PNG graph of how long memory lived. -** -** Draw the graph within these boundaries. -** STGD_MARGIN,STGD_MARGIN,STGD_WIDTH-STGD_MARGIN,STGD_HEIGHT-STGD_MARGIN -** -** Returns !0 on failure. -*/ -int -graphLifespan(STRequest * inRequest, STRun * aRun) -{ - int retval = 0; - - if (NULL != aRun) { - uint32_t *YData = NULL; - uint32_t YDataArray[STGD_SPACE_X]; - uint32_t traverse = 0; - uint32_t timeval = 0; - uint32_t loop = 0; - PRBool underLock = PR_FALSE; - - /* - ** Decide if this is custom or we should use the global cache. - */ - if (aRun == inRequest->mContext->mSortedRun) { - YData = inRequest->mContext->mLifespanYData; - underLock = PR_TRUE; - } - else { - YData = YDataArray; - } - - /* - ** Protect the shared data so that only one client has access to it - ** at any given time. - */ - if (PR_FALSE != underLock) { - PR_Lock(inRequest->mContext->mImageLock); - } - - /* - ** Only do the computations if we aren't cached already. - */ - if (YData != inRequest->mContext->mLifespanYData - || PR_FALSE == inRequest->mContext->mLifespanCached) { - uint32_t prevTimeval = 0; - uint32_t lifespan = 0; - - memset(YData, 0, sizeof(uint32_t) * STGD_SPACE_X); - - /* - ** Initialize our Y data. - ** Pretty brutal loop here.... - */ - for (traverse = 0; 0 == retval && traverse < STGD_SPACE_X; - traverse++) { - /* - ** Compute what timeval this Y data lands in. - */ - prevTimeval = timeval; - timeval = - (traverse * (globals.mMaxTimeval - globals.mMinTimeval)) / - STGD_SPACE_X; - - /* - ** Loop over the run. - ** Should an allocation have lived between - ** prevTimeval and timeval.... - */ - for (loop = 0; loop < aRun->mAllocationCount; loop++) { - lifespan = - aRun->mAllocations[loop]->mMaxTimeval - - aRun->mAllocations[loop]->mMinTimeval; - - if (prevTimeval < lifespan && timeval >= lifespan) { - YData[traverse] += - byteSize(&inRequest->mOptions, - aRun->mAllocations[loop]); - } - } - } - - /* - ** Did we cache this? - */ - if (YData == inRequest->mContext->mLifespanYData) { - inRequest->mContext->mLifespanCached = PR_TRUE; - } - } - - /* - ** Done with the lock. - */ - if (PR_FALSE != underLock) { - PR_Unlock(inRequest->mContext->mImageLock); - } - - if (0 == retval) { - uint32_t minMemory = (uint32_t) - 1; - uint32_t maxMemory = 0; - int transparent = 0; - gdImagePtr graph = NULL; - - /* - ** Go through and find the minimum and maximum sizes. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - if (YData[traverse] < minMemory) { - minMemory = YData[traverse]; - } - if (YData[traverse] > maxMemory) { - maxMemory = YData[traverse]; - } - } - - /* - ** We can now draw the graph. - */ - graph = createGraph(&transparent); - if (NULL != graph) { - gdSink theSink; - int red = 0; - int x1 = 0; - int y1 = 0; - int x2 = 0; - int y2 = 0; - uint32_t percents[11] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - char *timevals[11]; - char *bytes[11]; - char timevalSpace[11][32]; - char byteSpace[11][32]; - int legendColors[1]; - const char *legends[1] = { "Live Memory" }; - uint32_t cached = 0; - - /* - ** Figure out what the labels will say. - */ - for (traverse = 0; traverse < 11; traverse++) { - timevals[traverse] = timevalSpace[traverse]; - bytes[traverse] = byteSpace[traverse]; - - cached = - ((globals.mMaxTimeval - - globals.mMinTimeval) * percents[traverse]) / 100; - PR_snprintf(timevals[traverse], 32, ST_TIMEVAL_FORMAT, - ST_TIMEVAL_PRINTABLE(cached)); - PR_snprintf(bytes[traverse], 32, "%u", - ((maxMemory - - minMemory) * percents[traverse]) / 100); - } - - red = gdImageColorAllocate(graph, 255, 0, 0); - legendColors[0] = red; - - drawGraph(graph, -1, "Allocation Lifespans", "Lifespan", - "Bytes", 11, percents, (const char **) timevals, 11, - percents, (const char **) bytes, 1, legendColors, - legends); - - if (maxMemory != minMemory) { - int64_t in64 = 0; - int64_t ydata64 = 0; - int64_t spacey64 = 0; - int64_t mem64 = 0; - int32_t in32 = 0; - - /* - ** Go through our Y data and mark it up. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - x1 = traverse + STGD_MARGIN; - y1 = STGD_HEIGHT - STGD_MARGIN; - - /* - ** Need to do this math in 64 bits. - */ - ydata64 = (int64_t)YData[traverse]; - spacey64 = (int64_t)STGD_SPACE_Y; - mem64 = (int64_t)(maxMemory - minMemory); - - in64 = ydata64 * spacey64; - in64 /= mem64; - in32 = int32_t(in64); - - x2 = x1; - y2 = y1 - in32; - - gdImageLine(graph, x1, y1, x2, y2, red); - } - } - - - theSink.context = inRequest->mFD; - theSink.sink = pngSink; - gdImagePngToSink(graph, &theSink); - - gdImageDestroy(graph); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, createGraph); - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphLifespan); - } - - return retval; -} -#endif /* ST_WANT_GRAPHS */ - -#if ST_WANT_GRAPHS -/* -** graphWeight -** -** Output a PNG graph of Allocations by Weight -** -** Draw the graph within these boundaries. -** STGD_MARGIN,STGD_MARGIN,STGD_WIDTH-STGD_MARGIN,STGD_HEIGHT-STGD_MARGIN -** -** Returns !0 on failure. -*/ -int -graphWeight(STRequest * inRequest, STRun * aRun) -{ - int retval = 0; - - if (NULL != aRun) { - uint64_t *YData64 = NULL; - uint64_t YDataArray64[STGD_SPACE_X]; - uint32_t traverse = 0; - uint32_t timeval = globals.mMinTimeval; - uint32_t loop = 0; - PRBool underLock = PR_FALSE; - - /* - ** Decide if this is custom or we should use the global cache. - */ - if (aRun == inRequest->mContext->mSortedRun) { - YData64 = inRequest->mContext->mWeightYData64; - underLock = PR_TRUE; - } - else { - YData64 = YDataArray64; - } - - /* - ** Protect the shared data so that only one client has access to it - ** at any given time. - */ - if (PR_FALSE != underLock) { - PR_Lock(inRequest->mContext->mImageLock); - } - - /* - ** Only do the computations if we aren't cached already. - */ - if (YData64 != inRequest->mContext->mWeightYData64 - || PR_FALSE == inRequest->mContext->mWeightCached) { - uint32_t prevTimeval = 0; - - memset(YData64, 0, sizeof(uint64_t) * STGD_SPACE_X); - - /* - ** Initialize our Y data. - ** Pretty brutal loop here.... - */ - for (traverse = 0; 0 == retval && traverse < STGD_SPACE_X; - traverse++) { - /* - ** Compute what timeval this Y data lands in. - */ - prevTimeval = timeval; - timeval = - ((traverse * - (globals.mMaxTimeval - - globals.mMinTimeval)) / STGD_SPACE_X) + - globals.mMinTimeval; - - /* - ** Loop over the run. - ** Should an allocation have been allocated between - ** prevTimeval and timeval.... - */ - for (loop = 0; loop < aRun->mAllocationCount; loop++) { - if (prevTimeval < aRun->mAllocations[loop]->mMinTimeval - && timeval >= aRun->mAllocations[loop]->mMinTimeval) { - uint64_t size64 = 0; - uint64_t lifespan64 = 0; - uint64_t weight64 = 0; - - size64 = byteSize(&inRequest->mOptions, - aRun->mAllocations[loop]); - lifespan64 = aRun->mAllocations[loop]->mMaxTimeval - - aRun->mAllocations[loop]->mMinTimeval; - weight64 = size64 * lifespan64; - - YData64[traverse] += weight64; - } - } - } - - /* - ** Did we cache this? - */ - if (YData64 == inRequest->mContext->mWeightYData64) { - inRequest->mContext->mWeightCached = PR_TRUE; - } - } - - /* - ** Done with the lock. - */ - if (PR_FALSE != underLock) { - PR_Unlock(inRequest->mContext->mImageLock); - } - - if (0 == retval) { - uint64_t minWeight64 = (0xFFFFFFFFLL << 32) + 0xFFFFFFFFLL; - uint64_t maxWeight64 = 0; - int transparent = 0; - gdImagePtr graph = NULL; - - /* - ** Go through and find the minimum and maximum weights. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - if (YData64[traverse] < minWeight64) { - minWeight64 = YData64[traverse]; - } - if (YData64[traverse] > maxWeight64) { - maxWeight64 = YData64[traverse]; - } - } - - /* - ** We can now draw the graph. - */ - graph = createGraph(&transparent); - if (NULL != graph) { - gdSink theSink; - int red = 0; - int x1 = 0; - int y1 = 0; - int x2 = 0; - int y2 = 0; - uint32_t percents[11] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - char *timevals[11]; - char *bytes[11]; - char timevalSpace[11][32]; - char byteSpace[11][32]; - int legendColors[1]; - const char *legends[1] = { "Memory Weight" }; - uint64_t percent64 = 0; - uint64_t result64 = 0; - - uint32_t cached = 0; - uint64_t hundred64 = 100; - - /* - ** Figure out what the labels will say. - */ - for (traverse = 0; traverse < 11; traverse++) { - timevals[traverse] = timevalSpace[traverse]; - bytes[traverse] = byteSpace[traverse]; - - cached = - ((globals.mMaxTimeval - - globals.mMinTimeval) * percents[traverse]) / 100; - PR_snprintf(timevals[traverse], 32, ST_TIMEVAL_FORMAT, - ST_TIMEVAL_PRINTABLE(cached)); - - result64 = (maxWeight64 - minWeight64) * percents[traverse]; - result64 /= hundred64; - PR_snprintf(bytes[traverse], 32, "%llu", result64); - } - - red = gdImageColorAllocate(graph, 255, 0, 0); - legendColors[0] = red; - - drawGraph(graph, -1, "Allocation Weights", "Seconds", - "Weight", 11, percents, (const char **) timevals, - 11, percents, (const char **) bytes, 1, - legendColors, legends); - - if (maxWeight64 != minWeight64) { - int64_t in64 = 0; - int64_t spacey64 = 0; - int64_t weight64 = 0; - int32_t in32 = 0; - - /* - ** Go through our Y data and mark it up. - */ - for (traverse = 0; traverse < STGD_SPACE_X; traverse++) { - x1 = traverse + STGD_MARGIN; - y1 = STGD_HEIGHT - STGD_MARGIN; - - /* - ** Need to do this math in 64 bits. - */ - spacey64 = (int64_t)STGD_SPACE_Y; - weight64 = maxWeight64 - minWeight64; - - in64 = YData64[traverse] * spacey64; - in64 /= weight64; - in32 = int32_t(in64); - - x2 = x1; - y2 = y1 - in32; - - gdImageLine(graph, x1, y1, x2, y2, red); - } - } - - - theSink.context = inRequest->mFD; - theSink.sink = pngSink; - gdImagePngToSink(graph, &theSink); - - gdImageDestroy(graph); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, createGraph); - } - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphWeight); - } - - return retval; -} -#endif /* ST_WANT_GRAPHS */ - -#define ST_WEB_OPTION_BOOL(option_name, option_genre, option_help) \ - { \ - uint32_t convert = (uint32_t)outOptions->m##option_name; \ - \ - getDataPRUint32(inFormData, #option_name, 1, &convert, 1); \ - outOptions->m##option_name = (PRBool)convert; \ - } -#define ST_WEB_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - getDataString(inFormData, #option_name, 1, outOptions->m##option_name, sizeof(outOptions->m##option_name)); -#define ST_WEB_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - { \ - uint32_t loop = 0; \ - uint32_t found = 0; \ - char buffer[ST_OPTION_STRING_MAX]; \ - \ - for(loop = 0; loop < array_size; loop++) \ - { \ - buffer[0] = '\0'; \ - getDataString(inFormData, #option_name, (loop + 1), buffer, sizeof(buffer)); \ - \ - if('\0' != buffer[0]) \ - { \ - PR_snprintf(outOptions->m##option_name[found], sizeof(outOptions->m##option_name[found]), "%s", buffer); \ - found++; \ - } \ - } \ - \ - for(; found < array_size; found++) \ - { \ - outOptions->m##option_name[found][0] = '\0'; \ - } \ - } -#define ST_WEB_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) /* no implementation */ -#define ST_WEB_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - getDataPRUint32(inFormData, #option_name, 1, &outOptions->m##option_name, multiplier); -#define ST_WEB_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - { \ - uint64_t mul64 = multiplier; \ - \ - getDataPRUint64(inFormData, #option_name, 1, &outOptions->m##option_name##64, mul64); \ - } -/* -** fillOptions -** -** Given an appropriate hexcaped string, distill the option values -** and fill the given STOption struct. -** -** Note that the options passed in are not touched UNLESS there is -** a replacement found in the form data. -*/ -void -fillOptions(STOptions * outOptions, const FormData * inFormData) -{ - if (NULL != outOptions && NULL != inFormData) { - -#include "stoptions.h" - - /* - ** Special sanity check here for some options that need data validation. - */ - if (!outOptions->mCategoryName[0] - || !findCategoryNode(outOptions->mCategoryName, &globals)) { - PR_snprintf(outOptions->mCategoryName, - sizeof(outOptions->mCategoryName), "%s", - ST_ROOT_CATEGORY_NAME); - } - } -} - - -void -displayOptionString(STRequest * inRequest, - const char *option_name, - const char *option_genre, - const char *default_value, - const char *option_help, const char *value) -{ -#if 0 - PR_fprintf(inRequest->mFD, "\n", option_name); -#endif - PR_fprintf(inRequest->mFD, "
\n"); - PR_fprintf(inRequest->mFD, "

%s

\n", option_name); - PR_fprintf(inRequest->mFD, - "\n", - option_name, value); - PR_fprintf(inRequest->mFD, - "

Default value is \"%s\".

\n

%s

\n", - default_value, option_help); - PR_fprintf(inRequest->mFD, "
\n"); -} - -static void -displayOptionStringArray(STRequest * inRequest, - const char *option_name, - const char *option_genre, - uint32_t array_size, - const char *option_help, const char values[5] - [ST_OPTION_STRING_MAX]) -{ - /* values should not be a fixed length! */ - PR_ASSERT(array_size == 5); -#if 0 - PR_fprintf(inRequest->mFD, "\n", option_name); -#endif - PR_fprintf(inRequest->mFD, "
\n"); - PR_fprintf(inRequest->mFD, "

%s

\n", option_name); { - uint32_t loop = 0; - - for (loop = 0; loop < array_size; loop++) { - PR_fprintf(inRequest->mFD, - "
\n", - option_name, values[loop]); - } - } - PR_fprintf(inRequest->mFD, - "

Up to %u occurrences allowed.

\n

%s

\n", - array_size, option_help); - PR_fprintf(inRequest->mFD, "
\n"); -} - -static void -displayOptionInt(STRequest * inRequest, - const char *option_name, - const char *option_genre, - uint32_t default_value, - uint32_t multiplier, const char *option_help, uint32_t value) -{ -#if 0 - PR_fprintf(inRequest->mFD, "\n", option_name); -#endif - PR_fprintf(inRequest->mFD, "
\n"); - PR_fprintf(inRequest->mFD, "

%s

\n", option_name); - PR_fprintf(inRequest->mFD, - "\n", option_name, - value / multiplier); - PR_fprintf(inRequest->mFD, - "

Default value is %u.

\n

%s

\n", - default_value, option_help); - PR_fprintf(inRequest->mFD, "
\n"); -} - -static void -displayOptionInt64(STRequest * inRequest, - const char *option_name, - const char *option_genre, - uint64_t default_value, - uint64_t multiplier, - const char *option_help, uint64_t value) -{ -#if 0 - PR_fprintf(inRequest->mFD, "\n", option_name); -#endif - PR_fprintf(inRequest->mFD, "
\n"); - PR_fprintf(inRequest->mFD, "

%s

\n", option_name); { - uint64_t def64 = default_value; - uint64_t mul64 = multiplier; - uint64_t div64; - - div64 = value / mul64; - PR_fprintf(inRequest->mFD, - "\n", - option_name, div64); - PR_fprintf(inRequest->mFD, - "

Default value is %llu.

\n

%s

\n", - def64, option_help); - } - PR_fprintf(inRequest->mFD, "
\n"); -} - -/* -** displaySettings -** -** Present the settings for change during execution. -*/ -void -displaySettings(STRequest * inRequest) -{ - int applyRes = 0; - - /* - ** We've got a form to create. - */ - PR_fprintf(inRequest->mFD, "
\n"); - /* - ** Respect newlines in help text. - */ -#if 0 - PR_fprintf(inRequest->mFD, "
\n");
-#endif
-#define ST_WEB_OPTION_BOOL(option_name, option_genre, option_help) \
-    displayOptionBool(option_name, option_genre, option_help)
-#define ST_WEB_OPTION_STRING(option_name, option_genre, default_value, option_help) \
-    displayOptionString(inRequest, #option_name, #option_genre, default_value, option_help, inRequest->mOptions.m##option_name);
-#define ST_WEB_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \
-    displayOptionStringArray(inRequest, #option_name, #option_genre, array_size, option_help, inRequest->mOptions.m##option_name);
-#define ST_WEB_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help)  /* no implementation */
-#define ST_WEB_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \
-    displayOptionInt(inRequest, #option_name, #option_genre, default_value, multiplier, option_help, inRequest->mOptions.m##option_name);
-#define ST_WEB_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \
-    displayOptionInt64(inRequest, #option_name, #option_genre, default_value, multiplier, option_help, inRequest->mOptions.m##option_name##64);
-#include "stoptions.h"
-    /*
-     **  Give a submit/reset button, obligatory.
-     **  Done respecting newlines in help text.
-     */
-    PR_fprintf(inRequest->mFD,
-               " \n");
-#if 0
-    PR_fprintf(inRequest->mFD, "
\n"); -#endif - /* - ** Done with form. - */ - PR_fprintf(inRequest->mFD, "
\n"); -} - -int -handleLocalFile(STRequest * inRequest, const char *aFilename) -{ - static const char *const local_files[] = { - "spacetrace.css", - }; - static const size_t local_file_count = - sizeof(local_files) / sizeof(local_files[0]); - size_t i; - - for (i = 0; i < local_file_count; i++) { - if (0 == strcmp(local_files[i], aFilename)) - return 1; - } - return 0; -} - -/* -** displayFile -** -** reads a file from disk, and streams it to the request -*/ -int -displayFile(STRequest * inRequest, const char *aFilename) -{ - PRFileDesc *inFd; - const char *filepath = - PR_smprintf("res%c%s", PR_GetDirectorySeparator(), aFilename); - char buffer[2048]; - int32_t readRes; - - inFd = PR_Open(filepath, PR_RDONLY, PR_IRUSR); - if (!inFd) - return -1; - while ((readRes = PR_Read(inFd, buffer, sizeof(buffer))) > 0) { - PR_Write(inRequest->mFD, buffer, readRes); - } - if (readRes != 0) - return -1; - PR_Close(inFd); - return 0; -} - -/* -** displayIndex -** -** Present a list of the reports you can drill down into. -** Returns !0 on failure. -*/ -int -displayIndex(STRequest * inRequest) -{ - int retval = 0; - STOptions *options = &inRequest->mOptions; - - /* - ** Present reports in a list format. - */ - PR_fprintf(inRequest->mFD, "
    "); - PR_fprintf(inRequest->mFD, "\n
  • "); - htmlAnchor(inRequest, "root_callsites.html", "Root Callsites", - NULL, "mainmenu", options); - PR_fprintf(inRequest->mFD, "\n
  • "); - htmlAnchor(inRequest, "categories_summary.html", - "Categories Report", NULL, "mainmenu", options); - PR_fprintf(inRequest->mFD, "\n
  • "); - htmlAnchor(inRequest, "top_callsites.html", - "Top Callsites Report", NULL, "mainmenu", options); - PR_fprintf(inRequest->mFD, "\n
  • "); - htmlAnchor(inRequest, "top_allocations.html", - "Top Allocations Report", NULL, "mainmenu", options); - PR_fprintf(inRequest->mFD, "\n
  • "); - htmlAnchor(inRequest, "memory_leaks.html", - "Memory Leak Report", NULL, "mainmenu", options); -#if ST_WANT_GRAPHS - PR_fprintf(inRequest->mFD, "\n
  • Graphs"); - PR_fprintf(inRequest->mFD, "
      "); - PR_fprintf(inRequest->mFD, "\n
    • "); - htmlAnchor(inRequest, "footprint_graph.html", "Footprint", - NULL, "mainmenu graph", options); - PR_fprintf(inRequest->mFD, "\n
    • "); - htmlAnchor(inRequest, "lifespan_graph.html", - "Allocation Lifespans", NULL, "mainmenu graph", options); - PR_fprintf(inRequest->mFD, "\n
    • "); - htmlAnchor(inRequest, "times_graph.html", "Allocation Times", - NULL, "mainmenu graph", options); - PR_fprintf(inRequest->mFD, "\n
    • "); - htmlAnchor(inRequest, "weight_graph.html", - "Allocation Weights", NULL, "mainmenu graph", options); - PR_fprintf(inRequest->mFD, "\n
    \n"); -#endif /* ST_WANT_GRAPHS */ - PR_fprintf(inRequest->mFD, "\n
\n"); - return retval; -} - -/* -** initRequestOptions -** -** Given the request, set the options that are specific to the request. -** These can generally be determined in the following manner: -** Copy over global options. -** If getData present, attempt to use options therein. -*/ -void -initRequestOptions(STRequest * inRequest) -{ - if (NULL != inRequest) { - /* - ** Copy of global options. - */ - memcpy(&inRequest->mOptions, &globals.mCommandLineOptions, - sizeof(globals.mCommandLineOptions)); - /* - ** Decide what will override global options if anything. - */ - if (NULL != inRequest->mGetData) { - fillOptions(&inRequest->mOptions, inRequest->mGetData); - } - } -} - -STContext * -contextLookup(STOptions * inOptions) -/* -** Lookup a context that matches the options. -** The lookup may block, especially if the context needs to be created. -** Callers of this API must eventually call contextRelease with the -** return value; failure to do so will cause this applications -** to eventually not work as advertised. -** -** inOptions The options determine which context is relevant. -** returns The fully completed context on success. -** The context is read only in practice, so please do not -** write to it or anything it points to. -** NULL on failure. -*/ -{ - STContext *retval = NULL; - STContextCache *inCache = &globals.mContextCache; - - if (NULL != inOptions && NULL != inCache) { - uint32_t loop = 0; - STContext *categoryException = NULL; - PRBool newContext = PR_FALSE; - PRBool evictContext = PR_FALSE; - PRBool changeCategoryContext = PR_FALSE; - - /* - ** Own the context cache while we are in here. - */ - PR_Lock(inCache->mLock); - /* - ** Loop until successful. - ** Waiting on the condition variable makes sure we don't hog the - ** lock below. - */ - while (1) { - /* - ** Go over the cache items. - ** At this point we are looking for a cache hit, with multiple - ** readers. - */ - for (loop = 0; loop < inCache->mItemCount; loop++) { - /* - ** Must be in use. - */ - if (PR_FALSE != inCache->mItems[loop].mInUse) { - int delta[(STOptionGenre) MaxGenres]; - - /* - ** Compare the relevant options, figure out if different - ** in any genre that we care about. - */ - memset(&delta, 0, sizeof(delta)); -#define ST_WEB_OPTION_BOOL(option_name, option_genre, option_help) \ - if(inOptions->m##option_name != inCache->mItems[loop].mOptions.m##option_name) \ - { \ - delta[(STOptionGenre)option_genre]++; \ - } -#define ST_WEB_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - if(0 != strcmp(inOptions->m##option_name, inCache->mItems[loop].mOptions.m##option_name)) \ - { \ - delta[(STOptionGenre)option_genre]++; \ - } -#define ST_WEB_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - { \ - uint32_t macro_loop = 0; \ - \ - for(macro_loop = 0; macro_loop < array_size; macro_loop++) \ - { \ - if(0 != strcmp(inOptions->m##option_name[macro_loop], inCache->mItems[loop].mOptions.m##option_name[macro_loop])) \ - { \ - break; \ - } \ - } \ - \ - if(macro_loop != array_size) \ - { \ - delta[(STOptionGenre)option_genre]++; \ - } \ - } -#define ST_WEB_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) /* no implementation */ -#define ST_WEB_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - if(inOptions->m##option_name != inCache->mItems[loop].mOptions.m##option_name) \ - { \ - delta[(STOptionGenre)option_genre]++; \ - } -#define ST_WEB_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - if(inOptions->m##option_name##64 != inCache->mItems[loop].mOptions.m##option_name##64) \ - { \ - delta[(STOptionGenre)option_genre]++; \ - } -#include "stoptions.h" - /* - ** If there is no genre out of alignment, we accept this as the context. - */ - if (0 == delta[CategoryGenre] && - 0 == delta[DataSortGenre] && - 0 == delta[DataSetGenre] && 0 == delta[DataSizeGenre] - ) { - retval = &inCache->mItems[loop].mContext; - break; - } - - /* - ** A special exception to the rule here. - ** If all that is different is the category genre, and there - ** is no one looking at the context (zero ref count), - ** then there is some magic we can perform. - */ - if (NULL == retval && - 0 == inCache->mItems[loop].mReferenceCount && - 0 != delta[CategoryGenre] && - 0 == delta[DataSortGenre] && - 0 == delta[DataSetGenre] && 0 == delta[DataSizeGenre] - ) { - categoryException = &inCache->mItems[loop].mContext; - } - } - } - - /* - ** Pick up our category exception if relevant. - */ - if (NULL == retval && NULL != categoryException) { - retval = categoryException; - categoryException = NULL; - changeCategoryContext = PR_TRUE; - } - - /* - ** If we don't have a cache hit, then we need to check for an empty - ** spot to take over. - */ - if (NULL == retval) { - for (loop = 0; loop < inCache->mItemCount; loop++) { - /* - ** Must NOT be in use, then it will be the context. - */ - if (PR_FALSE == inCache->mItems[loop].mInUse) { - retval = &inCache->mItems[loop].mContext; - newContext = PR_TRUE; - break; - } - } - } - - /* - ** If we still don't have a return value, then we need to see if - ** there are any old items with zero ref counts that we - ** can take over. - */ - if (NULL == retval) { - for (loop = 0; loop < inCache->mItemCount; loop++) { - /* - ** Must be in use. - */ - if (PR_FALSE != inCache->mItems[loop].mInUse) { - /* - ** Must have a ref count of zero. - */ - if (0 == inCache->mItems[loop].mReferenceCount) { - /* - ** Must be older than any other we know of. - */ - if (NULL != retval) { - if (inCache->mItems[loop].mLastAccessed < - inCache->mItems[retval->mIndex]. - mLastAccessed) { - retval = &inCache->mItems[loop].mContext; - } - } - else { - retval = &inCache->mItems[loop].mContext; - } - } - } - } - - if (NULL != retval) { - evictContext = PR_TRUE; - } - } - - /* - ** If we still don't have a return value, then we can not avoid - ** waiting around until someone gives us the chance. - ** The chance, in specific, comes when a cache item reference - ** count returns to zero, upon which we can try to take - ** it over again. - */ - if (NULL == retval) { - /* - ** This has the side effect of release the context lock. - ** This is a good thing so that other clients can continue - ** to connect and hopefully have cache hits. - ** If they do not have cache hits, then we will end up - ** with a bunch of waiters here.... - */ - PR_WaitCondVar(inCache->mCacheMiss, PR_INTERVAL_NO_TIMEOUT); - } - - /* - ** If we have a return value, improve the reference count here. - */ - if (NULL != retval) { - /* - ** Decide if there are any changes to be made. - ** Do as little as possible, then fall through the context - ** cache lock to finish up. - ** This way, lengthy init operations will not block - ** other clients, only matches to this context. - */ - if (PR_FALSE != newContext || - PR_FALSE != evictContext || - PR_FALSE != changeCategoryContext) { - /* - ** Overwrite the prefs for this context. - ** They are changing. - */ - memcpy(&inCache->mItems[retval->mIndex].mOptions, - inOptions, - sizeof(inCache->mItems[retval->mIndex].mOptions)); - /* - ** As we are going to be changing the context, we need to write lock it. - ** This makes sure no readers are allowed while we are making our changes. - */ - PR_RWLock_Wlock(retval->mRWLock); - } - - /* - ** NOTE, ref count gets incremented here, inside content - ** cache lock so it can not be flushed once lock - ** released. - */ - inCache->mItems[retval->mIndex].mInUse = PR_TRUE; - inCache->mItems[retval->mIndex].mReferenceCount++; - /* - ** That's all folks. - */ - break; - } - - } /* while(1), try again */ - - /* - ** Done with context cache. - */ - PR_Unlock(inCache->mLock); - /* - ** Now that the context cached is free to continue accepting other - ** requests, we have a little more work to do. - */ - if (NULL != retval) { - PRBool unlock = PR_FALSE; - - /* - ** If evicting, we need to free off the old stuff. - */ - if (PR_FALSE != evictContext) { - unlock = PR_TRUE; - /* - ** We do not free the sorted run. - ** The category code takes care of this. - */ - retval->mSortedRun = NULL; -#if ST_WANT_GRAPHS - /* - ** There is no need to - ** PR_Lock(retval->mImageLock) - ** We are already under write lock for the entire structure. - */ - retval->mFootprintCached = PR_FALSE; - retval->mTimevalCached = PR_FALSE; - retval->mLifespanCached = PR_FALSE; - retval->mWeightCached = PR_FALSE; -#endif - } - - /* - ** If new or recently evicted, we need to fully init. - */ - if (PR_FALSE != newContext || PR_FALSE != evictContext) { - unlock = PR_TRUE; - retval->mSortedRun = - createRunFromGlobal(&inCache->mItems[retval->mIndex]. - mOptions, - &inCache->mItems[retval->mIndex]. - mContext); - } - - /* - ** If changing category, we need to do some sneaky stuff. - */ - if (PR_FALSE != changeCategoryContext) { - STCategoryNode *node = NULL; - - unlock = PR_TRUE; - /* - ** Just a category change. We don't need to harvest. Just find the - ** right node and set the cache.mSortedRun. We need to recompute - ** cost though. But that is cheap. - */ - node = - findCategoryNode(inCache->mItems[retval->mIndex].mOptions. - mCategoryName, &globals); - if (node) { - /* Recalculate cost of run */ - recalculateRunCost(&inCache->mItems[retval->mIndex]. - mOptions, retval, - node->runs[retval->mIndex]); - retval->mSortedRun = node->runs[retval->mIndex]; - } - -#if ST_WANT_GRAPHS - /* - ** There is no need to - ** PR_Lock(retval->mImageLock) - ** We are already under write lock for the entire structure. - */ - retval->mFootprintCached = PR_FALSE; - retval->mTimevalCached = PR_FALSE; - retval->mLifespanCached = PR_FALSE; - retval->mWeightCached = PR_FALSE; -#endif - } - - /* - ** Release the write lock if we took one to make changes. - */ - if (PR_FALSE != unlock) { - PR_RWLock_Unlock(retval->mRWLock); - } - - /* - ** Last thing possible, take a read lock on our return value. - ** This will cause us to block if the context is not fully - ** initialized in another thread holding the write lock. - */ - PR_RWLock_Rlock(retval->mRWLock); - } - } - - return retval; -} - -void -contextRelease(STContext * inContext) -/* -** After a successful call to contextLookup, one should call this API when -** done with the context. -** This effectively removes the usage of the client on a cached item. -*/ -{ - STContextCache *inCache = &globals.mContextCache; - - if (NULL != inContext && NULL != inCache) { - /* - ** Own the context cache while in here. - */ - PR_Lock(inCache->mLock); - /* - ** Give up the read lock on the context. - */ - PR_RWLock_Unlock(inContext->mRWLock); - /* - ** Decrement the reference count on the context. - ** If it was the last reference, notify that a new item is - ** available for eviction. - ** A waiting thread will wake up and eat it. - ** Also set when it was last accessed so the oldest unused item - ** can be targeted for eviction. - */ - inCache->mItems[inContext->mIndex].mReferenceCount--; - if (0 == inCache->mItems[inContext->mIndex].mReferenceCount) { - PR_NotifyCondVar(inCache->mCacheMiss); - inCache->mItems[inContext->mIndex].mLastAccessed = - PR_IntervalNow(); - } - - /* - ** Done with context cache. - */ - PR_Unlock(inCache->mLock); - } -} - - -/* -** handleRequest -** -** Based on what file they are asking for, perform some processing. -** Output the results to aFD. -** -** Returns !0 on error. -*/ -int -handleRequest(tmreader * aTMR, PRFileDesc * aFD, - const char *aFileName, const FormData * aGetData) -{ - int retval = 0; - - if (NULL != aTMR && NULL != aFD && NULL != aFileName - && '\0' != *aFileName) { - STRequest request; - - /* - ** Init the request. - */ - memset(&request, 0, sizeof(request)); - request.mFD = aFD; - request.mGetFileName = aFileName; - request.mGetData = aGetData; - /* - ** Set local options for this request. - */ - initRequestOptions(&request); - /* - ** Get our cached context for this client. - ** Simply based on the options. - */ - request.mContext = contextLookup(&request.mOptions); - if (NULL != request.mContext) { - /* - ** Attempt to find the file of interest. - */ - if (handleLocalFile(&request, aFileName)) { - displayFile(&request, aFileName); - } - else if (0 == strcmp("index.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Index"); - displayRes = displayIndex(&request); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayIndex); - } - - htmlFooter(&request); - } - else if (0 == strcmp("settings.html", aFileName) || - 0 == strcmp("options.html", aFileName)) { - htmlHeader(&request, "SpaceTrace Options"); - displaySettings(&request); - htmlFooter(&request); - } - else if (0 == strcmp("top_allocations.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Top Allocations Report"); - displayRes = - displayTopAllocations(&request, - request.mContext->mSortedRun, - "top-allocations", - "SpaceTrace Top Allocations Report", - 1); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayTopAllocations); - } - - htmlFooter(&request); - } - else if (0 == strcmp("top_callsites.html", aFileName)) { - int displayRes = 0; - tmcallsite **array = NULL; - uint32_t arrayCount = 0; - - /* - ** Display header after we figure out if we are going to focus - ** on a category. - */ - htmlHeader(&request, "SpaceTrace Top Callsites Report"); - if (NULL != request.mContext->mSortedRun - && 0 < request.mContext->mSortedRun->mAllocationCount) { - arrayCount = - callsiteArrayFromRun(&array, 0, - request.mContext->mSortedRun); - if (0 != arrayCount && NULL != array) { - displayRes = - displayTopCallsites(&request, array, arrayCount, - 0, - "top-callsites", - "Top Callsites Report", - 0); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayTopCallsites); - } - - /* - ** Done with the array. - */ - free(array); - array = NULL; - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, handleRequest); - } - - htmlFooter(&request); - } - else if (0 == strcmp("memory_leaks.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Memory Leaks Report"); - displayRes = - displayMemoryLeaks(&request, - request.mContext->mSortedRun); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayMemoryLeaks); - } - - htmlFooter(&request); - } - else if (0 == strncmp("allocation_", aFileName, 11)) { - int scanRes = 0; - uint32_t allocationIndex = 0; - - /* - ** Oh, what a hack.... - ** The index to the allocation structure in the global run - ** is in the filename. Better than the pointer value.... - */ - scanRes = PR_sscanf(aFileName + 11, "%u", &allocationIndex); - if (1 == scanRes - && globals.mRun.mAllocationCount > allocationIndex - && NULL != globals.mRun.mAllocations[allocationIndex]) { - STAllocation *allocation = - globals.mRun.mAllocations[allocationIndex]; - char buffer[128]; - int displayRes = 0; - - PR_snprintf(buffer, sizeof(buffer), - "SpaceTrace Allocation %u Details Report", - allocationIndex); - htmlHeader(&request, buffer); - displayRes = - displayAllocationDetails(&request, allocation); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayAllocationDetails); - } - - htmlFooter(&request); - } - else { - htmlNotFound(&request); - } - } - else if (0 == strncmp("callsite_", aFileName, 9)) { - int scanRes = 0; - uint32_t callsiteSerial = 0; - tmcallsite *resolved = NULL; - - /* - ** Oh, what a hack.... - ** The serial(key) to the callsite structure in the hash table - ** is in the filename. Better than the pointer value.... - */ - scanRes = PR_sscanf(aFileName + 9, "%u", &callsiteSerial); - if (1 == scanRes && 0 != callsiteSerial - && NULL != (resolved = - tmreader_callsite(aTMR, callsiteSerial))) { - char buffer[128]; - int displayRes = 0; - - PR_snprintf(buffer, sizeof(buffer), - "SpaceTrace Callsite %u Details Report", - callsiteSerial); - htmlHeader(&request, buffer); - displayRes = displayCallsiteDetails(&request, resolved); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayAllocationDetails); - } - - htmlFooter(&request); - } - else { - htmlNotFound(&request); - } - } - else if (0 == strcmp("root_callsites.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Root Callsites"); - displayRes = - displayCallsites(&request, aTMR->calltree_root.kids, - ST_FOLLOW_SIBLINGS, 0, - "callsites-root", - "SpaceTrace Root Callsites", - __LINE__); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayCallsites); - } - - htmlFooter(&request); - } -#if ST_WANT_GRAPHS - else if (0 == strcmp("footprint_graph.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Memory Footprint Report"); - PR_fprintf(request.mFD, "
\n"); - PR_fprintf(request.mFD, "\n"); - PR_fprintf(request.mFD, "
\n"); - htmlFooter(&request); - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("times_graph.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Allocation Times Report"); - PR_fprintf(request.mFD, "
\n"); - PR_fprintf(request.mFD, "\n"); - PR_fprintf(request.mFD, "
\n"); - htmlFooter(&request); - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("lifespan_graph.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, - "SpaceTrace Allocation Lifespans Report"); - PR_fprintf(request.mFD, "
\n"); - PR_fprintf(request.mFD, "\n"); - PR_fprintf(request.mFD, "
\n"); - htmlFooter(&request); - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("weight_graph.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "SpaceTrace Allocation Weights Report"); - PR_fprintf(request.mFD, "
\n"); - PR_fprintf(request.mFD, "\n"); - PR_fprintf(request.mFD, "
\n"); - htmlFooter(&request); - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("footprint.png", aFileName)) { - int graphRes = 0; - - graphRes = - graphFootprint(&request, request.mContext->mSortedRun); - if (0 != graphRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphFootprint); - } - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("times.png", aFileName)) { - int graphRes = 0; - - graphRes = - graphTimeval(&request, request.mContext->mSortedRun); - if (0 != graphRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphTimeval); - } - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("lifespan.png", aFileName)) { - int graphRes = 0; - - graphRes = - graphLifespan(&request, request.mContext->mSortedRun); - if (0 != graphRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphLifespan); - } - } -#endif /* ST_WANT_GRAPHS */ -#if ST_WANT_GRAPHS - else if (0 == strcmp("weight.png", aFileName)) { - int graphRes = 0; - - graphRes = - graphWeight(&request, request.mContext->mSortedRun); - if (0 != graphRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, graphWeight); - } - } -#endif /* ST_WANT_GRAPHS */ - else if (0 == strcmp("categories_summary.html", aFileName)) { - int displayRes = 0; - - htmlHeader(&request, "Category Report"); - displayRes = - displayCategoryReport(&request, &globals.mCategoryRoot, - 1); - if (0 != displayRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, displayMemoryLeaks); - } - - htmlFooter(&request); - } - else { - htmlNotFound(&request); - } - - /* - ** Release the context we obtained earlier. - */ - contextRelease(request.mContext); - request.mContext = NULL; - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, contextObtain); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, handleRequest); - } - - /* - ** Compact a little if you can after each request. - */ - heapCompact(); - return retval; -} - -/* -** handleClient -** -** main() of the new client thread. -** Read the fd for the request. -** Output the results. -*/ -void -handleClient(void *inArg) -{ - PRFileDesc *aFD = NULL; - - aFD = (PRFileDesc *) inArg; - if (NULL != aFD) { - PRStatus closeRes = PR_SUCCESS; - char aBuffer[2048]; - int32_t readRes = 0; - - readRes = PR_Read(aFD, aBuffer, sizeof(aBuffer)); - if (0 <= readRes) { - const char *sanityCheck = "GET /"; - - if (0 == strncmp(sanityCheck, aBuffer, 5)) { - char *eourl = NULL; - char *start = &aBuffer[5]; - char *getData = NULL; - int realFun = 0; - const char *crlf = "\015\012"; - char *eoline = NULL; - FormData *fdGet = NULL; - - /* - ** Truncate the line if possible. - ** Only want first one. - */ - eoline = strstr(aBuffer, crlf); - if (NULL != eoline) { - *eoline = '\0'; - } - - /* - ** Find the whitespace. - ** That is either end of line or the " HTTP/1.x" suffix. - ** We do not care. - */ - for (eourl = start; 0 == isspace(*eourl) && '\0' != *eourl; - eourl++) { - /* - ** No body. - */ - } - - /* - ** Cap it off. - ** Convert empty '/' to index.html. - */ - *eourl = '\0'; - if ('\0' == *start) { - strcpy(start, "index.html"); - } - - /* - ** Have we got any GET form data? - */ - getData = strchr(start, '?'); - if (NULL != getData) { - /* - ** Whack it off. - */ - *getData = '\0'; - getData++; - } - - /* - ** Convert get data into a more useful format. - */ - fdGet = FormData_Create(getData); - /* - ** This is totally a hack, but oh well.... - ** - ** Send that the request was OK, regardless. - ** - ** If we have any get data, then it is a set of options - ** we attempt to apply. - ** - ** Other code will tell the user they were wrong or if - ** there was an error. - ** If the filename contains a ".png", then send the image - ** mime type, otherwise, say it is text/html. - */ - PR_fprintf(aFD, "HTTP/1.1 200 OK%s", crlf); - PR_fprintf(aFD, "Server: %s%s", - "$Id: spacetrace.c,v 1.54 2006/11/01 23:02:17 timeless%mozdev.org Exp $", - crlf); - PR_fprintf(aFD, "Content-type: "); - if (NULL != strstr(start, ".png")) { - PR_fprintf(aFD, "image/png"); - } - else if (NULL != strstr(start, ".jpg")) { - PR_fprintf(aFD, "image/jpeg"); - } - else if (NULL != strstr(start, ".txt")) { - PR_fprintf(aFD, "text/plain"); - } - else if (NULL != strstr(start, ".css")) { - PR_fprintf(aFD, "text/css"); - } - else { - PR_fprintf(aFD, "text/html"); - } - PR_fprintf(aFD, crlf); - /* - ** One more to separate headers from content. - */ - PR_fprintf(aFD, crlf); - /* - ** Ready for the real fun. - */ - realFun = handleRequest(globals.mTMR, aFD, start, fdGet); - if (0 != realFun) { - REPORT_ERROR(__LINE__, handleRequest); - } - - /* - ** Free off get data if around. - */ - FormData_Destroy(fdGet); - fdGet = NULL; - } - else { - REPORT_ERROR(__LINE__, handleClient); - } - } - else { - REPORT_ERROR(__LINE__, lineReader); - } - - /* - ** Done with the connection. - */ - closeRes = PR_Close(aFD); - if (PR_SUCCESS != closeRes) { - REPORT_ERROR(__LINE__, PR_Close); - } - } - else { - REPORT_ERROR(__LINE__, handleClient); - } -} - -/* -** serverMode -** -** List on a port as a httpd. -** Output results interactively on demand. -** -** Returns !0 on error. -*/ -int -serverMode(void) -{ - int retval = 0; - PRFileDesc *socket = NULL; - - /* - ** Create a socket. - */ - socket = PR_NewTCPSocket(); - if (NULL != socket) { - PRStatus closeRes = PR_SUCCESS; - PRNetAddr bindAddr; - PRStatus bindRes = PR_SUCCESS; - - /* - ** Bind it to an interface/port. - ** Any interface. - */ - bindAddr.inet.family = PR_AF_INET; - bindAddr.inet.port = - PR_htons((uint16_t) globals.mCommandLineOptions.mHttpdPort); - bindAddr.inet.ip = PR_htonl(PR_INADDR_ANY); - bindRes = PR_Bind(socket, &bindAddr); - if (PR_SUCCESS == bindRes) { - PRStatus listenRes = PR_SUCCESS; - const int backlog = 0x20; - - /* - ** Start listening for clients. - ** Give a decent backlog, some of our processing will take - ** a bit. - */ - listenRes = PR_Listen(socket, backlog); - if (PR_SUCCESS == listenRes) { - PRFileDesc *connection = NULL; - int failureSum = 0; - char message[80]; - - /* - ** Output a little message saying we are receiving. - */ - PR_snprintf(message, sizeof(message), - "server accepting connections at http://localhost:%u/", - globals.mCommandLineOptions.mHttpdPort); - REPORT_INFO(message); - PR_fprintf(PR_STDOUT, "Peak memory used: %s bytes\n", - FormatNumber(globals.mPeakMemoryUsed)); - PR_fprintf(PR_STDOUT, "Allocations : %s total\n", - FormatNumber(globals.mMallocCount + - globals.mCallocCount + - globals.mReallocCount), - FormatNumber(globals.mFreeCount)); - PR_fprintf(PR_STDOUT, "Breakdown : %s malloc\n", - FormatNumber(globals.mMallocCount)); - PR_fprintf(PR_STDOUT, " %s calloc\n", - FormatNumber(globals.mCallocCount)); - PR_fprintf(PR_STDOUT, " %s realloc\n", - FormatNumber(globals.mReallocCount)); - PR_fprintf(PR_STDOUT, " %s free\n", - FormatNumber(globals.mFreeCount)); - PR_fprintf(PR_STDOUT, "Leaks : %s\n", - FormatNumber((globals.mMallocCount + - globals.mCallocCount + - globals.mReallocCount) - - globals.mFreeCount)); - /* - ** Keep accepting until we know otherwise. - ** - ** We do a thread per connection. - ** Up to the thread to close the connection when done. - ** - ** This is known by me to be suboptimal, and I would rather - ** do a thread pool if it ever becomes a resource issue. - ** Any issues would simply point to a need to get - ** more machines or a beefier machine to handle the - ** requests, as well as a need to do thread pooling and - ** avoid thread creation overhead. - ** The threads are not tracked, except possibly by NSPR - ** itself and PR_Cleanup will wait on them all to exit as - ** user threads so our shared data is valid. - */ - while (0 == retval) { - connection = - PR_Accept(socket, NULL, PR_INTERVAL_NO_TIMEOUT); - if (NULL != connection) { - PRThread *clientThread = NULL; - - /* - ** Thread per connection. - */ - clientThread = PR_CreateThread(PR_USER_THREAD, /* PR_Cleanup sync */ - handleClient, (void *) connection, PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, /* IO enabled */ - PR_UNJOINABLE_THREAD, - 0); - if (NULL == clientThread) { - PRStatus closeRes = PR_SUCCESS; - - failureSum += __LINE__; - REPORT_ERROR(__LINE__, PR_Accept); - /* - ** Close the connection as well, no service - */ - closeRes = PR_Close(connection); - if (PR_FAILURE == closeRes) { - REPORT_ERROR(__LINE__, PR_Close); - } - } - } - else { - failureSum += __LINE__; - REPORT_ERROR(__LINE__, PR_Accept); - } - } - - if (0 != failureSum) { - retval = __LINE__; - } - - /* - ** Output a little message saying it is all over. - */ - REPORT_INFO("server no longer accepting connections...."); - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_Listen); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_Bind); - } - - /* - ** Done with socket. - */ - closeRes = PR_Close(socket); - if (PR_SUCCESS != closeRes) { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_Close); - } - socket = NULL; - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_NewTCPSocket); - } - - return retval; -} - -/* -** batchMode -** -** Perform whatever batch requests we were asked to do. -*/ -int -batchMode(void) -{ - int retval = 0; - - if (0 != globals.mCommandLineOptions.mBatchRequestCount) { - uint32_t loop = 0; - int failureSum = 0; - int handleRes = 0; - char aFileName[1024]; - uint32_t sprintfRes = 0; - - /* - ** Go through and process the various files requested. - ** We do not stop on failure, as it is too costly to rerun the - ** batch job. - */ - for (loop = 0; - loop < globals.mCommandLineOptions.mBatchRequestCount; loop++) { - sprintfRes = - PR_snprintf(aFileName, sizeof(aFileName), "%s%c%s", - globals.mCommandLineOptions.mOutputDir, - PR_GetDirectorySeparator(), - globals.mCommandLineOptions.mBatchRequest[loop]); - if ((uint32_t) - 1 != sprintfRes) { - PRFileDesc *outFile = NULL; - - outFile = PR_Open(aFileName, ST_FLAGS, ST_PERMS); - if (NULL != outFile) { - PRStatus closeRes = PR_SUCCESS; - - handleRes = - handleRequest(globals.mTMR, outFile, - globals.mCommandLineOptions. - mBatchRequest[loop], NULL); - if (0 != handleRes) { - failureSum += __LINE__; - REPORT_ERROR(__LINE__, handleRequest); - } - - closeRes = PR_Close(outFile); - if (PR_SUCCESS != closeRes) { - failureSum += __LINE__; - REPORT_ERROR(__LINE__, PR_Close); - } - } - else { - failureSum += __LINE__; - REPORT_ERROR(__LINE__, PR_Open); - } - } - else { - failureSum += __LINE__; - REPORT_ERROR(__LINE__, PR_snprintf); - } - } - - if (0 != failureSum) { - retval = __LINE__; - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, outputReports); - } - - return retval; -} - -/* -** doRun -** -** Perform the actual processing this program requires. -** Returns !0 on failure. -*/ -int -doRun(void) -{ - int retval = 0; - - /* - ** Create the new trace-malloc reader. - */ - globals.mTMR = tmreader_new(globals.mProgramName, NULL); - if (NULL != globals.mTMR) { - int tmResult = 0; - int outputResult = 0; - -#if defined(DEBUG_dp) - PRIntervalTime start = PR_IntervalNow(); - - fprintf(stderr, "DEBUG: reading tracemalloc data...\n"); -#endif - tmResult = - tmreader_eventloop(globals.mTMR, - globals.mCommandLineOptions.mFileName, - tmEventHandler); - printf("\rReading... Done.\n"); -#if defined(DEBUG_dp) - fprintf(stderr, - "DEBUG: reading tracemalloc data ends: %dms [%d allocations]\n", - PR_IntervalToMilliseconds(PR_IntervalNow() - start), - globals.mRun.mAllocationCount); -#endif - if (0 == tmResult) { - REPORT_ERROR(__LINE__, tmreader_eventloop); - retval = __LINE__; - } - - if (0 == retval) { - /* - ** Decide if we're going into batch mode or server mode. - */ - if (0 != globals.mCommandLineOptions.mBatchRequestCount) { - /* - ** Output in one big step while everything still exists. - */ - outputResult = batchMode(); - if (0 != outputResult) { - REPORT_ERROR(__LINE__, batchMode); - retval = __LINE__; - } - } - else { - int serverRes = 0; - - /* - ** httpd time. - */ - serverRes = serverMode(); - if (0 != serverRes) { - REPORT_ERROR(__LINE__, serverMode); - retval = __LINE__; - } - } - - /* - ** Clear our categorization tree - */ - freeCategories(&globals); - } - } - else { - REPORT_ERROR(__LINE__, tmreader_new); - retval = __LINE__; - } - - return retval; -} - -int -initCaches(void) -/* -** Initialize the global caches. -** More involved since we have to allocated/create some objects. -** -** returns Zero if all is well. -** Non-zero on error. -*/ -{ - int retval = 0; - STContextCache *inCache = &globals.mContextCache; - - if (NULL != inCache && 0 != globals.mCommandLineOptions.mContexts) { - inCache->mLock = PR_NewLock(); - if (NULL != inCache->mLock) { - inCache->mCacheMiss = PR_NewCondVar(inCache->mLock); - if (NULL != inCache->mCacheMiss) { - inCache->mItems = - (STContextCacheItem *) calloc(globals.mCommandLineOptions. - mContexts, - sizeof(STContextCacheItem)); - if (NULL != inCache->mItems) { - uint32_t loop = 0; - char buffer[64]; - - inCache->mItemCount = - globals.mCommandLineOptions.mContexts; - /* - ** Init each item as needed. - */ - for (loop = 0; loop < inCache->mItemCount; loop++) { - inCache->mItems[loop].mContext.mIndex = loop; - PR_snprintf(buffer, sizeof(buffer), - "Context Item %d RW Lock", loop); - inCache->mItems[loop].mContext.mRWLock = - PR_NewRWLock(PR_RWLOCK_RANK_NONE, buffer); - if (NULL == inCache->mItems[loop].mContext.mRWLock) { - break; - } -#if ST_WANT_GRAPHS - inCache->mItems[loop].mContext.mImageLock = - PR_NewLock(); - if (NULL == inCache->mItems[loop].mContext.mImageLock) { - break; - } -#endif - } - - if (loop != inCache->mItemCount) { - retval = __LINE__; - REPORT_ERROR(__LINE__, initCaches); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, calloc); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_NewCondVar); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, PR_NewLock); - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, initCaches); - } - - return retval; -} - -int -destroyCaches(void) -/* -** Clean up any global caches we have laying around. -** -** returns Zero if all is well. -** Non-zero on error. -*/ -{ - int retval = 0; - STContextCache *inCache = &globals.mContextCache; - - if (NULL != inCache) { - uint32_t loop = 0; - - /* - ** Uninit item data one by one. - */ - for (loop = 0; loop < inCache->mItemCount; loop++) { - if (NULL != inCache->mItems[loop].mContext.mRWLock) { - PR_DestroyRWLock(inCache->mItems[loop].mContext.mRWLock); - inCache->mItems[loop].mContext.mRWLock = NULL; - } -#if ST_WANT_GRAPHS - if (NULL != inCache->mItems[loop].mContext.mImageLock) { - PR_DestroyLock(inCache->mItems[loop].mContext.mImageLock); - inCache->mItems[loop].mContext.mImageLock = NULL; - } -#endif - } - - inCache->mItemCount = 0; - if (NULL != inCache->mItems) { - free(inCache->mItems); - inCache->mItems = NULL; - } - - if (NULL != inCache->mCacheMiss) { - PR_DestroyCondVar(inCache->mCacheMiss); - inCache->mCacheMiss = NULL; - } - - if (NULL != inCache->mLock) { - PR_DestroyLock(inCache->mLock); - inCache->mLock = NULL; - } - } - else { - retval = __LINE__; - REPORT_ERROR(__LINE__, destroyCaches); - } - - return retval; -} - -/* -** main -** -** Process entry and exit. -*/ -int -main(int aArgCount, char **aArgArray) -{ - int retval = 0; - int optionsResult = 0; - PRStatus prResult = PR_SUCCESS; - int showedHelp = 0; - int looper = 0; - int cacheResult = 0; - - /* - ** NSPR init. - */ - PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); - /* - ** Initialize globals - */ - memset(&globals, 0, sizeof(globals)); - /* - ** Set the program name. - */ - globals.mProgramName = aArgArray[0]; - /* - ** Set the minimum timeval really high so other code - ** that checks the timeval will get it right. - */ - globals.mMinTimeval = ST_TIMEVAL_MAX; - /* - ** Handle initializing options. - */ - optionsResult = initOptions(aArgCount, aArgArray); - if (0 != optionsResult) { - REPORT_ERROR(optionsResult, initOptions); - retval = __LINE__; - } - - /* - ** Initialize our caches. - */ - cacheResult = initCaches(); - if (0 != cacheResult) { - retval = __LINE__; - REPORT_ERROR(__LINE__, initCaches); - } - - /* - ** Small alloc code init. - */ - globals.mCategoryRoot.runs = - (STRun **) calloc(globals.mCommandLineOptions.mContexts, - sizeof(STRun *)); - if (NULL == globals.mCategoryRoot.runs) { - retval = __LINE__; - REPORT_ERROR(__LINE__, calloc); - } - - /* - ** Show help on usage if need be. - */ - showedHelp = showHelp(); - /* - ** Only perform the run if everything is checking out. - */ - if (0 == showedHelp && 0 == retval) { - int runResult = 0; - - runResult = doRun(); - if (0 != runResult) { - REPORT_ERROR(runResult, doRun); - retval = __LINE__; - } - } - - if (0 != retval) { - REPORT_ERROR(retval, main); - } - - /* - ** Have NSPR join all client threads we started. - */ - prResult = PR_Cleanup(); - if (PR_SUCCESS != prResult) { - REPORT_ERROR(retval, PR_Cleanup); - retval = __LINE__; - } - /* - ** All threads are joined/done by this line. - */ - - /* - ** Options allocated a little. - */ -#define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) \ - if(NULL != globals.mCommandLineOptions.m##option_name) \ - { \ - free((void*)globals.mCommandLineOptions.m##option_name); \ - globals.mCommandLineOptions.m##option_name = NULL; \ - globals.mCommandLineOptions.m##option_name##Count = 0; \ - } -#include "stoptions.h" - - /* - ** globals has a small modification to clear up. - */ - if (NULL != globals.mCategoryRoot.runs) { - free(globals.mCategoryRoot.runs); - globals.mCategoryRoot.runs = NULL; - } - - /* - ** Blow away our caches. - */ - cacheResult = destroyCaches(); - if (0 != cacheResult) { - retval = __LINE__; - REPORT_ERROR(__LINE__, initCaches); - } - - /* - ** We are safe to kill our tmreader data. - */ - if (NULL != globals.mTMR) { - tmreader_destroy(globals.mTMR); - globals.mTMR = NULL; - } - - return retval; -} diff --git a/tools/trace-malloc/spacetrace.css b/tools/trace-malloc/spacetrace.css deleted file mode 100644 index 43065cc21f08..000000000000 --- a/tools/trace-malloc/spacetrace.css +++ /dev/null @@ -1,170 +0,0 @@ -/* 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/. */ - -body { - margin: 0px; - padding: 0px; - font: Arial, sans-serif; -} - -/* header stuff */ -.spacetrace-header { - color: white; - background: green; -/* min-height: 2em; */ -} - -.spacetrace-title { - font-size: x-large; - font-weight: bold; - padding: 0.5em; -} - -.navigate { -/* background: lightgrey; */ - color: black; - position: absolute; - right: 0px; - margin: 0px; - padding: 2px; -} - -.header-item { - border: 1px outset; - color: ButtonText; - background: ButtonFace; - margin: 0px; - padding: 2px; -} - -.header-item > a { - font-weight: bold; - text-decoration: none; -} - - -.header-item { - font-weight: bold; -} - -.category-title { - font-weight: bold; -} - -/* footer stuff */ -.footer-separator { - border: 1px inset; - display: none; -} - -.footer { - text-align: right; - display: none; -} - -.footer-text { - font-style: italic; -} - -.option-box { - border: solid black; - background: grey; - padding-left: .5em; - padding-right: .5em; - margin: .5em; -} - -.option-name { - font-weight: bold; - margin: 1em; -} - -.option-box input[type=text] -{ - border: inset thin; - padding: 2px; -} - -.option-help { - white-space: pre; - right: 0px; - background: white; - padding: 0.5em; - border: thin inset; -} - -.callsite-header { - padding: 10px; -} -/* data tables */ -#callsite-details { - position: absolute; - right: 1px; - top: 40px; - width: 20%; -} - -#callsites { - width: 75%; - height: 40%; - overflow: scroll; -} - -#caller-stack { - height: 45%; - width: 75%; - overflow: scroll; - padding-top: 5px; -} - -#allocations { - position: absolute; - right: 1px; - bottom: 1px; - height: 40%; - width: 20%; - overflow: scroll; -} - -/* headers at the top of specific call site pages */ - -table.summary { - border: 1px solid black; -} - -/* lists of callsites/etc */ -table.data td { - border-top: 1px solid; - padding: 5px; -} - -table.data { - clear: right; - border-collapse: collapse; -} - -tr.row-header { - background: #009090; - width: 100%; -} - -table.data th { - padding: 5px; - margin: 0px; - text-align: right; -} - -th.callsite { - text-align: left !important; -} - -/* links to source */ -.source-extra { - display: none; -} - -a.source, a.callsite { - text-decoration: none; -} - diff --git a/tools/trace-malloc/spacetrace.h b/tools/trace-malloc/spacetrace.h deleted file mode 100644 index 998be1304678..000000000000 --- a/tools/trace-malloc/spacetrace.h +++ /dev/null @@ -1,694 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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 spacetrace_h__ -#define spacetrace_h__ - -/* -** spacetrace.h -** -** SpaceTrace is meant to take the output of trace-malloc and present -** a picture of allocations over the run of the application. -*/ - -/* -** Required includes. -*/ -#include -#include "nspr.h" -#include "prlock.h" -#include "prrwlock.h" -#include "nsTraceMalloc.h" -#include "tmreader.h" -#include "formdata.h" - -/* -** Turn on to attempt adding support for graphs on your platform. -*/ -#if defined(HAVE_BOUTELL_GD) -#define ST_WANT_GRAPHS 1 -#endif /* HAVE_BOUTELL_GD */ -#if !defined(ST_WANT_GRAPHS) -#define ST_WANT_GRAPHS 0 -#endif - -/* -** REPORT_ERROR -** REPORT_INFO -** -** Just report errors and stuff in a consistent manner. -*/ -#define REPORT_ERROR(code, function) \ - PR_fprintf(PR_STDERR, "error(%d):\t%s\n", code, #function) -#define REPORT_ERROR_MSG(code, msg) \ - PR_fprintf(PR_STDERR, "error(%d):\t%s\n", code, msg) -#define REPORT_INFO(msg) \ - PR_fprintf(PR_STDOUT, "%s: %s\n", globals.mProgramName, (msg)) - -#if defined(DEBUG_blythe) && 1 -#define REPORT_blythe(code, msg) \ - PR_fprintf(PR_STDOUT, "gab(%d):\t%s\n", code, msg) -#else -#define REPORT_blythe(code, msg) -#endif /* DEBUG_blythe */ - -/* -** CALLSITE_RUN -** -** How to get a callsite run. -** Allows for further indirection if needed later. -*/ -#define CALLSITE_RUN(callsite) \ - ((STRun*)((callsite)->data)) - -/* -** ST_PERMS -** ST_FLAGS -** -** File permissions we desire. -** 0644 -*/ -#define ST_PERMS (PR_IRUSR | PR_IWUSR | PR_IRGRP | PR_IROTH) -#define ST_FLAGS (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE) - -/* -** Sorting order -*/ -#define ST_WEIGHT 0 /* size * timeval */ -#define ST_SIZE 1 -#define ST_TIMEVAL 2 -#define ST_COUNT 3 -#define ST_HEAPCOST 4 - -/* -** Callsite loop direction flags. -*/ -#define ST_FOLLOW_SIBLINGS 0 -#define ST_FOLLOW_PARENTS 1 - -/* -** Graph data. -*/ -#define STGD_WIDTH 640 -#define STGD_HEIGHT 480 -#define STGD_MARGIN 75 -#define STGD_SPACE_X (STGD_WIDTH - (2 * STGD_MARGIN)) -#define STGD_SPACE_Y (STGD_HEIGHT - (2 * STGD_MARGIN)) - -/* -** Minimum lifetime default, in seconds. -*/ -#define ST_DEFAULT_LIFETIME_MIN 10 - -/* -** Allocations fall to this boundry size by default. -** Overhead is taken after alignment. -** -** The msvcrt malloc has an alignment of 16 with an overhead of 8. -** The win32 HeapAlloc has an alignment of 8 with an overhead of 8. -*/ -#define ST_DEFAULT_ALIGNMENT_SIZE 16 -#define ST_DEFAULT_OVERHEAD_SIZE 8 - -/* -** Numer of substring match specifications to allow. -*/ -#define ST_SUBSTRING_MATCH_MAX 5 - -/* -** Max Number of patterns per rule -*/ -#define ST_MAX_PATTERNS_PER_RULE 16 - -/* -** Rule pointers and child pointers are allocated in steps of ST_ALLOC_STEP -*/ -#define ST_ALLOC_STEP 16 - -/* -** Name of the root category. Appears in UI. -*/ -#define ST_ROOT_CATEGORY_NAME "All" - -/* -** Size of our option string buffers. -*/ -#define ST_OPTION_STRING_MAX 256 - -/* -** Set the desired resolution of the timevals. -** The resolution is just mimicking what is recorded in the trace-malloc -** output, and that is currently milliseconds. -*/ -#define ST_TIMEVAL_RESOLUTION 1000 -#define ST_TIMEVAL_FORMAT "%.3f" -#define ST_TIMEVAL_PRINTABLE(timeval) ((double)(timeval) / (double)ST_TIMEVAL_RESOLUTION) -#define ST_TIMEVAL_PRINTABLE64(timeval) ((double)((int64_t)(timeval)) / (double)ST_TIMEVAL_RESOLUTION) -#define ST_TIMEVAL_MAX ((uint32_t)-1 - ((uint32_t)-1 % ST_TIMEVAL_RESOLUTION)) - -#define ST_MICROVAL_RESOLUTION 1000000 -#define ST_MICROVAL_FORMAT "%.6f" -#define ST_MICROVAL_PRINTABLE(timeval) ((double)(timeval) / (double)ST_MICROVAL_RESOLUTION) -#define ST_MICROVAL_PRINTABLE64(timeval) ((double)((int64_t)(timeval)) / (double)ST_MICROVAL_RESOLUTION) -#define ST_MICROVAL_MAX ((uint32_t)-1 - ((uint32_t)-1 % ST_MICROVAL_RESOLUTION)) - -/* -** Forward Declaration -*/ -typedef struct __struct_STCategoryNode STCategoryNode; -typedef struct __struct_STCategoryRule STCategoryRule; - - -/* -** STAllocEvent -** -** An event that happens to an allocation (malloc, free, et. al.) -*/ -typedef struct __struct_STAllocEvent -{ - /* - ** The type of allocation event. - ** This maps directly to the trace malloc events (i.e. TM_EVENT_MALLOC) - */ - char mEventType; - - /* - ** Each event, foremost, has a chronologically increasing ID in - ** relation to other allocation events. This is a time stamp - ** of sorts. - */ - uint32_t mTimeval; - - /* - ** Every event has a heap ID (pointer). - ** In the event of a realloc, this is the new heap ID. - ** In the event of a free, this is the previous heap ID value. - */ - uint32_t mHeapID; - - /* - ** Every event, along with the heap ID, tells of the size. - ** In the event of a realloc, this is the new size. - ** In th event of a free, this is the previous size. - */ - uint32_t mHeapSize; - - /* - ** Every event has a callsite/stack backtrace. - ** In the event of a realloc, this is the new callsite. - ** In the event of a free, this is the previous call site. - */ - tmcallsite* mCallsite; -} STAllocEvent; - -/* -** STAllocation -** -** An allocation is a temporal entity in the heap. -** It possibly lives under different heap IDs (pointers) and different -** sizes during its given time. -** An allocation is defined by the events during its lifetime. -** An allocation's lifetime is defined by the range of event IDs it holds. -*/ -typedef struct __struct_STAllocation -{ - /* - ** The array of events. - */ - uint32_t mEventCount; - STAllocEvent* mEvents; - - /* - ** The lifetime/lifespan of the allocation. - */ - uint32_t mMinTimeval; - uint32_t mMaxTimeval; - - /* - ** Index of this allocation in the global run. - */ - uint32_t mRunIndex; - - /* - ** The runtime cost of heap events in this allocation. - ** The cost is defined as the number of time units recorded as being - ** spent in heap code (time of malloc, free, et al.). - ** We do not track individual event cost in order to save space. - */ - uint32_t mHeapRuntimeCost; -} STAllocation; - -/* -** STCallsiteStats -** -** Stats regarding a run, kept mainly for callsite runs. -*/ -typedef struct __struct_STCallsiteStats -{ - /* - ** Sum timeval of the allocations. - ** Callsite runs total all allocations below the callsite. - */ - uint64_t mTimeval64; - - /* - ** Sum weight of the allocations. - ** Callsite runs total all allocations below the callsite. - */ - uint64_t mWeight64; - - /* - ** Sum size of the allocations. - ** Callsite runs total all allocations below the callsite. - */ - uint32_t mSize; - - /* - ** A stamp, indicated the relevance of the run. - ** If the stamp does not match the origin value, the - ** data contained here-in is considered invalid. - */ - uint32_t mStamp; - - /* - ** A sum total of allocations (note, not sizes) below the callsite. - ** This is NOT the same as STRun::mAllocationCount which - ** tracks the STRun::mAllocations array size. - */ - uint32_t mCompositeCount; - - /* - ** A sum total runtime cost of heap operations below the calliste. - ** The cost is defined as the number of time units recorded as being - ** spent in heap code (time of malloc, free, et al.). - */ - uint32_t mHeapRuntimeCost; -} STCallsiteStats; - -/* -** STRun -** -** A run is a closed set of allocations. -** Given a run, we can deduce information about the contained allocations. -** We can also determine if an allocation lives beyond a run (leak). -** -** A run might be used to represent allocations for an entire application. -** A run might also be used to represent allocations from a single callstack. -*/ -typedef struct __struct_STRun -{ - /* - ** The array of allocations. - */ - uint32_t mAllocationCount; - STAllocation** mAllocations; - - /* - ** Callsites like to keep some information. - ** As callsites are possibly shared between all contexts, each - ** different context needs to keep different stats. - */ - STCallsiteStats *mStats; - -} STRun; - -/* -** Categorize allocations -** -** The objective is to have a tree of categories with each leaf node of the tree -** matching a set of callsites that belong to the category. Each category can -** signify a functional area like say css and hence the user can browse this -** tree looking for how much of each of these are live at an instant. -*/ - -/* -** STCategoryNode -*/ - -struct __struct_STCategoryNode -{ - /* - ** Category name - */ - const char *categoryName; - - /* - ** Pointer to parent node. NULL for Root. - */ - STCategoryNode *parent; - - /* - ** For non-leaf nodes, an array of children node pointers. - ** NULL if leaf node. - */ - STCategoryNode** children; - uint32_t nchildren; - - /* - ** The Run(s). Valid for both leaf and parent nodes. - ** One run per --Context to handle multiple data sets. - ** The relevant index for the particular request will be - ** mIndex stored by the mContext of the request. - */ - STRun **runs; -}; - - -struct __struct_STCategoryRule -{ - /* - ** The pattern for the rule. Patterns are an array of strings. - ** A callsite needs to pass substring match for all the strings. - */ - char* pats[ST_MAX_PATTERNS_PER_RULE]; - uint32_t patlen[ST_MAX_PATTERNS_PER_RULE]; - uint32_t npats; - - /* - ** Category name that this rule belongs to - */ - const char* categoryName; - - /* - ** The node this should be categorized into - */ - STCategoryNode* node; -}; - - -/* -** CategoryName to Node mapping table -*/ -typedef struct __struct_STCategoryMapEntry { - STCategoryNode* node; - const char * categoryName; -} STCategoryMapEntry; - -/* -** Option genres. -** -** This helps to determine what functionality each option effects. -** In specific, this will help use determine when and when not to -** totally recaclulate the sorted run and categories. -** Be very aware that adding things to a particular genre, or adding a genre, -** may completely screw up the caching algorithms of SpaceTrace. -** See contextLookup() or ask someone that knows if you are in doubt. -*/ -typedef enum __enum_STOptionGenre -{ - CategoryGenre = 0, - DataSortGenre, - DataSetGenre, - DataSizeGenre, - UIGenre, - ServerGenre, - BatchModeGenre, - - /* - ** Last one please. - */ - MaxGenres -} -STOptionGenre; - -/* -** STOptions -** -** Structure containing the varios options for the code. -** The definition of these options exists in a different file. -** We access that definition via macros to inline our structure definition. -*/ -#define ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) PRBool m##option_name; -#define ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) char m##option_name[ST_OPTION_STRING_MAX]; -#define ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) char m##option_name[array_size][ST_OPTION_STRING_MAX]; -#define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) const char** m##option_name; uint32_t m##option_name##Count; -#define ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) uint32_t m##option_name; -#define ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) uint64_t m##option_name##64; - -typedef struct __struct_STOptions -{ -#include "stoptions.h" -} -STOptions; - -typedef struct __struct_STContext -/* -** A per request, thread safe, manner of accessing the contained members. -** A reader/writer lock ensures that the data is properly initialized before -** readers of the data begin their work. -** -** mRWLock reader/writer lock. -** writer lock is held to ensure initialization, though -** others can be attempting to acquire read locks -** at that time. -** writer lock is also used in destruction to make sure -** there are no more readers of data contained herein. -** reader lock is to allow multiple clients to read the -** data at the same time; implies is they must not -** write anything. -** mIndex Consider this much like thread private data or thread -** local storage in a few places. -** The index is specifically reserved for this context's -** usage in other data structure array's provided -** for the particular thread/client/context. -** This should not be modified after initialization. -** mSortedRun A pre sorted run taken from the global run, with our -** options applied. -** mImageLock An overly simplistic locking mechanism to protect the -** shared image cache. -** The proper implementation would have a reader/writer -** lock per cached image data. -** However, this will prove to be simpler for the time -** being. -** mFootprintCached Whether or not YData contains something useful. -** mTimevalCached Whether or not YData contains something useful. -** mLifespanCached Whether or not YData contains something useful. -** mWeightCached Whether or not YData contains something useful. -** mFootprintYData Precomputed cached graph data. -** mTimevalYData Precomputed cached graph data. -** mLifespanYData Precomputed cached graph data. -** mWeightYData Precomputed cached graph data. -*/ -{ - PRRWLock* mRWLock; - uint32_t mIndex; - STRun* mSortedRun; -#if ST_WANT_GRAPHS - PRLock* mImageLock; - PRBool mFootprintCached; - PRBool mTimevalCached; - PRBool mLifespanCached; - PRBool mWeightCached; - uint32_t mFootprintYData[STGD_SPACE_X]; - uint32_t mTimevalYData[STGD_SPACE_X]; - uint32_t mLifespanYData[STGD_SPACE_X]; - uint64_t mWeightYData64[STGD_SPACE_X]; -#endif -} -STContext; - - -typedef struct __struct_STContextCacheItem -/* -** This basically pools the common items that the context cache will -** want to track on a per context basis. -** -** mOptions What options this item represents. -** mContext State/data this cache item is wrapping. -** mReferenceCount A count of clients currently using this item. -** Should this item be 0, then the cache might -** decide to evict this context. -** Should this item not be 0, once it reaches -** zero a condition variable in the context cache -** will be signaled to notify the availability. -** mLastAccessed A timestamp of when this item was last accessed/released. -** Ignore this unless the reference count is 0, -** This is used to evict the oldest unused item from -** the context cache. -** mInUse Mainly PR_FALSE only at the beginning of the process, -** but this indicates that the item has not yet been -** used at all, and thus shouldn't be evaluated for -** a cache hit. -*/ -{ - STOptions mOptions; - STContext mContext; - int32_t mReferenceCount; - PRIntervalTime mLastAccessed; - PRBool mInUse; -} -STContextCacheItem; - - -typedef struct __struct_STContextCache -/* -** A thread safe, possibly blocking, cache of context items. -** -** mLock Must hold the lock to read/access/write to this struct, as -** well as any items it holds. -** mCacheMiss All items are busy and there were no cache matches. -** This condition variable is used to wait until an item becomes -** "available" to be evicted from the cache. -** mItems Array of items. -** mItemCount Number of items in array. -** This is generally the same as the global option's command line -** mContexts.... -*/ -{ - PRLock* mLock; - PRCondVar* mCacheMiss; - STContextCacheItem* mItems; - uint32_t mItemCount; -} -STContextCache; - - -/* -** STRequest -** -** Things specific to a request. -*/ -typedef struct __struct_STRequest -{ - /* - ** Sink/where to output. - */ - PRFileDesc* mFD; - - /* - ** The filename requested. - */ - const char* mGetFileName; - - /* - ** The GET form data, if any. - */ - const FormData* mGetData; - - /* - ** Options specific to this request. - */ - STOptions mOptions; - - /* - ** The context/data/state of the request. - */ - STContext* mContext; -} STRequest; - - -/* -** STGlobals -** -** Various globals we keep around. -*/ -typedef struct __struct_STGlobals -{ - /* - ** The string which identifies this program. - */ - const char* mProgramName; - - /* - ** Options derived from the command line. - ** These are used as defaults, and should remain static during - ** the run of the application. - */ - STOptions mCommandLineOptions; - - /* - ** Context cache. - ** As clients come in, based on their options, a different context - ** will be used to service them. - */ - STContextCache mContextCache; - - /* - ** Various counters for different types of events. - */ - uint32_t mMallocCount; - uint32_t mCallocCount; - uint32_t mReallocCount; - uint32_t mFreeCount; - - /* - ** Total events, operation counter. - */ - uint32_t mOperationCount; - - /* - ** The "run" of the input. - */ - STRun mRun; - - /* - ** Operation minimum/maximum timevals. - ** So that we can determine the overall timeval of the run. - ** NOTE: These are NOT the options to control the data set. - */ - uint32_t mMinTimeval; - uint32_t mMaxTimeval; - - /* - ** Calculates peak allocation overall for all allocations. - */ - uint32_t mPeakMemoryUsed; - uint32_t mMemoryUsed; - - /* - ** A list of rules for categorization read in from the mCategoryFile - */ - STCategoryRule** mCategoryRules; - uint32_t mNRules; - - /* - ** CategoryName to Node mapping table - */ - STCategoryMapEntry** mCategoryMap; - uint32_t mNCategoryMap; - - /* - ** Categorized allocations. For now we support only one tree. - */ - STCategoryNode mCategoryRoot; - - /* - ** tmreader hash tables. - ** Moved into globals since we need to destroy these only after all - ** client threads are finishes (after PR_Cleanup). - */ - tmreader* mTMR; -} STGlobals; - - -/* -** Function prototypes -*/ -extern STRun* createRun(STContext* inContext, uint32_t aStamp); -extern void freeRun(STRun* aRun); -extern int initCategories(STGlobals* g); -extern int categorizeRun(STOptions* inOptions, STContext* inContext, const STRun* aRun, STGlobals* g); -extern STCategoryNode* findCategoryNode(const char *catName, STGlobals *g); -extern int freeCategories(STGlobals* g); -extern int displayCategoryReport(STRequest* inRequest, STCategoryNode *root, int depth); - -extern int recalculateAllocationCost(STOptions* inOptions, STContext* inContext, STRun* aRun, STAllocation* aAllocation, PRBool updateParent); -extern void htmlHeader(STRequest* inRequest, const char* aTitle); -extern void htmlFooter(STRequest* inRequest); -extern void htmlAnchor(STRequest* inRequest, - const char* aHref, - const char* aText, - const char* aTarget, - const char* aClass, - STOptions* inOptions); -extern char *FormatNumber(int32_t num); - -/* -** shared globals -*/ -extern STGlobals globals; - -#endif /* spacetrace_h__ */ diff --git a/tools/trace-malloc/stoptions.h b/tools/trace-malloc/stoptions.h deleted file mode 100644 index f750ecba79b6..000000000000 --- a/tools/trace-malloc/stoptions.h +++ /dev/null @@ -1,302 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -/* -** stoptions.h -** -** Abstract the spacetrace options into a reusable format, such that -** many different pieces of the code can utilize the common list. -*/ - -/* -** There are three types of options. -** The destinction is quite important. -** -** CMD options are accessible from only the comamnd line. -** Such options should be considered global/static for the entire -** run of the application. -** Once set, no one can change these options during the run. -** -** WEB options are accessible from the web server options page. -** Such options can and will be changed on a per user basis during -** the run of the application. -** You should NEVER make an option a WEB only option, as this will -** break batch mode processing, and will likely not correctly -** define the options structure itself. -** These options will control the data caching used in the application -** to match a client to a cache of data. -** -** ALL options are both CMD and WEB options, with the properties of WEB -** options (the user will change these on a per client basis). -** Most likely this is the type of option you will desire to create. -*/ - -/* -** All types of options have some combination of the following elements: -** -** option_name The name of the option. -** option_genre Area the option effects; STOptionGenre. -** default_value The default value for the option. -** array_size Used to size a string array. -** multiplier Some numbers prefer conversion. -** option_help Help text to explain the option. -** -** NOTE! that the multiplier should be applied to the default value if you -** are going to assign the default_value into anything. -** -** Be very aware that adding things to a particular genre, or adding a genre, -** may completely screw up the caching algorithms of SpaceTrace. -** See contextLookup() or ask someone that knows if you are in doubt. -** -** The actual definition of the WEB and CMD macros however is left to the -** end user. -** We cover those that you do not define herein. -*/ -#if !defined(ST_CMD_OPTION_BOOL) -#define ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) -#endif -#if !defined(ST_WEB_OPTION_BOOL) -#define ST_WEB_OPTION_BOOL(option_name, option_genre, option_help) -#endif -#if !defined(ST_CMD_OPTION_STRING) -#define ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) -#endif -#if !defined(ST_WEB_OPTION_STRING) -#define ST_WEB_OPTION_STRING(option_name, option_genre, default_value, option_help) -#endif -#if !defined(ST_CMD_OPTION_STRING_ARRAY) -#define ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) -#endif -#if !defined(ST_WEB_OPTION_STRING_ARRAY) -#define ST_WEB_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) -#endif -#if !defined(ST_CMD_OPTION_STRING_PTR_ARRAY) -#define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) -#endif -#if !defined(ST_WEB_OPTION_STRING_PTR_ARRAY) -#define ST_WEB_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) -#endif -#if !defined(ST_CMD_OPTION_UINT32) -#define ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) -#endif -#if !defined(ST_WEB_OPTION_UINT32) -#define ST_WEB_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) -#endif -#if !defined(ST_CMD_OPTION_UINT64) -#define ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) -#endif -#if !defined(ST_WEB_OPTION_UINT64) -#define ST_WEB_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) -#endif - -/* -** ALL macros expand to both CMD and WEB macros. -** This basically means such options are accessible from both the command -** line and from the web options. -*/ -#define ST_ALL_OPTION_BOOL(option_name, option_genre, option_help) \ - ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) \ - ST_WEB_OPTION_BOOL(option_name, option_genre, option_help) -#define ST_ALL_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) \ - ST_WEB_OPTION_STRING(option_name, option_genre, default_value, option_help) -#define ST_ALL_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) \ - ST_WEB_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) -#define ST_ALL_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) \ - ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) \ - ST_WEB_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) -#define ST_ALL_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) \ - ST_WEB_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) -#define ST_ALL_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) \ - ST_WEB_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) - - - -/**************************************************************************** -** BEGIN, THE OPTIONS -** -** Order is somewhat relevant in that it will control 3 different things: -** 1) The order the members will be in the options structure. -** 2) The order the options are presented on the command line. -** 3) The order the options are presented on the web options page. -*/ - -ST_ALL_OPTION_STRING(CategoryName, - CategoryGenre, - ST_ROOT_CATEGORY_NAME, - "Specify a category for reports to focus upon.\n" - "See http://lxr.mozilla.org/mozilla/source/tools/trace-malloc/rules.txt\n") - -ST_ALL_OPTION_UINT32(OrderBy, - DataSortGenre, - ST_SIZE, /* for dp :-D */ - 1, - "Determine the sort order.\n" - "0 by weight (size * lifespan).\n" - "1 by size.\n" - "2 by lifespan.\n" - "3 by allocation count.\n" - "4 by performance cost.\n") - -ST_ALL_OPTION_STRING_ARRAY(RestrictText, - DataSetGenre, - ST_SUBSTRING_MATCH_MAX, - "Exclude allocations which do not have this text in their backtrace.\n" - "Multiple restrictions are treated as a logical AND operation.\n") - -ST_ALL_OPTION_UINT32(SizeMin, - DataSetGenre, - 0, - 1, - "Exclude allocations that are below this byte size.\n") - -ST_ALL_OPTION_UINT32(SizeMax, - DataSetGenre, - 0xFFFFFFFF, - 1, - "Exclude allocations that are above this byte size.\n") - -ST_ALL_OPTION_UINT32(LifetimeMin, - DataSetGenre, - ST_DEFAULT_LIFETIME_MIN, - ST_TIMEVAL_RESOLUTION, - "Allocations must live this number of seconds or be ignored.\n") - -ST_ALL_OPTION_UINT32(LifetimeMax, - DataSetGenre, - ST_TIMEVAL_MAX / ST_TIMEVAL_RESOLUTION, - ST_TIMEVAL_RESOLUTION, - "Allocations living longer than this number of seconds will be ignored.\n") - -ST_ALL_OPTION_UINT32(TimevalMin, - DataSetGenre, - 0, - ST_TIMEVAL_RESOLUTION, - "Allocations existing solely before this second will be ignored.\n" - "Live allocations at this second and after can be considered.\n") - -ST_ALL_OPTION_UINT32(TimevalMax, - DataSetGenre, - ST_TIMEVAL_MAX / ST_TIMEVAL_RESOLUTION, - ST_TIMEVAL_RESOLUTION, - "Allocations existing solely after this second will be ignored.\n" - "Live allocations at this second and before can be considered.\n") - -ST_ALL_OPTION_UINT32(AllocationTimevalMin, - DataSetGenre, - 0, - ST_TIMEVAL_RESOLUTION, - "Live and dead allocations created before this second will be ignored.\n") - -ST_ALL_OPTION_UINT32(AllocationTimevalMax, - DataSetGenre, - ST_TIMEVAL_MAX / ST_TIMEVAL_RESOLUTION, - ST_TIMEVAL_RESOLUTION, - "Live and dead allocations created after this second will be ignored.\n") - -ST_ALL_OPTION_UINT32(AlignBy, - DataSizeGenre, - ST_DEFAULT_ALIGNMENT_SIZE, - 1, - "All allocation sizes are made to be a multiple of this number.\n" - "Closer to actual heap conditions; set to 1 for true sizes.\n") - -ST_ALL_OPTION_UINT32(Overhead, - DataSizeGenre, - ST_DEFAULT_OVERHEAD_SIZE, - 1, - "After alignment, all allocations are made to increase by this number.\n" - "Closer to actual heap conditions; set to 0 for true sizes.\n") - -ST_ALL_OPTION_UINT32(ListItemMax, - UIGenre, - 500, - 1, - "Specifies the maximum number of list items to present in each list.\n") - -ST_ALL_OPTION_UINT64(WeightMin, - DataSetGenre, - 0, - 1, - "Exclude allocations that are below this weight (lifespan * size).\n") - -ST_ALL_OPTION_UINT64(WeightMax, - DataSetGenre, - (0xFFFFFFFFLL << 32) + 0xFFFFFFFFLL, - 1, - "Exclude allocations that are above this weight (lifespan * size).\n") - -ST_CMD_OPTION_STRING(FileName, - DataSetGenre, - "-", - "Specifies trace-malloc input file.\n" - "\"-\" indicates stdin will be used as input.\n") - -ST_CMD_OPTION_STRING(CategoryFile, - CategoryGenre, - "rules.txt", - "Specifies the category rules file.\n" - "This file contains rules about how to categorize allocations.\n") - - -ST_CMD_OPTION_UINT32(HttpdPort, - ServerGenre, - 1969, - 1, - "Specifies the default port the web server will listen on.\n") - -ST_CMD_OPTION_STRING(OutputDir, - BatchModeGenre, - ".", - "Specifies a directory to output batch mode requests.\n" - "The directory must exist and must not use a trailing slash.\n") - -ST_CMD_OPTION_STRING_PTR_ARRAY(BatchRequest, - BatchModeGenre, - "This implicitly turns on batch mode.\n" - "Save each requested file into the output dir, then exit.\n") - -ST_CMD_OPTION_UINT32(Contexts, - ServerGenre, - 1, - 1, - "How many configurations to cache at the cost of a lot of memory.\n" - "Dedicated servers can cache more client configurations for performance.\n") - -ST_CMD_OPTION_BOOL(Help, - UIGenre, - "Show command line help.\n" - "See http://www.mozilla.org/projects/footprint/spaceTrace.html\n") - -/* -** END, THE OPTIONS -****************************************************************************/ - -/* -** Everything is undefined after the header is included. -** This sets it up for multiple inclusion if so desired. -*/ -#undef ST_ALL_OPTION_BOOL -#undef ST_CMD_OPTION_BOOL -#undef ST_WEB_OPTION_BOOL -#undef ST_ALL_OPTION_STRING -#undef ST_CMD_OPTION_STRING -#undef ST_WEB_OPTION_STRING -#undef ST_ALL_OPTION_STRING_ARRAY -#undef ST_CMD_OPTION_STRING_ARRAY -#undef ST_WEB_OPTION_STRING_ARRAY -#undef ST_ALL_OPTION_STRING_PTR_ARRAY -#undef ST_CMD_OPTION_STRING_PTR_ARRAY -#undef ST_WEB_OPTION_STRING_PTR_ARRAY -#undef ST_ALL_OPTION_UINT32 -#undef ST_CMD_OPTION_UINT32 -#undef ST_WEB_OPTION_UINT32 -#undef ST_ALL_OPTION_UINT64 -#undef ST_CMD_OPTION_UINT64 -#undef ST_WEB_OPTION_UINT64 diff --git a/tools/trace-malloc/tmfrags.c b/tools/trace-malloc/tmfrags.c deleted file mode 100644 index 8dcfd453f541..000000000000 --- a/tools/trace-malloc/tmfrags.c +++ /dev/null @@ -1,950 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "nspr.h" -#include "tmreader.h" - - -#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg)); -#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0) - - -#define ticks2msec(reader, ticks) ticks2xsec((reader), (ticks), 1000) -#define ticks2usec(reader, ticks) ticks2xsec((reader), (ticks), 1000000) -#define TICK_RESOLUTION 1000 -#define TICK_PRINTABLE(timeval) ((double)(timeval) / (double)ST_TIMEVAL_RESOLUTION) - - -typedef struct __struct_Options -/* -** Options to control how we perform. -** -** mProgramName Used in help text. -** mInputName Name of the file. -** mOutput Output file, append. -** Default is stdout. -** mOutputName Name of the file. -** mHelp Whether or not help should be shown. -** mOverhead How much overhead an allocation will have. -** mAlignment What boundry will the end of an allocation line up on. -** mPageSize Controls the page size. A page containing only fragments -** is not fragmented. A page containing any life memory -** costs mPageSize in bytes. -*/ -{ - const char* mProgramName; - char* mInputName; - FILE* mOutput; - char* mOutputName; - int mHelp; - unsigned mOverhead; - unsigned mAlignment; - unsigned mPageSize; -} -Options; - - -typedef struct __struct_Switch -/* -** Command line options. -*/ -{ - const char* mLongName; - const char* mShortName; - int mHasValue; - const char* mValue; - const char* mDescription; -} -Switch; - -#define DESC_NEWLINE "\n\t\t" - -static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."}; -static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."}; -static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."}; -static Switch gAlignmentSwitch = {"--alignment", "-al", 1, NULL, "All allocation sizes are made to be a multiple of this number." DESC_NEWLINE "Closer to actual heap conditions; set to 1 for true sizes." DESC_NEWLINE "Default value is 16."}; -static Switch gOverheadSwitch = {"--overhead", "-ov", 1, NULL, "After alignment, all allocations are made to increase by this number." DESC_NEWLINE "Closer to actual heap conditions; set to 0 for true sizes." DESC_NEWLINE "Default value is 8."}; -static Switch gPageSizeSwitch = {"--page-size", "-ps", 1, NULL, "Sets the page size which aids the identification of fragmentation." DESC_NEWLINE "Closer to actual heap conditions; set to 4294967295 for true sizes." DESC_NEWLINE "Default value is 4096."}; - -static Switch* gSwitches[] = { - &gInputSwitch, - &gOutputSwitch, - &gAlignmentSwitch, - &gOverheadSwitch, - &gPageSizeSwitch, - &gHelpSwitch -}; - - -typedef struct __struct_AnyArray -/* -** Variable sized item array. -** -** mItems The void pointer items. -** mItemSize Size of each different item. -** mCount The number of items in the array. -** mCapacity How many more items we can hold before reallocing. -** mGrowBy How many items we allocate when we grow. -*/ -{ - void* mItems; - unsigned mItemSize; - unsigned mCount; - unsigned mCapacity; - unsigned mGrowBy; -} -AnyArray; - - -typedef int (*arrayMatchFunc)(void* inContext, AnyArray* inArray, void* inItem, unsigned inItemIndex) -/* -** Callback function for the arrayIndexFn function. -** Used to determine an item match by customizable criteria. -** -** inContext The criteria and state of the search. -** User specified/created. -** inArray The array the item is in. -** inItem The item to evaluate for match. -** inItemIndex The index of this particular item in the array. -** -** return int 0 to specify a match. -** !0 to continue the search performed by arrayIndexFn. -*/ -; - - -typedef enum __enum_HeapEventType -/* -** Simple heap events are really one of two things. -*/ -{ - FREE, - ALLOC -} -HeapEventType; - - -typedef enum __enum_HeapObjectType -/* -** The various types of heap objects we track. -*/ -{ - ALLOCATION, - FRAGMENT -} -HeapObjectType; - - -typedef struct __struct_HeapObject HeapObject; -typedef struct __struct_HeapHistory -/* -** A marker as to what has happened. -** -** mTimestamp When history occurred. -** mTMRSerial The historical state as known to the tmreader. -** mObjectIndex Index to the object that was before or after this event. -** The index as in the index according to all heap objects -** kept in the TMState structure. -** We use an index instead of a pointer as the array of -** objects can change location in the heap. -*/ -{ - unsigned mTimestamp; - unsigned mTMRSerial; - unsigned mObjectIndex; -} -HeapHistory; - - -struct __struct_HeapObject -/* -** An object in the heap. -** -** A special case should be noted here. If either the birth or death -** history leads to an object of the same type, then this object -** is the same as that object, but was modified somehow. -** Also note that multiple objects may have the same birth object, -** as well as the same death object. -** -** mUniqueID Each object is unique. -** mType Either allocation or fragment. -** mHeapOffset Where in the heap the object is. -** mSize How much of the heap the object takes. -** mBirth History about the birth event. -** mDeath History about the death event. -*/ -{ - unsigned mUniqueID; - - HeapObjectType mType; - unsigned mHeapOffset; - unsigned mSize; - - HeapHistory mBirth; - HeapHistory mDeath; -}; - - -typedef struct __struct_TMState -/* -** State of our current operation. -** Stats we are trying to calculate. -** -** mOptions Obilgatory options pointer. -** mTMR The tmreader, used in tmreader API calls. -** mLoopExitTMR Set to non zero in order to quickly exit from tmreader -** input loop. This will also result in an error. -** uMinTicks Start of run, milliseconds. -** uMaxTicks End of run, milliseconds. -*/ -{ - Options* mOptions; - tmreader* mTMR; - - int mLoopExitTMR; - - unsigned uMinTicks; - unsigned uMaxTicks; -} -TMState; - - -int initOptions(Options* outOptions, int inArgc, char** inArgv) -/* -** returns int 0 if successful. -*/ -{ - int retval = 0; - int loop = 0; - int switchLoop = 0; - int match = 0; - const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]); - Switch* current = NULL; - - /* - ** Set any defaults. - */ - memset(outOptions, 0, sizeof(Options)); - outOptions->mProgramName = inArgv[0]; - outOptions->mInputName = strdup("-"); - outOptions->mOutput = stdout; - outOptions->mOutputName = strdup("stdout"); - outOptions->mAlignment = 16; - outOptions->mOverhead = 8; - - if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName) - { - retval = __LINE__; - ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup."); - } - - /* - ** Go through and attempt to do the right thing. - */ - for(loop = 1; loop < inArgc && 0 == retval; loop++) - { - match = 0; - current = NULL; - - for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++) - { - if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop])) - { - match = __LINE__; - } - else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop])) - { - match = __LINE__; - } - - if(match) - { - if(gSwitches[switchLoop]->mHasValue) - { - /* - ** Attempt to absorb next option to fullfill value. - */ - if(loop + 1 < inArgc) - { - loop++; - - current = gSwitches[switchLoop]; - current->mValue = inArgv[loop]; - } - } - else - { - current = gSwitches[switchLoop]; - } - - break; - } - } - - if(0 == match) - { - outOptions->mHelp = __LINE__; - retval = __LINE__; - ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch."); - } - else if(NULL == current) - { - outOptions->mHelp = __LINE__; - retval = __LINE__; - ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value."); - } - else - { - /* - ** Do something based on address/swtich. - */ - if(current == &gInputSwitch) - { - CLEANUP(outOptions->mInputName); - outOptions->mInputName = strdup(current->mValue); - if(NULL == outOptions->mInputName) - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to strdup."); - } - } - else if(current == &gOutputSwitch) - { - CLEANUP(outOptions->mOutputName); - if(NULL != outOptions->mOutput && stdout != outOptions->mOutput) - { - fclose(outOptions->mOutput); - outOptions->mOutput = NULL; - } - - outOptions->mOutput = fopen(current->mValue, "a"); - if(NULL == outOptions->mOutput) - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to open output file."); - } - else - { - outOptions->mOutputName = strdup(current->mValue); - if(NULL == outOptions->mOutputName) - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to strdup."); - } - } - } - else if(current == &gHelpSwitch) - { - outOptions->mHelp = __LINE__; - } - else if(current == &gAlignmentSwitch) - { - unsigned arg = 0; - char* endScan = NULL; - - errno = 0; - arg = strtoul(current->mValue, &endScan, 0); - if(0 == errno && endScan != current->mValue) - { - outOptions->mAlignment = arg; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); - } - } - else if(current == &gOverheadSwitch) - { - unsigned arg = 0; - char* endScan = NULL; - - errno = 0; - arg = strtoul(current->mValue, &endScan, 0); - if(0 == errno && endScan != current->mValue) - { - outOptions->mOverhead = arg; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); - } - } - else if(current == &gPageSizeSwitch) - { - unsigned arg = 0; - char* endScan = NULL; - - errno = 0; - arg = strtoul(current->mValue, &endScan, 0); - if(0 == errno && endScan != current->mValue) - { - outOptions->mPageSize = arg; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); - } - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mLongName, "No handler for command line switch."); - } - } - } - - return retval; -} - - -uint32_t ticks2xsec(tmreader* aReader, uint32_t aTicks, uint32_t aResolution) -/* -** Convert platform specific ticks to second units -*/ -{ - return (uint32)((aResolution * aTicks) / aReader->ticksPerSec); -} - - -void cleanOptions(Options* inOptions) -/* -** Clean up any open handles. -*/ -{ - unsigned loop = 0; - - CLEANUP(inOptions->mInputName); - CLEANUP(inOptions->mOutputName); - if(NULL != inOptions->mOutput && stdout != inOptions->mOutput) - { - fclose(inOptions->mOutput); - } - - memset(inOptions, 0, sizeof(Options)); -} - - -void showHelp(Options* inOptions) -/* -** Show some simple help text on usage. -*/ -{ - int loop = 0; - const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]); - const char* valueText = NULL; - - printf("usage:\t%s [arguments]\n", inOptions->mProgramName); - printf("\n"); - printf("arguments:\n"); - - for(loop = 0; loop < switchCount; loop++) - { - if(gSwitches[loop]->mHasValue) - { - valueText = " "; - } - else - { - valueText = ""; - } - - printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText); - printf("\t %s%s", gSwitches[loop]->mShortName, valueText); - printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription); - } - - printf("This tool reports heap fragmentation stats from a trace-malloc log.\n"); -} - - -AnyArray* arrayCreate(unsigned inItemSize, unsigned inGrowBy) -/* -** Create an array container object. -*/ -{ - AnyArray* retval = NULL; - - if(0 != inGrowBy && 0 != inItemSize) - { - retval = (AnyArray*)calloc(1, sizeof(AnyArray)); - retval->mItemSize = inItemSize; - retval->mGrowBy = inGrowBy; - } - - return retval; -} - - -void arrayDestroy(AnyArray* inArray) -/* -** Release the memory the array contains. -** This will release the items as well. -*/ -{ - if(NULL != inArray) - { - if(NULL != inArray->mItems) - { - free(inArray->mItems); - } - free(inArray); - } -} - - -unsigned arrayAlloc(AnyArray* inArray, unsigned inItems) -/* -** Resize the item array capcity to a specific number of items. -** This could possibly truncate the array, so handle that as well. -** -** returns unsigned <= inArray->mCapacity on success. -*/ -{ - unsigned retval = (unsigned)-1; - - if(NULL != inArray) - { - void* moved = NULL; - - moved = realloc(inArray->mItems, inItems * inArray->mItemSize); - if(NULL != moved) - { - inArray->mItems = moved; - inArray->mCapacity = inItems; - if(inArray->mCount > inItems) - { - inArray->mCount = inItems; - } - - retval = inItems; - } - } - - return retval; -} - - -void* arrayItem(AnyArray* inArray, unsigned inIndex) -/* -** Return the array item at said index. -** Zero based index. -** -** returns void* NULL on failure. -*/ -{ - void* retval = NULL; - - if(NULL != inArray && inIndex < inArray->mCount) - { - retval = (void*)((char*)inArray->mItems + (inArray->mItemSize * inIndex)); - } - - return retval; -} - - -unsigned arrayIndex(AnyArray* inArray, void* inItem, unsigned inStartIndex) -/* -** Go through the array from the index specified looking for an item -** match based on byte for byte comparison. -** We allow specifying the start index in order to handle arrays with -** duplicate items. -** -** returns unsigned >= inArray->mCount on failure. -*/ -{ - unsigned retval = (unsigned)-1; - - if(NULL != inArray && NULL != inItem && inStartIndex < inArray->mCount) - { - void* curItem = NULL; - - for(retval = inStartIndex; retval < inArray->mCount; retval++) - { - curItem = arrayItem(inArray, retval); - if(0 == memcmp(inItem, curItem, inArray->mItemSize)) - { - break; - } - } - } - - - return retval; -} - - -unsigned arrayIndexFn(AnyArray* inArray, arrayMatchFunc inFunc, void* inFuncContext, unsigned inStartIndex) -/* -** Go through the array from the index specified looking for an item -** match based upon the return value of inFunc (0, Zero, is a match). -** We allow specifying the start index in order to facilitate looping over -** the array which could have multiple matches. -** -** returns unsigned >= inArray->mCount on failure. -*/ -{ - unsigned retval = (unsigned)-1; - - if(NULL != inArray && NULL != inFunc && inStartIndex < inArray->mCount) - { - void* curItem = NULL; - - for(retval = inStartIndex; retval < inArray->mCount; retval++) - { - curItem = arrayItem(inArray, retval); - if(0 == inFunc(inFuncContext, inArray, curItem, retval)) - { - break; - } - } - } - - return retval; -} - - -unsigned arrayAddItem(AnyArray* inArray, void* inItem) -/* -** Add a new item to the array. -** This is done by copying the item. -** -** returns unsigned < inArray->mCount on success. -*/ -{ - unsigned retval = (unsigned)-1; - - if(NULL != inArray && NULL != inItem) - { - int noCopy = 0; - - /* - ** See if the array should grow. - */ - if(inArray->mCount == inArray->mCapacity) - { - unsigned allocRes = 0; - - allocRes = arrayAlloc(inArray, inArray->mCapacity + inArray->mGrowBy); - if(allocRes > inArray->mCapacity) - { - noCopy = __LINE__; - } - } - - if(0 == noCopy) - { - retval = inArray->mCount; - - inArray->mCount++; - memcpy(arrayItem(inArray, retval), inItem, inArray->mItemSize); - } - } - - return retval; -} - - -HeapObject* initHeapObject(HeapObject* inObject) -/* -** Function to init the heap object just right. -** Sets the unique ID to something unique. -*/ -{ - HeapObject* retval = inObject; - - if(NULL != inObject) - { - static unsigned uniqueGenerator = 0; - - memset(inObject, -1, sizeof(HeapObject)); - - inObject->mUniqueID = uniqueGenerator; - uniqueGenerator++; - } - - return retval; -} - - -int simpleHeapEvent(TMState* inStats, HeapEventType inType, unsigned mTimestamp, unsigned inSerial, unsigned inHeapID, unsigned inSize) -/* -** A new heap event will cause the creation of a new heap object. -** The new heap object will displace, or replace, a heap object of a different type. -*/ -{ - int retval = 0; - HeapObject newObject; - - /* - ** Set the most basic object details. - */ - initHeapObject(&newObject); - newObject.mHeapOffset = inHeapID; - newObject.mSize = inSize; - if(FREE == inType) - { - newObject.mType = FRAGMENT; - } - else if(ALLOC == inType) - { - newObject.mType = ALLOCATION; - } - - /* - ** Add it to the heap object array. - */ - - /* - ** TODO GAB - ** - ** First thing to do is to add the new object to the heap in order to - ** obtain a valid index. - ** - ** Next, find all matches to this range of heap memory that this event - ** refers to, that are alive during this timestamp (no death yet). - ** Fill in the death event of those objects. - ** If the objects contain some portions outside of the range, then - ** new objects for those ranges need to be created that carry on - ** the same object type, have the index of the old object for birth, - ** and the serial of the old object, new timestamp of course. - ** The old object's death points to the new object, which tells why the - ** fragmentation took place. - ** The new object birth points to the old object only if a fragment. - ** An allocation only has a birth object when it is a realloc (complex) - ** heap event. - ** - ** I believe this give us enough information to look up particular - ** details of the heap at any given time. - */ - - return retval; -} - - -int complexHeapEvent(TMState* inStats, unsigned mTimestamp, unsigned inOldSerial, unsigned inOldHeapID, unsigned inOSize, unsigned inNewSerial, unsigned inNewHeapID, unsigned inNewSize) -/* -** Generally, this event intends to chain one old heap object to a newer heap object. -** Otherwise, the functionality should recognizable ala simpleHeapEvent. -*/ -{ - int retval = 0; - - /* - ** TODO GAB - */ - - return retval; -} - - -unsigned actualByteSize(Options* inOptions, unsigned retval) -/* -** Apply alignment and overhead to size to figure out actual byte size. -** This by default mimics spacetrace with default options (msvc crt heap). -*/ -{ - if(0 != retval) - { - unsigned eval = 0; - unsigned over = 0; - - eval = retval - 1; - if(0 != inOptions->mAlignment) - { - over = eval % inOptions->mAlignment; - } - retval = eval + inOptions->mOverhead + inOptions->mAlignment - over; - } - - return retval; -} - - -void tmEventHandler(tmreader* inReader, tmevent* inEvent) -/* -** Callback from the tmreader_eventloop. -** Build up our fragmentation information herein. -*/ -{ - char type = inEvent->type; - TMState* stats = (TMState*)inReader->data; - - /* - ** Only intersted in handling events of a particular type. - */ - switch(type) - { - default: - return; - - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - case TM_EVENT_REALLOC: - case TM_EVENT_FREE: - break; - } - - /* - ** Should we even try to look? - ** Set mLoopExitTMR to non-zero to abort the read loop faster. - */ - if(0 == stats->mLoopExitTMR) - { - Options* options = (Options*)stats->mOptions; - unsigned timestamp = ticks2msec(stats->mTMR, inEvent->u.alloc.interval); - unsigned actualSize = actualByteSize(options, inEvent->u.alloc.size); - unsigned heapID = inEvent->u.alloc.ptr; - unsigned serial = inEvent->serial; - - /* - ** Check the timestamp range of our overall state. - */ - if(stats->uMinTicks > timestamp) - { - stats->uMinTicks = timestamp; - } - if(stats->uMaxTicks < timestamp) - { - stats->uMaxTicks = timestamp; - } - - /* - ** Realloc in general deserves some special attention if dealing - ** with an old allocation (not new memory). - */ - if(TM_EVENT_REALLOC == type && 0 != inEvent->u.alloc.oldserial) - { - unsigned oldActualSize = actualByteSize(options, inEvent->u.alloc.oldsize); - unsigned oldHeapID = inEvent->u.alloc.oldptr; - unsigned oldSerial = inEvent->u.alloc.oldserial; - - if(0 == actualSize) - { - /* - ** Reallocs of size zero are to become free events. - */ - stats->mLoopExitTMR = simpleHeapEvent(stats, FREE, timestamp, serial, oldHeapID, oldActualSize); - } - else if(heapID != oldHeapID || actualSize != oldActualSize) - { - /* - ** Reallocs which moved generate two events. - ** Reallocs which changed size generate two events. - ** - ** One event to free the old memory area. - ** Another event to allocate the new memory area. - ** They are to be linked to one another, so the history - ** and true origin can be tracked. - */ - stats->mLoopExitTMR = complexHeapEvent(stats, timestamp, oldSerial, oldHeapID, oldActualSize, serial, heapID, actualSize); - } - else - { - /* - ** The realloc is not considered an operation and is skipped. - ** It is not an operation, because it did not move or change - ** size; this can happen if a realloc falls within the - ** alignment of an allocation. - ** Say if you realloc a 1 byte allocation to 2 bytes, it will - ** not really change heap impact unless you have 1 set as - ** the alignment of your allocations. - */ - } - } - else if(TM_EVENT_FREE == type) - { - /* - ** Generate a free event to create a fragment. - */ - stats->mLoopExitTMR = simpleHeapEvent(stats, FREE, timestamp, serial, heapID, actualSize); - } - else - { - /* - ** Generate an allocation event to clear fragments. - */ - stats->mLoopExitTMR = simpleHeapEvent(stats, ALLOC, timestamp, serial, heapID, actualSize); - } - } -} - - -int tmfrags(Options* inOptions) -/* -** Load the input file and report stats. -*/ -{ - int retval = 0; - TMState stats; - - memset(&stats, 0, sizeof(stats)); - stats.mOptions = inOptions; - stats.uMinTicks = 0xFFFFFFFFU; - - /* - ** Need a tmreader. - */ - stats.mTMR = tmreader_new(inOptions->mProgramName, &stats); - if(NULL != stats.mTMR) - { - int tmResult = 0; - - tmResult = tmreader_eventloop(stats.mTMR, inOptions->mInputName, tmEventHandler); - if(0 == tmResult) - { - retval = __LINE__; - ERROR_REPORT(retval, inOptions->mInputName, "Problem reading trace-malloc data."); - } - if(0 != stats.mLoopExitTMR) - { - retval = stats.mLoopExitTMR; - ERROR_REPORT(retval, inOptions->mInputName, "Aborted trace-malloc input loop."); - } - - tmreader_destroy(stats.mTMR); - stats.mTMR = NULL; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, inOptions->mProgramName, "Unable to obtain tmreader."); - } - - return retval; -} - - -int main(int inArgc, char** inArgv) -{ - int retval = 0; - Options options; - - retval = initOptions(&options, inArgc, inArgv); - if(options.mHelp) - { - showHelp(&options); - } - else if(0 == retval) - { - retval = tmfrags(&options); - } - - cleanOptions(&options); - return retval; -} - diff --git a/tools/trace-malloc/tmreader.c b/tools/trace-malloc/tmreader.c deleted file mode 100644 index 71a58e92edba..000000000000 --- a/tools/trace-malloc/tmreader.c +++ /dev/null @@ -1,892 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ -#include -#include -#include -#include -#include /* XXX push error reporting out to clients? */ -#ifndef XP_WIN -#include -#else -#include -#endif -#include "prlog.h" -#include "plhash.h" -/* make sure this happens before tmreader.h */ -#define PL_ARENA_CONST_ALIGN_MASK 2 -#include "plarena.h" - -#include "prnetdb.h" -#include "nsTraceMalloc.h" -#include "tmreader.h" - -#undef DEBUG_tmreader - -static int accum_byte(FILE *fp, uint32_t *uip) -{ - int c = getc(fp); - if (c == EOF) - return 0; - *uip = (*uip << 8) | c; - return 1; -} - -static int get_uint32(FILE *fp, uint32_t *uip) -{ - int c; - uint32_t ui; - - c = getc(fp); - if (c == EOF) - return 0; - ui = 0; - if (c & 0x80) { - c &= 0x7f; - if (c & 0x40) { - c &= 0x3f; - if (c & 0x20) { - c &= 0x1f; - if (c & 0x10) { - if (!accum_byte(fp, &ui)) - return 0; - } else { - ui = (uint32_t) c; - } - if (!accum_byte(fp, &ui)) - return 0; - } else { - ui = (uint32_t) c; - } - if (!accum_byte(fp, &ui)) - return 0; - } else { - ui = (uint32_t) c; - } - if (!accum_byte(fp, &ui)) - return 0; - } else { - ui = (uint32_t) c; - } - *uip = ui; - return 1; -} - -static char *get_string(FILE *fp) -{ - char *cp; - int c; - static char buf[256]; - static char *bp = buf, *ep = buf + sizeof buf; - static size_t bsize = sizeof buf; - - cp = bp; - do { - c = getc(fp); - if (c == EOF) - return 0; - if (cp == ep) { - if (bp == buf) { - bp = malloc(2 * bsize); - if (bp) - memcpy(bp, buf, bsize); - } else { - bp = realloc(bp, 2 * bsize); - } - if (!bp) - return 0; - cp = bp + bsize; - bsize *= 2; - ep = bp + bsize; - } - *cp++ = c; - } while (c != '\0'); - return strdup(bp); -} - -static int get_tmevent(FILE *fp, tmevent *event) -{ - int c; - char *s; - - c = getc(fp); - if (c == EOF) - return 0; - event->type = (char) c; - if (!get_uint32(fp, &event->serial)) - return 0; - switch (c) { - case TM_EVENT_LIBRARY: - s = get_string(fp); - if (!s) - return 0; - event->u.libname = s; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u libname=\"%s\"\n", event->type, event->serial, - event->u.libname); -#endif - break; - - case TM_EVENT_FILENAME: - s = get_string(fp); - if (!s) - return 0; - event->u.srcname = s; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u srcname=\"%s\"\n", - event->type, event->serial, event->u.srcname); -#endif - break; - - case TM_EVENT_METHOD: - if (!get_uint32(fp, &event->u.method.library)) - return 0; - if (!get_uint32(fp, &event->u.method.filename)) - return 0; - if (!get_uint32(fp, &event->u.method.linenumber)) - return 0; - s = get_string(fp); - if (!s) - return 0; - event->u.method.name = s; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u library=%u filename=%u linenumber=%u " - "name=\"%s\"\n", - event->type, event->serial, - event->u.method.library, event->u.method.filename, - event->u.method.linenumber, event->u.method.name); -#endif - break; - - case TM_EVENT_CALLSITE: - if (!get_uint32(fp, &event->u.site.parent)) - return 0; - if (!get_uint32(fp, &event->u.site.method)) - return 0; - if (!get_uint32(fp, &event->u.site.offset)) - return 0; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u parent=%u method=%u offset=%u\n", - event->type, event->serial, - event->u.site.parent, event->u.site.method, - event->u.site.offset); -#endif - break; - - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - case TM_EVENT_FREE: - if (!get_uint32(fp, &event->u.alloc.interval)) - return 0; - if (!get_uint32(fp, &event->u.alloc.cost)) - return 0; - if (!get_uint32(fp, &event->u.alloc.ptr)) - return 0; - if (!get_uint32(fp, &event->u.alloc.size)) - return 0; - event->u.alloc.oldserial = 0; - event->u.alloc.oldptr = 0; - event->u.alloc.oldsize = 0; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u interval=%u cost=%u ptr=0x%x size=%u\n", - event->type, event->serial, - event->u.alloc.interval, event->u.alloc.cost, - event->u.alloc.ptr, event->u.alloc.size); -#endif -#if defined(DEBUG_dp) - if (c == TM_EVENT_MALLOC) - printf("%d malloc %d 0x%p\n", event->u.alloc.cost, - event->u.alloc.size, event->u.alloc.ptr); - else if (c == TM_EVENT_CALLOC) - printf("%d calloc %d 0x%p\n", event->u.alloc.cost, - event->u.alloc.size, event->u.alloc.ptr); - else - printf("%d free %d 0x%p\n", event->u.alloc.cost, - event->u.alloc.size, event->u.alloc.ptr); -#endif - break; - - case TM_EVENT_REALLOC: - if (!get_uint32(fp, &event->u.alloc.interval)) - return 0; - if (!get_uint32(fp, &event->u.alloc.cost)) - return 0; - if (!get_uint32(fp, &event->u.alloc.ptr)) - return 0; - if (!get_uint32(fp, &event->u.alloc.size)) - return 0; - if (!get_uint32(fp, &event->u.alloc.oldserial)) - return 0; - if (!get_uint32(fp, &event->u.alloc.oldptr)) - return 0; - if (!get_uint32(fp, &event->u.alloc.oldsize)) - return 0; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u interval=%u cost=%u ptr=0x%x size=%u " - "oldserial=%u oldptr=0x%x oldsize=%u\n", - event->type, event->serial, - event->u.alloc.interval, event->u.alloc.cost, - event->u.alloc.ptr, event->u.alloc.size, - event->u.alloc.oldserial, event->u.alloc.oldptr, - event->u.alloc.oldsize); -#endif -#if defined(DEBUG_dp) - printf("%d realloc %d 0x%p %d\n", event->u.alloc.cost, - event->u.alloc.size, event->u.alloc.ptr, event->u.alloc.oldsize); -#endif - break; - - case TM_EVENT_STATS: - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxstack)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxdepth)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_parents)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_maxkids)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidhits)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidmisses)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calltree_kidsteps)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.callsite_recurrences)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.backtrace_calls)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.backtrace_failures)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.btmalloc_failures)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.dladdr_failures)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.malloc_calls)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.malloc_failures)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calloc_calls)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.calloc_failures)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.realloc_calls)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.realloc_failures)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.free_calls)) - return 0; - if (!get_uint32(fp, &event->u.stats.tmstats.null_free_calls)) - return 0; - if (!get_uint32(fp, &event->u.stats.calltree_maxkids_parent)) - return 0; - if (!get_uint32(fp, &event->u.stats.calltree_maxstack_top)) - return 0; -#ifdef DEBUG_tmreader - fprintf(stderr, "tmevent %c %u\n", event->type, event->serial); -#endif - break; - default: - fprintf(stderr, "Unknown event type 0x%x\n", (unsigned int)event->type); - return 0; - } - return 1; -} - -static void *arena_alloc(void* pool, size_t size) -{ - PLArenaPool* arena = (PLArenaPool*)pool; - void* result; - PL_ARENA_ALLOCATE(result, arena, size); - memset(result, 0, size); - return result; -} - -static void *generic_alloctable(void *pool, size_t size) -{ - return arena_alloc(pool, size); -} - -static void generic_freetable(void *pool, void *item) -{ - /* do nothing - arena-allocated */ -} - -static PLHashEntry *filename_allocentry(void *pool, const void *key) -{ - return (PLHashEntry*)arena_alloc(pool, sizeof(PLHashEntry)); -} - -static PLHashEntry *callsite_allocentry(void *pool, const void *key) -{ - return (PLHashEntry*)arena_alloc(pool, sizeof(tmcallsite)); -} - -static void init_graphnode(tmgraphnode* node) -{ - node->in = node->out = NULL; - node->up = node->down = node->next = NULL; - node->low = 0; - node->allocs.bytes.direct = node->allocs.bytes.total = 0; - node->allocs.calls.direct = node->allocs.calls.total = 0; - node->frees.bytes.direct = node->frees.bytes.total = 0; - node->frees.calls.direct = node->frees.calls.total = 0; - node->sqsum = 0; - node->sort = -1; -} - -static PLHashEntry *graphnode_allocentry(void *pool, const void *key) -{ - tmgraphnode* node = (tmgraphnode*)arena_alloc(pool, sizeof(tmgraphnode)); - if (!node) - return NULL; - init_graphnode(node); - return &node->entry; -} - -static void init_method(tmmethodnode *node) -{ - node->graphnode.in = node->graphnode.out = NULL; - node->graphnode.up = node->graphnode.down = node->graphnode.next = NULL; - node->graphnode.low = 0; - node->graphnode.allocs.bytes.direct = node->graphnode.allocs.bytes.total = 0; - node->graphnode.allocs.calls.direct = node->graphnode.allocs.calls.total = 0; - node->graphnode.frees.bytes.direct = node->graphnode.frees.bytes.total = 0; - node->graphnode.frees.calls.direct = node->graphnode.frees.calls.total = 0; - node->graphnode.sqsum = 0; - node->graphnode.sort = -1; - node->sourcefile = NULL; - node->linenumber = 0; -} - -static PLHashEntry *method_allocentry(void *pool, const void *key) -{ - tmmethodnode *node = - (tmmethodnode*) arena_alloc(pool, sizeof(tmmethodnode)); - if (!node) - return NULL; - init_method(node); - return &node->graphnode.entry; -} - -static void graphnode_freeentry(void *pool, PLHashEntry *he, unsigned flag) -{ - /* Always free the value, which points to a strdup'd string. */ - free(he->value); -#if 0 /* using arenas now, no freeing! */ - /* Free the whole thing if we're told to. */ - if (flag == HT_FREE_ENTRY) - free((void*) he); -#endif -} - -static void component_freeentry(void *pool, PLHashEntry *he, unsigned flag) -{ - if (flag == HT_FREE_ENTRY) { - tmgraphnode *comp = (tmgraphnode*) he; - - /* Free the key, which was strdup'd (N.B. value also points to it). */ - free((void*) tmcomponent_name(comp)); -#if 0 /* using arenas now, no freeing! */ - free((void*) comp); -#endif - } -} - -static PLHashAllocOps filename_hashallocops = { - generic_alloctable, generic_freetable, - filename_allocentry, graphnode_freeentry -}; - -static PLHashAllocOps callsite_hashallocops = { - generic_alloctable, generic_freetable, - callsite_allocentry, graphnode_freeentry -}; - -static PLHashAllocOps graphnode_hashallocops = { - generic_alloctable, generic_freetable, - graphnode_allocentry, graphnode_freeentry -}; - -static PLHashAllocOps method_hashallocops = { - generic_alloctable, generic_freetable, - method_allocentry, graphnode_freeentry -}; - -static PLHashAllocOps component_hashallocops = { - generic_alloctable, generic_freetable, - graphnode_allocentry, component_freeentry -}; - -static PLHashNumber hash_serial(const void *key) -{ - return (PLHashNumber) key; -} - -tmreader *tmreader_new(const char *program, void *data) -{ - tmreader *tmr; - - tmr = calloc(1, sizeof *tmr); - if (!tmr) - return NULL; - tmr->program = program; - tmr->data = data; - PL_INIT_ARENA_POOL(&tmr->arena, "TMReader", 256*1024); - - tmr->libraries = PL_NewHashTable(100, hash_serial, PL_CompareValues, - PL_CompareStrings, &graphnode_hashallocops, - &tmr->arena); - tmr->filenames = PL_NewHashTable(100, hash_serial, PL_CompareValues, - PL_CompareStrings, &filename_hashallocops, - &tmr->arena); - tmr->components = PL_NewHashTable(10000, PL_HashString, PL_CompareStrings, - PL_CompareValues, &component_hashallocops, - &tmr->arena); - tmr->methods = PL_NewHashTable(10000, hash_serial, PL_CompareValues, - PL_CompareStrings, &method_hashallocops, - &tmr->arena); - tmr->callsites = PL_NewHashTable(200000, hash_serial, PL_CompareValues, - PL_CompareValues, &callsite_hashallocops, - &tmr->arena); - tmr->calltree_root.entry.value = (void*) strdup("root"); - - if (!tmr->libraries || !tmr->components || !tmr->methods || - !tmr->callsites || !tmr->calltree_root.entry.value || - !tmr->filenames) { - tmreader_destroy(tmr); - return NULL; - } - return tmr; -} - -void tmreader_destroy(tmreader *tmr) -{ - if (tmr->libraries) - PL_HashTableDestroy(tmr->libraries); - if (tmr->filenames) - PL_HashTableDestroy(tmr->filenames); - if (tmr->components) - PL_HashTableDestroy(tmr->components); - if (tmr->methods) - PL_HashTableDestroy(tmr->methods); - if (tmr->callsites) - PL_HashTableDestroy(tmr->callsites); - PL_FinishArenaPool(&tmr->arena); - free(tmr); -} - -int tmreader_eventloop(tmreader *tmr, const char *filename, - tmeventhandler eventhandler) -{ - FILE *fp; - char buf[NS_TRACE_MALLOC_MAGIC_SIZE]; - tmevent event; - static const char magic[] = NS_TRACE_MALLOC_MAGIC; - - if (strcmp(filename, "-") == 0) { - fp = stdin; - } else { -#if defined(XP_WIN32) - fp = fopen(filename, "rb"); -#else - fp = fopen(filename, "r"); -#endif - if (!fp) { - fprintf(stderr, "%s: can't open %s: %s.\n", - tmr->program, filename, strerror(errno)); - return 0; - } - } - - if (read(fileno(fp), buf, sizeof buf) != sizeof buf || - strncmp(buf, magic, sizeof buf) != 0) { - fprintf(stderr, "%s: bad magic string %s at start of %s.\n", - tmr->program, buf, filename); - fprintf(stderr, "either the data file is out of date,\nor your tools are out of date.\n"); - return 0; - } - - /* Read in ticks per second. Used to convert platform specific intervals to time values */ - if (read(fileno(fp), &tmr->ticksPerSec, sizeof tmr->ticksPerSec) != sizeof tmr->ticksPerSec) { - fprintf(stderr, "%s: Cannot read ticksPerSec. Log file read error.\n", - tmr->program); - return 0; - } - tmr->ticksPerSec = PR_ntohl(tmr->ticksPerSec); -#ifdef DEBUG_dp - printf("DEBUG: ticks per sec = %d\n", tmr->ticksPerSec); -#endif - while (get_tmevent(fp, &event)) { - switch (event.type) { - case TM_EVENT_LIBRARY: { - const void *key; - PLHashNumber hash; - PLHashEntry **hep, *he; - - key = (const void*) (uintptr_t) event.serial; - hash = hash_serial(key); - hep = PL_HashTableRawLookup(tmr->libraries, hash, key); - he = *hep; - PR_ASSERT(!he); - if (he) exit(2); - - he = PL_HashTableRawAdd(tmr->libraries, hep, hash, key, - event.u.libname); - if (!he) { - perror(tmr->program); - return -1; - } - break; - } - - case TM_EVENT_FILENAME: { - const void *key; - PLHashNumber hash; - PLHashEntry **hep, *he; - - key = (const void*) (uintptr_t) event.serial; - hash = hash_serial(key); - hep = PL_HashTableRawLookup(tmr->filenames, hash, key); - he = *hep; - PR_ASSERT(!he); - if (he) exit(2); - - he = PL_HashTableRawAdd(tmr->filenames, hep, hash, key, - event.u.srcname); - if (!he) { - perror(tmr->program); - return -1; - } - break; - } - - case TM_EVENT_METHOD: { - const void *key, *sourcekey; - PLHashNumber hash, sourcehash; - PLHashEntry **hep, *he, **sourcehep, *sourcehe; - char *name, *head, *mark, save; - tmgraphnode *comp, *lib; - tmmethodnode *meth; - - key = (const void*) (uintptr_t) event.serial; - hash = hash_serial(key); - hep = PL_HashTableRawLookup(tmr->methods, hash, key); - he = *hep; - PR_ASSERT(!he); - if (he) exit(2); - - name = event.u.method.name; - he = PL_HashTableRawAdd(tmr->methods, hep, hash, key, name); - if (!he) { - perror(tmr->program); - return -1; - } - meth = (tmmethodnode*) he; - - meth->linenumber = event.u.method.linenumber; - sourcekey = (const void*) (uintptr_t) event.u.method.filename; - sourcehash = hash_serial(sourcekey); - sourcehep = PL_HashTableRawLookup(tmr->filenames, sourcehash, sourcekey); - sourcehe = *sourcehep; - meth->sourcefile = filename_name(sourcehe); - - head = name; - mark = strchr(name, ':'); - if (!mark) { - mark = name; - while (*mark != '\0' && *mark == '_') - mark++; - head = mark; - mark = strchr(head, '_'); - if (!mark) { - mark = strchr(head, '+'); - if (!mark) - mark = head + strlen(head); - } - } - - save = *mark; - *mark = '\0'; - hash = PL_HashString(head); - hep = PL_HashTableRawLookup(tmr->components, hash, head); - he = *hep; - if (he) { - comp = (tmgraphnode*) he; - } else { - head = strdup(head); - if (head) { - he = PL_HashTableRawAdd(tmr->components, hep, hash, head, - head); - } - if (!he) { - perror(tmr->program); - return -1; - } - comp = (tmgraphnode*) he; - - key = (const void*) (uintptr_t) event.u.method.library; - hash = hash_serial(key); - lib = (tmgraphnode*) - *PL_HashTableRawLookup(tmr->libraries, hash, key); - if (lib) { - comp->up = lib; - comp->next = lib->down; - lib->down = comp; - } - } - *mark = save; - - meth->graphnode.up = comp; - meth->graphnode.next = comp->down; - comp->down = &(meth->graphnode); - break; - } - - case TM_EVENT_CALLSITE: { - const void *key, *mkey; - PLHashNumber hash, mhash; - PLHashEntry **hep, *he; - tmcallsite *site, *parent; - tmmethodnode *meth; - - key = (const void*) (uintptr_t) event.serial; - hash = hash_serial(key); - hep = PL_HashTableRawLookup(tmr->callsites, hash, key); - he = *hep; - - /* there should not be an entry here! */ - PR_ASSERT(!he); - if (he) exit(2); - - if (event.u.site.parent == 0) { - parent = &tmr->calltree_root; - } else { - parent = tmreader_callsite(tmr, event.u.site.parent); - if (!parent) { - fprintf(stderr, "%s: no parent for %lu (%lu)!\n", - tmr->program, (unsigned long) event.serial, - (unsigned long) event.u.site.parent); - continue; - } - } - - he = PL_HashTableRawAdd(tmr->callsites, hep, hash, key, NULL); - if (!he) { - perror(tmr->program); - return -1; - } - - site = (tmcallsite*) he; - site->parent = parent; - site->siblings = parent->kids; - parent->kids = site; - site->kids = NULL; - - mkey = (const void*) (uintptr_t) event.u.site.method; - mhash = hash_serial(mkey); - meth = (tmmethodnode*) - *PL_HashTableRawLookup(tmr->methods, mhash, mkey); - site->method = meth; - site->offset = event.u.site.offset; - site->allocs.bytes.direct = site->allocs.bytes.total = 0; - site->allocs.calls.direct = site->allocs.calls.total = 0; - site->frees.bytes.direct = site->frees.bytes.total = 0; - site->frees.calls.direct = site->frees.calls.total = 0; - break; - } - - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - case TM_EVENT_REALLOC: { - tmcallsite *site; - uint32_t size, oldsize; - double delta, sqdelta, sqszdelta = 0; - tmgraphnode *comp, *lib; - tmmethodnode *meth; - - site = tmreader_callsite(tmr, event.serial); - if (!site) { - fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n", - tmr->program, event.type, (unsigned long) event.serial); - continue; - } - - size = event.u.alloc.size; - oldsize = event.u.alloc.oldsize; - delta = (double)size - (double)oldsize; - site->allocs.bytes.direct += (unsigned long)delta; - if (event.type != TM_EVENT_REALLOC) - site->allocs.calls.direct++; - meth = site->method; - if (meth) { - meth->graphnode.allocs.bytes.direct += (unsigned long)delta; - sqdelta = delta * delta; - if (event.type == TM_EVENT_REALLOC) { - sqszdelta = ((double)size * size) - - ((double)oldsize * oldsize); - meth->graphnode.sqsum += sqszdelta; - } else { - meth->graphnode.sqsum += sqdelta; - meth->graphnode.allocs.calls.direct++; - } - comp = meth->graphnode.up; - if (comp) { - comp->allocs.bytes.direct += (unsigned long)delta; - if (event.type == TM_EVENT_REALLOC) { - comp->sqsum += sqszdelta; - } else { - comp->sqsum += sqdelta; - comp->allocs.calls.direct++; - } - lib = comp->up; - if (lib) { - lib->allocs.bytes.direct += (unsigned long)delta; - if (event.type == TM_EVENT_REALLOC) { - lib->sqsum += sqszdelta; - } else { - lib->sqsum += sqdelta; - lib->allocs.calls.direct++; - } - } - } - } - break; - } - - case TM_EVENT_FREE: { - tmcallsite *site; - uint32_t size; - tmgraphnode *comp, *lib; - tmmethodnode *meth; - - site = tmreader_callsite(tmr, event.serial); - if (!site) { - fprintf(stderr, "%s: no callsite for '%c' (%lu)!\n", - tmr->program, event.type, (unsigned long) event.serial); - continue; - } - size = event.u.alloc.size; - site->frees.bytes.direct += size; - site->frees.calls.direct++; - meth = site->method; - if (meth) { - meth->graphnode.frees.bytes.direct += size; - meth->graphnode.frees.calls.direct++; - comp = meth->graphnode.up; - if (comp) { - comp->frees.bytes.direct += size; - comp->frees.calls.direct++; - lib = comp->up; - if (lib) { - lib->frees.bytes.direct += size; - lib->frees.calls.direct++; - } - } - } - break; - } - - case TM_EVENT_STATS: - break; - } - - eventhandler(tmr, &event); - } - - return 1; -} - -tmgraphnode *tmreader_library(tmreader *tmr, uint32_t serial) -{ - const void *key; - PLHashNumber hash; - - key = (const void*) (uintptr_t) serial; - hash = hash_serial(key); - return (tmgraphnode*) *PL_HashTableRawLookup(tmr->libraries, hash, key); -} - -tmgraphnode *tmreader_filename(tmreader *tmr, uint32_t serial) -{ - const void *key; - PLHashNumber hash; - - key = (const void*) (uintptr_t) serial; - hash = hash_serial(key); - return (tmgraphnode*) *PL_HashTableRawLookup(tmr->filenames, hash, key); -} - -tmgraphnode *tmreader_component(tmreader *tmr, const char *name) -{ - PLHashNumber hash; - - hash = PL_HashString(name); - return (tmgraphnode*) *PL_HashTableRawLookup(tmr->components, hash, name); -} - -tmmethodnode *tmreader_method(tmreader *tmr, uint32_t serial) -{ - const void *key; - PLHashNumber hash; - - key = (const void*) (uintptr_t) serial; - hash = hash_serial(key); - return (tmmethodnode*) *PL_HashTableRawLookup(tmr->methods, hash, key); -} - -tmcallsite *tmreader_callsite(tmreader *tmr, uint32_t serial) -{ - const void *key; - PLHashNumber hash; - - key = (const void*) (uintptr_t) serial; - hash = hash_serial(key); - return (tmcallsite*) *PL_HashTableRawLookup(tmr->callsites, hash, key); -} - -int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to, tmcallsite *site) -{ - tmgraphlink *outlink; - tmgraphedge *edge; - - for (outlink = from->out; outlink; outlink = outlink->next) { - if (outlink->node == to) { - /* - * Say the stack looks like this: ... => JS => js => JS => js. - * We must avoid overcounting JS=>js because the first edge total - * includes the second JS=>js edge's total (which is because the - * lower site's total includes all its kids' totals). - */ - edge = TM_LINK_TO_EDGE(outlink, TM_EDGE_OUT_LINK); - if (!to->low || to->low < from->low) { - /* Add the direct and total counts to edge->allocs. */ - edge->allocs.bytes.direct += site->allocs.bytes.direct; - edge->allocs.bytes.total += site->allocs.bytes.total; - edge->allocs.calls.direct += site->allocs.calls.direct; - edge->allocs.calls.total += site->allocs.calls.total; - - /* Now update the free counts. */ - edge->frees.bytes.direct += site->frees.bytes.direct; - edge->frees.bytes.total += site->frees.bytes.total; - edge->frees.calls.direct += site->frees.calls.direct; - edge->frees.calls.total += site->frees.calls.total; - } - return 1; - } - } - - edge = (tmgraphedge*) malloc(sizeof(tmgraphedge)); - if (!edge) - return 0; - edge->links[TM_EDGE_OUT_LINK].node = to; - edge->links[TM_EDGE_OUT_LINK].next = from->out; - from->out = &edge->links[TM_EDGE_OUT_LINK]; - edge->links[TM_EDGE_IN_LINK].node = from; - edge->links[TM_EDGE_IN_LINK].next = to->in; - to->in = &edge->links[TM_EDGE_IN_LINK]; - edge->allocs = site->allocs; - edge->frees = site->frees; - return 1; -} diff --git a/tools/trace-malloc/tmreader.h b/tools/trace-malloc/tmreader.h deleted file mode 100644 index 6e4dc757f607..000000000000 --- a/tools/trace-malloc/tmreader.h +++ /dev/null @@ -1,191 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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 tmreader_h___ -#define tmreader_h___ - -#include "plhash.h" -#include "nsTraceMalloc.h" -#include "plarena.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct tmreader tmreader; -typedef struct tmevent tmevent; -typedef struct tmcounts tmcounts; -typedef struct tmallcounts tmallcounts; -typedef struct tmgraphlink tmgraphlink; -typedef struct tmgraphedge tmgraphedge; -typedef struct tmgraphnode tmgraphnode; -typedef struct tmcallsite tmcallsite; -typedef struct tmmethodnode tmmethodnode; - -struct tmevent { - char type; - uint32_t serial; - union { - char *libname; - char *srcname; - struct { - uint32_t library; - uint32_t filename; - uint32_t linenumber; - char *name; - } method; - struct { - uint32_t parent; - uint32_t method; - uint32_t offset; - } site; - struct { - uint32_t interval; /* in ticks */ - uint32_t ptr; - uint32_t size; - uint32_t oldserial; - uint32_t oldptr; - uint32_t oldsize; - uint32_t cost; /* in ticks */ - } alloc; - struct { - nsTMStats tmstats; - uint32_t calltree_maxkids_parent; - uint32_t calltree_maxstack_top; - } stats; - } u; -}; - -struct tmcounts { - uint32_t direct; /* things allocated by this node's code */ - uint32_t total; /* direct + things from all descendents */ -}; - -struct tmallcounts { - tmcounts bytes; - tmcounts calls; -}; - -struct tmgraphnode { - PLHashEntry entry; /* key is serial or name, value must be name */ - tmgraphlink *in; - tmgraphlink *out; - tmgraphnode *up; /* parent in supergraph, e.g., JS for JS_*() */ - tmgraphnode *down; /* subgraph kids, declining bytes.total order */ - tmgraphnode *next; /* next kid in supergraph node's down list */ - int low; /* 0 or lowest current tree walk level */ - tmallcounts allocs; - tmallcounts frees; - double sqsum; /* sum of squared bytes.direct */ - int sort; /* sorted index in node table, -1 if no table */ -}; - -struct tmmethodnode { - tmgraphnode graphnode; - char *sourcefile; - uint32_t linenumber; -}; - -#define tmgraphnode_name(node) ((char*) (node)->entry.value) -#define tmmethodnode_name(node) ((char*) (node)->graphnode.entry.value) - -#define tmlibrary_serial(lib) ((uint32_t) (lib)->entry.key) -#define tmcomponent_name(comp) ((const char*) (comp)->entry.key) -#define filename_name(hashentry) ((char*)hashentry->value) - -/* Half a graphedge, not including per-edge allocation stats. */ -struct tmgraphlink { - tmgraphlink *next; /* next fanning out from or into a node */ - tmgraphnode *node; /* the other node (to if OUT, from if IN) */ -}; - -/* - * It's safe to downcast a "from" tmgraphlink (one linked from a node's out - * pointer) to tmgraphedge. To go from an "out" (linked via tmgraphedge.from) - * or "in" (linked via tmgraphedge.to) list link to its containing edge, use - * TM_LINK_TO_EDGE(link, which). - */ -struct tmgraphedge { - tmgraphlink links[2]; - tmallcounts allocs; - tmallcounts frees; -}; - -/* Indices into tmgraphedge.links -- out must come first. */ -#define TM_EDGE_OUT_LINK 0 -#define TM_EDGE_IN_LINK 1 - -#define TM_LINK_TO_EDGE(link,which) ((tmgraphedge*) &(link)[-(which)]) - -struct tmcallsite { - PLHashEntry entry; /* key is site serial number */ - tmcallsite *parent; /* calling site */ - tmcallsite *siblings; /* other sites reached from parent */ - tmcallsite *kids; /* sites reached from here */ - tmmethodnode *method; /* method node in tmr->methods graph */ - uint32_t offset; /* pc offset from start of method */ - tmallcounts allocs; - tmallcounts frees; - void *data; /* tmreader clients can stick arbitrary - * data onto a callsite. - */ -}; - -struct tmreader { - const char *program; - void *data; - PLHashTable *libraries; - PLHashTable *filenames; - PLHashTable *components; - PLHashTable *methods; - PLHashTable *callsites; - PLArenaPool arena; - tmcallsite calltree_root; - uint32_t ticksPerSec; -}; - -typedef void (*tmeventhandler)(tmreader *tmr, tmevent *event); - -/* The tmreader constructor and destructor. */ -extern tmreader *tmreader_new(const char *program, void *data); -extern void tmreader_destroy(tmreader *tmr); - -/* - * Return -1 on permanent fatal error, 0 if filename can't be opened or is not - * a trace-malloc logfile, and 1 on success. - */ -extern int tmreader_eventloop(tmreader *tmr, const char *filename, - tmeventhandler eventhandler); - -/* Map serial number or name to graphnode or callsite. */ -extern tmgraphnode *tmreader_library(tmreader *tmr, uint32_t serial); -extern tmgraphnode *tmreader_filename(tmreader *tmr, uint32_t serial); -extern tmgraphnode *tmreader_component(tmreader *tmr, const char *name); -extern tmmethodnode *tmreader_method(tmreader *tmr, uint32_t serial); -extern tmcallsite *tmreader_callsite(tmreader *tmr, uint32_t serial); - -/* - * Connect node 'from' to node 'to' with an edge, if there isn't one already - * connecting the nodes. Add site's allocation stats to the edge only if we - * create the edge, or if we find that it exists, but that to->low is zero or - * less than from->low. - * - * If the callsite tree already totals allocation costs (tmcounts.total for - * each site includes tmcounts.direct for that site, plus tmcounts.total for - * all kid sites), then the node->low watermarks should be set from the tree - * level when walking the callsite tree, and should be set to non-zero values - * only if zero (the root is at level 0). A low watermark should be cleared - * when the tree walk unwinds past the level at which it was set non-zero. - * - * Return 0 on error (malloc failure) and 1 on success. - */ -extern int tmgraphnode_connect(tmgraphnode *from, tmgraphnode *to, - tmcallsite *site); - -#ifdef __cplusplus -} -#endif - -#endif /* tmreader_h___ */ diff --git a/tools/trace-malloc/tmstats.c b/tools/trace-malloc/tmstats.c deleted file mode 100644 index f97a07dad0a3..000000000000 --- a/tools/trace-malloc/tmstats.c +++ /dev/null @@ -1,830 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- - * - * 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/. */ - -#include -#include -#include -#include -#include -#include -#include - -#include "nspr.h" -#include "tmreader.h" - -#define ERROR_REPORT(num, val, msg) fprintf(stderr, "error(%d):\t\"%s\"\t%s\n", (num), (val), (msg)); -#define CLEANUP(ptr) do { if(NULL != ptr) { free(ptr); ptr = NULL; } } while(0) - - -#define COST_RESOLUTION 1000 -#define COST_PRINTABLE(cost) ((double)(cost) / (double)COST_RESOLUTION) - - -typedef struct __struct_Options -/* -** Options to control how we perform. -** -** mProgramName Used in help text. -** mInputName Name of the file. -** mOutput Output file, append. -** Default is stdout. -** mOutputName Name of the file. -** mHelp Whether or not help should be shown. -** mOverhead How much overhead an allocation will have. -** mAlignment What boundry will the end of an allocation line up on. -** mAverages Whether or not to display averages. -** mDeviances Whether or not to display standard deviations. -** mRunLength Whether or not to display run length. -*/ -{ - const char* mProgramName; - char* mInputName; - FILE* mOutput; - char* mOutputName; - int mHelp; - unsigned mOverhead; - unsigned mAlignment; - int mAverages; - int mDeviances; - int mRunLength; -} -Options; - - -typedef struct __struct_Switch -/* -** Command line options. -*/ -{ - const char* mLongName; - const char* mShortName; - int mHasValue; - const char* mValue; - const char* mDescription; -} -Switch; - -#define DESC_NEWLINE "\n\t\t" - -static Switch gInputSwitch = {"--input", "-i", 1, NULL, "Specify input file." DESC_NEWLINE "stdin is default."}; -static Switch gOutputSwitch = {"--output", "-o", 1, NULL, "Specify output file." DESC_NEWLINE "Appends if file exists." DESC_NEWLINE "stdout is default."}; -static Switch gHelpSwitch = {"--help", "-h", 0, NULL, "Information on usage."}; -static Switch gAlignmentSwitch = {"--alignment", "-al", 1, NULL, "All allocation sizes are made to be a multiple of this number." DESC_NEWLINE "Closer to actual heap conditions; set to 1 for true sizes." DESC_NEWLINE "Default value is 16."}; -static Switch gOverheadSwitch = {"--overhead", "-ov", 1, NULL, "After alignment, all allocations are made to increase by this number." DESC_NEWLINE "Closer to actual heap conditions; set to 0 for true sizes." DESC_NEWLINE "Default value is 8."}; -static Switch gAveragesSwitch = {"--averages", "-avg", 0, NULL, "Display averages."}; -static Switch gDeviationsSwitch = {"--deviations", "-dev", 0, NULL, "Display standard deviations from the average." DESC_NEWLINE "Implies --averages."}; -static Switch gRunLengthSwitch = {"--run-length", "-rl", 0, NULL, "Display the run length in seconds."}; - -static Switch* gSwitches[] = { - &gInputSwitch, - &gOutputSwitch, - &gAlignmentSwitch, - &gOverheadSwitch, - &gAveragesSwitch, - &gDeviationsSwitch, - &gRunLengthSwitch, - &gHelpSwitch -}; - - -typedef struct _struct_VarianceState -/* -** State for a single pass variance calculation. -*/ -{ - unsigned mCount; - uint64_t mSum; - uint64_t mSquaredSum; -} -VarianceState; - - -typedef struct __struct_TMStats -/* -** Stats we are trying to calculate. -** -** mOptions Obilgatory options pointer. -** uMemoryInUse Current tally of memory in use. -** uPeakMemory Heap topped out at this byte level. -** uObjectsInUse Different allocations outstanding. -** uPeakObjects Highest object count. -** uMallocs Number of malloc calls. -** uCallocs Number of calloc calls. -** uReallocs Number of realloc calls. -** uFrees Number of free calls. -** uMallocSize Bytes from malloc. -** uCallocSize Bytes from calloc. -** uReallocSize Bytes from realloc. -** uFreeSize Bytes from free. -** mMallocSizeVar Variance of bytes. -** mCallocSizeVar Variance of bytes. -** mReallocSizeVar Variance of bytes. -** mFreeSizeVar Variance of bytes. -** uMallocCost Time of mallocs. -** uCallocCost Time of callocs. -** uReallocCost Time of reallocs. -** uFreeCost Time of frees. -** mMallocCostVar Variance of cost. -** mCallocCostVar Variance of cost. -** mReallocCostVar Variance of cost. -** mFreeCostVar Variance of cost. -** uMinTicks Start of run. -** uMaxTicks End of run. -*/ -{ - Options* mOptions; - unsigned uMemoryInUse; - unsigned uPeakMemory; - unsigned uObjectsInUse; - unsigned uPeakObjects; - unsigned uMallocs; - unsigned uCallocs; - unsigned uReallocs; - unsigned uFrees; - - unsigned uMallocSize; - unsigned uCallocSize; - unsigned uReallocSize; - unsigned uFreeSize; - VarianceState mMallocSizeVar; - VarianceState mCallocSizeVar; - VarianceState mReallocSizeVar; - VarianceState mFreeSizeVar; - - unsigned uMallocCost; - unsigned uCallocCost; - unsigned uReallocCost; - unsigned uFreeCost; - VarianceState mMallocCostVar; - VarianceState mCallocCostVar; - VarianceState mReallocCostVar; - VarianceState mFreeCostVar; - - unsigned uMinTicks; - unsigned uMaxTicks; -} -TMStats; - - -int initOptions(Options* outOptions, int inArgc, char** inArgv) -/* -** returns int 0 if successful. -*/ -{ - int retval = 0; - int loop = 0; - int switchLoop = 0; - int match = 0; - const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]); - Switch* current = NULL; - - /* - ** Set any defaults. - */ - memset(outOptions, 0, sizeof(Options)); - outOptions->mProgramName = inArgv[0]; - outOptions->mInputName = strdup("-"); - outOptions->mOutput = stdout; - outOptions->mOutputName = strdup("stdout"); - outOptions->mAlignment = 16; - outOptions->mOverhead = 8; - - if(NULL == outOptions->mOutputName || NULL == outOptions->mInputName) - { - retval = __LINE__; - ERROR_REPORT(retval, "stdin/stdout", "Unable to strdup."); - } - - /* - ** Go through and attempt to do the right thing. - */ - for(loop = 1; loop < inArgc && 0 == retval; loop++) - { - match = 0; - current = NULL; - - for(switchLoop = 0; switchLoop < switchCount && 0 == retval; switchLoop++) - { - if(0 == strcmp(gSwitches[switchLoop]->mLongName, inArgv[loop])) - { - match = __LINE__; - } - else if(0 == strcmp(gSwitches[switchLoop]->mShortName, inArgv[loop])) - { - match = __LINE__; - } - - if(match) - { - if(gSwitches[switchLoop]->mHasValue) - { - /* - ** Attempt to absorb next option to fullfill value. - */ - if(loop + 1 < inArgc) - { - loop++; - - current = gSwitches[switchLoop]; - current->mValue = inArgv[loop]; - } - } - else - { - current = gSwitches[switchLoop]; - } - - break; - } - } - - if(0 == match) - { - outOptions->mHelp = __LINE__; - retval = __LINE__; - ERROR_REPORT(retval, inArgv[loop], "Unknown command line switch."); - } - else if(NULL == current) - { - outOptions->mHelp = __LINE__; - retval = __LINE__; - ERROR_REPORT(retval, inArgv[loop], "Command line switch requires a value."); - } - else - { - /* - ** Do something based on address/swtich. - */ - if(current == &gInputSwitch) - { - CLEANUP(outOptions->mInputName); - outOptions->mInputName = strdup(current->mValue); - if(NULL == outOptions->mInputName) - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to strdup."); - } - } - else if(current == &gOutputSwitch) - { - CLEANUP(outOptions->mOutputName); - if(NULL != outOptions->mOutput && stdout != outOptions->mOutput) - { - fclose(outOptions->mOutput); - outOptions->mOutput = NULL; - } - - outOptions->mOutput = fopen(current->mValue, "a"); - if(NULL == outOptions->mOutput) - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to open output file."); - } - else - { - outOptions->mOutputName = strdup(current->mValue); - if(NULL == outOptions->mOutputName) - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to strdup."); - } - } - } - else if(current == &gHelpSwitch) - { - outOptions->mHelp = __LINE__; - } - else if(current == &gAlignmentSwitch) - { - unsigned arg = 0; - char* endScan = NULL; - - errno = 0; - arg = strtoul(current->mValue, &endScan, 0); - if(0 == errno && endScan != current->mValue) - { - outOptions->mAlignment = arg; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); - } - } - else if(current == &gOverheadSwitch) - { - unsigned arg = 0; - char* endScan = NULL; - - errno = 0; - arg = strtoul(current->mValue, &endScan, 0); - if(0 == errno && endScan != current->mValue) - { - outOptions->mOverhead = arg; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mValue, "Unable to convert to a number."); - } - } - else if(current == &gAveragesSwitch) - { - outOptions->mAverages = __LINE__; - } - else if(current == &gDeviationsSwitch) - { - outOptions->mAverages = __LINE__; - outOptions->mDeviances = __LINE__; - } - else if(current == &gRunLengthSwitch) - { - outOptions->mRunLength = __LINE__; - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, current->mLongName, "No handler for command line switch."); - } - } - } - - return retval; -} - - -void cleanOptions(Options* inOptions) -/* -** Clean up any open handles. -*/ -{ - unsigned loop = 0; - - CLEANUP(inOptions->mInputName); - CLEANUP(inOptions->mOutputName); - if(NULL != inOptions->mOutput && stdout != inOptions->mOutput) - { - fclose(inOptions->mOutput); - } - - memset(inOptions, 0, sizeof(Options)); -} - - -void showHelp(Options* inOptions) -/* -** Show some simple help text on usage. -*/ -{ - int loop = 0; - const int switchCount = sizeof(gSwitches) / sizeof(gSwitches[0]); - const char* valueText = NULL; - - printf("usage:\t%s [arguments]\n", inOptions->mProgramName); - printf("\n"); - printf("arguments:\n"); - - for(loop = 0; loop < switchCount; loop++) - { - if(gSwitches[loop]->mHasValue) - { - valueText = " "; - } - else - { - valueText = ""; - } - - printf("\t%s%s\n", gSwitches[loop]->mLongName, valueText); - printf("\t %s%s", gSwitches[loop]->mShortName, valueText); - printf(DESC_NEWLINE "%s\n\n", gSwitches[loop]->mDescription); - } - - printf("This tool reports simple heap usage and allocation call counts.\n"); - printf("Useful for eyeballing trace-malloc numbers quickly.\n"); -} - - -void addVariance(VarianceState* inVariance, unsigned inValue) -/* -** Add a value to a variance state. -*/ -{ - uint64_t squared; - uint64_t bigValue; - - bigValue = inValue; - inVariance->mSum += bigValue; - - squared = bigValue * bigValue; - inVariance->mSquaredSum += squared; - - inVariance->mCount++; -} - - -double getAverage(VarianceState* inVariance) -/* -** Determine the mean/average based on the given state. -*/ -{ - double retval = 0.0; - - if(NULL != inVariance && 0 < inVariance->mCount) - { - double count; - int64_t isum; - - /* - ** Avoids a compiler error (not impl) under MSVC. - */ - isum = inVariance->mSum; - - count = (double)inVariance->mCount; - - retval = (double)isum / count; - } - - return retval; -} - - -double getVariance(VarianceState* inVariance) -/* -** Determine the variance based on the given state. -*/ -{ - double retval = 0.0; - - if(NULL != inVariance && 1 < inVariance->mCount) - { - double count; - double avg; - double squaredAvg; - int64_t isquaredSum; - - /* - ** Avoids a compiler error (not impl) under MSVC. - */ - isquaredSum = inVariance->mSquaredSum; - - count = (double)inVariance->mCount; - - avg = getAverage(inVariance); - squaredAvg = avg * avg; - - retval = ((double)isquaredSum - (count * squaredAvg)) / (count - 1.0); - } - - return retval; -} - - -double getStdDev(VarianceState* inVariance) -/* -** Determine the standard deviation based on the given state. -*/ -{ - double retval = 0.0; - double variance; - - variance = getVariance(inVariance); - retval = sqrt(variance); - - return retval; -} - - -unsigned actualByteSize(Options* inOptions, unsigned retval) -/* -** Apply alignment and overhead to size to figure out actual byte size. -** This by default mimics spacetrace with default options (msvc crt heap). -*/ -{ - if(0 != retval) - { - unsigned eval = 0; - unsigned over = 0; - - eval = retval - 1; - if(0 != inOptions->mAlignment) - { - over = eval % inOptions->mAlignment; - } - retval = eval + inOptions->mOverhead + inOptions->mAlignment - over; - } - - return retval; -} - - -uint32_t ticks2xsec(tmreader* aReader, uint32_t aTicks, uint32_t aResolution) -/* -** Convert platform specific ticks to second units -** Returns 0 on success. -*/ -{ - return (uint32_t)((aResolution * aTicks) / aReader->ticksPerSec); -} -#define ticks2msec(reader, ticks) ticks2xsec((reader), (ticks), 1000) - - -void tmEventHandler(tmreader* inReader, tmevent* inEvent) -/* -** Callback from the tmreader_eventloop. -** Keep it simple in here, this is where we'll spend the most time. -** The goal is to be fast. -*/ -{ - TMStats* stats = (TMStats*)inReader->data; - Options* options = (Options*)stats->mOptions; - char type = inEvent->type; - unsigned size = inEvent->u.alloc.size; - unsigned actualSize = 0; - unsigned actualOldSize = 0; - uint32_t interval = 0; - - /* - ** To match spacetrace stats, reallocs of size zero are frees. - ** Adjust the size to match what free expects. - */ - if(TM_EVENT_REALLOC == type && 0 == size) - { - type = TM_EVENT_FREE; - if(0 != inEvent->u.alloc.oldserial) - { - size = inEvent->u.alloc.oldsize; - } - } - - /* - ** Adjust the size due to the options. - */ - actualSize = actualByteSize(options, size); - if(TM_EVENT_REALLOC == type && 0 != inEvent->u.alloc.oldserial) - { - actualOldSize = actualByteSize(options, inEvent->u.alloc.oldsize); - } - - /* - ** Modify event specific data. - */ - switch(type) - { - case TM_EVENT_MALLOC: - stats->uMallocs++; - stats->uMallocSize += actualSize; - stats->uMallocCost += ticks2msec(inReader, inEvent->u.alloc.cost); - stats->uMemoryInUse += actualSize; - stats->uObjectsInUse++; - - addVariance(&stats->mMallocSizeVar, actualSize); - addVariance(&stats->mMallocCostVar, inEvent->u.alloc.cost); - break; - - case TM_EVENT_CALLOC: - stats->uCallocs++; - stats->uCallocSize += actualSize; - stats->uCallocCost += ticks2msec(inReader, inEvent->u.alloc.cost); - stats->uMemoryInUse += actualSize; - stats->uObjectsInUse++; - - addVariance(&stats->mCallocSizeVar, actualSize); - addVariance(&stats->mCallocCostVar, inEvent->u.alloc.cost); - break; - - case TM_EVENT_REALLOC: - stats->uReallocs++; - stats->uReallocSize -= actualOldSize; - stats->uReallocSize += actualSize; - stats->uReallocCost += ticks2msec(inReader, inEvent->u.alloc.cost); - stats->uMemoryInUse -= actualOldSize; - stats->uMemoryInUse += actualSize; - if(0 == inEvent->u.alloc.oldserial) - { - stats->uObjectsInUse++; - } - - if(actualSize > actualOldSize) - { - addVariance(&stats->mReallocSizeVar, actualSize - actualOldSize); - } - else - { - addVariance(&stats->mReallocSizeVar, actualOldSize - actualSize); - } - addVariance(&stats->mReallocCostVar, inEvent->u.alloc.cost); - break; - - case TM_EVENT_FREE: - stats->uFrees++; - stats->uFreeSize += actualSize; - stats->uFreeCost += ticks2msec(inReader, inEvent->u.alloc.cost); - stats->uMemoryInUse -= actualSize; - stats->uObjectsInUse--; - - addVariance(&stats->mFreeSizeVar, actualSize); - addVariance(&stats->mFreeCostVar, inEvent->u.alloc.cost); - break; - - default: - /* - ** Don't care. - */ - break; - } - - switch(type) - { - case TM_EVENT_MALLOC: - case TM_EVENT_CALLOC: - case TM_EVENT_REALLOC: - /* - ** Check the peaks. - */ - if(stats->uMemoryInUse > stats->uPeakMemory) - { - stats->uPeakMemory = stats->uMemoryInUse; - } - if(stats->uObjectsInUse > stats->uPeakObjects) - { - stats->uPeakObjects = stats->uObjectsInUse; - } - - /* - ** Falling through. - */ - - case TM_EVENT_FREE: - /* - ** Check the overall time. - */ - interval = ticks2msec(inReader, inEvent->u.alloc.interval); - if(stats->uMinTicks > interval) - { - stats->uMinTicks = interval; - } - if(stats->uMaxTicks < interval) - { - stats->uMaxTicks = interval; - } - break; - - default: - /* - ** Don't care. - */ - break; - } - -} - -int report_stats(Options* inOptions, TMStats* inStats) -{ - int retval = 0; - - fprintf(inOptions->mOutput, "Peak Memory Usage: %11d\n", inStats->uPeakMemory); - fprintf(inOptions->mOutput, "Memory Leaked: %11d\n", inStats->uMemoryInUse); - fprintf(inOptions->mOutput, "\n"); - - fprintf(inOptions->mOutput, "Peak Object Count: %11d\n", inStats->uPeakObjects); - fprintf(inOptions->mOutput, "Objects Leaked: %11d\n", inStats->uObjectsInUse); - if(0 != inOptions->mAverages && 0 != inStats->uObjectsInUse) - { - fprintf(inOptions->mOutput, "Average Leaked Object Size: %11.4f\n", (double)inStats->uMemoryInUse / (double)inStats->uObjectsInUse); - } - fprintf(inOptions->mOutput, "\n"); - - fprintf(inOptions->mOutput, "Call Total: %11d\n", inStats->uMallocs + inStats->uCallocs + inStats->uReallocs + inStats->uFrees); - fprintf(inOptions->mOutput, " malloc: %11d\n", inStats->uMallocs); - fprintf(inOptions->mOutput, " calloc: %11d\n", inStats->uCallocs); - fprintf(inOptions->mOutput, " realloc: %11d\n", inStats->uReallocs); - fprintf(inOptions->mOutput, " free: %11d\n", inStats->uFrees); - fprintf(inOptions->mOutput, "\n"); - - fprintf(inOptions->mOutput, "Byte Total (sans free): %11d\n", inStats->uMallocSize + inStats->uCallocSize + inStats->uReallocSize); - fprintf(inOptions->mOutput, " malloc: %11d\n", inStats->uMallocSize); - fprintf(inOptions->mOutput, " calloc: %11d\n", inStats->uCallocSize); - fprintf(inOptions->mOutput, " realloc: %11d\n", inStats->uReallocSize); - fprintf(inOptions->mOutput, " free: %11d\n", inStats->uFreeSize); - if(0 != inOptions->mAverages) - { - fprintf(inOptions->mOutput, "Byte Averages:\n"); - fprintf(inOptions->mOutput, " malloc: %11.4f\n", getAverage(&inStats->mMallocSizeVar)); - fprintf(inOptions->mOutput, " calloc: %11.4f\n", getAverage(&inStats->mCallocSizeVar)); - fprintf(inOptions->mOutput, " realloc: %11.4f\n", getAverage(&inStats->mReallocSizeVar)); - fprintf(inOptions->mOutput, " free: %11.4f\n", getAverage(&inStats->mFreeSizeVar)); - } - if(0 != inOptions->mDeviances) - { - fprintf(inOptions->mOutput, "Byte Standard Deviations:\n"); - fprintf(inOptions->mOutput, " malloc: %11.4f\n", getStdDev(&inStats->mMallocSizeVar)); - fprintf(inOptions->mOutput, " calloc: %11.4f\n", getStdDev(&inStats->mCallocSizeVar)); - fprintf(inOptions->mOutput, " realloc: %11.4f\n", getStdDev(&inStats->mReallocSizeVar)); - fprintf(inOptions->mOutput, " free: %11.4f\n", getStdDev(&inStats->mFreeSizeVar)); - } - fprintf(inOptions->mOutput, "\n"); - - fprintf(inOptions->mOutput, "Overhead Total: %11.4f\n", COST_PRINTABLE(inStats->uMallocCost) + COST_PRINTABLE(inStats->uCallocCost) + COST_PRINTABLE(inStats->uReallocCost) + COST_PRINTABLE(inStats->uFreeCost)); - fprintf(inOptions->mOutput, " malloc: %11.4f\n", COST_PRINTABLE(inStats->uMallocCost)); - fprintf(inOptions->mOutput, " calloc: %11.4f\n", COST_PRINTABLE(inStats->uCallocCost)); - fprintf(inOptions->mOutput, " realloc: %11.4f\n", COST_PRINTABLE(inStats->uReallocCost)); - fprintf(inOptions->mOutput, " free: %11.4f\n", COST_PRINTABLE(inStats->uFreeCost)); - if(0 != inOptions->mAverages) - { - fprintf(inOptions->mOutput, "Overhead Averages:\n"); - fprintf(inOptions->mOutput, " malloc: %11.4f\n", COST_PRINTABLE(getAverage(&inStats->mMallocCostVar))); - fprintf(inOptions->mOutput, " calloc: %11.4f\n", COST_PRINTABLE(getAverage(&inStats->mCallocCostVar))); - fprintf(inOptions->mOutput, " realloc: %11.4f\n", COST_PRINTABLE(getAverage(&inStats->mReallocCostVar))); - fprintf(inOptions->mOutput, " free: %11.4f\n", COST_PRINTABLE(getAverage(&inStats->mFreeCostVar))); - } - if(0 != inOptions->mDeviances) - { - fprintf(inOptions->mOutput, "Overhead Standard Deviations:\n"); - fprintf(inOptions->mOutput, " malloc: %11.4f\n", COST_PRINTABLE(getStdDev(&inStats->mMallocCostVar))); - fprintf(inOptions->mOutput, " calloc: %11.4f\n", COST_PRINTABLE(getStdDev(&inStats->mCallocCostVar))); - fprintf(inOptions->mOutput, " realloc: %11.4f\n", COST_PRINTABLE(getStdDev(&inStats->mReallocCostVar))); - fprintf(inOptions->mOutput, " free: %11.4f\n", COST_PRINTABLE(getStdDev(&inStats->mFreeCostVar))); - } - fprintf(inOptions->mOutput, "\n"); - - if(0 != inOptions->mRunLength) - { - unsigned length = inStats->uMaxTicks - inStats->uMinTicks; - - fprintf(inOptions->mOutput, "Run Length: %11.4f\n", COST_PRINTABLE(length)); - fprintf(inOptions->mOutput, "\n"); - } - - return retval; -} - - -int tmstats(Options* inOptions) -/* -** As quick as possible, load the input file and report stats. -*/ -{ - int retval = 0; - tmreader* tmr = NULL; - TMStats stats; - - memset(&stats, 0, sizeof(stats)); - stats.mOptions = inOptions; - stats.uMinTicks = 0xFFFFFFFFU; - - /* - ** Need a tmreader. - */ - tmr = tmreader_new(inOptions->mProgramName, &stats); - if(NULL != tmr) - { - int tmResult = 0; - - tmResult = tmreader_eventloop(tmr, inOptions->mInputName, tmEventHandler); - if(0 == tmResult) - { - retval = __LINE__; - ERROR_REPORT(retval, inOptions->mInputName, "Problem reading trace-malloc data."); - } - - tmreader_destroy(tmr); - tmr = NULL; - - if(0 == retval) - { - retval = report_stats(inOptions, &stats); - } - } - else - { - retval = __LINE__; - ERROR_REPORT(retval, inOptions->mProgramName, "Unable to obtain tmreader."); - } - - return retval; -} - - -int main(int inArgc, char** inArgv) -{ - int retval = 0; - Options options; - - retval = initOptions(&options, inArgc, inArgv); - if(options.mHelp) - { - showHelp(&options); - } - else if(0 == retval) - { - retval = tmstats(&options); - } - - cleanOptions(&options); - return retval; -} - diff --git a/tools/trace-malloc/types.dat b/tools/trace-malloc/types.dat deleted file mode 100644 index ba0a0e4defe3..000000000000 --- a/tools/trace-malloc/types.dat +++ /dev/null @@ -1,5842 +0,0 @@ -# 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/. - -# This file contains type inference information that is intended to be -# used with TraceMalloc.pm. The format of the file is: -# -# -# Stack1 -# Stack2 -# ... -# StackN -# -# Where Stack1...StackN imply that the object's type is -# InferredType. Note that in many cases, we'll ``roll up'' storage -# that's part of an object's implementation into the object itself. - -# Here's a handy regexp for cleaning up strings copied from the -# uncategorized file: -# -# \(^ *([0-9]+) \|\[.*\]$\) -# - -#---------------------------------------------------------------------- - - -__builtin_new -__builtin_vec_new -nsDeque::GrowCapacity(void) -nsDeque::Push(void *) -nsStringRecycler::Recycle(nsString *) - -#---------------------------------------------------------------------- -# -# AtomImpl -# - -# Give AtomImpl objects the memory they allocate for storage - -__builtin_new -AtomImpl::operator new(unsigned int, basic_nsAReadableString const &) - -# Give AtomImpl objects the memory allocated for their table - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -NS_NewPermanentAtom(char const *) -NS_NewAtom(nsAString const &) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -NS_NewAtom(nsAString const &) -NS_NewAtom(char const *) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -NS_NewAtom(nsAString const &) -NS_NewAtom(unsigned short const *) - -#---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsString::nsString(nsString const &) -nsAttrSelector::nsAttrSelector(nsAttrSelector const &) -nsCSSSelector::nsCSSSelector(nsCSSSelector const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsString::nsString(nsString const &) -nsAttrSelector::nsAttrSelector(nsAttrSelector const &) -nsAttrSelector::nsAttrSelector(nsAttrSelector const &) -nsCSSSelector::nsCSSSelector(nsCSSSelector const &) - - -__builtin_new -nsCSSRule::operator new(unsigned int) - -#---------------------------------------------------------------------- -# -# CSSLoaderImpl -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -CSSLoaderImpl::CSSLoaderImpl(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsString::AppendWithConversion(char const *, int) -nsString::AssignWithConversion(char const *) -CSSLoaderImpl::SetCharset(nsString const &) - - -PL_strdup -URLKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -CSSLoaderImpl::SheetComplete(nsICSSStyleSheet *, SheetLoadData *) - -#---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -CSSNameSpaceRuleImpl::SetURLSpec(nsString const &) - -#---------------------------------------------------------------------- -# -# nsFont -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsString::nsString(nsString const &) -nsFont::nsFont(nsFont const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsString::AppendWithConversion(char const *, int) -nsString::AssignWithConversion(char const *) -nsFont::nsFont(char const *, unsigned char, unsigned char, unsigned short, unsigned char, int, float) - -#---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -CSSImportRuleImpl::SetURLSpec(nsString const &) - - -__builtin_new -nsClassList::ParseClasses(nsClassList **, basic_nsAReadableString const &) - -# ---------------------------------------------------------------------- -# -# nsLocalFile -# - - -__builtin_new -nsLocalFile::Clone(nsIFile **) - - -PR_Malloc -_PR_Getfd -PR_GetConnectStatus -PR_OpenFile -PR_Open -nsLocalFile::OpenNSPRFileDesc(int, int, PRFileDesc **) - - -PR_Calloc -PR_LoadLibrary -PR_LoadLibraryWithFlags -PR_LoadLibrary -nsLocalFile::Load(PRLibrary **) - - -__strdup -PR_LoadLibrary -PR_LoadLibraryWithFlags -PR_LoadLibrary -nsLocalFile::Load(PRLibrary **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsACString const &) -nsLocalFile::AppendRelativePath(char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Clone(void const *, unsigned int) -nsLocalFile::InitWithPath(char const *) - - -PL_strdup -nsLocalFile::ParseURL(char const *, char **, char **, char **, char **) - -# ---------------------------------------------------------------------- - - -__builtin_new -nsXULAttribute::operator new(unsigned int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(nsAString const &, unsigned short *) -ToNewUnicode(nsAString const &) -nsXULAttributeValue::SetValue(nsAString const &, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsXULAttributeValue::SetValue(nsAString const &, int) - - -__builtin_new -nsXULAttributes::Create(nsIContent *, nsXULAttributes **) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -NS_NewAtom(nsAString const &) -NS_NewAtom(unsigned short const *) -nsClassList::ParseClasses(nsClassList **, nsAString const &) -nsXULAttributes::UpdateClassList(nsAString const &) - - -__builtin_new -nsXULElement::Create(nsINodeInfo *, nsIContent **) - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsXULElement::EnsureSlots(void) - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsXULElement::AppendChildTo(nsIContent *, int, int) - - -__builtin_new -nsXULElement::EnsureSlots(void) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsXULElement::AppendChildTo(nsIContent *, int, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsXULElement::EnsureSlots(void) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsXULElement::AddBroadcastListener(nsAString const &, nsIDOMElement *) - - -iconv_close - - -tsearch - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -CSSDeclarationImpl::AppendValue(nsCSSProperty, nsCSSValue const &) - - -__builtin_new -CSSDeclarationImpl::AppendValue(nsCSSProperty, nsCSSValue const &) - - -__builtin_new -CSSDeclarationImpl::SetValueImportant(nsCSSProperty) - - -__builtin_new -CSSDeclarationImpl::operator new(unsigned int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -CSSDeclarationImpl::AppendValue(nsCSSProperty, nsCSSValue const &) - - -__builtin_new -__builtin_vec_new -nsVoidArray::InsertElementAt(void *, int) - - -__builtin_new -__builtin_vec_new -nsVoidArray::nsVoidArray(int) - - -__builtin_new -__builtin_vec_new -nsVoidArray::Compact(void) - - -__builtin_new -__builtin_vec_new -nsVoidArray::ReplaceElementAt(void *, int) - - -__builtin_new -nsCheapVoidArray::SwitchToVector(void) -nsCheapVoidArray::AppendElement(void *) -nsGenericHTMLContainerElement::AppendChildTo(nsIContent *, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::Compact(void) -nsAutoVoidArray::Compact(void) -nsCheapVoidArray::Compact(void) -nsGenericHTMLContainerElement::Compact(void) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsCheapVoidArray::AppendElement(void *) -nsGenericHTMLContainerElement::AppendChildTo(nsIContent *, int, int) - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsCheapVoidArray::AppendElement(void *) -nsGenericHTMLContainerElement::AppendChildTo(nsIContent *, int, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsString::nsString(basic_nsAReadableString const &) -nsGenericAttribute::nsGenericAttribute(nsINodeInfo *, basic_nsAReadableString const &) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) - - -__builtin_new -nsSupportsArray::Create(nsISupports *, nsID const &, void **) - - -__builtin_new -__builtin_vec_new -nsZipArchive::BuildFileList(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsZipReaderCache::GetZip(nsIFile *, nsIZipReader **) - - -__builtin_new -__builtin_vec_new -InMemoryDataSource::AllocTable(void *, unsigned int) - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -InMemoryDataSource::LockedAssert(nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -InMemoryDataSource::InMemoryDataSource(nsISupports *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -InMemoryDataSource::AllocEntry(void *, void const *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -Assertion::operator new(unsigned int, nsFixedSizeAllocator &) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -InMemoryDataSource::AllocEntry(void *, void const *) -PL_HashTableRawAdd -PL_HashTableAdd -InMemoryDataSource::SetReverseArcs(nsIRDFNode *, Assertion *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -InMemoryDataSource::AllocEntry(void *, void const *) -PL_HashTableRawAdd -PL_HashTableAdd -InMemoryDataSource::SetForwardArcs(nsIRDFResource *, Assertion *) - - -PL_DHashAllocTable -PL_DHashTableInit -InMemoryDataSource::Init(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsString::nsString(nsAString const &) -nsNameSpaceMap::Put(nsAString const &, nsIAtom *) -RDFXMLDataSourceImpl::AddNameSpace(nsIAtom *, nsString const &) - - -__builtin_new -__builtin_vec_new -xptiTypelibGuts::xptiTypelibGuts(XPTHeader *) - -# ---------------------------------------------------------------------- -# -# nsPluginTag -# - - -__builtin_new -__builtin_vec_new -nsPluginTag::nsPluginTag(nsPluginInfo *) - - -__builtin_new -__builtin_vec_new -new_str(char const *) -nsPluginTag::nsPluginTag(nsPluginInfo *) - - -__builtin_new -__builtin_vec_new -nsPluginTag::nsPluginTag(char const *, char const *, char const *, char const *, char const *const *, char const *const *, char const *const *, int, long long) - - -__builtin_new -__builtin_vec_new -nsPluginTag::nsPluginTag(nsPluginTag *) - -#---------------------------------------------------------------------- -# -# nsXBLInsertionPoint -# - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsXBLInsertionPoint::AddChild(nsIContent *) - -#---------------------------------------------------------------------- -# -# nsXBLBinding -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLBinding::GetInsertionPointsFor(nsIContent *, nsISupportsArray **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXBLBinding::GetInsertionPointsFor(nsIContent *, nsISupportsArray **) - - -__builtin_new -nsXBLBinding::GetInsertionPointsFor(nsIContent *, nsISupportsArray **) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -NS_NewAtom(nsAString const &) -NS_NewAtom(char const *) -nsXBLBinding::nsXBLBinding(nsIXBLPrototypeBinding *) - -# ---------------------------------------------------------------------- -# -# nsXBLPrototypeBinding -# - - -__builtin_new -nsXBLPrototypeBinding::InitClass(nsCString const &, nsIScriptContext *, void *, void **) - - -__builtin_new -nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -js_LookupProperty -JS_DefinePropertyWithTinyId -JS_LookupProperty -nsXBLPrototypeBinding::InitClass(nsCString const &, nsIScriptContext *, void *, void **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsXBLPrototypeBinding::nsXBLPrototypeBinding(nsCString const &, nsIContent *, nsXBLDocumentInfo *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsXBLPrototypeBinding::nsXBLPrototypeBinding(basic_nsAReadableString const &, nsIContent *, nsXBLDocumentInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - - -__builtin_new -nsISupportsKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - - -__builtin_new -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsXBLPrototypeBinding::nsXBLPrototypeBinding(nsACString const &, nsXBLDocumentInfo *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsXBLPrototypeBinding::InitClass(nsCString const &, nsIScriptContext *, void *, void **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AssignFromReadable(nsACString const &) -nsACString::AssignFromReadable(nsACString const &) -nsCString::nsCString(nsACString const &) -nsXBLPrototypeBinding::nsXBLPrototypeBinding(nsACString const &, nsXBLDocumentInfo *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsACString const &) -nsXBLJSClass::nsXBLJSClass(nsCString const &) -nsXBLPrototypeBinding::InitClass(nsCString const &, nsIScriptContext *, void *, void **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsXBLPrototypeBinding::InitClass(nsCString const &, nsIScriptContext *, void *, void **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXBLPrototypeBinding::ConstructInsertionTable(nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXBLPrototypeBinding::ConstructInterfaceTable(nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsXBLAttributeEntry::Create(nsIAtom *, nsIAtom *, nsIContent *) -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - -#---------------------------------------------------------------------- -# -# -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsGenericContainerElement::GetAttr(int, nsIAtom *, nsIAtom *&, nsAString &) const -nsGenericContainerElement::GetAttr(int, nsIAtom *, nsAString &) const -nsXBLPrototypeProperty::ParseProperty(nsIScriptContext *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsGenericContainerElement::GetAttr(int, nsIAtom *, nsIAtom *&, nsAString &) const -nsGenericContainerElement::GetAttr(int, nsIAtom *, nsAString &) const -nsXBLPrototypeProperty::ParseMethod(nsIScriptContext *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsGenericContainerElement::GetAttr(int, nsIAtom *, nsIAtom *&, nsAString &) const -nsGenericContainerElement::GetAttr(int, nsIAtom *, nsAString &) const -nsXBLPrototypeProperty::ParseField(nsIScriptContext *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AppendFromReadable(nsAString const &) -nsAString::AppendFromReadable(nsAString const &) -nsXBLPrototypeProperty::ParseField(nsIScriptContext *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AppendFromReadable(nsACString const &) -nsACString::do_AppendFromElementPtr(char const *) -nsXBLPrototypeBinding::GetBindingURI(nsCString &) -nsXBLPrototypeProperty::ConstructProperty(nsIContent *, nsIContent *) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -js_AddRootRT -JS_AddNamedRootRT -NS_NewXBLPrototypeBinding(nsACString const &, nsIContent *, nsXBLDocumentInfo *, nsIXBLPrototypeBinding **) -nsXBLPrototypeProperty::ParseMethod(nsIScriptContext *) - -# ---------------------------------------------------------------------- -# -# The frame arena -# - - -PR_Malloc -PL_ArenaAllocate -FrameArena::AllocateFrame(unsigned int, void **) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocLeafNode(void) -nsDST::Insert(void *, void *, void **) -PresShell::SetSubShellFor(nsIContent *, nsISupports *) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -PresShell::AppendReflowCommandInternal(nsIReflowCommand *, nsVoidArray &) - -# The anonymous content table in the PresShell - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -PresShell::SetAnonymousContentFor(nsIContent *, nsISupportsArray *) - - -__builtin_new -nsISupportsKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -PresShell::SetAnonymousContentFor(nsIContent *, nsISupportsArray *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -PresShell::SetAnonymousContentFor(nsIContent *, nsISupportsArray *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -PresShell::SetAnonymousContentFor(nsIContent *, nsISupportsArray *) - -# ---------------------------------------------------------------------- -# -# StackArena -# - - -PR_Malloc -StackArena::StackArena(void) - - -PR_Malloc -StackArena::Allocate(unsigned int, void **) - - -PR_Malloc -StackBlock::StackBlock(void) -StackArena::StackArena(void) - - -__builtin_new -__builtin_vec_new -StackArena::StackArena(void) - - -PR_Malloc -StackArena::Allocate(unsigned int, void **) - -# The following will only show up if you turn off the FrameArena - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsBoxLayoutState::Allocate(unsigned int, nsIPresShell *) - - -# ---------------------------------------------------------------------- -# -# nsFrameManager -# - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocLeafNode(void) -nsDST::LeafNode::operator new(unsigned int, nsDST::NodeArena *) -nsDST::Insert(void *, void *, void **) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocTwoNode(void) -nsDST::ConvertToTwoNode(nsDST::LeafNode **) -nsDST::Insert(void *, void *, void **) -FrameManager::SetFrameProperty(nsIFrame *, nsIAtom *, void *, void (*)(nsIPresContext *, nsIFrame *, nsIAtom *, void *)) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocTwoNode(void) -nsDST::TwoNode::operator new(unsigned int, nsDST::NodeArena *) -nsDST::ConvertToTwoNode(nsDST::LeafNode **) -nsDST::Insert(void *, void *, void **) -FrameManager::SetPrimaryFrameFor(nsIContent *, nsIFrame *) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocTwoNode(void) -nsDST::TwoNode::operator new(unsigned int, nsDST::NodeArena *) -nsDST::ConvertToTwoNode(nsDST::LeafNode **) -nsDST::Insert(void *, void *, void **) -FrameManager::SetFrameProperty(nsIFrame *, nsIAtom *, void *, void (*)(nsIPresContext *, nsIFrame *, nsIAtom *, void *)) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -FrameHashTable::Put(void *, void *) -FrameManager::SetPlaceholderFrameFor(nsIFrame *, nsIFrame *) - - -__builtin_new -nsDST::NewMemoryArena(unsigned int) -FrameManager::Init(nsIPresShell *, nsIStyleSet *) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocTwoNode(void) -nsDST::ConvertToTwoNode(nsDST::LeafNode **) -nsDST::Insert(void *, void *, void **) -FrameManager::SetPrimaryFrameFor(nsIContent *, nsIFrame *) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocLeafNode(void) -nsDST::Insert(void *, void *, void **) -FrameManager::SetFrameProperty(nsIFrame *, nsIAtom *, void *, void (*)(nsIPresContext *, nsIFrame *, nsIAtom *, void *)) - - -PR_Malloc -PL_ArenaAllocate -nsDST::NodeArena::AllocLeafNode(void) -nsDST::Insert(void *, void *, void **) -FrameManager::SetPrimaryFrameFor(nsIContent *, nsIFrame *) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -UndisplayedMap::AppendNodeFor(UndisplayedNode *, nsIContent *) - - -__builtin_new -UndisplayedMap::AddNodeFor(nsIContent *, nsIContent *, nsIStyleContext *) - - -PR_Malloc -PL_ArenaFinish -PL_NewHashTable -UndisplayedMap::UndisplayedMap(unsigned int) - - -PR_Calloc -PR_NewLock - - -PR_Calloc -PR_NewMonitor - -# ---------------------------------------------------------------------- -# -# RDFServiceImpl -# - - -PR_Malloc -PL_ArenaFinish -PL_NewHashTable -RDFServiceImpl::Init(void) - - -PR_Malloc -nsRDFParserUtils::GetQuotedAttributeValue(nsString const &, nsString const &, nsString &) -PL_HashTableRawAdd -PL_HashTableAdd -RDFServiceImpl::RegisterDataSource(nsIRDFDataSource *, int) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -RDFServiceImpl::RegisterResource(nsIRDFResource *, int) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -PL_HashTableAdd -RDFServiceImpl::RegisterLiteral(nsIRDFLiteral *, int) - - -PR_Malloc -nsRDFParserUtils::IsJavaScriptLanguage(nsString const &, char const **) -PL_NewHashTable -RDFServiceImpl::Init(void) - - -PR_Malloc -nsRDFParserUtils::IsJavaScriptLanguage(nsString const &, char const **) -PL_HashTableRawAdd -PL_HashTableAdd -RDFServiceImpl::RegisterDataSource(nsIRDFDataSource *, int) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawRemove -RDFServiceImpl::UnregisterResource(nsIRDFResource *) - - -PL_strdup -RDFServiceImpl::RegisterDataSource(nsIRDFDataSource *, int) - -# ---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsRDFResource::Init(char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsString::operator=(nsString const &) -nsHTMLImageLoader::SetURL(nsString const &) - - -__builtin_new -__builtin_vec_new -nsHTMLEntities::AddRefTable(void) - - -__builtin_new -nsAVLTree::AddItem(void *) -nsHTMLEntities::AddRefTable(void) - - -__builtin_new -__builtin_vec_new -nsStaticCaseInsensitiveNameTable::Init(char const **, int) - - -__builtin_new -CNavDTD::CNavDTD(void) - - -__builtin_new -__builtin_vec_new -InitializeElementTable(void) -CNavDTD::CNavDTD(void) - - -__builtin_new -__builtin_vec_new -nsDeque::GrowCapacity(void) -nsDeque::Push(void *) -CNodeRecycler::RecycleNode(nsCParserNode *) -CNavDTD::CloseContainersTo(int, nsHTMLTag, int) - - -__builtin_new -COtherDTD::COtherDTD(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsScanner::Append(char const *, unsigned int) - - -__builtin_new -nsSlidingString::AppendBuffer(unsigned short *, unsigned short *, unsigned short *) -nsScanner::AppendToBuffer(unsigned short *, unsigned short *, unsigned short *) - - -__builtin_new -nsScanner::AppendToBuffer(unsigned short *, unsigned short *, unsigned short *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(basic_nsAReadableString const &, unsigned short *) -ToNewUnicode(basic_nsAReadableString const &) -nsScanner::Append(basic_nsAReadableString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -CopyUnicodeTo(nsReadingIterator const &, nsReadingIterator const &, basic_nsAWritableString &) -nsScanner::CopyUnusedData(nsString &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsString::nsString(nsString const &) -nsScanner::nsScanner(nsString &, int, nsString const &, nsCharsetSource) - - -__builtin_new -__builtin_vec_new -nsDeque::GrowCapacity(void) -nsDeque::Push(void *) -nsHTMLTokenizer::ScanDocStructure(int) - - -__builtin_new -__builtin_vec_new -nsDeque::GrowCapacity(void) -nsDeque::Push(void *) -nsHTMLTokenizer::AddToken(CToken *&, unsigned int, nsDeque *, nsTokenAllocator *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -CToken::operator new(unsigned int, nsFixedSizeAllocator &) -nsTokenAllocator::CreateTokenOfType(eHTMLTokenTypes, nsHTMLTag) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsNodeAllocator::nsNodeAllocator(void) - -# ---------------------------------------------------------------------- -# -# xptiWorkingSet -# - - -__builtin_new -__builtin_vec_new -xptiWorkingSet::NewFileArray(unsigned int) - - -__builtin_new -__builtin_vec_new -xptiWorkingSet::ExtendFileArray(unsigned int) - -# ---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -HTMLContentSink::OnStreamComplete(nsIStreamLoader *, nsISupports *, unsigned int, unsigned int, char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsString::nsString(nsString const &) -HTMLContentSink::SetTitle(nsString const &) - - -__builtin_new -__builtin_vec_new -DeviceContextImpl::DeviceContextImpl(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -DeviceContextImpl::CreateFontAliasTable(void) - - -__builtin_new -FontAliasKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -DeviceContextImpl::AliasFont(nsString const &, nsString const &, nsString const &, int) - - -__builtin_new -__builtin_vec_new -nsCompressedMap::nsCompressedMap(unsigned short *, unsigned int) - - -__builtin_new -__builtin_vec_new -nsHTMLDocument::nsHTMLDocument(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsHTMLDocument::nsHTMLDocument(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsHTMLDocument::InvalidateHashTables(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsString::nsString(basic_nsAReadableString const &) -nsHTMLDocument::SetReferrer(basic_nsAReadableString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsString::nsString(basic_nsAReadableString const &) -nsHTMLDocument::SetLastModified(basic_nsAReadableString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsString::nsString(basic_nsAReadableString const &) -nsHTMLDocument::SetTitle(basic_nsAReadableString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsString::nsString(nsAString const &) -mozilla::dom::DocumentType::DocumentType(nsAString const &, nsIDOMNamedNodeMap *, nsIDOMNamedNodeMap *, nsAString const &, nsAString const &, nsAString const &) - -#---------------------------------------------------------------------- -# -# XPC stuff -# - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -Native2WrappedNativeMap::Native2WrappedNativeMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -ClassInfo2WrappedNativeProtoMap::ClassInfo2WrappedNativeProtoMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -IID2NativeInterfaceMap::IID2NativeInterfaceMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -IID2WrappedJSClassMap::IID2WrappedJSClassMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -IID2ThisTranslatorMap::IID2ThisTranslatorMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -XPCNativeScriptableSharedMap::XPCNativeScriptableSharedMap(int) - - -__builtin_new -XPCNativeScriptableSharedMap::GetNewOrUsed(unsigned int, char *, XPCNativeScriptableInfo *) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -JSContext2XPCContextMap::JSContext2XPCContextMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -NativeSetMap::NativeSetMap(int) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -JSObject2WrappedJSMap::JSObject2WrappedJSMap(int) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -nsXPCWrappedJS::GetNewOrUsed(XPCCallContext &, JSObject *, nsID const &, nsISupports *, nsXPCWrappedJS **) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -XPCWrappedNativeProtoMap::XPCWrappedNativeProtoMap(int) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext &, XPCWrappedNativeScope *, nsIClassInfo *, XPCNativeScriptableCreateInfo const *, int) - - -__builtin_new -XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext &, XPCWrappedNativeScope *, nsIClassInfo *, XPCNativeScriptableCreateInfo const *, int) - - -__builtin_new -__builtin_vec_new -XPCNativeSet::NewInstance(XPCCallContext &, XPCNativeInterface **, unsigned short) -XPCNativeSet::GetNewOrUsed(XPCCallContext &, nsIClassInfo *) -XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext &, XPCWrappedNativeScope *, nsIClassInfo *, XPCNativeScriptableCreateInfo const *, int) - - -__builtin_new -XPCNativeScriptableInfo::Construct(XPCCallContext &, XPCNativeScriptableCreateInfo const *) -XPCWrappedNativeProto::Init(XPCCallContext &, XPCNativeScriptableCreateInfo const *) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -XPCNativeSet::GetNewOrUsed(XPCCallContext &, nsIClassInfo *) -XPCWrappedNativeProto::GetNewOrUsed(XPCCallContext &, XPCWrappedNativeScope *, nsIClassInfo *, XPCNativeScriptableCreateInfo const *, int) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -XPCWrappedNative::~XPCWrappedNative(void) - - -__builtin_new -XPCWrappedNative::FindTearOff(XPCCallContext &, XPCNativeInterface *, int, unsigned int *) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -XPCWrappedNative::GetNewOrUsed(XPCCallContext &, nsISupports *, XPCWrappedNativeScope *, XPCNativeInterface *, XPCWrappedNative **) - - -JS_DHashAllocTable -JS_DHashTableInit -JS_NewDHashTable -js_LookupProperty -js_GetProperty -XPCWrappedNativeScope::SetGlobal(XPCCallContext &, JSObject *) - - -__builtin_new -__builtin_vec_new -nsXPCWrappedNativeClass::BuildMemberDescriptors(XPCContext *) - -#---------------------------------------------------------------------- - - -__builtin_new -__builtin_vec_new -nsNetModRegEntry::nsNetModRegEntry(char const *, nsINetNotify *, unsigned int *) -nsNetModuleMgr::RegisterModule(char const *, nsINetNotify *) - - -__builtin_new -nsProxyObjectManager::nsProxyObjectManager(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsProxyObjectManager::nsProxyObjectManager(void) - - -__builtin_new -__builtin_vec_new -nsProxyEventClass::nsProxyEventClass(nsID const &, nsIInterfaceInfo *) - - -__builtin_new -nsHashtable::Put(nsHashKey *, void *) -nsProxyEventClass::nsProxyEventClass(nsID const &, nsIInterfaceInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsProxyEventClass::nsProxyEventClass(nsID const &, nsIInterfaceInfo *) - - -__builtin_new -nsProxyEventKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *, int, nsISupports *, nsID const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *, int, nsISupports *, nsID const &) - -# ---------------------------------------------------------------------- -# -# nsComponentManagerImpl -# - - -__builtin_new -nsComponentManagerImpl::Init(void) - - -__builtin_new -nsComponentManagerImpl::GetServiceByContractID(char const *, nsID const &, void **) - - -__builtin_new -nsComponentManagerImpl::GetService(nsID const &, nsID const &, void **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsComponentManagerImpl::Init(void) - - -__builtin_vec_new -nsComponentManagerImpl::Init(void) - - -__builtin_new -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -__builtin_new -nsComponentManagerImpl::RegisterFactory(nsID const &, char const *, char const *, nsIFactory *, int) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::HashContractID(char const *, nsID const &) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsComponentManagerImpl::Init(void) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsComponentManagerImpl::GetLoaderForType(char const *, nsIComponentLoader **) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::ContractIDToClassID(char const *, nsID *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsComponentManagerImpl::RegisterFactory(nsID const &, char const *, char const *, nsIFactory *, int) - - -__builtin_new -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -__builtin_new -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::RegisterFactory(nsID const &, char const *, char const *, nsIFactory *, int) - - -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -PR_Malloc -bufio_SetBufferSize -nsXPTCStubBase::Sentinel9(void) -NR_RegSetBufferSize -nsRegistry::SetBufferSize(int) -nsComponentManagerImpl::AutoRegister(int, nsIFile *) - - -__builtin_new -nsComponentManagerImpl::HashContractID(char const *, nsID const &) - - -__builtin_new -nsComponentManagerImpl::RegisterComponentCommon(nsID const &, char const *, char const *, char const *, int, int, char const *) - - -__builtin_new -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::RegisterComponentCommon(nsID const &, char const *, char const *, char const *, int, int, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::HashContractID(char const *, nsID const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::RegisterFactory(nsID const &, char const *, char const *, nsIFactory *, int) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::ContractIDToClassID(char const *, nsID *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::HashContractID(char const *, nsFactoryEntry *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsComponentManagerImpl::HashContractID(char const *, nsFactoryEntry *) - - -__builtin_new -nsComponentManagerImpl::GetService(char const *, nsID const &, nsISupports **, nsIShutdownListener *) - - -__builtin_new -nsComponentManagerImpl::GetService(nsID const &, nsID const &, nsISupports **, nsIShutdownListener *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AssignFromReadable(nsACString const &) -nsACString::do_AssignFromElementPtr(char const *) -nsCString::nsCString(char const *) -nsFactoryEntry::nsFactoryEntry(nsID const &, char const *, int) -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -PL_strdup -nsComponentManagerImpl::HashContractID(char const *, nsFactoryEntry *) - - -PL_strdup -nsFactoryEntry::nsFactoryEntry(nsID const &, char const *, int) -nsComponentManagerImpl::PlatformPrePopulateRegistry(void) - - -PL_DHashAllocTable -PL_DHashTableInit -nsComponentManagerImpl::Init(void) - -# ---------------------------------------------------------------------- - - -__builtin_new -nsZipArchive::BuildFileList(void) - - -__builtin_new -nsStaticCaseInsensitiveNameTable::Init(char const **, int) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsStaticCaseInsensitiveNameTable::Init(char const **, int) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsStaticCaseInsensitiveNameTable::Init(char const **, int) - -# ---------------------------------------------------------------------- -# -# nsDrawingSurfaceGTK -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsDrawingSurfaceGTK::Init(_GdkGC *, unsigned int, unsigned int, unsigned int) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsDrawingSurfaceGTK::Init(_GdkGC *, unsigned int, unsigned int, unsigned int) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsDrawingSurfaceGTK type_info function - - -PR_Malloc -nsDrawingSurfaceGTK::Init(_GdkGC *, unsigned int, unsigned int, unsigned int) - -# ---------------------------------------------------------------------- -# -# nsNativeComponentLoader -# - - -__builtin_new -nsNativeComponentLoader::Init(nsIComponentManager *, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsNativeComponentLoader::Init(nsIComponentManager *, nsISupports *) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsNativeComponentLoader::CreateDll - - -__builtin_new -nsNativeComponentLoader::CreateDll(nsIFile *, char const *, long long *, long long *, nsDll **) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsNativeComponentLoader::CreateDll(nsIFile *, char const *, long long *, long long *, nsDll **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsNativeComponentLoader::CreateDll(nsIFile *, char const *, long long *, long long *, nsDll **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsNativeComponentLoader::CreateDll(nsIFile *, char const *, long long *, long long *, nsDll **) - - -PL_strdup -nsDll::nsDll(nsIFile *, char const *, long long *, long long *) -nsNativeComponentLoader::CreateDll(nsIFile *, char const *, long long *, long long *, nsDll **) - -# ---------------------------------------------------------------------- - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsDirectoryService::Set(char const *, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsDirectoryService::Init(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsDirectoryService::Set(char const *, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsDirectoryService::Init(char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsDirectoryService::Init(void) - -#---------------------------------------------------------------------- -# -# nsResProtocolHandler -# - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsResProtocolHandler::AppendSubstitution(char const *, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsResProtocolHandler::nsResProtocolHandler(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsResProtocolHandler::AppendSubstitution(char const *, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsResProtocolHandler::SetSubstitution(char const *, nsIURI *) - -# ---------------------------------------------------------------------- -# -# nsChromeRegistry -# - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsChromeRegistry::LoadDataSource(nsCString const &, nsIRDFDataSource **, int, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsChromeRegistry::LoadDataSource(nsCString const &, nsIRDFDataSource **, int, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsChromeRegistry::LoadDataSource(nsCString const &, nsIRDFDataSource **, int, char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsACString const &) -nsStdURL::GetSpec(char **) -RDFXMLDataSourceImpl::Init(char const *) -nsChromeRegistry::LoadDataSource(nsCString const &, nsIRDFDataSource **, int, char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsChromeRegistry::LoadDataSource(nsCString const &, nsIRDFDataSource **, int, char const *) - -# ---------------------------------------------------------------------- - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsZipReaderCache::GetZip(nsIFile *, nsIZipReader **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsZipReaderCache::GetZip(nsIFile *, nsIZipReader **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsZipReaderCache::nsZipReaderCache(void) - - -__builtin_new -nsZipReaderCache::GetZip(nsIFile *, nsIZipReader **) - -# ---------------------------------------------------------------------- -# -# nsXBLDocumentInfo -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLDocumentInfo::SetPrototypeBinding(nsACString const &, nsIXBLPrototypeBinding *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXBLDocumentInfo::SetPrototypeBinding(nsACString const &, nsIXBLPrototypeBinding *) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLDocumentInfo::SetPrototypeBinding(nsCString const &, nsIXBLPrototypeBinding *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLDocumentInfo::SetPrototypeBinding(basic_nsAReadableString const &, nsIXBLPrototypeBinding *) - - -__builtin_new -nsXBLDocumentInfo::SetPrototypeBinding(nsCString const &, nsIXBLPrototypeBinding *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLDocumentInfo::SetPrototypeBinding(nsCString const &, nsIXBLPrototypeBinding *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsXBLDocumentInfo::SetPrototypeBinding(basic_nsAReadableString const &, nsIXBLPrototypeBinding *) - - -__builtin_new -nsXBLDocumentInfo::SetPrototypeBinding(basic_nsAReadableString const &, nsIXBLPrototypeBinding *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(char const *) -nsCString::operator=(char const *) -nsXBLDocumentInfo::nsXBLDocumentInfo(char const *, nsIDocument *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXBLDocumentInfo::SetPrototypeBinding(nsACString const &, nsIXBLPrototypeBinding *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AssignFromReadable(nsACString const &) -nsACString::do_AssignFromElementPtr(char const *) -nsXBLDocumentInfo::nsXBLDocumentInfo(char const *, nsIDocument *) - - -__builtin_new -nsXBLDocumentInfo::SetPrototypeBinding(nsACString const &, nsIXBLPrototypeBinding *) - -# ---------------------------------------------------------------------- -# -# nsXULPrototypeCache -# - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULPrototypeCache::PutPrototype(nsIXULPrototypeDocument *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXULPrototypeCache::nsXULPrototypeCache(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULPrototypeCache::PutStyleSheet(nsICSSStyleSheet *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsXULPrototypeCache::nsXULPrototypeCache(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULPrototypeCache::PutXBLDocumentInfo(nsXBLDocumentInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsXULPrototypeCache::PutScript(nsIURI *, void *) - -# nsXULPrototypeElement - -__builtin_new -XULContentSinkImpl::CreateElement(nsINodeInfo *, nsXULPrototypeElement **) - -# nsXULPrototypeNode - -__builtin_new -__builtin_vec_new -XULContentSinkImpl::CloseContainer(nsIParserNode const &) - -# nsXULPrototypeScript - -__builtin_new -XULContentSinkImpl::OpenScript(nsIParserNode const &) - -# ---------------------------------------------------------------------- -# -# nsExternalHelperAppService -# - - -__builtin_new -nsExternalHelperAppService::nsExternalHelperAppService(void) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsExternalHelperAppService::AddMimeInfoToCache(nsIMIMEInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsExternalHelperAppService::AddMimeInfoToCache(nsIMIMEInfo *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsExternalHelperAppService::AddMimeInfoToCache(nsIMIMEInfo *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsExternalHelperAppService::AddMimeInfoToCache(nsIMIMEInfo *) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsTArray::InsertElementAt(int, nsCString const &) -nsMIMEInfoImpl::SetFileExtensions(char const *) -nsExternalHelperAppService::AddDefaultMimeTypesToCache(void) - -# ---------------------------------------------------------------------- -# -# nsCategoryManager -# - - -__builtin_new -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -__17nsObjectHashtablePFP9nsHashKeyPvPv_PvPvPFP9nsHashKeyPvPv_iT2Uii -CategoryNode::CategoryNode(void) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -__17nsObjectHashtablePFP9nsHashKeyPvPv_PvPvPFP9nsHashKeyPvPv_iT2Uii -nsCategoryManager::nsCategoryManager(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -__17nsObjectHashtablePFP9nsHashKeyPvPv_PvPvPFP9nsHashKeyPvPv_iT2Uii -CategoryNode::CategoryNode(void) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -__17nsObjectHashtablePFP9nsHashKeyPvPv_PvPvPFP9nsHashKeyPvPv_iT2Uii -nsCategoryManager::nsCategoryManager(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AssignFromReadable(nsACString const &) -nsACString::do_AssignFromElementPtr(char const *) -nsCString::nsCString(char const *) -nsCategoryManager::AddCategoryEntry(char const *, char const *, char const *, int, int, char **) - -# ---------------------------------------------------------------------- -# -# nsScriptNameSpaceManager -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsScriptNameSpaceManager::RegisterClassName(char const *, int) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsScriptNameSpaceManager::FillHashWithDOMInterfaces(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsScriptNameSpaceManager::FillHash(nsICategoryManager *, char const *, nsGlobalNameStruct::nametype) - - -__builtin_new -nsScriptNameSpaceManager::RegisterClassName(char const *, int) - -# ---------------------------------------------------------------------- -# -# nsScriptSecurityManager -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsScriptSecurityManager::InitPolicies(unsigned int, char const **, nsISecurityPref *) - - -__builtin_new -nsScriptSecurityManager::EnumeratePolicyCallback(char const *, void *) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsScriptSecurityManager::EnumeratePolicyCallback(char const *, void *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsScriptSecurityManager::InitPrefs(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -__17nsObjectHashtablePFP9nsHashKeyPvPv_PvPvPFP9nsHashKeyPvPv_iT2Uii -nsScriptSecurityManager::EnumeratePolicyCallback(char const *, void *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsScriptSecurityManager::InitPolicies(unsigned int, char const **, nsISecurityPref *) - -# ---------------------------------------------------------------------- -# -# nsStringBundleService -# - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsStringBundleService::insertIntoCache(nsIStringBundle *, nsCStringKey *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsStringBundleService::insertIntoCache(nsIStringBundle *, nsCStringKey *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsStringBundleService::nsStringBundleService(void) - - -PR_Malloc -PL_ArenaAllocate -nsStringBundleService::insertIntoCache(nsIStringBundle *, nsCStringKey *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsStringBundleService::insertIntoCache(nsIStringBundle *, nsCStringKey *) - -# ---------------------------------------------------------------------- - - -__builtin_new -CSSStyleSheetImpl::CSSStyleSheetImpl(void) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -CSSStyleSheetImpl::AppendStyleRule(nsICSSRule *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -CSSStyleSheetImpl::CheckRuleForAttributes(nsICSSRule *) - - -__builtin_new -AtomKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -CSSStyleSheetImpl::CheckRuleForAttributes(nsICSSRule *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -CSSStyleSheetImpl::CheckRuleForAttributes(nsICSSRule *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -CSSStyleSheetInner::CSSStyleSheetInner(nsICSSStyleSheet *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -HTMLStyleSheetImpl::HTMLStyleSheetImpl(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawRemove -nsHashtable::Remove(nsHashKey *) -HTMLStyleSheetImpl::DropMappedAttributes(nsIHTMLMappedAttributes *) - - -__builtin_new -AttributeKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -HTMLStyleSheetImpl::UniqueMappedAttributes(nsIHTMLMappedAttributes *, nsIHTMLMappedAttributes *&) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -HTMLStyleSheetImpl::UniqueMappedAttributes(nsIHTMLMappedAttributes *, nsIHTMLMappedAttributes *&) - - -__builtin_new -nsStyleContextData::Create(nsIPresContext *) - - -__builtin_new -__builtin_vec_new -nsStyleContent::AllocateCounterResets(unsigned int) - - -__builtin_new -__builtin_vec_new -nsStyleContent::AllocateContents(unsigned int) - - -__builtin_new -xptiManifest::Read(xptiInterfaceInfoManager *, xptiWorkingSet *) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -PL_HashTableAdd -xptiManifest::Read(xptiInterfaceInfoManager *, xptiWorkingSet *) - - -__builtin_new -SelectorList::AddSelector(nsCSSSelector const &) -CSSParserImpl::ParseSelectorGroup(int &, SelectorList *&) - - -__builtin_new -CSSParserImpl::ParseContent(int &, nsICSSDeclaration *, int &) - -# ---------------------------------------------------------------------- -# -# RuleHash -# - - -__builtin_new -RuleHash::AppendRuleToTable(nsHashtable &, int, nsICSSStyleRule *) - - -__builtin_new -RuleHash::AppendRuleToTable(nsHashtable &, nsIAtom *, nsICSSStyleRule *) - - -__builtin_new -RuleHash::AppendRuleToTable(nsHashtable &, nsIAtom *, nsICSSStyleRule *, int) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -RuleHash::AppendRuleToTable(nsHashtable &, int, nsICSSStyleRule *) - - -__builtin_new -AtomKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -RuleHash::AppendRuleToTable(nsHashtable &, nsIAtom *, nsICSSStyleRule *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -RuleHash::RuleHash(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -RuleHash::AppendRuleToTable(nsHashtable &, nsIAtom *, nsICSSStyleRule *) - - -__builtin_new -__builtin_vec_new -RuleHash::EnumerateAllRules(nsIAtom *, nsIAtom *, nsVoidArray const &, void (*)(nsICSSStyleRule *, void *), void *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -RuleHash::AppendRuleToTable(nsHashtable &, nsIAtom *, nsICSSStyleRule *, int) - -# ---------------------------------------------------------------------- -# -# nsCSSSelector -# - - -__builtin_new -nsCSSSelector::nsCSSSelector(nsCSSSelector const &) - - -__builtin_new -nsAtomList::nsAtomList(nsAtomList const &) -nsCSSSelector::nsCSSSelector(nsCSSSelector const &) - - -__builtin_new -nsAttrSelector::nsAttrSelector(nsAttrSelector const &) -nsCSSSelector::nsCSSSelector(nsCSSSelector const &) - - -__builtin_new -nsAttrSelector::nsAttrSelector(nsAttrSelector const &) -nsAttrSelector::nsAttrSelector(nsAttrSelector const &) -nsCSSSelector::nsCSSSelector(nsCSSSelector const &) - -# ---------------------------------------------------------------------- -# -# StyleSetImpl -# - - -__builtin_new -CSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor *&, nsIStyleRuleProcessor *) -StyleSetImpl::ClearOverrideRuleProcessors(void) - - -__builtin_new -CSSRuleProcessor::GetRuleCascade(nsIPresContext *, nsIAtom *) -CSSRuleProcessor::RulesMatching(nsIPresContext *, nsIAtom *, nsIContent *, nsIStyleContext *, nsIRuleWalker *) -StyleSetImpl::ReplaceBackstopStyleSheets(nsISupportsArray *) - - -__builtin_new -CSSRuleProcessor::GetRuleCascade(nsIPresContext *, nsIAtom *) -CSSRuleProcessor::RulesMatching(nsIPresContext *, nsIAtom *, nsIContent *, nsIAtom *, nsIStyleContext *, nsICSSPseudoComparator *, nsIRuleWalker *) -StyleSetImpl::ResolveStyleFor(nsIPresContext *, nsIContent *, nsIStyleContext *, int) - - -__builtin_new -nsSupportsArray::Create(nsISupports *, nsID const &, void **) -NS_NewISupportsArray(nsISupportsArray **) -StyleSetImpl::EnsureArray(nsISupportsArray **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsRuleNode::Transition(nsIStyleRule *, nsIRuleNode **) -nsRuleWalker::Forward(nsIStyleRule *) -StyleSetImpl::AddImportantRules(nsIRuleNode *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsRuleNode::Transition(nsIStyleRule *, nsIRuleNode **) -nsRuleWalker::Forward(nsIStyleRule *) -nsHTMLBodyElement::WalkInlineStyleRules(nsIRuleWalker *) -HTMLCSSStyleSheetImpl::RulesMatching(nsIPresContext *, nsIAtom *, nsIContent *, nsIStyleContext *, nsIRuleWalker *) -StyleSetImpl::ReplaceBackstopStyleSheets(nsISupportsArray *) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -CSSRuleProcessor::CascadeSheetRulesInto(nsISupports *, void *) -nsSupportsArray::EnumerateBackwards(int (*)(nsISupports *, void *), void *) -CSSRuleProcessor::CascadeSheetRulesInto(nsISupports *, void *) -CSSRuleProcessor::GetRuleCascade(nsIPresContext *, nsIAtom *) -CSSRuleProcessor::RulesMatching(nsIPresContext *, nsIAtom *, nsIContent *, nsIStyleContext *, nsIRuleWalker *) -StyleSetImpl::ReplaceBackstopStyleSheets(nsISupportsArray *) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -CSSRuleProcessor::AppendStyleSheet(nsICSSStyleSheet *) -CSSStyleSheetImpl::GetStyleRuleProcessor(nsIStyleRuleProcessor *&, nsIStyleRuleProcessor *) -StyleSetImpl::ClearOverrideRuleProcessors(void) - -//---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsString::operator=(nsString const &) -StyleListImpl::ResetFrom(nsStyleList const *, nsIPresContext *) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -CSSRuleProcessor::CascadeSheetRulesInto(nsISupports *, void *) -nsSupportsArray::EnumerateBackwards(int (*)(nsISupports *, void *), void *) -CSSRuleProcessor::CascadeSheetRulesInto(nsISupports *, void *) -CSSRuleProcessor::GetRuleCascade(nsIPresContext *, nsIAtom *) -CSSRuleProcessor::RulesMatching(nsIPresContext *, nsIAtom *, nsIContent *, nsIAtom *, nsIStyleContext *, nsICSSPseudoComparator *, nsIRuleWalker *) -StyleSetImpl::ResolveStyleFor(nsIPresContext *, nsIContent *, nsIStyleContext *, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -CSSRuleProcessor::ClearRuleCascades(void) -nsSupportsArray::EnumerateBackwards(int (*)(nsISupports *, void *), void *) -CSSRuleProcessor::GetRuleCascade(nsIPresContext *, nsIAtom *) -CSSRuleProcessor::RulesMatching(nsIPresContext *, nsIAtom *, nsIContent *, nsIAtom *, nsIStyleContext *, nsICSSPseudoComparator *, nsIRuleWalker *) -StyleSetImpl::ResolveStyleFor(nsIPresContext *, nsIContent *, nsIStyleContext *, int) - -# ---------------------------------------------------------------------- - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -StyleContextCache::VerifyList(unsigned int) - - -__builtin_new -StyleContextCache::AllocateList(void) - -# ---------------------------------------------------------------------- -# -# nsPersistentProperties -# - - -__builtin_new -nsPersistentProperties::Create(nsISupports *, nsID const &, void **) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -nsPersistentProperties::SetStringProperty(nsAString const &, nsAString &, nsAString &) -nsPersistentProperties::Load(nsIInputStream *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCppSharedAllocator::allocate(unsigned int, void const *) -nsCRT::strndup(unsigned short const *, unsigned int) -nsCRT::strdup(unsigned short const *) -nsString::ToNewUnicode(void) const -nsPersistentProperties::SetStringProperty(nsString const &, nsString &, nsString &) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -nsPersistentProperties::SetStringProperty(nsString const &, nsString &, nsString &) - - -PR_Malloc -PL_ArenaFinish -PL_NewHashTable -nsPersistentProperties::nsPersistentProperties(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsPersistentProperties::SetStringProperty(nsAString const &, nsAString &, nsAString &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(nsAString const &, unsigned short *) -ToNewUnicode(nsAString const &) -nsPersistentProperties::SetStringProperty(nsAString const &, nsAString &, nsAString &) - -# ---------------------------------------------------------------------- -# -# nsCSSValue -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCppSharedAllocator::allocate(unsigned int, void const *) -nsCRT::strndup(unsigned short const *, unsigned int) -nsCRT::strdup(unsigned short const *) -nsString::ToNewUnicode(void) const -nsCSSValue::operator=(nsCSSValue const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsCSSValue::SetStringValue(nsAString const &, nsCSSUnit) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(nsAString const &, unsigned short *) -ToNewUnicode(nsAString const &) -nsCSSValue::SetStringValue(nsAString const &, nsCSSUnit) - -# ---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStringKey::Clone(void) const - -#---------------------------------------------------------------------- -# -# nsTextFragment -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsTextFragment::SetTo(unsigned short const *, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsAString const &) -nsTextFragment::operator=(nsAString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -char * AllocateStringCopy(basic_nsAReadableString const &, char *) -ToNewCString(basic_nsAReadableString const &) -nsTextFragment::operator=(basic_nsAReadableString const &) - -#---------------------------------------------------------------------- -# -# nsTextBoxFrame -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsTextBoxFrame::UpdateAttributes(nsIPresContext *, nsIAtom *, int &, int &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsTextBoxFrame::CalculateTitleForWidth(nsIPresContext *, nsRenderingContext &, int) - -# ---------------------------------------------------------------------- -# -# nsPopupSetFrame -# - - -__builtin_new -nsPopupSetFrame::AddPopupFrame(nsIFrame *) - -#---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsACString const &) -nsStdURL::GetSpec(char **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsString::ToNewCString(void) const -nsSimpleURI::SetSpec(char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsAString const &) -nsSimpleURI::SetSpec(char const *) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -PL_HashTableAdd -nsNodeInfoManager::GetNodeInfo(nsIAtom *, nsIAtom *, int, nsINodeInfo *&) - - -PR_Malloc -PL_ArenaFinish -PL_NewHashTable -nsNodeInfoManager::nsNodeInfoManager(void) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawRemove -PL_HashTableRemove -nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *) - - -XPT_ArenaMalloc -xptiInterfaceInfo::CopyName(char const *, xptiWorkingSet *) - - -__builtin_new -xptiInterfaceInfo::PartiallyResolveLocked(XPTInterfaceDescriptor *, xptiWorkingSet *) - - -XPT_ArenaMalloc - - -siglongjmp -pthread_create - - -XkbAllocClientMap - - -_XiCheckExtInit - - -_XAllocScratch - - -XUnlockDisplay - - -_XlcCreateLC - - -XkbUseExtension - - -_XimServerDestroy - - -_XlcAddCharSet - - -XInitExtension - - -_XlcGenericLoader - - -_XwcDefaultDrawImageString - - -_XlcAddCT - - -XShmCreateImage - - -_XFreeAtomTable - - -XCreateRegion - - -XIntersectRegion - - -_XlcCreateLocaleDataBase - - -_XUpdateAtomCache - - -XrmMergeDatabases - - -XrmParseCommand - - -XOpenDisplay - - -XCreateGC - - -_XlcResetConverter - - -_XEnq - - -_XimLcctstowcs - - -XtMalloc - - -XtCalloc - - -Xpermalloc - - -_XlcCreateDefaultCharSet - - -_XimLocalSetICValues - - -_XimLocalCreateIC - - -_XlcSetConverter - - -_XkbGetCharset - - -g_malloc - - -g_realloc - - -g_malloc0 - - -_XimLcctstoutf8 - - -loader_png -gdk_imlib_load_image - - -loader_png -gdk_imlib_save_image - - -_dl_lookup_versioned_symbol_skip - - -_dl_dst_substitute - - -_dl_map_object_deps - - -_dl_map_object - - -_dl_debug_message - - -PR_Malloc -bufio_SetBufferSize -nsXPTCStubBase::Sentinel9(void) -NR_RegSetBufferSize -nsRegistry::SetBufferSize(int) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsXBLService::nsXBLService(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsXBLService::nsXBLService(void) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -InMemoryAssertionEnumeratorImpl::operator new(unsigned int, nsFixedSizeAllocator &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsGenericModule::nsGenericModule(char const *, unsigned int, nsModuleComponentInfo *, unsigned int (*)(nsIModule *), void (*)(nsIModule *)) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsGenericModule::GetClassObject(nsIComponentManager *, nsID const &, nsID const &, void **) - - -__builtin_new -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsGenericModule::GetClassObject(nsIComponentManager *, nsID const &, nsID const &, void **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsGenericModule::nsGenericModule(char const *, unsigned int, nsModuleComponentInfo *, void (*)(nsIModule *)) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::nsHashtable(unsigned int, int) -nsGenericModule::nsGenericModule(char const *, unsigned int, nsModuleComponentInfo *, unsigned int (*)(nsIModule *), void (*)(nsIModule *)) - - -gettext -gettext -setlocale -setlocale -nsUNIXCharset::nsUNIXCharset(void) - -# ---------------------------------------------------------------------- -# -# nsLocaleService -# - - -textdomain -textdomain -setlocale -setlocale -nsLocaleService::nsLocaleService(void) - - -setlocale -setlocale -setlocale -nsLocaleService::nsLocaleService(void) - - -PR_Malloc -PL_ArenaFinish -PL_NewHashTable -nsLocale::nsLocale(void) - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -PL_HashTableAdd -nsLocale::AddCategory(unsigned short const *, unsigned short const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::do_AssignFromElementPtr(unsigned short const *) -nsString::nsString(unsigned short const *) -nsLocale::AddCategory(unsigned short const *, unsigned short const *) - -# ---------------------------------------------------------------------- -# -# nsServiceManagerImpl (obsolete?) -# - - -__builtin_new -nsServiceManagerImpl::nsServiceManagerImpl(void) -NS_NewServiceManager(nsIServiceManager **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsServiceManagerImpl::nsServiceManagerImpl(void) - - -__builtin_new -nsHashtable::Put(nsHashKey *, void *) -nsServiceManagerImpl::GetService(nsID const &, nsID const &, nsISupports **, nsIShutdownListener *) - - -__builtin_new -nsServiceManagerImpl::nsServiceManagerImpl(void) -NS_NewServiceManager(nsIServiceManager **) - - -__builtin_new -nsServiceManagerImpl::GetService(nsID const &, nsID const &, nsISupports **, nsIShutdownListener *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsServiceManagerImpl::GetService(nsID const &, nsID const &, nsISupports **, nsIShutdownListener *) - -#---------------------------------------------------------------------- -# -# nsXMLElement -# - - -__builtin_new -nsGenericContainerElement::SetAttribute(nsINodeInfo *, basic_nsAReadableString const &, int) -nsGenericXMLElement::SetAttribute(nsINodeInfo *, basic_nsAReadableString const &, int) - - -__builtin_new -nsGenericContainerElement::SetAttribute(nsINodeInfo *, basic_nsAReadableString const &, int) -nsXMLElement::SetAttribute(nsINodeInfo *, basic_nsAReadableString const &, int) - - -__builtin_new -nsGenericContainerElement::SetAttr(nsINodeInfo *, nsAString const &, int) -nsXMLElement::SetAttr(nsINodeInfo *, nsAString const &, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsString::nsString(nsAString const &) -nsGenericContainerElement::SetAttr(nsINodeInfo *, nsAString const &, int) -nsXMLElement::SetAttr(nsINodeInfo *, nsAString const &, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsCheapVoidArray::AppendElement(void *) -nsGenericContainerElement::AppendChildTo(nsIContent *, int, int) -nsXMLContentSink::AddContentAsLeaf(nsIContent *) - -#---------------------------------------------------------------------- -# -# nsXMLDocument -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsDocument::nsDocument(void) -nsMarkupDocument::nsMarkupDocument(void) -nsXMLDocument::nsXMLDocument(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsString::AppendWithConversion(char const *, int) -nsString::AssignWithConversion(char const *) -nsDocument::StartDocumentLoad(char const *, nsIChannel *, nsILoadGroup *, nsISupports *, nsIStreamListener **, int) -nsXMLDocument::StartDocumentLoad(char const *, nsIChannel *, nsILoadGroup *, nsISupports *, nsIStreamListener **, int) - -#---------------------------------------------------------------------- - - -__builtin_new -nsGCCache::nsGCCache(void) - -#---------------------------------------------------------------------- -# -# prefs -# - - -_init -PL_HashTableRawAdd -PL_HashTableAdd -pref_HashPref - - -_init -PL_NewHashTable -PREF_Init - - -pref_HashPref - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsPref::nsPref(void) - - -PREF_RegisterCallback - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsCString::nsCString(nsCString const &) -nsTArray::InsertElementAt(int, nsCString const &) -nsPrefBranch::AddObserver(char const *, nsIObserver *) - -#---------------------------------------------------------------------- - - -PR_Calloc -PR_SetThreadPrivate -nsThread::RegisterThreadSelf(void) - - -XFreeFont - - -__builtin_new -nsFontGTK::operator new(unsigned int) - - -__builtin_new -nsCheapVoidArray::SwitchToVector(void) -nsCheapVoidArray::AppendElement(void *) -nsGenericContainerElement::AppendChildTo(nsIContent *, int) - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsCheapVoidArray::AppendElement(void *) -nsGenericContainerElement::AppendChildTo(nsIContent *, int, int) - -#---------------------------------------------------------------------- -# -# nsObserverService -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsObserverService::GetObserverList(unsigned short const *, nsIObserverList **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsObserverService::GetObserverList(unsigned short const *, nsIObserverList **) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsObserverService::GetObserverList(nsString const &, nsIObserverList **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsObserverService::GetObserverList(nsString const &, nsIObserverList **) - - -__builtin_new -NS_NewObserverList(nsIObserverList **) -nsObserverService::GetObserverList(nsString const &, nsIObserverList **) - - -__builtin_new -nsObserverService::GetObserverList(nsString const &, nsIObserverList **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsObserverService::GetObserverList(nsString const &, nsIObserverList **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsObserverService::GetObserverList(char const *, nsObserverList **) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsObserverList::AddObserver(nsIObserver *, int) - -#---------------------------------------------------------------------- - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsViewManager::nsViewManager(void) - - -__builtin_new -nsViewManager2::AddToDisplayList(int *, nsView *, nsRect &, nsRect &, unsigned int, int, int) - -# ---------------------------------------------------------------------- -# -# nsBindingManager -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsBindingManager::SetContentListFor(nsIContent *, nsISupportsArray *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsBindingManager::SetInsertionParent(nsIContent *, nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsBindingManager::SetAnonymousNodesFor(nsIContent *, nsISupportsArray *) - - -__builtin_new -nsISupportsKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsBindingManager::SetBinding(nsIContent *, nsIXBLBinding *) - - -__builtin_new -nsBindingManager::SetBinding(nsIContent *, nsIXBLBinding *) - - -__builtin_new -nsBindingManager::SetInsertionParent(nsIContent *, nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsBindingManager::SetBinding(nsIContent *, nsIXBLBinding *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsBindingManager::SetBinding(nsIContent *, nsIXBLBinding *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsBindingManager::SetInsertionParent(nsIContent *, nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsBindingManager::SetInsertionParent(nsIContent *, nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsBindingManager::SetWrappedJS(nsIContent *, nsIXPConnectWrappedJS *) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsBindingManager::AddToAttachedQueue(nsIXBLBinding *) - -# ---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsString::nsString(nsAString const &) -NameSpaceManagerImpl::RegisterNameSpace(nsAString const &, int &) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsLayoutUtils::GetDynamicScriptContext(JSContext *, nsIScriptContext **) -NameSpaceManagerImpl::NameSpaceManagerImpl(void) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -NameSpaceManagerImpl::RegisterNameSpace(basic_nsAReadableString const &, int &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsStr::StrAppend(nsStr &, nsStr const &, unsigned int, int) -nsStr::StrAssign(nsStr &, nsStr const &, unsigned int, int) -nsString::nsString(nsString const &) -nsLayoutUtils::CopyNewlineNormalizedUnicodeTo(nsReadingIterator &, nsReadingIterator const &, basic_nsAWritableString &) -NameSpaceManagerImpl::NameSpaceManagerImpl(void) - - -__builtin_new -nsErrorService::Create(nsISupports *, nsID const &, void **) - - -__builtin_new -nsVoidKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsInt2StrHashtable::Put(unsigned int, char const *) -nsErrorService::RegisterErrorStringBundleKey(unsigned int, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsInt2StrHashtable::Put(unsigned int, char const *) -nsErrorService::RegisterErrorStringBundleKey(unsigned int, char const *) - - -__builtin_new -ArenaImpl::Create(nsISupports *, nsID const &, void **) -NS_NewHeapArena(nsIArena **, unsigned int) -nsDocument::Init(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsDocument::nsDocument(void) - - -__builtin_new -nsDocument::SetHeaderData(nsIAtom *, basic_nsAReadableString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsDocument::AddReference(void *, nsISupports *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(basic_nsAReadableString const &) -nsDocHeaderData::nsDocHeaderData(nsIAtom *, basic_nsAReadableString const &) - - -__builtin_new -XPCContext::newXPCContext(XPCJSRuntime *, JSContext *) - - -__builtin_new -nsEventQueueServiceImpl::Create(nsISupports *, nsID const &, void **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsEventQueueServiceImpl::nsEventQueueServiceImpl(void) - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsEventListenerManager::AddEventListener(nsIDOMEventListener *, EventArrayType, int, nsHashKey *, int) - - -PR_Malloc -nsEventListenerManager::AddEventListener(nsIDOMEventListener *, EventArrayType, int, nsHashKey *, int) -nsEventListenerManager::SetJSEventListener(nsIScriptContext *, nsISupports *, nsIAtom *, int) -nsEventListenerManager::AddScriptEventListener(nsIScriptContext *, nsISupports *, nsIAtom *, nsAString const &, int) - - -PR_Malloc -nsEventListenerManager::AddEventListener(nsIDOMEventListener *, EventArrayType, int, nsHashKey *, int) -nsEventListenerManager::AddEventListenerByType(nsIDOMEventListener *, nsAString const &, int) - - -PR_Malloc -nsEventListenerManager::AddEventListener(nsIDOMEventListener *, EventArrayType, int, nsHashKey *, int) -nsEventListenerManager::AddEventListenerByIID(nsIDOMEventListener *, nsID const &, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::ReplaceElementAt(void *, int) -nsEventListenerManager::GetListenersByType(EventArrayType, nsHashKey *, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::ReplaceElementAt(void *, int) -nsEventListenerManager::GetListenersByType(EventArrayType, nsHashKey *, int) - - -__builtin_new -nsEventListenerManager::AddEventListener(nsIDOMEventListener *, nsID const &, int, int) - - -PR_Malloc -nsEventListenerManager::AddEventListener(nsIDOMEventListener *, nsID const &, int, int) - - -__builtin_new -nsCParserNode::AddAttribute(CToken *) - - -__builtin_new -__builtin_vec_new -nsDeque::GrowCapacity(void) -nsDeque::Push(void *) -nsCParserNode::AddAttribute(CToken *) - - -PR_Malloc -nsSocketTransportService::Init(void) - - -PR_Malloc -nsSocketTransport::AsyncWrite(nsIInputStream *, nsIStreamObserver *, nsISupports *) - - -PR_Malloc -_PR_Getfd -PR_GetConnectStatus -PR_Socket -PR_OpenTCPSocket -nsSocketTransport::doConnection(short) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -CompositeDataSourceImpl::CompositeDataSourceImpl(void) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -CompositeDataSourceImpl::GetTargets(nsIRDFResource *, nsIRDFResource *, int, nsISimpleEnumerator **) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -CompositeDataSourceImpl::ArcLabelsIn(nsIRDFNode *, nsISimpleEnumerator **) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -CompositeDataSourceImpl::ArcLabelsOut(nsIRDFResource *, nsISimpleEnumerator **) - -# ---------------------------------------------------------------------- -# -# nsHTMLValue -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(basic_nsAReadableString const &, unsigned short *) -ToNewUnicode(basic_nsAReadableString const &) -nsHTMLValue::nsHTMLValue(basic_nsAReadableString const &, nsHTMLUnit) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsHTMLValue::SetStringValue(nsAString const &, nsHTMLUnit) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(nsAString const &, unsigned short *) -ToNewUnicode(nsAString const &) -nsHTMLValue::nsHTMLValue(nsAString const &, nsHTMLUnit) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(nsAString const &, unsigned short *) -ToNewUnicode(nsAString const &) -nsHTMLValue::SetStringValue(nsAString const &, nsHTMLUnit) - -# ---------------------------------------------------------------------- - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsMemCache::GetCachedNetData(char const *, unsigned int, nsINetDataCacheRecord **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsMemCache::Init(void) - - -__builtin_new -nsOpaqueKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsMemCache::GetCachedNetData(char const *, unsigned int, nsINetDataCacheRecord **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsOpaqueKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsMemCache::GetCachedNetData(char const *, unsigned int, nsINetDataCacheRecord **) - - -__builtin_new -nsOpaqueKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsMemCache::GetCachedNetData(char const *, unsigned int, nsINetDataCacheRecord **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsOpaqueKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsMemCache::GetCachedNetData(char const *, unsigned int, nsINetDataCacheRecord **) - - -__builtin_new -__builtin_vec_new -nsMemCacheRecord::SetMetaData(unsigned int, char const *) - - -__builtin_new -__builtin_vec_new -nsMemCacheRecord::Init(char const *, unsigned int, unsigned int, nsMemCache *) - - -PR_Realloc -nsXPIDLString type_info function -nsXPIDLString type_info function -nsTextFormatter::vsmprintf(unsigned short const *, void *) -nsTextFormatter::smprintf(unsigned short const *,...) - - -PR_Malloc -nsXPIDLString type_info function -nsXPIDLString type_info function -nsTextFormatter::vsmprintf(unsigned short const *, void *) - - -PR_Realloc -nsXPIDLString type_info function -nsXPIDLString type_info function -nsTextFormatter::vsmprintf(unsigned short const *, void *) - -#---------------------------------------------------------------------- -# -# nsPresContext -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsPresContext::nsPresContext(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresContext::LoadImage(nsString const &, nsIFrame *, imgIRequest **) - -#---------------------------------------------------------------------- -# -# nsPresState -# - - -__builtin_new -nsPresState::SetStateProperty(nsAString const &, nsAString const &) - - -__builtin_new -nsPresState::SetStatePropertyAsSupports(nsAString const &, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresState::SetStatePropertyAsSupports(basic_nsAReadableString const &, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsPresState::SetStateProperty(basic_nsAReadableString const &, basic_nsAReadableString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsPresState::SetStatePropertyAsSupports(basic_nsAReadableString const &, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresState::SetStateProperty(basic_nsAReadableString const &, basic_nsAReadableString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsSupportsWStringImpl::SetDataWithLength(unsigned int, unsigned short const *) -nsSupportsWStringImpl::SetData(unsigned short const *) -nsPresState::SetStateProperty(basic_nsAReadableString const &, basic_nsAReadableString const &) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresState::SetStatePropertyAsSupports(basic_nsAReadableString const &, nsISupports *) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresState::SetStateProperty(basic_nsAReadableString const &, basic_nsAReadableString const &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsSupportsWStringImpl::SetDataWithLength(unsigned int, unsigned short const *) -nsSupportsWStringImpl::SetData(unsigned short const *) -nsPresState::SetStateProperty(basic_nsAReadableString const &, basic_nsAReadableString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsPresState::SetStateProperty(nsAString const &, nsAString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsPresState::SetStatePropertyAsSupports(nsAString const &, nsISupports *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresState::SetStateProperty(nsAString const &, nsAString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsPresState::SetStatePropertyAsSupports(nsAString const &, nsISupports *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsSupportsStringImpl::SetDataWithLength(unsigned int, char const *) -nsSupportsStringImpl::SetData(char const *) -nsPresState::SetStateProperty(nsAString const &, nsAString const &) - -# ---------------------------------------------------------------------- -# -# Prefs stuff -# - - -PL_strdup -pref_HashPref - - -PL_strdup -PREF_LockPref - - -PL_strdup -PREF_RegisterCallback - -#---------------------------------------------------------------------- -# -# Imagelib Stuff -# - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -imgRequest::AddProxy(imgRequestProxy *) - - -__builtin_new -ImageRequestImpl::AddObserver(nsIImageRequestObserver *) - - -PR_Malloc -XP_AddObserver -ImageRequestImpl::Init(void *, char const *, nsIImageRequestObserver *, unsigned int const *, unsigned int, unsigned int, unsigned int, ilINetContext *) - - -__builtin_new -ImageNetContextImpl::GetURL(ilIURL *, ImgCachePolicy, ilINetReader *, int) - -# il_group_notify() is really a call to a static rounting il_init_scaling() - -PR_Malloc -il_group_notify(_IL_GroupContext *, long) -il_size(il_container_struct *) -ImgDCallbk::ImgDCBImageSize(void) - - -PR_Calloc -il_gif_write(il_container_struct *, unsigned char const *, int) - - -PR_Malloc -il_gif_write(il_container_struct *, unsigned char const *, int) - - -PR_Calloc -il_gif_init(il_container_struct *) - - -PR_Calloc -IL_GetImage - - -PR_Calloc -il_get_container(_IL_GroupContext *, ImgCachePolicy, char const *, _NI_IRGB *, IL_DitherMode, int, int, int) - - -PR_Calloc -IL_CreateTrueColorSpace - - -PR_Calloc -il_size(il_container_struct *) -ImgDCallbk::ImgDCBImageSize(void) - - -PR_Calloc -IL_CreateGreyScaleColorSpace - - -PR_Malloc -il_BACat(char **, unsigned int, char const *, unsigned int) - - -PR_Realloc -il_BACat(char **, unsigned int, char const *, unsigned int) - - -PR_Malloc -ImageConsumer::OnStartRequest(nsIChannel *, nsISupports *) - -# These are really called from `static' routines in ilclient.cpp, -# *not* ImgDCallbk::CreateInstance() - -PR_Calloc -ImgDCallbk::CreateInstance(nsID const &, il_container_struct *, nsID const &, void **) - -#---------------------------------------------------------------------- - - -__builtin_new -__builtin_vec_new -nsImageGTK::Init(int, int, int, nsMaskRequirements) - -#---------------------------------------------------------------------- -# -# nsLayoutHistoryState -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsLayoutHistoryState::nsLayoutHistoryState(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsLayoutHistoryState::nsLayoutHistoryState(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsLayoutHistoryState::AddState(unsigned int, nsIPresState *, nsIStatefulFrame::StateType) - - -__builtin_new -nsVoidKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsLayoutHistoryState::AddState(unsigned int, nsIPresState *, nsIStatefulFrame::StateType) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsLayoutHistoryState::AddState(nsCString const &, nsIPresState *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsLayoutHistoryState::AddState(nsCString const &, nsIPresState *) - -# ---------------------------------------------------------------------- -# -# nsCookieService -# - - -PR_Realloc -Local_SACat(char **, char const *) -COOKIE_GetCookie(char *) - - -PR_Malloc -cookie_IsFromHost(_cookie_CookieStruct *, char *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsAString const &) -COOKIE_Read(void) -nsCookieService::Init(void) - -# ---------------------------------------------------------------------- - - -PR_Realloc -nsMemoryImpl::Realloc(void *, unsigned int) -nsMemory::Realloc(void *, unsigned int) -nsReplacementPolicy::AssociateCacheEntryWithRecord(nsINetDataCacheRecord *, nsINetDataCache *, nsCachedNetData **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsReplacementPolicy::Init(unsigned int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AssignFromReadable(nsACString const &) -nsACString::do_AssignFromElementPtr(char const *) -nsHttpHeaderArray::SetHeader(nsHttpAtom, char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsHTTPHandler::SetServerCapabilities(char const *, int, unsigned int) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsHTTPHandler::nsHTTPHandler(void) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsHTTPHandler::SetServerCapabilities(char const *, int, unsigned int) - - -PR_Malloc -PL_ArenaAllocate -ArenaImpl::Alloc(unsigned int) -nsCachedNetData::operator new(unsigned int, nsIArena *) - - -PR_Malloc -ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo *, nsIInputStream *, unsigned int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsSegmentedBuffer::AppendNewSegment(void) - - -PL_strndup -ExtractString - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -__17nsObjectHashtablePFP9nsHashKeyPvPv_PvPvPFP9nsHashKeyPvPv_iT2Uii -nsJAR::nsJAR(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsJAR::nsJAR(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewCString(nsACString const &) -nsIOService::ResolveRelativePath(char const *, char const *, char **) -nsJARURI::SetSpec(char const *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsStreamConverterService::Init(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsLayoutUtils::GetDynamicScriptContext(JSContext *, nsIScriptContext **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsDNSService::GetLookupEntry(char const *, nsDNSLookup **) - - -PL_DHashAllocTable -PL_DHashTableInit -nsDNSService::Init(void) - - -__builtin_new -nsDNSService::GetLookupEntry(char const *, nsDNSLookup **) - - -__builtin_new -nsDNSService::Lookup(char const *, nsIDNSListener *, nsISupports *, nsIRequest **) - - -__builtin_new -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsDNSService::GetLookupEntry(char const *, nsDNSLookup **) - - -gethostbyname2 -PR_GetIPNodeByName -nsDNSLookup::InitiateLookup(void) - - -__builtin_new -nsSupportsArray::Create(nsISupports *, nsID const &, void **) -NS_NewISupportsArray(nsISupportsArray **) -nsDNSLookup::Init(char const *) - - -__builtin_new -nsDNSLookup::Create(char const *) - -# ---------------------------------------------------------------------- -# -# nsFormControlList -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsFormControlList::AddElementToTable(nsIFormControl *, basic_nsAReadableString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsFormControlList::nsFormControlList(nsIDOMHTMLFormElement *) - - -__builtin_new -nsFormControlList::AddElementToTable(nsIFormControl *, basic_nsAReadableString const &) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsFormControlList::AddElementToTable(nsIFormControl *, basic_nsAReadableString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsFormControlList::AddElementToTable(nsIFormControl *, basic_nsAReadableString const &) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsFormControlList::AddElementToTable(nsIFormControl *, nsAString const &) - -# ---------------------------------------------------------------------- -# -# nsControllerCommandManager -# - - -__builtin_new -__builtin_vec_new -NS_NewControllerCommandManager(nsIControllerCommandManager **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsControllerCommandManager::nsControllerCommandManager(void) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsControllerCommandManager::RegisterCommand(nsAString const &, nsIControllerCommand *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsControllerCommandManager::RegisterCommand(unsigned short const *, nsIControllerCommand *) - - -__builtin_new -nsStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsControllerCommandManager::RegisterCommand(unsigned short const *, nsIControllerCommand *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsSupportsHashtable::nsSupportsHashtable(unsigned int, int) -nsControllerCommandManager::nsControllerCommandManager(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsConsoleService::nsConsoleService(void) - - -__builtin_new -mozilla::dom::Element::GetDOMSlots(void) - - -__builtin_new -HTMLAttribute::CopyHTMLAttributes(HTMLAttribute *, HTMLAttribute **) - -# ---------------------------------------------------------------------- -# -# HTMLAttributesImpl -# - - -__builtin_new -HTMLAttributesImpl::SetAttributeFor(nsIAtom *, nsAString const &, int, nsIHTMLContent *, nsIHTMLStyleSheet *) - - -__builtin_new -HTMLAttributesImpl::SetAttributeFor(nsIAtom *, nsHTMLValue const &, int, nsIHTMLContent *, nsIHTMLStyleSheet *, int &) - - -__builtin_new -__builtin_vec_new -HTMLAttributesImpl::SetAttributeName(nsIAtom *, int &) - - -__builtin_new -nsHTMLMappedAttributes::SetAttribute(nsIAtom *, nsHTMLValue const &) -HTMLAttributesImpl::SetAttributeFor(nsIAtom *, nsHTMLValue const &, int, nsIHTMLContent *, nsIHTMLStyleSheet *, int &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCRT::strndup(unsigned short const *, unsigned int) -nsCRT::strdup(unsigned short const *) -nsHTMLValue::nsHTMLValue(nsHTMLValue const &) -HTMLAttributesImpl::SetAttributeFor(nsIAtom *, nsHTMLValue const &, int, nsIHTMLContent *, nsIHTMLStyleSheet *, int &) - - -__builtin_new -nsHTMLMappedAttributes::nsHTMLMappedAttributes(nsHTMLMappedAttributes const &) -nsHTMLMappedAttributes::Clone(nsHTMLMappedAttributes **) const -HTMLAttributesImpl::EnsureSingleMappedFor(nsIHTMLContent *, nsIHTMLStyleSheet *, int) - -# ---------------------------------------------------------------------- - - -__builtin_new -__builtin_vec_new -nsEntityConverter::LoadVersionPropertyFile(void) - - -__builtin_new -__builtin_vec_new -nsTableFrame::nsTableFrame(void) - - -__builtin_new -__builtin_vec_new -nsTableFrame::BalanceColumnWidths(nsIPresContext *, nsHTMLReflowState const &, nsSize const &, nsSize *) - - -__builtin_new -nsTableFrame::Init(nsIPresContext *, nsIContent *, nsIFrame *, nsIStyleContext *, nsIFrame *) - - -__builtin_new -nsTableCellFrame::GetFrameName(nsString &) const - - -__builtin_new -nsCellMap::AppendCell(nsTableCellMap &, nsTableCellFrame &, int, int) - - -__builtin_new -nsCellMap::Grow(nsTableCellMap &, int, int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::nsVoidArray(int) -nsCellMap::Grow(nsTableCellMap &, int, int) - - -__builtin_new -nsTableCellMap::InsertGroupCellMap(nsTableRowGroupFrame &, nsTableRowGroupFrame *&) - - -__builtin_new -nsTableCellMap::AddColsAtEnd(unsigned int) - - -__builtin_new -__builtin_vec_new -nsEncoderSupport::nsEncoderSupport(void) - - -__builtin_new -Init__18nsFrameImageLoaderP14nsIPresContextP13nsIImageGroupRC8nsStringPCUiPC6nsSizeP8nsIFrame16nsImageAnimationPFP14nsIPresContextP19nsIFrameImageLoaderP8nsIFramePvUi_UiPvT9 - - -__builtin_new -AddFrame__18nsFrameImageLoaderP8nsIFramePFP14nsIPresContextP19nsIFrameImageLoaderP8nsIFramePvUi_UiPvT3 - - - -__builtin_new -nsFloaterCacheFreeList::Alloc(void) - - -__builtin_new -nsDocLoaderImpl::AddChannelInfo(nsIChannel *) - - -__builtin_new -nsDocLoaderImpl::AddRequestInfo(nsIRequest *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsTokenAllocator::nsTokenAllocator(void) - - -__builtin_new -__builtin_vec_new -SinkContext::AddText(basic_nsAReadableString const &) - - -__builtin_new -__builtin_vec_new -SinkContext::GrowStack(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsScanner::Append(char const *, unsigned int) - - -__builtin_new -nsParser::Parse(nsIURI *, nsIStreamObserver *, int, void *, nsDTDMode) - - -__builtin_new -nsParser::Parse(basic_nsAReadableString const &, void *, nsString const &, int, int, nsDTDMode) - - -__builtin_new -__builtin_vec_new -nsParser::OnDataAvailable(nsIChannel *, nsISupports *, nsIInputStream *, unsigned int, unsigned int) - - -__builtin_new -__builtin_vec_new -InitializeElementTable(void) - - -__builtin_new -nsStorageStream::Init(unsigned int, unsigned int, nsIMemory *) - - -__builtin_new -__builtin_vec_new -nsEntryStack::EnsureCapacityFor(int, int) - - -__builtin_new -nsCacheManager::Init(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(unsigned short const *) -nsScriptError::Init(unsigned short const *, unsigned short const *, unsigned short const *, unsigned int, unsigned int, unsigned int, char const *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -~.* -~.* -basic_nsAWritableString::Assign(char const *) -nsScriptError::Init(unsigned short const *, unsigned short const *, unsigned short const *, unsigned int, unsigned int, unsigned int, char const *) - - -PR_Malloc -bufio_SetBufferSize - - -PR_Malloc -nsMemoryImpl::Alloc -nsMemory::Alloc -ToNewUnicode - - -PR_Malloc -nsMemoryImpl::Alloc -nsMemory::Alloc -nsStr::Alloc - - -__builtin_new -nsDiskCacheDevice::Init(void) - - -__builtin_new -__builtin_vec_new -XULContentSinkImpl::AddAttributes(nsIParserNode const &, nsXULPrototypeElement *) - -# -# XPCNativeInterface::NewInstance allocates an array of XPCNativeMember -# objects, and it also allocates an array of bytes to use for -# XPCNativeInterface objects. Trace would be the same for each. -# - -__builtin_new -__builtin_vec_new -XPCNativeInterface::NewInstance(XPCCallContext &, nsIInterfaceInfo *) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -XPCNativeInterface::GetNewOrUsed(XPCCallContext &, nsID const *) - - -__builtin_new -__builtin_vec_new -nsDiskCacheBlockFile::Open(nsILocalFile *, unsigned int) - -#---------------------------------------------------------------------- -# -# nsConflictSet -# - - -__builtin_new -__builtin_vec_new -nsConflictSet::AllocBindingTable(void *, unsigned int) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsConflictSet::AllocBindingEntry(void *, void const *) - - -__builtin_new -__builtin_vec_new -nsConflictSet::AllocClusterTable(void *, unsigned int) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsConflictSet::AllocClusterEntry(void *, void const *) - - -__builtin_new -__builtin_vec_new -nsConflictSet::AllocSupportTable(void *, unsigned int) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsConflictSet::AllocSupportEntry(void *, void const *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsRDFConMemberTestNode::Element::Clone(void *) const - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsRDFConInstanceTestNode::Element::Clone(void *) const - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsRDFConInstanceTestNode::FilterInstantiations(InstantiationSet &, void *) const - - -__builtin_new -MemoryElementSet::Add(MemoryElement *) - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsTemplateMatchRefSet::AddToTable(nsTemplateMatch *) -nsTemplateMatchRefSet::Add(nsTemplateMatch const *) -nsConflictSet::Add(nsTemplateMatch *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsConflictSet::Init(void) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsConflictSet::SupportEntry::Create(nsFixedSizeAllocator &) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsConflictSet::ClusterEntry::Create(nsFixedSizeAllocator &) - -#---------------------------------------------------------------------- - - -__builtin_new -nsAssignmentSet::Add(nsAssignment const &) - -#---------------------------------------------------------------------- -# -# nsXULTemplateBuilder -# - - -__builtin_new -nsXULTemplateBuilder::CompileSimpleRule(nsIContent *, int, InnerNode *) - - -PL_DHashAllocTable -PL_DHashTableInit -nsXULContentBuilder::nsXULContentBuilder(void) - - -PL_DHashAllocTable -PL_DHashTableInit -nsContentSupportMap::Init(void) - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsXULContentBuilder::BuildContentFromTemplate(nsIContent *, nsIContent *, nsIContent *, int, nsIRDFResource *, int, nsTemplateMatch *, nsIContent **, int *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCRT::strndup(unsigned short const *, unsigned int) -nsCRT::strdup(unsigned short const *) -nsXULTemplateBuilder::AddBindingsFor(nsXULTemplateBuilder *, nsAString const &, void *) - -#---------------------------------------------------------------------- -# -# nsRuleNetwork -# - - -PL_DHashAllocTable -PL_DHashTableInit -nsRuleNetwork::Init(void) - -#---------------------------------------------------------------------- -# -# nsTemplateRule -# - - -__builtin_new -nsTemplateRule::AddBinding(int, nsIRDFResource *, int) - -#---------------------------------------------------------------------- -# -# nsTemplateMatch -# - - -__builtin_new -nsAssignmentSet::Add(nsAssignment const &) -nsTemplateRule::ComputeAssignmentFor(nsConflictSet &, nsTemplateMatch *, int, Value *) const -nsTemplateMatch::GetAssignmentFor(nsConflictSet &, int, Value *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsInstantiationNode::Propagate(InstantiationSet const &, void *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsRDFConMemberTestNode::FilterInstantiations(InstantiationSet &, void *) const - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsTemplateMatch::Create(nsFixedSizeAllocator &, nsTemplateRule const *, Instantiation const &, nsAssignmentSet const &) - -#---------------------------------------------------------------------- - - -__builtin_new -__builtin_vec_new -ReteNodeSet::Add(ReteNode *) - -#---------------------------------------------------------------------- - - -__builtin_new -__builtin_vec_new -nsStaticComponentLoader::GetModuleInfo(void) - - -__builtin_new -__builtin_vec_new -RuleHash::EnumerateAllRules(int, nsIAtom *, nsIAtom *, nsVoidArray const &, void (*)(nsICSSStyleRule *, void *), void *) - - -__builtin_new -__builtin_vec_new -XPCNativeSet::NewInstance(XPCCallContext &, nsIInterfaceInfo *) - - -JS_DHashAllocTable -JS_DHashTableFinish -JS_DHashTableOperate -XPCNativeSet::ClearCacheEntryForClassInfo(nsIClassInfo *) - - -__builtin_new -__builtin_vec_new -XPCNativeSet::NewInstanceMutate(XPCNativeSet *, XPCNativeInterface *, unsigned short) - - -__builtin_new -__builtin_vec_new -nsResourceSet::Add(nsIRDFResource *) - - -__builtin_new -__builtin_vec_new -nsXPCWrappedJSClass::nsXPCWrappedJSClass(XPCCallContext &, nsID const &, nsIInterfaceInfo *) - - -__builtin_new -orkinHeap::Alloc(nsIMdbEnv *, unsigned int, void **) - - -__builtin_new -nsGenericContainerElement::SetAttribute(nsINodeInfo *, nsAString const &, int) - -# -# Space for LiteralImpl is allocated using global operator new so -# that extra space can be allocated for its string value. -# - -__builtin_new -LiteralImpl::Create - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -XULContentSinkImpl::FlushText(int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCRT::strndup(unsigned short const *, unsigned int) -nsCRT::strdup(unsigned short const *) -nsString::ToNewUnicode(void) const -nsPersistentProperties::SetStringProperty(nsString const &, nsString &, nsString &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCRT::strndup(unsigned short const *, unsigned int) -nsCRT::strdup(unsigned short const *) -nsCSSValue::operator=(nsCSSValue const &) - -#---------------------------------------------------------------------- -# -# nsXULDocument -# - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsAutoVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsXULDocument::AddObserver(nsIDocumentObserver *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULDocument::SetBoxObjectFor(nsIDOMElement *, nsIBoxObject *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULDocument::SetTemplateBuilderFor(nsIContent *, nsIXULTemplateBuilder *) - -# ---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsElementMap::Add(nsAString const &, nsIContent *) -nsXULDocument::AddElementToMap(nsIContent *) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsElementMap::Add(nsAString const &, nsIContent *) -nsXULDocument::AddElementForID(nsAString const &, nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsXULTreeElement::SelectCallback(nsITimer *, void *) -PL_HashTableRawAdd -PL_HashTableAdd -nsElementMap::Add(nsAString const &, nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -NS_NewControllerCommandManager(nsIControllerCommandManager **) -PL_HashTableRawAdd -PL_HashTableAdd -nsElementMap::Add(nsAString const &, nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsElementMap::Add(nsAString const &, nsIContent *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::AddBucket(unsigned int) -nsFixedSizeAllocator::Init(char const *, unsigned int const *, int, int, int) -nsElementMap::nsElementMap(void) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -unsigned short * AllocateStringCopy(nsAString const &, unsigned short *) -ToNewUnicode(nsAString const &) -nsElementMap::Add(nsAString const &, nsIContent *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsXULDocument::AddReference(void *, nsISupports *) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsXULDocument::PrepareToWalk(void) - - -PL_DHashAllocTable -PL_DHashTableInit -PL_NewDHashTable -nsXULDocument::AddBroadcastListenerFor(nsIDOMElement *, nsIDOMElement *, nsAString const &) - -#---------------------------------------------------------------------- - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ToNewUnicode(nsAString const &) -nsHTMLValue::nsHTMLValue(nsAString const &, nsHTMLUnit) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ExtractURLScheme -nsStdURL::Resolve(char const *, char **) -CSSParserImpl::ParseURL(int &, nsCSSValue &) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -ExtractURLScheme -nsStdURL::Resolve(char const *, char **) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsRuleNode::Transition(nsIStyleRule *, nsIRuleNode **) -nsRuleWalker::Forward(nsIStyleRule *) - -# -# Doesn't inherit nsISupports -# - -__builtin_new -nsRuleNode::Transition(nsIStyleRule *, nsIRuleNode **) - -# -# No vtable. -# - -__builtin_new -nsClassList::ParseClasses(nsClassList **, nsAString const &) - -# -# Doesn't inherit nsISupports -# - -__builtin_new -nsCheapVoidArray::SwitchToVector(void) - - -__builtin_new -nsEventListenerManager::GetListenersByType(EventArrayType, nsHashKey *, int) - -#---------------------------------------------------------------------- - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableInit(PLHashTable *, unsigned int, unsigned int (*)(void const *), int (*)(void const *, void const *), int (*)(void const *, void const *), PLHashAllocOps const *, void *) -nsHashtable::nsHashtable(unsigned int, int) -nsObjectHashtable::nsObjectHashtable(void *(*)(nsHashKey *, void *, void *), void *, int (*)(nsHashKey *, void *, void *), void *, unsigned int, int) -nsServiceManagerImpl::nsServiceManagerImpl(void) - - -__builtin_new -nsXPIDLCString::PrepareForUseAsOutParam(void) - - -__builtin_new -nsXBLBinding::InitClass - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -InMemoryDataSource::LockedAssert(nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -nsXBLPrototypeBinding::ConstructAttributeTable(nsIContent *) - -#---------------------------------------------------------------------- -# -# nsRuleNode -# - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsSupportsHashtable::Put(nsHashKey *, nsISupports *, nsISupports **) -nsRuleNode::Transition(nsIStyleRule *, nsIRuleNode **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AppendFromReadable(nsAString const &) -nsAString::do_AppendFromElementPtr(unsigned short const *) -nsRuleNode::ComputeDisplayData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AppendFromReadable(nsAString const &) -nsAString::do_AppendFromElementPtr(unsigned short const *) -nsRuleNode::ComputeBackgroundData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AppendFromReadable(nsAString const &) -nsAString::do_AppendFromElementPtr(unsigned short const *) -nsRuleNode::ComputeListData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - -# ---------------------------------------------------------------------- - -# This stuff will only show off if you've turned off the FrameArena -# in nsPresShell.cpp - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeOutlineData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeContentData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeTableData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeUIResetData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeXULData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::SetDefaultOnRoot(nsStyleStructID, nsIStyleContext *) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeListData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeTextData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeTextResetData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputePaddingData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeFontData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeVisibilityData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeColorData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - -# ---------------------------------------------------------------------- -# -# nsBookmarksService -# - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -InMemoryDataSource::LockedAssert(nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) -InMemoryDataSource::Assert(nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) -BookmarkParser::updateAtom(nsIRDFDataSource *, nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int *) - - -PR_Malloc -PL_ArenaAllocate -nsFixedSizeAllocator::Alloc(unsigned int) -Assertion::Create(nsFixedSizeAllocator &, nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) -InMemoryDataSource::LockedAssert(nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) -InMemoryDataSource::Assert(nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int) -BookmarkParser::updateAtom(nsIRDFDataSource *, nsIRDFResource *, nsIRDFResource *, nsIRDFNode *, int *) - -# ---------------------------------------------------------------------- -# -# The following types will only be visible if nsPresShell.cpp is compiled -# with the DEBUG_TRACEMALLOC_FRAMEARENA defined. -# - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStyleContext::SetStyle(nsStyleStructID, nsStyleStruct const &) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStyleBorder::operator new(unsigned int, nsIPresContext *) - -# XXX This one is a bit sloppy, and may include some of the other -# style data structs. - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeDisplayData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStyleContext::SetStyle(nsStyleStructID, nsStyleStruct const &) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeBorderData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeUIData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputePositionData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStylePadding::operator new(unsigned int, nsIPresContext *) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStyleMargin::operator new(unsigned int, nsIPresContext *) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeBackgroundData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsStyleBackground::nsStyleBackground(nsStyleBackground const &) - -# XXX this'll may be subsumed as nsResetStyleData - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsRuleNode::ComputeDisplayData(nsStyleStruct *, nsCSSStruct const &, nsIStyleContext *, nsRuleNode *, nsRuleNode::RuleDetail const &, int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -nsStyleDisplay::nsStyleDisplay(nsStyleDisplay const &) - -# ---------------------------------------------------------------------- -# The following will only show up if you turn off the FrameArena -# in nsPresShell.cpp - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStyleContext::GetUniqueStyleData(nsIPresContext *, nsStyleStructID const &) - - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsPresContext::AllocateFromShell(unsigned int, void **) -nsStyleFont::operator new(unsigned int, nsIPresContext *) - -# ---------------------------------------------------------------------- -# -# Frames -# - - -__builtin_new -nsLineBox::SetCombinedArea(nsRect const &) - -# This will only appear when the FrameArena is off. - -PR_Malloc -FrameArena::AllocateFrame(unsigned int, void **) -PresShell::AllocateFrame(unsigned int, void **) -nsLineBox::operator new(unsigned int, nsIPresShell *) - -# ---------------------------------------------------------------------- -# -# nsCacheService -# - - -__builtin_new -nsCacheService::ActivateEntry(nsCacheRequest *, nsCacheEntry **) - - -__builtin_new -nsCacheEntry::CreateDescriptor(nsCacheRequest *, int, nsICacheEntryDescriptor **) -nsCacheService::ProcessRequest(nsCacheRequest *, int, nsICacheEntryDescriptor **) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsCString::SetCapacity(unsigned int) -nsCString::SetLength(unsigned int) -nsACString::do_AppendFromReadable(nsACString const &) -nsACString::do_AppendFromElementPtr(char const *) -nsCacheService::CreateRequest(nsCacheSession *, char const *, int, int, nsICacheListener *, nsCacheRequest **) - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsCacheEntryHashTable::AddEntry(nsCacheEntry *) -nsCacheService::ActivateEntry(nsCacheRequest *, nsCacheEntry **) - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsCacheEntryHashTable::RemoveEntry(nsCacheEntry *) - -# ---------------------------------------------------------------------- - - -PL_DHashAllocTable -PL_DHashTableInit -nsCacheMetaData::Init(void) - -# ---------------------------------------------------------------------- -# -# nsXMLMIMEDataSource -# - - -PR_Malloc -PL_ArenaFinish -PL_HashTableRawAdd -PL_HashTableAdd -nsXMLMIMEDataSource::InitFromFile(nsIFile *) - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsXMLMIMEDataSource::AddMapping(char const *, char const *, char const *, nsIURI *, unsigned int, unsigned int) - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -nsTArray::InsertElementAt(int, nsCString const &) -nsXMLMIMEDataSource::AddMapping(char const *, char const *, char const *, nsIURI *, unsigned int, unsigned int) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsXMLMIMEDataSource::AddMapping(char const *, char const *, char const *, nsIURI *, unsigned int, unsigned int) - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsCStringKey::Clone(void) const -nsHashtable::Put(nsHashKey *, void *) -nsXMLMIMEDataSource::AddMapping(char const *, char const *, char const *, nsIURI *, unsigned int, unsigned int) - -#---------------------------------------------------------------------- -# -# nsRegion -# - - -__builtin_new -__builtin_vec_new -RgnRectMemoryAllocator::RgnRectMemoryAllocator(unsigned int) -nsRegion::Offset(int, int) - - -__builtin_new -__builtin_vec_new -RgnRectMemoryAllocator::Alloc(void) -nsRegion::Or(nsRegion const &, nsRectFast const &) - - -__builtin_new -__builtin_vec_new -RgnRectMemoryAllocator::Alloc(void) -nsRegion::SetToElements(unsigned int) - -#---------------------------------------------------------------------- -# -# nsCharsetMenu -# - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsCharsetConverterManager::GetRegistryEnumeration2(char *, int, nsISupportsArray **) -nsCharsetConverterManager::GetEncoderList(nsISupportsArray **) -nsCharsetMenu::InitResources(void) - - -__builtin_new -nsCharsetMenu::AddCharsetToItemArray(nsVoidArray *, nsIAtom *, nsMenuEntry **, int) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsCharsetConverterManager::GetRegistryEnumeration2(char *, int, nsISupportsArray **) -nsCharsetConverterManager::GetDecoderList(nsISupportsArray **) -nsCharsetMenu::InitResources(void) - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -InMemoryDataSource::AddObserver(nsIRDFObserver *) -nsCharsetMenu::AddObserver(nsIRDFObserver *) - -#---------------------------------------------------------------------- -# -# nsLoadGroup -# - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsLoadGroup::AddRequest(nsIRequest *, nsISupports *) - -#---------------------------------------------------------------------- -# -# Wallet -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -Wallet_Decrypt2 - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::AssignFromReadable(nsAString const &) -Wallet_RandomName - - -PR_Malloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -Wallet_RandomName - - -__builtin_new -__builtin_vec_new -Wallet_Decrypt2 - - -__builtin_new -Wallet_RandomName - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -Wallet_Decrypt2 - - -PR_Realloc -nsVoidArray::SizeTo(int) -nsVoidArray::GrowArrayBy(int) -nsVoidArray::InsertElementAt(void *, int) -Wallet_RandomName - -#---------------------------------------------------------------------- -# -# nsMemoryCacheDevice -# - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsCacheEntryHashTable::RemoveEntry(nsCacheEntry *) -nsMemoryCacheDevice::EvictEntry(nsCacheEntry *) - -#---------------------------------------------------------------------- -# -# nsSHEntry -# - - -PR_Malloc -nsMemoryImpl::Alloc(unsigned int) -nsMemory::Alloc(unsigned int) -nsStr::Alloc(nsStr &, unsigned int) -nsStr::Realloc(nsStr &, unsigned int) -nsStr::EnsureCapacity(nsStr &, unsigned int) -nsStr::GrowCapacity(nsStr &, unsigned int) -nsString::SetCapacity(unsigned int) -nsString::SetLength(unsigned int) -nsAString::do_AssignFromReadable(nsAString const &) -nsAString::do_AssignFromElementPtr(unsigned short const *) -nsSHEntry::SetTitle(unsigned short const *) - -# ---------------------------------------------------------------------- - - -PR_Malloc -PL_HashTableFinalize(PLHashTable *) -PL_HashTableRawAdd -nsHashtable::Put(nsHashKey *, void *) -nsOutlinerStyleCache::GetStyleContext(nsICSSPseudoComparator *, nsIPresContext *, nsIContent *, nsIStyleContext *, nsIAtom *, nsISupportsArray *, nsIStyleContext **) - -# ---------------------------------------------------------------------- -# -# nsMsgDatabase -# - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsMsgDatabase::AddHdrToCache(nsIMsgDBHdr *, unsigned int) - - -PL_DHashAllocTable -PL_DHashTableFinish -PL_DHashTableOperate -nsMsgDatabase::AddHdrToUseCache(nsIMsgDBHdr *, unsigned int) - -# ---------------------------------------------------------------------- -# -# nsMsgFolderDataSource -# - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -nsMsgFolderDataSource::getFolderArcLabelsOut(nsISupportsArray **) - -# ---------------------------------------------------------------------- -# -# singsign -# - - -__builtin_new -SI_DeletePersistentUserData - -# ---------------------------------------------------------------------- -# -# LocalStoreImpl -# - - -__builtin_new -__builtin_vec_new -nsSupportsArray::GrowArrayBy(int) -nsSupportsArray::InsertElementAt(nsISupports *, unsigned int) -nsSupportsArray::AppendElement(nsISupports *) -LocalStoreImpl::AddObserver(nsIRDFObserver *) - -# ---------------------------------------------------------------------- -# -# NSS -# - - -PR_Malloc -PL_ArenaAllocate -PORT_ArenaAlloc - - -PR_Malloc -PL_ArenaAllocate -nss_ZAlloc diff --git a/tools/trace-malloc/uncategorized.pl b/tools/trace-malloc/uncategorized.pl deleted file mode 100755 index 0501bfc3fffc..000000000000 --- a/tools/trace-malloc/uncategorized.pl +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/perl -w -# -# 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/. - -# This tool is used to construct the ``type inference'' file. It -# prints the total number of bytes that are attributed to a type that -# cannot be inferred, grouped by stack trace; e.g., -# -# (100) PR_Malloc -# (50) foo -# (50) foo2::foo2 -# (25) bar -# (25) baz -# (50) __builtin_new -# (50) foo2::foo2 -# -# -# Which indicates that 100 bytes were allocated by uninferrable -# classes via PR_Malloc(). Of that 100 bytes, 50 were allocated from -# calls by foo(), 25 from calls by bar(), and 25 from calls by baz(). -# 50 bytes were allocated by __builtin_new from foo2's ctor. -# -# -# From this, we might be able to infer the type of the object that was -# created by examining the PR_Malloc() usage in foo() and the -# ::operator new() usage in foo2(), and could add new type inference -# rules; e.g., -# -# -# foo -# foo2 -# -# # Attribute ::operator new() usage in foo2's ctor to foo2 -# -# __builtin_new -# foo2::foo2 - -use 5.004; -use strict; -use Getopt::Long; - -# So we can find TraceMalloc.pm -use FindBin; -use lib "$FindBin::Bin"; - -use TraceMalloc; - -# Collect program options -$::opt_help = 0; -$::opt_depth = 10; -$::opt_types = "${FindBin::Bin}/types.dat"; -GetOptions("help", "depth=n", "types=s"); - -if ($::opt_help) { - die "usage: uncategorized.pl [options] - --help Display this message - --depth= Display at most stack frames - --types= Read type heuristics from "; -} - -# Initialize type inference juju from the type file specified by -# ``--types''. -TraceMalloc::init_type_inference($::opt_types); - -# Read the objects from the dump file. For each object, remember up to -# ``--depth'' stack frames (from the top). Thread together common -# stack prefixes, accumulating the number of bytes attributed to the -# prefix. - -# This'll hold the inverted stacks -$::Stacks = { '#bytes#' => 0 }; - -sub collect_stacks($) { - my ($object) = @_; - my $stack = $object->{'stack'}; - - return unless ($object->{'type'} eq 'void*') && (TraceMalloc::infer_type($stack) eq 'void*'); - - my $count = 0; - my $link = \%::Stacks; - FRAME: foreach my $frame (@$stack) { - last FRAME unless $count++ < $::opt_depth; - - $link->{'#bytes#'} += $object->{'size'}; - $link->{$frame} = { '#bytes#' => 0 } unless $link->{$frame}; - $link = $link->{$frame}; - } -} - -TraceMalloc::read(\&collect_stacks); - -# Do a depth-first walk of the inverted stack tree. - -sub walk($$) { - my ($links, $indent) = @_; - - my @keys; - KEY: foreach my $key (keys %$links) { - next KEY if $key eq '#bytes#'; - $keys[$#keys + 1] = $key; - } - - foreach my $key (sort { $links->{$b}->{'#bytes#'} <=> $links->{$a}->{'#bytes#'} } @keys) { - for (my $i = 0; $i < $indent; ++$i) { - print " "; - } - - print "($links->{$key}->{'#bytes#'}) $key\n"; - - walk($links->{$key}, $indent + 1); - } -} - -walk(\%::Stacks, 0); - diff --git a/xpcom/base/nsTraceRefcnt.cpp b/xpcom/base/nsTraceRefcnt.cpp index a20c26c92a5e..44c53cc289f2 100644 --- a/xpcom/base/nsTraceRefcnt.cpp +++ b/xpcom/base/nsTraceRefcnt.cpp @@ -32,10 +32,6 @@ #include #endif -#ifdef NS_TRACE_MALLOC -#include "nsTraceMalloc.h" -#endif - #include "mozilla/BlockingResourceBase.h" #include "mozilla/PoisonIOInterposer.h" @@ -1024,14 +1020,6 @@ NS_LogInit() nsTraceRefcnt::SetActivityIsLegal(true); } #endif - -#ifdef NS_TRACE_MALLOC - // XXX we don't have to worry about shutting down trace-malloc; it - // handles this itself, through an atexit() callback. - if (!NS_TraceMallocHasStarted()) { - NS_TraceMallocStartup(-1); // -1 == no logging - } -#endif } EXPORT_XPCOM_API(void) diff --git a/xpcom/base/nscore.h b/xpcom/base/nscore.h index 31badbcb9acf..1140392dc731 100644 --- a/xpcom/base/nscore.h +++ b/xpcom/base/nscore.h @@ -242,7 +242,7 @@ * sense to touch memory pages and free that memory at shutdown, * unless we are running leak stats. */ -#if defined(NS_TRACE_MALLOC) || defined(NS_BUILD_REFCNT_LOGGING) || defined(MOZ_VALGRIND) +#if defined(NS_BUILD_REFCNT_LOGGING) || defined(MOZ_VALGRIND) #define NS_FREE_PERMANENT_DATA #endif diff --git a/xpcom/glue/standalone/nsXPCOMGlue.cpp b/xpcom/glue/standalone/nsXPCOMGlue.cpp index f51606d96718..35b55528bc92 100644 --- a/xpcom/glue/standalone/nsXPCOMGlue.cpp +++ b/xpcom/glue/standalone/nsXPCOMGlue.cpp @@ -155,70 +155,6 @@ NS_HIDDEN __typeof(dlclose) __wrap_dlclose; #define dlclose __wrap_dlclose #endif -#ifdef NS_TRACE_MALLOC -extern "C" { -NS_EXPORT_(__ptr_t) __libc_malloc(size_t); -NS_EXPORT_(__ptr_t) __libc_calloc(size_t, size_t); -NS_EXPORT_(__ptr_t) __libc_realloc(__ptr_t, size_t); -NS_EXPORT_(void) __libc_free(__ptr_t); -NS_EXPORT_(__ptr_t) __libc_memalign(size_t, size_t); -NS_EXPORT_(__ptr_t) __libc_valloc(size_t); -} - -static __ptr_t (*_malloc)(size_t) = __libc_malloc; -static __ptr_t (*_calloc)(size_t, size_t) = __libc_calloc; -static __ptr_t (*_realloc)(__ptr_t, size_t) = __libc_realloc; -static void (*_free)(__ptr_t) = __libc_free; -static __ptr_t (*_memalign)(size_t, size_t) = __libc_memalign; -static __ptr_t (*_valloc)(size_t) = __libc_valloc; - -NS_EXPORT_(__ptr_t) malloc(size_t size) -{ - return _malloc(size); -} - -NS_EXPORT_(__ptr_t) calloc(size_t nmemb, size_t size) -{ - return _calloc(nmemb, size); -} - -NS_EXPORT_(__ptr_t) realloc(__ptr_t ptr, size_t size) -{ - return _realloc(ptr, size); -} - -NS_EXPORT_(void) free(__ptr_t ptr) -{ - _free(ptr); -} - -NS_EXPORT_(void) cfree(__ptr_t ptr) -{ - _free(ptr); -} - -NS_EXPORT_(__ptr_t) memalign(size_t boundary, size_t size) -{ - return _memalign(boundary, size); -} - -NS_EXPORT_(int) -posix_memalign(void** memptr, size_t alignment, size_t size) -{ - __ptr_t ptr = _memalign(alignment, size); - if (!ptr) { - return ENOMEM; - } - *memptr = ptr; - return 0; -} - -NS_EXPORT_(__ptr_t) valloc(size_t size) -{ - return _valloc(size); -} -#endif /* NS_TRACE_MALLOC */ - typedef void* LibHandleType; static LibHandleType @@ -322,17 +258,6 @@ typedef Scoped ScopedCloseFile; static void XPCOMGlueUnload() { -#if !defined(XP_WIN) && !defined(XP_MACOSX) && defined(NS_TRACE_MALLOC) - if (sTop) { - _malloc = __libc_malloc; - _calloc = __libc_calloc; - _realloc = __libc_realloc; - _free = __libc_free; - _memalign = __libc_memalign; - _valloc = __libc_valloc; - } -#endif - while (sTop) { CloseLibHandle(sTop->libHandle); @@ -468,15 +393,6 @@ XPCOMGlueLoad(const char* aXPCOMFile) return nullptr; } -#if !defined(XP_WIN) && !defined(XP_MACOSX) && defined(NS_TRACE_MALLOC) - _malloc = (__ptr_t(*)(size_t)) GetSymbol(sTop->libHandle, "malloc"); - _calloc = (__ptr_t(*)(size_t, size_t)) GetSymbol(sTop->libHandle, "calloc"); - _realloc = (__ptr_t(*)(__ptr_t, size_t)) GetSymbol(sTop->libHandle, "realloc"); - _free = (void(*)(__ptr_t)) GetSymbol(sTop->libHandle, "free"); - _memalign = (__ptr_t(*)(size_t, size_t)) GetSymbol(sTop->libHandle, "memalign"); - _valloc = (__ptr_t(*)(size_t)) GetSymbol(sTop->libHandle, "valloc"); -#endif - return sym; }