1. Fix jsdhash/pldhash.[ch] so that add/remove cycles for a given k do not
create a long chain of removed sentinels. Also, when adding k to a table
where k is not mapped, but where k hashes to a chain that includes removed
sentinels, recycle the first removed sentinel in the chain for k's entry.
2. Cache cx->resolving till js_DestroyContext, to avoid high JSDHashTable
new/destroy overhead in js_LookupProperty.
3. Add NS_TraceStack to nsTraceMalloc.[ch] and clean the .c file up a bit.
git-svn-id: svn://10.0.0.236/trunk@102796 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -53,6 +53,7 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include "plhash.h"
|
||||
#include "pratom.h"
|
||||
#include "prlog.h"
|
||||
#include "prmon.h"
|
||||
#include "prprf.h"
|
||||
@@ -232,15 +233,15 @@ typedef void (__stdcall *FREEDEBUGPROC) ( void *, int);
|
||||
|
||||
struct AllocationFuncs
|
||||
{
|
||||
MALLOCPROC malloc_proc;
|
||||
CALLOCPROC calloc_proc;
|
||||
REALLOCPROC realloc_proc;
|
||||
MALLOCPROC malloc_proc;
|
||||
CALLOCPROC calloc_proc;
|
||||
REALLOCPROC realloc_proc;
|
||||
FREEPROC free_proc;
|
||||
#ifdef _DEBUG
|
||||
MALLOCDEBUGPROC malloc_debug_proc;
|
||||
CALLOCDEBUGPROC calloc_debug_proc;
|
||||
REALLOCDEBUGPROC realloc_debug_proc;
|
||||
FREEDEBUGPROC free_debug_proc;
|
||||
MALLOCDEBUGPROC malloc_debug_proc;
|
||||
CALLOCDEBUGPROC calloc_debug_proc;
|
||||
REALLOCDEBUGPROC realloc_debug_proc;
|
||||
FREEDEBUGPROC free_debug_proc;
|
||||
#endif
|
||||
int prevent_reentry;
|
||||
}gAllocFuncs;
|
||||
@@ -271,6 +272,24 @@ static logfile *logfp = &default_logfile;
|
||||
static PRMonitor *tmmon = NULL;
|
||||
static char *sdlogname = NULL; /* filename for shutdown leak log */
|
||||
|
||||
/*
|
||||
* This counter suppresses tracing, in case any tracing code needs to malloc,
|
||||
* and it must be tested and manipulated only within tmmon.
|
||||
*/
|
||||
static uint32 suppress_tracing = 0;
|
||||
|
||||
#define TM_ENTER_MONITOR() \
|
||||
PR_BEGIN_MACRO \
|
||||
if (tmmon) \
|
||||
PR_EnterMonitor(tmmon); \
|
||||
PR_END_MACRO
|
||||
|
||||
#define TM_EXIT_MONITOR() \
|
||||
PR_BEGIN_MACRO \
|
||||
if (tmmon) \
|
||||
PR_ExitMonitor(tmmon); \
|
||||
PR_END_MACRO
|
||||
|
||||
/* We don't want more than 32 logfiles open at once, ok? */
|
||||
typedef uint32 lfd_set;
|
||||
|
||||
@@ -319,8 +338,7 @@ retry:
|
||||
|
||||
static void flush_logfile(logfile *fp)
|
||||
{
|
||||
int len, cnt;
|
||||
int fd;
|
||||
int len, cnt, fd;
|
||||
char *bp;
|
||||
|
||||
len = fp->pos;
|
||||
@@ -442,11 +460,10 @@ struct callsite {
|
||||
};
|
||||
|
||||
/* NB: these counters are incremented and decremented only within tmmon. */
|
||||
static uint32 suppress_tracing = 0;
|
||||
static uint32 library_serial_generator = 0;
|
||||
static uint32 method_serial_generator = 0;
|
||||
static uint32 callsite_serial_generator = 0;
|
||||
static uint32 tmstats_serial_generator = 0;
|
||||
static uint32 library_serial_generator = 0;
|
||||
static uint32 method_serial_generator = 0;
|
||||
static uint32 callsite_serial_generator = 0;
|
||||
static uint32 tmstats_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};
|
||||
@@ -534,12 +551,11 @@ static PLHashTable *libraries = NULL;
|
||||
/* Table mapping method names to logged 'N' record serial numbers. */
|
||||
static PLHashTable *methods = NULL;
|
||||
|
||||
#if XP_WIN32
|
||||
#ifdef XP_WIN32
|
||||
|
||||
#define MAX_STACKFRAMES 256
|
||||
#define MAX_UNMANGLED_NAME_LEN 256
|
||||
|
||||
|
||||
|
||||
static callsite *calltree(int skip)
|
||||
{
|
||||
logfile *fp = logfp;
|
||||
@@ -570,19 +586,19 @@ static callsite *calltree(int skip)
|
||||
|
||||
ok = EnsureSymInitialized();
|
||||
if (! ok)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Get the context information for this thread. That way we will
|
||||
* know where our sp, fp, pc, etc. are and can fill in the
|
||||
* STACKFRAME with the initial values.
|
||||
* Get the context information for this thread. That way we will know
|
||||
* where our sp, fp, pc, etc. are, and we can fill in the STACKFRAME with
|
||||
* the initial values.
|
||||
*/
|
||||
context.ContextFlags = CONTEXT_FULL;
|
||||
ok = GetThreadContext(myThread, &context);
|
||||
if (! ok)
|
||||
return 0;
|
||||
return 0;
|
||||
|
||||
/* Setup initial stack frame to walk from */
|
||||
/* Setup initial stack frame from which to walk. */
|
||||
memset(&(frame[0]), 0, sizeof(frame[0]));
|
||||
frame[0].AddrPC.Offset = context.Eip;
|
||||
frame[0].AddrPC.Mode = AddrModeFlat;
|
||||
@@ -590,40 +606,38 @@ static callsite *calltree(int skip)
|
||||
frame[0].AddrStack.Mode = AddrModeFlat;
|
||||
frame[0].AddrFrame.Offset = context.Ebp;
|
||||
frame[0].AddrFrame.Mode = AddrModeFlat;
|
||||
while (1) {
|
||||
PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf;
|
||||
if (framenum)
|
||||
{
|
||||
memcpy(&(frame[framenum]),&(frame[framenum-1]),sizeof(STACKFRAME));
|
||||
}
|
||||
for (;;) {
|
||||
PIMAGEHLP_SYMBOL symbol = (PIMAGEHLP_SYMBOL) buf;
|
||||
if (framenum)
|
||||
memcpy(&(frame[framenum]),&(frame[framenum-1]),sizeof(STACKFRAME));
|
||||
|
||||
ok = _StackWalk(IMAGE_FILE_MACHINE_I386,
|
||||
myProcess,
|
||||
myThread,
|
||||
&(frame[framenum]),
|
||||
&context,
|
||||
0, /* read process memory routine */
|
||||
_SymFunctionTableAccess, /* function table access
|
||||
routine */
|
||||
_SymGetModuleBase, /* module base routine */
|
||||
0); /* translate address routine */
|
||||
ok = _StackWalk(IMAGE_FILE_MACHINE_I386,
|
||||
myProcess,
|
||||
myThread,
|
||||
&(frame[framenum]),
|
||||
&context,
|
||||
0, /* read process memory hook */
|
||||
_SymFunctionTableAccess, /* function table access hook */
|
||||
_SymGetModuleBase, /* module base hook */
|
||||
0); /* translate address hook */
|
||||
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
if (skip)
|
||||
{
|
||||
skip--;
|
||||
continue;/*skip tells us to skip the first skip amount of stackframes*/
|
||||
}
|
||||
if (frame[framenum].AddrPC.Offset == 0)
|
||||
break;
|
||||
framenum++;
|
||||
if (!ok)
|
||||
break;
|
||||
if (skip) {
|
||||
/* skip tells us to skip the first skip amount of stackframes */
|
||||
skip--;
|
||||
continue;
|
||||
}
|
||||
if (frame[framenum].AddrPC.Offset == 0)
|
||||
break;
|
||||
framenum++;
|
||||
}
|
||||
|
||||
depth = framenum;
|
||||
maxstack = (depth > tmstats.calltree_maxstack);
|
||||
if (maxstack)
|
||||
tmstats.calltree_maxstack = depth;
|
||||
|
||||
/* Reverse the stack again, finding and building a path in the tree. */
|
||||
parent = &calltree_root;
|
||||
do {
|
||||
@@ -675,17 +689,16 @@ static callsite *calltree(int skip)
|
||||
/*
|
||||
* Not in tree at all, or not logged to fp: let's find our symbolic
|
||||
* callsite info. XXX static syms are masked by nearest lower global
|
||||
* Load up the info for the dll.
|
||||
*/
|
||||
|
||||
if (!_SymGetModuleInfo(myProcess,frame[framenum].AddrPC.Offset,&imagehelp))/*load up the info for the dll*/
|
||||
{
|
||||
if (!_SymGetModuleInfo(myProcess,
|
||||
frame[framenum].AddrPC.Offset,
|
||||
&imagehelp)) {
|
||||
DWORD error = GetLastError();
|
||||
PR_ASSERT(error);
|
||||
library = "unknown";/* ew */
|
||||
}
|
||||
else
|
||||
{
|
||||
library = imagehelp.ModuleName;
|
||||
library = "unknown"; /* XXX mjudge sez "ew!" */
|
||||
} else {
|
||||
library = imagehelp.ModuleName;
|
||||
}
|
||||
|
||||
symbol = (PIMAGEHLP_SYMBOL) buf;
|
||||
@@ -842,9 +855,8 @@ static callsite *calltree(int skip)
|
||||
return site;
|
||||
}
|
||||
|
||||
#else /*XP_UNIX*/
|
||||
|
||||
#else
|
||||
/*XP_UNIX*/
|
||||
static callsite *calltree(uint32 *bp)
|
||||
{
|
||||
logfile *fp = logfp;
|
||||
@@ -1116,8 +1128,7 @@ backtrace(int skip)
|
||||
return site;
|
||||
}
|
||||
|
||||
#else
|
||||
/*XP_UNIX*/
|
||||
#else /*XP_UNIX*/
|
||||
|
||||
callsite *
|
||||
backtrace(int skip)
|
||||
@@ -1153,7 +1164,7 @@ backtrace(int skip)
|
||||
}
|
||||
|
||||
|
||||
#endif /*XP_WIN32*/
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
|
||||
typedef struct allocation {
|
||||
@@ -1228,7 +1239,7 @@ static PLHashTable *new_allocations(void)
|
||||
|
||||
#define get_allocations() (allocations ? allocations : new_allocations())
|
||||
|
||||
#if XP_UNIX
|
||||
#ifdef XP_UNIX
|
||||
|
||||
__ptr_t malloc(size_t size)
|
||||
{
|
||||
@@ -1238,8 +1249,7 @@ __ptr_t malloc(size_t size)
|
||||
allocation *alloc;
|
||||
|
||||
ptr = __libc_malloc(size);
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.malloc_calls++;
|
||||
if (!ptr) {
|
||||
tmstats.malloc_failures++;
|
||||
@@ -1257,8 +1267,7 @@ __ptr_t malloc(size_t size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -1270,8 +1279,7 @@ __ptr_t calloc(size_t count, size_t size)
|
||||
allocation *alloc;
|
||||
|
||||
ptr = __libc_calloc(count, size);
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.calloc_calls++;
|
||||
if (!ptr) {
|
||||
tmstats.calloc_failures++;
|
||||
@@ -1290,8 +1298,7 @@ __ptr_t calloc(size_t count, size_t size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -1304,8 +1311,7 @@ __ptr_t realloc(__ptr_t ptr, size_t size)
|
||||
PLHashEntry **hep, *he;
|
||||
allocation *alloc;
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.realloc_calls++;
|
||||
if (suppress_tracing == 0) {
|
||||
oldptr = ptr;
|
||||
@@ -1323,13 +1329,11 @@ __ptr_t realloc(__ptr_t ptr, size_t size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
|
||||
ptr = __libc_realloc(ptr, size);
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
if (!ptr && size) {
|
||||
/*
|
||||
* When realloc() fails, the original block is not freed or moved, so
|
||||
@@ -1346,8 +1350,9 @@ __ptr_t realloc(__ptr_t ptr, size_t size)
|
||||
suppress_tracing++;
|
||||
if (ptr != oldptr) {
|
||||
/*
|
||||
* If we're reallocating (not allocating new space by passing
|
||||
* null to realloc) and realloc moved the block, free oldptr.
|
||||
* If we're reallocating (not merely allocating new space by
|
||||
* passing null to realloc) and realloc has moved the block,
|
||||
* free oldptr.
|
||||
*/
|
||||
if (he)
|
||||
PL_HashTableRemove(allocations, oldptr);
|
||||
@@ -1356,8 +1361,8 @@ __ptr_t realloc(__ptr_t ptr, size_t size)
|
||||
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 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);
|
||||
@@ -1369,8 +1374,7 @@ __ptr_t realloc(__ptr_t ptr, size_t size)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -1380,8 +1384,7 @@ void free(__ptr_t ptr)
|
||||
callsite *site;
|
||||
allocation *alloc;
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.free_calls++;
|
||||
if (!ptr) {
|
||||
tmstats.null_free_calls++;
|
||||
@@ -1393,17 +1396,18 @@ void free(__ptr_t ptr)
|
||||
site = (callsite*) he->value;
|
||||
if (site) {
|
||||
alloc = (allocation*) he;
|
||||
log_event2(logfp, TM_EVENT_FREE, site->serial, alloc->size);
|
||||
log_event2(logfp, TM_EVENT_FREE, site->serial,
|
||||
alloc->size);
|
||||
}
|
||||
PL_HashTableRawRemove(allocations, hep, he);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
__libc_free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* XP_UNIX */
|
||||
|
||||
static const char magic[] = NS_TRACE_MALLOC_MAGIC;
|
||||
|
||||
@@ -1426,10 +1430,11 @@ PR_IMPLEMENT(void) NS_TraceMallocStartup(int logfd)
|
||||
|
||||
atexit(NS_TraceMallocShutdown);
|
||||
tmmon = PR_NewMonitor();
|
||||
/*register listeners for win32*/
|
||||
|
||||
#ifdef XP_WIN32
|
||||
/* Register listeners for win32. */
|
||||
{
|
||||
StartupHooker();
|
||||
StartupHooker();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1494,8 +1499,8 @@ PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[])
|
||||
int pipefds[2];
|
||||
|
||||
switch (*tmlogname) {
|
||||
#if XP_UNIX
|
||||
case '|':
|
||||
#ifdef XP_UNIX
|
||||
case '|':
|
||||
if (pipe(pipefds) == 0) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
@@ -1544,7 +1549,7 @@ PR_IMPLEMENT(int) NS_TraceMallocStartupArgs(int argc, char* argv[])
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
#endif /*XP_UNIX*/
|
||||
#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" */
|
||||
@@ -1610,32 +1615,26 @@ PR_IMPLEMENT(void) NS_TraceMallocDisable()
|
||||
{
|
||||
logfile *fp;
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
for (fp = logfile_list; fp; fp = fp->next)
|
||||
flush_logfile(fp);
|
||||
suppress_tracing++;
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void) NS_TraceMallocEnable()
|
||||
{
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
suppress_tracing--;
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
|
||||
PR_IMPLEMENT(int) NS_TraceMallocChangeLogFD(int fd)
|
||||
{
|
||||
logfile *oldfp, *fp;
|
||||
struct stat sb;
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
oldfp = logfp;
|
||||
if (oldfp->fd != fd) {
|
||||
flush_logfile(oldfp);
|
||||
@@ -1646,13 +1645,10 @@ PR_IMPLEMENT(int) NS_TraceMallocChangeLogFD(int fd)
|
||||
(void) write(fd, magic, NS_TRACE_MALLOC_MAGIC_SIZE);
|
||||
logfp = fp;
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
return oldfp->fd;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PRIntn
|
||||
lfd_clr_enumerator(PLHashEntry *he, PRIntn i, void *arg)
|
||||
{
|
||||
@@ -1667,7 +1663,7 @@ 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);
|
||||
@@ -1678,8 +1674,7 @@ NS_TraceMallocCloseLogFD(int fd)
|
||||
{
|
||||
logfile *fp;
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
|
||||
fp = get_logfile(fd);
|
||||
if (fp) {
|
||||
@@ -1710,44 +1705,39 @@ NS_TraceMallocCloseLogFD(int fd)
|
||||
}
|
||||
}
|
||||
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
close(fd);
|
||||
}
|
||||
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
NS_TraceMallocLogTimestamp(const char *caption)
|
||||
{
|
||||
logfile *fp;
|
||||
#if defined(XP_UNIX)
|
||||
#ifdef XP_UNIX
|
||||
struct timeval tv;
|
||||
#endif
|
||||
#if defined(XP_WIN32)
|
||||
#ifdef XP_WIN32
|
||||
struct _timeb tb;
|
||||
#endif
|
||||
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
|
||||
fp = logfp;
|
||||
log_byte(fp, TM_EVENT_TIMESTAMP);
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
#ifdef XP_UNIX
|
||||
gettimeofday(&tv, NULL);
|
||||
log_uint32(fp, (uint32) tv.tv_sec);
|
||||
log_uint32(fp, (uint32) tv.tv_usec);
|
||||
#endif
|
||||
#if defined(XP_WIN32)
|
||||
#ifdef XP_WIN32
|
||||
_ftime(&tb);
|
||||
log_uint32(fp, (uint32) tb.time);
|
||||
log_uint32(fp, (uint32) tb.millitm);
|
||||
#endif
|
||||
log_string(fp, caption);
|
||||
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
static PRIntn
|
||||
@@ -1775,6 +1765,18 @@ allocation_enumerator(PLHashEntry *he, PRIntn i, void *arg)
|
||||
return HT_ENUMERATE_NEXT;
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
NS_TraceStack(int skip, FILE *ofp)
|
||||
{
|
||||
callsite *site;
|
||||
|
||||
site = backtrace(skip + 1);
|
||||
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)
|
||||
@@ -1796,32 +1798,28 @@ NS_TraceMallocFlushLogfiles()
|
||||
{
|
||||
logfile *fp;
|
||||
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
TM_ENTER_MONITOR();
|
||||
|
||||
for (fp = logfile_list; fp; fp = fp->next)
|
||||
flush_logfile(fp);
|
||||
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
#ifdef XP_WIN32
|
||||
|
||||
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
PR_IMPLEMENT(void)
|
||||
MallocCallback(void *aPtr, size_t size)
|
||||
{
|
||||
callsite *site;
|
||||
PLHashEntry *he;
|
||||
allocation *alloc;
|
||||
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.malloc_calls++;
|
||||
if (!aPtr) {
|
||||
tmstats.malloc_failures++;
|
||||
} else if (suppress_tracing == 0) {
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
site = backtrace(4);
|
||||
if (site)
|
||||
log_event2(logfp, TM_EVENT_MALLOC, site->serial, size);
|
||||
@@ -1834,13 +1832,10 @@ MallocCallback(void *aPtr, size_t size)
|
||||
alloc->size = size;
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
}
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
CallocCallback(void *ptr, size_t count, size_t size)
|
||||
{
|
||||
@@ -1848,12 +1843,11 @@ CallocCallback(void *ptr, size_t count, size_t size)
|
||||
PLHashEntry *he;
|
||||
allocation *alloc;
|
||||
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.calloc_calls++;
|
||||
if (!ptr) {
|
||||
tmstats.calloc_failures++;
|
||||
} else if (suppress_tracing == 0) {
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
site = backtrace(1);
|
||||
size *= count;
|
||||
if (site)
|
||||
@@ -1867,9 +1861,8 @@ CallocCallback(void *ptr, size_t count, size_t size)
|
||||
alloc->size = size;
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
}
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
@@ -1881,13 +1874,12 @@ ReallocCallback(void * oldptr, void *ptr, size_t size)
|
||||
PLHashEntry **hep, *he;
|
||||
allocation *alloc;
|
||||
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.realloc_calls++;
|
||||
if (suppress_tracing == 0) {
|
||||
oldsite = NULL;
|
||||
oldsize = 0;
|
||||
he = NULL;
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
if (oldptr && get_allocations()) {
|
||||
hash = hash_pointer(oldptr);
|
||||
hep = PL_HashTableRawLookup(allocations, hash, oldptr);
|
||||
@@ -1898,31 +1890,15 @@ ReallocCallback(void * oldptr, void *ptr, size_t size)
|
||||
oldsize = alloc->size;
|
||||
}
|
||||
}
|
||||
#ifdef EXIT_TMMON_AROUND_REALLOC
|
||||
/* XXX rusty.lynch@intel.com found that oldsize gets corrupted on
|
||||
his SMP Linux box occasionally, unless tmmon is held across
|
||||
the call to __libc_realloc. Figure out why that stack var
|
||||
is being trashed, and until then use his workaround. */
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
#endif
|
||||
}
|
||||
if (!ptr && size) {
|
||||
tmstats.realloc_failures++;
|
||||
#ifndef EXIT_TMMON_AROUND_REALLOC
|
||||
if (tmmon && suppress_tracing == 0)
|
||||
PR_ExitMonitor(tmmon);
|
||||
#endif
|
||||
}
|
||||
if (!ptr && size) {
|
||||
tmstats.realloc_failures++;
|
||||
|
||||
/*
|
||||
* When realloc() fails, the original block is not freed or moved, so
|
||||
* we'll leave the allocation entry untouched.
|
||||
*/
|
||||
} else if (suppress_tracing == 0) {
|
||||
#ifdef EXIT_TMMON_AROUND_REALLOC
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
#endif
|
||||
/*
|
||||
* When realloc() fails, the original block is not freed or moved, so
|
||||
* we'll leave the allocation entry untouched.
|
||||
*/
|
||||
} else if (suppress_tracing == 0) {
|
||||
site = backtrace(1);
|
||||
if (site) {
|
||||
log_event4(logfp, TM_EVENT_REALLOC, site->serial, size,
|
||||
@@ -1954,9 +1930,8 @@ ReallocCallback(void * oldptr, void *ptr, size_t size)
|
||||
alloc->size = size;
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
}
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
PR_IMPLEMENT(void)
|
||||
@@ -1966,12 +1941,11 @@ FreeCallback(void * ptr)
|
||||
callsite *site;
|
||||
allocation *alloc;
|
||||
|
||||
TM_ENTER_MONITOR();
|
||||
tmstats.free_calls++;
|
||||
if (!ptr) {
|
||||
tmstats.null_free_calls++;
|
||||
} else if (suppress_tracing == 0) {
|
||||
if (tmmon)
|
||||
PR_EnterMonitor(tmmon);
|
||||
if (get_allocations()) {
|
||||
hep = PL_HashTableRawLookup(allocations, hash_pointer(ptr), ptr);
|
||||
he = *hep;
|
||||
@@ -1984,11 +1958,10 @@ FreeCallback(void * ptr)
|
||||
PL_HashTableRawRemove(allocations, hep, he);
|
||||
}
|
||||
}
|
||||
if (tmmon)
|
||||
PR_ExitMonitor(tmmon);
|
||||
}
|
||||
TM_EXIT_MONITOR();
|
||||
}
|
||||
|
||||
#endif /*XP_WIN32*/
|
||||
|
||||
|
||||
#endif /* NS_TRACE_MALLOC */
|
||||
|
||||
@@ -161,6 +161,15 @@ PR_EXTERN(void) NS_TraceMallocCloseLogFD(int fd);
|
||||
*/
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user