зеркало из https://github.com/mozilla/gecko-dev.git
Getting gc leak-detector to work on linux. Non-nspr changes. code=beard,wade r=warren
This commit is contained in:
Родитель
0a7bf6c176
Коммит
80ee64b1e3
|
@ -55,13 +55,13 @@ DIRS += \
|
|||
$(NULL)
|
||||
endif
|
||||
|
||||
DIRS += $(NSPRPUB_DIR)
|
||||
|
||||
# boehm needs to be built before XPCOM
|
||||
ifdef GC_LEAK_DETECTOR
|
||||
DIRS += gc/boehm
|
||||
endif
|
||||
|
||||
DIRS += $(NSPRPUB_DIR)
|
||||
|
||||
DIRS += dbm modules/libreg js xpcom js/src/xpconnect
|
||||
|
||||
ifdef MOZ_OJI
|
||||
|
|
|
@ -5,3 +5,4 @@ NO_MDUPDATE=@MOZ_NSPRENV_NO_MDUPDATE@
|
|||
NS_USE_NATIVE=@MOZ_NSPRENV_NS_USE_NATIVE@
|
||||
MOZILLA_CLIENT=@MOZ_NSPRENV_MOZILLA_CLIENT@
|
||||
CLASSIC_NSPR=@MOZ_NSPRENV_CLASSIC_NSPR@
|
||||
GC_LEAK_DETECTOR=@MOZ_NSPRENV_GC_LEAK_DETECTOR@
|
||||
|
|
|
@ -9900,7 +9900,6 @@ if test "${enable_tests+set}" = set; then
|
|||
fi
|
||||
|
||||
|
||||
|
||||
MOZ_MONOLITHIC_TOOLKIT=1
|
||||
|
||||
case "$target" in
|
||||
|
@ -11611,6 +11610,8 @@ then
|
|||
|
||||
MOZ_NSPRENV_USE_PTHREADS=$USE_PTHREADS
|
||||
|
||||
MOZ_NSPRENV_GC_LEAK_DETECTOR=$GC_LEAK_DETECTOR
|
||||
|
||||
MOZ_NSPRENV_CLASSIC_NSPR=
|
||||
case "$target" in
|
||||
*-linux*)
|
||||
|
@ -11670,6 +11671,7 @@ esac
|
|||
|
||||
|
||||
|
||||
|
||||
fi
|
||||
|
||||
|
||||
|
@ -12076,6 +12078,7 @@ s%@MOZ_NSPRENV_MOZILLA_CLIENT@%$MOZ_NSPRENV_MOZILLA_CLIENT%g
|
|||
s%@MOZ_NSPRENV_CLASSIC_NSPR@%$MOZ_NSPRENV_CLASSIC_NSPR%g
|
||||
s%@MOZ_NSPRENV_DIST@%$MOZ_NSPRENV_DIST%g
|
||||
s%@MOZ_NSPRENV_OVERRIDE_MAKE@%$MOZ_NSPRENV_OVERRIDE_MAKE%g
|
||||
s%@MOZ_NSPRENV_GC_LEAK_DETECTOR@%$MOZ_NSPRENV_GC_LEAK_DETECTOR%g
|
||||
s%@MOZ_DEFINES@%$MOZ_DEFINES%g
|
||||
|
||||
CEOF
|
||||
|
|
|
@ -3939,6 +3939,11 @@ dnl Same as detected above.
|
|||
dnl
|
||||
MOZ_NSPRENV_USE_PTHREADS=$USE_PTHREADS
|
||||
|
||||
dnl
|
||||
dnl GC_LEAK_DETECTOR
|
||||
dnl
|
||||
MOZ_NSPRENV_GC_LEAK_DETECTOR=$GC_LEAK_DETECTOR
|
||||
|
||||
dnl
|
||||
dnl CLASSIC_NSPR
|
||||
dnl
|
||||
|
@ -4037,6 +4042,7 @@ AC_SUBST(MOZ_NSPRENV_MOZILLA_CLIENT)
|
|||
AC_SUBST(MOZ_NSPRENV_CLASSIC_NSPR)
|
||||
AC_SUBST(MOZ_NSPRENV_DIST)
|
||||
AC_SUBST(MOZ_NSPRENV_OVERRIDE_MAKE)
|
||||
AC_SUBST(MOZ_NSPRENV_GC_LEAK_DETECTOR)
|
||||
fi
|
||||
dnl ========================================================
|
||||
|
||||
|
|
|
@ -27,12 +27,17 @@ include $(DEPTH)/config/autoconf.mk
|
|||
MODULE=boehm
|
||||
LIBRARY_NAME=boehm
|
||||
|
||||
DEFINES += -DATOMIC_UNCOLLECTABLE -DNO_SIGNALS -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS -DSILENT -DLARGE_CONFIG
|
||||
DEFINES += -DNO_SIGNALS -DNO_EXECUTE_PERMISSION -DALL_INTERIOR_POINTERS -DLARGE_CONFIG
|
||||
|
||||
DEFINES += -DREDIRECT_MALLOC=GC_malloc
|
||||
# Define following when attempting to take over ALL calls to malloc/free. For now just
|
||||
# intercepting new/delete to concentrate on making collector work on Linux.
|
||||
#DEFINES += -DREDIRECT_MALLOC=GC_MALLOC_UNCOLLECTABLE
|
||||
DEFINES += -DREDIRECT_MALLOC=GC_MALLOC
|
||||
#DEFINES += -DSILENT
|
||||
|
||||
ifeq ($(OS_ARCH),Linux)
|
||||
DEFINES += -DLINUX_THREADS -D_REENTRANT
|
||||
#DEFINES += -DLINUX_THREADS -D_REENTRANT
|
||||
DEFINES += -DTHREADS -DGENERIC_THREADS -D_REENTRANT -DGC_DEBUG -DFIND_LEAK -DOPERATOR_NEW_ARRAY -DSAVE_CALL_CHAIN -DUSE_PROC
|
||||
endif
|
||||
ifdef ($(OS_ARCH)$(OS_RELEASE),SUNOS5)
|
||||
DEFINES += -DSOLARIS_THREADS -D_SOLARIS_PTHREADS -D_REENTRANT
|
||||
|
@ -83,4 +88,6 @@ LOBJS := $(LCPPSRCS:.cc=.$(OBJ_SUFFIX))
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
export::
|
||||
make install
|
||||
|
||||
|
|
|
@ -408,6 +408,10 @@ GC_PTR p;
|
|||
register GC_PTR base = GC_base(p);
|
||||
register ptr_t clobbered;
|
||||
|
||||
/* ignore free(NULL) */
|
||||
if (p == 0)
|
||||
return;
|
||||
|
||||
if (base == 0) {
|
||||
GC_err_printf1("Attempt to free invalid pointer %lx\n",
|
||||
(unsigned long)p);
|
||||
|
|
|
@ -260,7 +260,76 @@ void GC_register_dynamic_libraries()
|
|||
# endif /* !USE_PROC ... */
|
||||
# endif /* SUNOS */
|
||||
|
||||
#if defined(LINUX) && defined(__ELF__) || defined(SCO_ELF)
|
||||
#if defined(LINUX) && defined(USE_PROC)
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#define BUFSIZE 32000
|
||||
|
||||
/* Register all possible root segments using kernel proces info read
|
||||
from /proc. This adds every read/write piece of the virtual address
|
||||
space to the root set, so it does more than register dynamic
|
||||
libraries */
|
||||
void GC_register_dynamic_libraries()
|
||||
{
|
||||
int mapfile;
|
||||
char *fname = "/proc/self/maps";
|
||||
unsigned int start, end, offset, inode;
|
||||
char perms[10], path[512];
|
||||
static char buffer[BUFSIZE];
|
||||
int e;
|
||||
|
||||
|
||||
GC_printf0("[[register mmap data start.]]\n");
|
||||
memset(buffer,0,BUFSIZE);
|
||||
mapfile = open(fname, O_RDONLY); /* Don't use fopen - it mallocs */
|
||||
offset = 0;
|
||||
do {
|
||||
e = read(mapfile, buffer + offset, BUFSIZE - offset - 1);
|
||||
offset = offset + e;
|
||||
} while (e > 0);
|
||||
|
||||
if (offset >= (BUFSIZE - 1)) {
|
||||
ABORT("map buffer too small\n");
|
||||
} else {
|
||||
int result, count;
|
||||
|
||||
char *next = buffer;
|
||||
|
||||
close(mapfile);
|
||||
buffer[offset] = '\0';
|
||||
do {
|
||||
result = sscanf(next,
|
||||
"%x-%x %s %x %*s %d %n",
|
||||
&start, &end, perms, &offset, &inode, &count);
|
||||
next = next + count;
|
||||
if (result > 0) {
|
||||
char *c = strstr(perms, "rw");
|
||||
int isroot = (c != 0);
|
||||
/* GC_printf6("%8x-%8x %s %8x device %8d %d",
|
||||
start, end, perms, offset, inode, isroot); */
|
||||
if (inode != 0) {
|
||||
result = sscanf(next, "%s\n%n", path, &count);
|
||||
next = next + count;
|
||||
} else {
|
||||
strcpy(path, "mmap zero"); /* dumb... */
|
||||
}
|
||||
GC_printf3("[[registering roots %8x-%8x for mmap: %s]]\n",
|
||||
start, end, path);
|
||||
if (isroot) {
|
||||
GC_add_roots_inner((char *)start, (char *)end, TRUE);
|
||||
}
|
||||
}
|
||||
} while (result > 0);
|
||||
}
|
||||
GC_printf0("[[register mmap data finish.]]\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(LINUX) && !defined(USE_PROC)
|
||||
|
||||
/* This code shouldn't be used anymore - the /proc version is more complete */
|
||||
|
||||
/* Dynamic loading code for Linux running ELF. Somewhat tested on
|
||||
* Linux/x86, untested but hopefully should work on Linux/Alpha.
|
||||
|
@ -311,6 +380,8 @@ void GC_register_dynamic_libraries()
|
|||
struct link_map *lm = GC_FirstDLOpenedLinkMap();
|
||||
|
||||
|
||||
GC_printf0("[[register dynamic libraries start.]]\n");
|
||||
|
||||
for (lm = GC_FirstDLOpenedLinkMap();
|
||||
lm != (struct link_map *) 0; lm = lm->l_next)
|
||||
{
|
||||
|
@ -320,6 +391,8 @@ void GC_register_dynamic_libraries()
|
|||
char * start;
|
||||
register int i;
|
||||
|
||||
GC_printf1("[[registering roots for library: %s]]\n", lm->l_name);
|
||||
|
||||
e = (ElfW(Ehdr) *) lm->l_addr;
|
||||
p = ((ElfW(Phdr) *)(((char *)(e)) + e->e_phoff));
|
||||
offset = ((unsigned long)(lm->l_addr));
|
||||
|
@ -336,7 +409,12 @@ void GC_register_dynamic_libraries()
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* as a hack, register the link_map itself as a root. */
|
||||
GC_add_roots_inner(lm, lm + 1, TRUE);
|
||||
}
|
||||
|
||||
GC_printf0("[[register dynamic libraries finish.]]\n");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -26,11 +26,15 @@ Authors: John R. Ellis and Jesse Hull
|
|||
|
||||
#include "gc_cpp.h"
|
||||
|
||||
void* operator new( size_t size ) {
|
||||
return GC_MALLOC_UNCOLLECTABLE( size );}
|
||||
void* operator new( size_t size )
|
||||
{
|
||||
return GC_MALLOC( size );
|
||||
}
|
||||
|
||||
void operator delete( void* obj ) {
|
||||
GC_FREE( obj );}
|
||||
void operator delete( void* obj )
|
||||
{
|
||||
GC_FREE( obj );
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// This new operator is used by VC++ in case of Debug builds !
|
||||
|
@ -49,11 +53,15 @@ void* operator new( size_t size,
|
|||
|
||||
#ifdef OPERATOR_NEW_ARRAY
|
||||
|
||||
void* operator new[]( size_t size ) {
|
||||
return GC_MALLOC_UNCOLLECTABLE( size );}
|
||||
void* operator new[]( size_t size )
|
||||
{
|
||||
return GC_MALLOC( size );
|
||||
}
|
||||
|
||||
void operator delete[]( void* obj ) {
|
||||
GC_FREE( obj );}
|
||||
void operator delete[]( void* obj )
|
||||
{
|
||||
GC_FREE( obj );
|
||||
}
|
||||
|
||||
#endif /* OPERATOR_NEW_ARRAY */
|
||||
|
||||
|
|
|
@ -441,6 +441,7 @@ void GC_print_callers (/* struct callinfo info[NFRAMES] */);
|
|||
# define UNLOCK() mutex_unlock(&GC_allocate_ml);
|
||||
# endif
|
||||
# ifdef LINUX_THREADS
|
||||
#error "DADDY?"
|
||||
# include <pthread.h>
|
||||
# ifdef __i386__
|
||||
inline static int GC_test_and_set(volatile unsigned int *addr) {
|
||||
|
|
|
@ -661,7 +661,7 @@
|
|||
# endif
|
||||
# ifdef LINUX
|
||||
# define OS_TYPE "LINUX"
|
||||
# define STACKBOTTOM ((ptr_t)0xc0000000)
|
||||
# define STACKBOTTOM ((ptr_t)0xbffffb44) /* address of argv */
|
||||
/* Appears to be 0xe0000000 for at least one 2.1.91 kernel. */
|
||||
/* Probably needs to be more flexible, but I don't yet */
|
||||
/* fully understand how flexible. */
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
/*
|
||||
generic_threads.c
|
||||
|
||||
A module that permits clients of the GC to supply callback functions
|
||||
for thread stack scanning.
|
||||
|
||||
by Patrick C. Beard.
|
||||
generic_threads.c
|
||||
|
||||
A module that permits clients of the GC to supply callback functions
|
||||
for thread stack scanning.
|
||||
|
||||
by Patrick C. Beard.
|
||||
*/
|
||||
|
||||
#include "generic_threads.h"
|
||||
|
@ -13,10 +13,14 @@
|
|||
|
||||
static void mark_range(char* begin, char* end)
|
||||
{
|
||||
while (begin < end) {
|
||||
GC_PUSH_ONE_STACK(*(word*)begin, 0);
|
||||
begin += ALIGNMENT;
|
||||
}
|
||||
/* use the mark stack API, which will do more sanity checking. */
|
||||
GC_push_all(begin, end);
|
||||
/*
|
||||
while (begin < end) {
|
||||
GC_PUSH_ONE_STACK(*(word*)begin, 0);
|
||||
begin += ALIGNMENT;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -27,9 +31,9 @@ static void mark_range(char* begin, char* end)
|
|||
static void default_mark_all_stacks(GC_mark_range_proc marker)
|
||||
{
|
||||
#ifdef STACK_GROWS_DOWN
|
||||
mark_range(GC_approx_sp(), GC_get_stack_base());
|
||||
mark_range(GC_approx_sp(), GC_get_stack_base());
|
||||
#else
|
||||
mark_range(GC_get_stack_base(), GC_approx_sp());
|
||||
mark_range(GC_get_stack_base(), GC_approx_sp());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -43,34 +47,34 @@ GC_generic_proc GC_generic_stopper = &default_proc;
|
|||
GC_generic_proc GC_generic_starter = &default_proc;
|
||||
|
||||
void GC_generic_init_threads(GC_generic_mark_all_stacks_proc mark_all_stacks,
|
||||
void* mutex,
|
||||
GC_generic_proc locker, GC_generic_proc unlocker,
|
||||
GC_generic_proc stopper, GC_generic_proc starter)
|
||||
void* mutex,
|
||||
GC_generic_proc locker, GC_generic_proc unlocker,
|
||||
GC_generic_proc stopper, GC_generic_proc starter)
|
||||
{
|
||||
GC_generic_mark_all_stacks = mark_all_stacks;
|
||||
GC_generic_mutex = mutex;
|
||||
GC_generic_locker = locker;
|
||||
GC_generic_unlocker = unlocker;
|
||||
GC_generic_stopper = stopper;
|
||||
GC_generic_starter = starter;
|
||||
GC_generic_mark_all_stacks = mark_all_stacks;
|
||||
GC_generic_mutex = mutex;
|
||||
GC_generic_locker = locker;
|
||||
GC_generic_unlocker = unlocker;
|
||||
GC_generic_stopper = stopper;
|
||||
GC_generic_starter = starter;
|
||||
|
||||
GC_dont_expand = 1;
|
||||
// GC_set_max_heap_size(20L * 1024L * 1024L);
|
||||
GC_dont_expand = 1;
|
||||
// GC_set_max_heap_size(20L * 1024L * 1024L);
|
||||
}
|
||||
|
||||
#if !defined(WIN32_THREADS) && !defined(LINUX_THREADS)
|
||||
void GC_push_all_stacks()
|
||||
{
|
||||
GC_generic_mark_all_stacks(&mark_range);
|
||||
GC_generic_mark_all_stacks(&mark_range);
|
||||
}
|
||||
|
||||
void GC_stop_world()
|
||||
{
|
||||
GC_generic_stopper(GC_generic_mutex);
|
||||
GC_generic_stopper(GC_generic_mutex);
|
||||
}
|
||||
|
||||
void GC_start_world()
|
||||
{
|
||||
GC_generic_starter(GC_generic_mutex);
|
||||
GC_generic_starter(GC_generic_mutex);
|
||||
}
|
||||
#endif /* WIN32_THREADS */
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
/* Boehm, February 7, 1996 4:32 pm PST */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "gc_priv.h"
|
||||
|
||||
extern ptr_t GC_clear_stack(); /* in misc.c, behaves like identity */
|
||||
|
@ -354,7 +356,7 @@ int obj_kind;
|
|||
size_t lb;
|
||||
# endif
|
||||
{
|
||||
return(GC_realloc(p, lb));
|
||||
return(GC_REALLOC(p, lb));
|
||||
}
|
||||
# endif /* REDIRECT_MALLOC */
|
||||
|
||||
|
@ -429,7 +431,16 @@ int obj_kind;
|
|||
# endif
|
||||
{
|
||||
# ifndef IGNORE_FREE
|
||||
GC_free(p);
|
||||
GC_FREE(p);
|
||||
# endif
|
||||
}
|
||||
# endif /* REDIRECT_MALLOC */
|
||||
|
||||
/* fake __mmap() */
|
||||
|
||||
__ptr_t
|
||||
__mmap (__ptr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
|
||||
{
|
||||
raise(SIGINT);
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ void GC_mark_from_mark_stack()
|
|||
# define SPLIT_RANGE_WORDS 128 /* Must be power of 2. */
|
||||
|
||||
GC_objects_are_marked = TRUE;
|
||||
# ifdef OS2 /* Use untweaked version to circumvent compiler problem */
|
||||
# if defined(OS2) /* Use untweaked version to circumvent compiler problem */
|
||||
while (GC_mark_stack_top_reg >= GC_mark_stack_reg && credit >= 0) {
|
||||
# else
|
||||
while ((((ptr_t)GC_mark_stack_top_reg - (ptr_t)GC_mark_stack_reg) | credit)
|
||||
|
|
|
@ -858,7 +858,35 @@ void GC_print_callers(struct callinfo info[NFRAMES])
|
|||
}
|
||||
}
|
||||
|
||||
#endif /* NFRAMES > 1 */
|
||||
#endif /* NFRAMES > 2 */
|
||||
|
||||
#elif defined(LINUX)
|
||||
|
||||
#define __USE_GNU
|
||||
#include <dlfcn.h>
|
||||
#include "call_tree.h"
|
||||
|
||||
void GC_print_callers(struct callinfo info[NFRAMES])
|
||||
{
|
||||
register int i;
|
||||
call_tree* current_tree;
|
||||
Dl_info dlinfo;
|
||||
/* static char symbol_name[1024], unmangled_name[1024], file_name[256]; */
|
||||
|
||||
current_tree = (call_tree*)(info[0].ci_pc);
|
||||
|
||||
GC_err_printf0("Callers at location:\n");
|
||||
while (current_tree && current_tree->pc) {
|
||||
if (dladdr(current_tree->pc, &dlinfo) >= 0) {
|
||||
GC_err_printf4("%s[%s,0x%08X,0x%08X]\n", dlinfo.dli_sname, dlinfo.dli_fname, current_tree->pc, dlinfo.dli_saddr);
|
||||
} else {
|
||||
/* pc2name((word)current_tree->pc, symbol_name, sizeof(symbol_name)); */
|
||||
/* MWUnmangle(symbol_name, unmangled_name, sizeof(unmangled_name)); */
|
||||
GC_err_printf2("%s(%08X)\n", "(unknown)", current_tree->pc);
|
||||
}
|
||||
current_tree = current_tree->parent;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
|
|
@ -1862,6 +1862,7 @@ word len;
|
|||
((ptr_t)end_block - (ptr_t)start_block) + HBLKSIZE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifndef MSWIN32
|
||||
/* Replacement for UNIX system call. */
|
||||
/* Other calls that write to the heap */
|
||||
|
@ -1902,6 +1903,8 @@ word len;
|
|||
return(result);
|
||||
}
|
||||
#endif /* !MSWIN32 */
|
||||
#endif
|
||||
|
||||
|
||||
/*ARGSUSED*/
|
||||
GC_bool GC_page_was_ever_dirty(h)
|
||||
|
@ -2392,3 +2395,86 @@ void GC_save_callers(struct callinfo info[NFRAMES])
|
|||
#endif
|
||||
|
||||
#endif /* POWERPC && MACOS */
|
||||
|
||||
#if defined(SAVE_CALL_CHAIN) && defined(LINUX)
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
#include "call_tree.h"
|
||||
|
||||
typedef struct stack_frame stack_frame;
|
||||
|
||||
#if defined(__i386)
|
||||
struct stack_frame {
|
||||
stack_frame* next;
|
||||
void* pc;
|
||||
};
|
||||
|
||||
static stack_frame* getStackFrame()
|
||||
{
|
||||
jmp_buf jb;
|
||||
stack_frame* currentFrame;
|
||||
setjmp(jb);
|
||||
currentFrame = (stack_frame*)(jb[0].__jmpbuf[JB_BP]);
|
||||
currentFrame = currentFrame->next;
|
||||
return currentFrame;
|
||||
}
|
||||
#endif /* __i386 */
|
||||
|
||||
static call_tree* find_tree(stack_frame* frame)
|
||||
{
|
||||
/* primordial root of the call tree. */
|
||||
static call_tree root = { 0, 0, 0, 0 };
|
||||
|
||||
long pc = (long)frame->pc;
|
||||
|
||||
if ((pc < 0x08000000) || (pc > 0x7fffffff) || (frame->next < frame)) {
|
||||
return &root;
|
||||
} else {
|
||||
call_tree* parent = find_tree(frame->next);
|
||||
call_tree** link = &parent->children;
|
||||
call_tree* tree = *link;
|
||||
while (tree != NULL) {
|
||||
if (tree->pc == frame->pc)
|
||||
break;
|
||||
link = &tree->siblings;
|
||||
tree = *link;
|
||||
}
|
||||
if (tree == NULL) {
|
||||
/* no tree exists for this frame, so we create one. */
|
||||
tree = (call_tree*) GC_scratch_alloc(sizeof(call_tree));
|
||||
if (tree != NULL) {
|
||||
tree->pc = frame->pc;
|
||||
tree->parent = parent;
|
||||
tree->siblings = parent->children;
|
||||
parent->children = tree;
|
||||
tree->children = NULL;
|
||||
}
|
||||
} else {
|
||||
if (parent->children != tree) {
|
||||
/* splay tree to front of list. */
|
||||
*link = tree->siblings;
|
||||
tree->siblings = parent->children;
|
||||
parent->children = tree;
|
||||
}
|
||||
}
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
|
||||
void GC_save_callers(struct callinfo info[NFRAMES])
|
||||
{
|
||||
stack_frame* currentFrame;
|
||||
call_tree* currentTree;
|
||||
|
||||
currentFrame = getStackFrame(); // GC_save_callers's frame.
|
||||
currentFrame = currentFrame->next; // GC_debug_malloc's frame.
|
||||
currentFrame = currentFrame->next; // GC_debug_malloc's caller's frame.
|
||||
|
||||
currentTree = find_tree(currentFrame);
|
||||
|
||||
info[0].ci_pc = (word) currentTree;
|
||||
}
|
||||
|
||||
#endif /* defined(SAVE_CALL_CHAIN) && defined(LINUX) */
|
||||
|
||||
|
|
|
@ -109,36 +109,36 @@ register word sz;
|
|||
- WORDS_TO_BYTES(sz));
|
||||
|
||||
/* go through all words in block */
|
||||
while( p <= plim ) {
|
||||
if( mark_bit_from_hdr(hhdr, word_no) ) {
|
||||
p += sz;
|
||||
} else {
|
||||
FOUND_FREE(hbp, word_no);
|
||||
INCR_WORDS(sz);
|
||||
while( p <= plim ) {
|
||||
if( mark_bit_from_hdr(hhdr, word_no) ) {
|
||||
p += sz;
|
||||
} else {
|
||||
FOUND_FREE(hbp, word_no);
|
||||
INCR_WORDS(sz);
|
||||
#if !defined(FIND_LEAK) || 1
|
||||
if (GC_root_size) {
|
||||
/* object is available - put on list */
|
||||
obj_link(p) = list;
|
||||
list = ((ptr_t)p);
|
||||
/* Clear object, advance p to next object in the process */
|
||||
q = p + sz;
|
||||
p++; /* Skip link field */
|
||||
while (p < q) {
|
||||
*p++ = 0;
|
||||
}
|
||||
} else {
|
||||
/* roots gone, just advance. */
|
||||
p += sz;
|
||||
}
|
||||
#else
|
||||
/* let leaks accumulate. */
|
||||
p += sz;
|
||||
#endif
|
||||
}
|
||||
word_no += sz;
|
||||
if (GC_root_size) {
|
||||
/* object is available - put on list */
|
||||
obj_link(p) = list;
|
||||
list = ((ptr_t)p);
|
||||
/* Clear object, advance p to next object in the process */
|
||||
q = p + sz;
|
||||
p++; /* Skip link field */
|
||||
while (p < q) {
|
||||
*p++ = 0;
|
||||
}
|
||||
} else {
|
||||
/* roots gone, just advance. */
|
||||
p += sz;
|
||||
}
|
||||
#else
|
||||
/* let leaks accumulate. */
|
||||
p += sz;
|
||||
#endif
|
||||
}
|
||||
word_no += sz;
|
||||
}
|
||||
# ifdef GATHERSTATS
|
||||
GC_mem_found += n_words_found;
|
||||
GC_mem_found += n_words_found;
|
||||
# endif
|
||||
return(list);
|
||||
}
|
||||
|
|
|
@ -271,6 +271,11 @@ nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
|
|||
rv = servMgr->RegisterService(kComponentManagerCID, NS_STATIC_CAST(nsIComponentManager*, compMgr));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
#ifdef GC_LEAK_DETECTOR
|
||||
rv = NS_InitLeakDetector();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
#endif
|
||||
|
||||
// 3. Register the global services with the component manager so that
|
||||
// clients can create new objects.
|
||||
|
||||
|
@ -305,11 +310,6 @@ nsresult NS_COM NS_InitXPCOM(nsIServiceManager* *result,
|
|||
return rv;
|
||||
}
|
||||
|
||||
#ifdef GC_LEAK_DETECTOR
|
||||
rv = NS_InitLeakDetector();
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
#endif
|
||||
|
||||
rv = RegisterGenericFactory(compMgr, kMemoryCID,
|
||||
NS_MEMORY_CLASSNAME,
|
||||
NS_MEMORY_PROGID,
|
||||
|
|
Загрузка…
Ссылка в новой задаче