diff --git a/src/dmalloc.h b/src/dmalloc.h index e88eafa38d90273087c9d6f37aa56e859578d443..15e3c699df64ca2c1a32fba7b693ea40f2ac5127 100644 --- a/src/dmalloc.h +++ b/src/dmalloc.h @@ -1,5 +1,5 @@ /* - * $Id: dmalloc.h,v 1.23 2000/03/27 06:34:05 hubbe Exp $ + * $Id: dmalloc.h,v 1.24 2000/04/08 02:01:08 hubbe Exp $ */ extern char *debug_xalloc(long); @@ -35,7 +35,8 @@ void search_all_memheaders_for_references(void); /* Beware! names of named memory regions are never ever freed!! /Hubbe */ void *debug_malloc_name(void *p, char *fn, int line); -void debug_malloc_copy_names(void *p, void *p2); +int debug_malloc_copy_names(void *p, void *p2); +char *dmalloc_find_name(void *p); /* glibc 2.1 defines this as a macro. */ #ifdef strdup @@ -63,6 +64,23 @@ void dmalloc_accept_leak(void *); #define dmalloc_touch_fd(X) debug_malloc_touch_fd((X),DMALLOC_LOCATION()) #define dmalloc_register_fd(X) debug_malloc_register_fd((X),DMALLOC_LOCATION()) #define dmalloc_close_fd(X) debug_malloc_close_fd((X),DMALLOC_LOCATION()) + +/* Beware, these do not exist without DMALLOC */ +struct memory_map; +void dmalloc_set_mmap(void *ptr, struct memory_map *m); +void dmalloc_set_mmap_template(void *ptr, struct memory_map *m); +void dmalloc_set_mmap_from_template(void *p, void *p2); +void dmalloc_describe_location(void *p, int offset); +struct memory_map *dmalloc_alloc_mmap(char *name, int line); +void dmalloc_add_mmap_entry(struct memory_map *m, + char *name, + int offset, + int size, + int count, + struct memory_map *recur, + int recur_offset); + + #else #define dmalloc_touch_fd(X) (X) #define dmalloc_register_fd(X) (X) @@ -85,6 +103,7 @@ void dmalloc_accept_leak(void *); #define dmalloc_unregister(X,Y) #define debug_free(X,Y,Z) free((X)) #define debug_malloc_name(P,FN,LINE) -#define debug_malloc_copy_names(p,p2) +#define debug_malloc_copy_names(p,p2) 0 #define search_all_memheaders_for_references() +#define dmalloc_find_name(X) "unknown (no dmalloc)" #endif diff --git a/src/encode.c b/src/encode.c index 66b52b9781917e90e03285064df978cfc78c0a25..4b8797c78aefd9501056aa2f27c392ddf0662c70 100644 --- a/src/encode.c +++ b/src/encode.c @@ -25,7 +25,7 @@ #include "version.h" #include "bignum.h" -RCSID("$Id: encode.c,v 1.57 2000/04/06 09:03:29 hubbe Exp $"); +RCSID("$Id: encode.c,v 1.58 2000/04/08 02:01:08 hubbe Exp $"); /* #define ENCODE_DEBUG */ @@ -573,7 +573,7 @@ static void encode_value2(struct svalue *val, struct encode_data *data) { INT32 e; struct program *p=val->u.program; - if(p->init || p->exit || p->gc_marked || p->gc_check || + if(p->init || p->exit || p->gc_marked || p->gc_check_func || (p->flags & PROGRAM_HAS_C_METHODS)) error("Cannot encode C programs.\n"); code_entry(type_to_tag(val->type), 1,data); diff --git a/src/gc.c b/src/gc.c index c7e124730ad7813843107666f6f20a03ee4accde..1e8f63c72b9d40e4e9ba77409d07848c3942f953 100644 --- a/src/gc.c +++ b/src/gc.c @@ -29,7 +29,7 @@ struct callback *gc_evaluator_callback=0; #include "block_alloc.h" -RCSID("$Id: gc.c,v 1.52 2000/03/07 23:51:29 hubbe Exp $"); +RCSID("$Id: gc.c,v 1.53 2000/04/08 02:01:08 hubbe Exp $"); /* Run garbage collect approximate every time we have * 20 percent of all arrays, objects and programs is @@ -131,23 +131,77 @@ void *gc_svalue_location=0; void describe_location(void *memblock, TYPE_T type, void *location) { + struct program *p; if(!location) return; - fprintf(stderr,"**Location of (short) svalue: %p\n",location); +/* fprintf(stderr,"**Location of (short) svalue: %p\n",location); */ + if(type==T_UNKNOWN) type=attempt_to_identify(memblock); + fprintf(stderr," <from %s %p offset %ld>\n", + get_name_of_type(type), + memblock, + ((long)location - (long)memblock)); + switch(type) { + case T_UNKNOWN: + for(p=first_program;p;p=p->next) + { + if(memblock == (void *)p->program) + { + fprintf(stderr," **In memory block for program at %p\n",p); + memblock=p; + type=T_PROGRAM; + goto describe_program_location; + } + } + break; + case T_PROGRAM: + describe_program_location: { + long e; struct program *p=(struct program *)memblock; char *ptr=(char *)location; - if(ptr >= (char *)p->inherits && ptr<(char*)(p->inherits+p->num_inherits)) - fprintf(stderr,"**In inherit block.\n"); - if(ptr >= (char *)p->strings && ptr<(char*)(p->strings+p->num_strings)) - fprintf(stderr,"**In string block.\n"); + if(location == (void *)&p->prev) + fprintf(stderr," **In p->prev\n"); + + if(location == (void *)&p->next) + fprintf(stderr," **In p->next\n"); + + if(ptr >= (char *)p->inherits && ptr<(char*)(p->inherits+p->num_inherits)) + { + e=((long)ptr - (long)(p->inherits)) / sizeof(struct inherit); + fprintf(stderr," **In p->inherits[%ld] (%s)\n", + e, + p->inherits[e].name ? p->inherits[e].name->str : "no name"); + return; + } + + if(ptr >= (char *)p->constants && ptr<(char*)(p->constants+p->num_constants)) + { + e=((long)ptr - (long)(p->constants)) / sizeof(struct program_constant); + fprintf(stderr," **In p->constants[%ld] (%s)\n", + e, + p->constants[e].name ? p->constants[e].name->str : "no name"); + return; + } + if(ptr >= (char *)p->identifiers && ptr<(char*)(p->identifiers+p->num_identifiers)) - fprintf(stderr,"**In identifier block.\n"); + { + e=((long)ptr - (long)(p->identifiers)) / sizeof(struct identifier); + fprintf(stderr," **In p->identifiers[%ld] (%s)\n", + e, + p->identifiers[e].name ? p->constants[e].name->str : "no name"); + return; + } + +#define FOO(NTYP,TYP,NAME) \ + if(location == (void *)&p->NAME) fprintf(stderr," **In p->" #NAME "\n"); \ + if(ptr >= (char *)p->NAME && ptr<(char*)(p->NAME+p->PIKE_CONCAT(num_,NAME))) \ + fprintf(stderr," **In p->" #NAME "[%ld]\n",((long)ptr - (long)(p->NAME)) / sizeof(TYP)); +#include "program_areas.h" return; } @@ -155,12 +209,28 @@ void describe_location(void *memblock, TYPE_T type, void *location) case T_OBJECT: { struct object *o=(struct object *)memblock; - if(o->prog) + struct program *p; + + if(location == (void *)&o->parent) fprintf(stderr," **In o->parent\n"); + if(location == (void *)&o->prog) fprintf(stderr," **In o->prog\n"); + if(location == (void *)&o->next) fprintf(stderr," **In o->next\n"); + if(location == (void *)&o->prev) fprintf(stderr," **In o->prev\n"); + + p=o->prog; + + if(!o->prog) + { + p=id_to_program(o->program_id); + if(p) + fprintf(stderr," **(We are lucky, found program for destructed object)\n"); + } + + if(p) { INT32 e,d; - for(e=0;e<(INT32)o->prog->num_inherits;e++) + for(e=0;e<(INT32)p->num_inherits;e++) { - struct inherit tmp=o->prog->inherits[e]; + struct inherit tmp=p->inherits[e]; char *base=o->storage + tmp.storage_offset; for(d=0;d<(INT32)tmp.prog->num_identifiers;d++) @@ -170,9 +240,19 @@ void describe_location(void *memblock, TYPE_T type, void *location) if(location == (void *)(base + id->func.offset)) { - fprintf(stderr,"**In variable %s\n",id->name->str); + fprintf(stderr," **In variable %s\n",id->name->str); } } + + if((char *)location >= base && (char *)location <= base + + ( tmp.prog->storage_needed - tmp.prog->inherits[0].storage_offset )) + { + fprintf(stderr," **In storage for inherit %d",e); + if(tmp.name) + fprintf(stderr," (%s)",tmp.name->str); + fprintf(stderr,"\n"); + } + } } return; @@ -182,7 +262,7 @@ void describe_location(void *memblock, TYPE_T type, void *location) { struct array *a=(struct array *)memblock; struct svalue *s=(struct svalue *)location; - fprintf(stderr,"**In index %ld\n",(long)(s-ITEM(a))); + fprintf(stderr," **In index %ld\n",(long)(s-ITEM(a))); return; } } @@ -252,6 +332,8 @@ void low_describe_something(void *a, int t, int dm) case T_OBJECT: p=((struct object *)a)->prog; fprintf(stderr,"**Parent identifier: %d\n",((struct object *)a)->parent_identifier); + fprintf(stderr,"**Program id: %ld\n",((struct object *)a)->program_id); + if( ((struct object *)a)->parent) { fprintf(stderr,"**Describing object's parent:\n"); @@ -262,7 +344,9 @@ void low_describe_something(void *a, int t, int dm) if(!p) { fprintf(stderr,"**The object is destructed.\n"); - break; + p=id_to_program(((struct object *)a)->program_id); + + if(!p) break; } fprintf(stderr,"**Attempting to describe program object was instantiated from:\n"); @@ -313,6 +397,9 @@ void low_describe_something(void *a, int t, int dm) fprintf(stderr,"**num inherits: %d\n",p->num_inherits); } +#define FOO(NUMTYPE,TYPE,NAME) \ + fprintf(stderr,"* " #NAME " %p[%d]\n",p->NAME,p->PIKE_CONCAT(num_,NAME)); +#include "program_areas.h" break; } @@ -406,7 +493,13 @@ void debug_describe_svalue(struct svalue *s) }else{ if(!s->u.object->prog) { - fprintf(stderr," Function in destructed object.\n"); + struct program *p=id_to_program(s->u.object->program_id); + if(p) + { + fprintf(stderr," Function (destructed) name: %s\n",ID_FROM_INT(p,s->subtype)->name->str); + }else{ + fprintf(stderr," Function in destructed object.\n"); + } }else{ fprintf(stderr," Function name: %s\n",ID_FROM_INT(s->u.object->prog,s->subtype)->name->str); } @@ -417,7 +510,7 @@ void debug_describe_svalue(struct svalue *s) #endif -INT32 gc_check(void *a) +INT32 real_gc_check(void *a) { #ifdef PIKE_DEBUG if(check_for) diff --git a/src/gc.h b/src/gc.h index 988926ad759e4efa2f23f6598640f74b96a0dc12..718a25125dc6aefad5a1306a4c496f743d6d2b65 100644 --- a/src/gc.h +++ b/src/gc.h @@ -1,5 +1,5 @@ /* - * $Id: gc.h,v 1.23 2000/02/02 00:38:27 hubbe Exp $ + * $Id: gc.h,v 1.24 2000/04/08 02:01:08 hubbe Exp $ */ #ifndef GC_H #define GC_H @@ -55,7 +55,7 @@ int debug_gc_check(void *x, TYPE_T t, void *data); void describe_something(void *a, int t, int dm); void describe(void *x); void debug_describe_svalue(struct svalue *s); -INT32 gc_check(void *a); +INT32 real_gc_check(void *a); void locate_references(void *a); int debug_gc_is_referenced(void *a); int gc_external_mark(void *a); @@ -65,13 +65,18 @@ void do_gc(void); void f__gc_status(INT32 args); /* Prototypes end here */ +#define gc_check_svalues(S,N) real_gc_check_svalues(debug_malloc_pass(S),N) +#define gc_check_short_svalue(S,N) real_gc_check_short_svalue(debug_malloc_pass(S),N) +#define gc_xmark_svalues(S,N) real_gc_xmark_svalues(debug_malloc_pass(S),N) +#define gc_check(VP) real_gc_check(debug_malloc_pass(VP)) + #ifdef PIKE_DEBUG #define GC_FREE() do { num_objects-- ; if(num_objects < 0) fatal("Panic!! less than zero objects!\n"); }while(0) #else -#define debug_gc_check_svalues(S,N,T,V) gc_check_svalues(S,N) -#define debug_gc_check_short_svalue(S,N,T,V) gc_check_short_svalue(S,N) -#define debug_gc_xmark_svalue(S,N,X) gc_xmark_svalue(S,N) -#define debug_gc_check(VP,T,V) gc_check(VP) +#define debug_gc_check_svalues(S,N,T,V) gc_check_svalues((S),N) +#define debug_gc_check_short_svalue(S,N,T,V) gc_check_short_svalue((S),N) +#define debug_gc_xmark_svalues(S,N,X) gc_xmark_svalues((S),N) +#define debug_gc_check(VP,T,V) gc_check((VP)) #define GC_FREE() do { num_objects-- ; }while(0) #endif @@ -84,8 +89,8 @@ void f__gc_status(INT32 args); #ifdef PIKE_DEBUG -#define gc_is_referenced debug_gc_is_referenced -#define gc_do_free debug_gc_do_free +#define gc_is_referenced(X) debug_gc_is_referenced(debug_malloc_pass(X)) +#define gc_do_free(X) debug_gc_do_free(debug_malloc_pass(X)) #else #define gc_is_referenced(X) (get_marker(X)->refs < *(INT32 *)(X)) #define gc_do_free(X) ( ! (get_marker(X)->flags & GC_REFERENCED ) ) diff --git a/src/interpret.c b/src/interpret.c index 9cd971ad3de071578f25583889677030afd47759..cf3253e546db9ace468995f96c771772de20edbe 100644 --- a/src/interpret.c +++ b/src/interpret.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: interpret.c,v 1.138 2000/04/04 00:26:09 hubbe Exp $"); +RCSID("$Id: interpret.c,v 1.139 2000/04/08 02:01:08 hubbe Exp $"); #include "interpret.h" #include "object.h" #include "program.h" @@ -620,8 +620,11 @@ static void do_trace_call(INT32 args) DO_IF_DMALLOC( \ X->context.prog=0; \ X->context.parent=0; \ + X->context.name=0; \ X->scope=0; \ + X->current_object=0; \ X->malloced_locals=0; \ + X->expendible=0; \ X->locals=0; \ ) \ }while(0) diff --git a/src/interpret.h b/src/interpret.h index 90bf599eb7fb98c7de9059b1dbb38087d06e2631..d943d8636723023a309037094e1cdef11efd1763 100644 --- a/src/interpret.h +++ b/src/interpret.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: interpret.h,v 1.39 2000/03/28 18:00:00 grubba Exp $ + * $Id: interpret.h,v 1.40 2000/04/08 02:01:08 hubbe Exp $ */ #ifndef INTERPRET_H #define INTERPRET_H @@ -20,7 +20,7 @@ struct pike_frame { INT32 refs; /* must be first */ INT32 args; - INT16 fun; + unsigned INT16 fun; INT16 num_locals; INT16 num_args; INT16 malloced_locals; diff --git a/src/language.yacc b/src/language.yacc index e1dea41bc8814d205d6d08fd1ebaf9006ba6560a..17a7d2488b44fa395f9ca65244d0d33de4591e0a 100644 --- a/src/language.yacc +++ b/src/language.yacc @@ -188,7 +188,7 @@ /* This is the grammar definition of Pike. */ #include "global.h" -RCSID("$Id: language.yacc,v 1.178 2000/04/07 19:59:40 grubba Exp $"); +RCSID("$Id: language.yacc,v 1.179 2000/04/08 02:01:08 hubbe Exp $"); #ifdef HAVE_MEMORY_H #include <memory.h> #endif @@ -1667,12 +1667,6 @@ local_function: F_IDENTIFIER push_compiler_frame1 func_args low_add_local_name(compiler_frame->previous, $1->u.sval.u.string, type, n); -#ifdef LAMBDA_DEBUG - fprintf(stderr,"FNORD: "); - simple_describe_type(type); - fprintf(stderr,"\n"); -#endif /* LAMBDA_DEBUG */ - $<number>$=id; free_string(name); } diff --git a/src/object.c b/src/object.c index 42dcc63bccd5cb42468bd3e6e718979f6fcd50b6..62d8313c46e05ca7aaad09decedede27c7e0acd1 100644 --- a/src/object.c +++ b/src/object.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: object.c,v 1.98 2000/04/06 21:07:58 hubbe Exp $"); +RCSID("$Id: object.c,v 1.99 2000/04/08 02:01:09 hubbe Exp $"); #include "object.h" #include "dynamic_buffer.h" #include "interpret.h" @@ -88,7 +88,28 @@ struct object *low_clone(struct program *p) o=(struct object *)xalloc( ((long)(((struct object *)0)->storage))+p->storage_needed); - debug_malloc_copy_names(o, p); +#ifdef DEBUG_MALLOC + if(!debug_malloc_copy_names(o, p)) + { + /* Didn't find a given name, revert to ad-hoc method */ + char *tmp; + INT32 line,pos; + + for(pos=0;pos<100;pos++) + { + tmp=get_line(p->program+pos, p, &line); + if(tmp && line) + { + debug_malloc_name(o, tmp, line); + break; + } + if(pos+1>=(long)p->num_program) + break; + } + + } + dmalloc_set_mmap_from_template(o,p); +#endif o->prog=p; add_ref(p); @@ -100,6 +121,11 @@ struct object *low_clone(struct program *p) first_object->prev=o; first_object=o; o->refs=1; + +#ifdef PIKE_DEBUG + o->program_id=p->id; +#endif + INITIALIZE_PROT(o); return o; } @@ -481,6 +507,7 @@ void low_destruct(struct object *o,int do_free) u=(union anything *)(pike_frame->current_storage + pike_frame->context.prog->identifiers[d].func.offset); free_short_svalue(u, pike_frame->context.prog->identifiers[d].run_time_type); + DO_IF_DMALLOC(u->refs=(void *)-1); } } } @@ -1190,8 +1217,8 @@ void gc_check_all_objects(void) int q; SET_FRAME_CONTEXT(p->inherits[e]); - if(pike_frame->context.prog->gc_check) - pike_frame->context.prog->gc_check(o); + if(pike_frame->context.prog->gc_check_func) + pike_frame->context.prog->gc_check_func(o); for(q=0;q<(int)pike_frame->context.prog->num_variable_index;q++) { diff --git a/src/object.h b/src/object.h index c216ea74d7bc30df41ff7ce50c221bc085f1b353..d13a426d4c2119a239765597feb2025a617507d5 100644 --- a/src/object.h +++ b/src/object.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: object.h,v 1.39 2000/03/28 17:59:14 grubba Exp $ + * $Id: object.h,v 1.40 2000/04/08 02:01:09 hubbe Exp $ */ #ifndef OBJECT_H #define OBJECT_H @@ -29,6 +29,9 @@ struct object INT16 parent_identifier; struct object *next; struct object *prev; +#if PIKE_DEBUG + long program_id; +#endif char storage[1]; }; diff --git a/src/pike_memory.c b/src/pike_memory.c index c1299a702dca5e70dca6556ed839fb510063688d..10e88b1e4402c366a25b8fa2b66ea9f790379599 100644 --- a/src/pike_memory.c +++ b/src/pike_memory.c @@ -10,7 +10,7 @@ #include "pike_macros.h" #include "gc.h" -RCSID("$Id: pike_memory.c,v 1.62 2000/04/06 21:00:20 hubbe Exp $"); +RCSID("$Id: pike_memory.c,v 1.63 2000/04/08 02:01:09 hubbe Exp $"); /* strdup() is used by several modules, so let's provide it */ #ifndef HAVE_STRDUP @@ -1416,8 +1416,9 @@ void *__wrap_strdup(const char *s) #endif -void dump_memhdr_locations(struct memhdr *from, - struct memhdr *notfrom) +void low_dump_memhdr_locations(struct memhdr *from, + struct memhdr *notfrom, + int indent) { struct memloc *l; if(!from) return; @@ -1430,16 +1431,29 @@ void dump_memhdr_locations(struct memhdr *from, if(notfrom && find_location(notfrom, l->location)) continue; - fprintf(stderr," %s %s (%d times) %s\n", + + fprintf(stderr,"%*s %s %s (%d times) %s\n", + indent,"", LOCATION_IS_DYNAMIC(l->location) ? "-->" : "***", LOCATION_NAME(l->location), l->times, find_location(&no_leak_memlocs, l->location) ? "" : ( from->flags & MEM_REFERENCED ? "*" : "!*!") ); + + /* Allow linked memhdrs */ +/* dump_memhdr_locations(my_find_memhdr(l,0),notfrom,indent+2); */ } } +void dump_memhdr_locations(struct memhdr *from, + struct memhdr *notfrom) +{ + low_dump_memhdr_locations(from,notfrom, 2); +} + +static void low_dmalloc_describe_location(struct memhdr *mh, int offset); + static void find_references_to(void *block) { unsigned long h; @@ -1461,7 +1475,11 @@ static void find_references_to(void *block) { if(p[e] == block) { - fprintf(stderr," <from %p word %d>\n",p,e); +/* fprintf(stderr," <from %p word %d>\n",p,e); */ + describe_location(p,T_UNKNOWN,p+e); + + low_dmalloc_describe_location(m, e * sizeof(void *)); + m->flags |= MEM_WARN_ON_FREE; } } @@ -1722,7 +1740,7 @@ struct dmalloc_string static struct dmalloc_string *dstrhash[DSTRHSIZE]; -LOCATION dynamic_location(char *file, int line) +static LOCATION low_dynamic_location(char type, char *file, int line) { struct dmalloc_string **prev, *str; int len=strlen(file); @@ -1736,7 +1754,7 @@ LOCATION dynamic_location(char *file, int line) if(hval == str->hval && str->str[len+1]==':' && !MEMCMP(str->str+1, file, len) && - str->str[0]=='D' && + str->str[0]==type && atoi(str->str+len+2) == line) { *prev=str->next; @@ -1749,7 +1767,7 @@ LOCATION dynamic_location(char *file, int line) if(!str) { str=malloc( sizeof(struct dmalloc_string) + len + 20); - sprintf(str->str, "D%s:%d", file, line); + sprintf(str->str, "%c%s:%d", type, file, line); str->hval=hval; str->next=dstrhash[h]; dstrhash[h]=str; @@ -1760,6 +1778,11 @@ LOCATION dynamic_location(char *file, int line) return str->str; } +LOCATION dynamic_location(char *file, int line) +{ + return low_dynamic_location('D',file,line); +} + void * debug_malloc_name(void *p,char *file, int line) { @@ -1783,8 +1806,9 @@ void * debug_malloc_name(void *p,char *file, int line) * one pointer to another. Used by clone() to copy * the name(s) of the program. */ -void debug_malloc_copy_names(void *p, void *p2) +int debug_malloc_copy_names(void *p, void *p2) { + int names=0; if(p) { struct memhdr *mh,*from; @@ -1796,12 +1820,42 @@ void debug_malloc_copy_names(void *p, void *p2) for(l=from->locations;l;l=l->next) { if(LOCATION_IS_DYNAMIC(l->location)) + { add_location(mh, l->location); + names++; + } + } + } + + mt_unlock(&debug_malloc_mutex); + } + return names; +} + +char *dmalloc_find_name(void *p) +{ + char *name=0; + if(p) + { + struct memhdr *mh; + mt_lock(&debug_malloc_mutex); + + if((mh=my_find_memhdr(p,0))) + { + struct memloc *l; + for(l=mh->locations;l;l=l->next) + { + if(LOCATION_IS_DYNAMIC(l->location)) + { + name=LOCATION_NAME(l->location); + break; + } } } mt_unlock(&debug_malloc_mutex); } + return name; } int debug_malloc_touch_fd(int fd, LOCATION location) @@ -1842,4 +1896,153 @@ void reset_debug_malloc(void) } } +struct memory_map +{ + char name[128]; + struct memory_map *next; + struct memory_map_entry *entries; +}; + +struct memory_map_entry +{ + struct memory_map_entry *next; + char name[128]; + int offset; + int size; + int count; + int recur_offset; + struct memory_map *recur; +}; + +BLOCK_ALLOC(memory_map, 255) +BLOCK_ALLOC(memory_map_entry, 511) + +void dmalloc_set_mmap(void *ptr, struct memory_map *m) +{ + debug_malloc_update_location(ptr, m->name+1); +} + +void dmalloc_set_mmap_template(void *ptr, struct memory_map *m) +{ + debug_malloc_update_location(ptr,m->name); +} + +void dmalloc_set_mmap_from_template(void *p, void *p2) +{ + int names=0; + if(p) + { + struct memhdr *mh,*from; + mt_lock(&debug_malloc_mutex); + + if((from=my_find_memhdr(p2,0)) && (mh=my_find_memhdr(p,0))) + { + struct memloc *l; + for(l=from->locations;l;l=l->next) + { + if(l->location[0]=='T') + { + add_location(mh, l->location+1); + names++; + } + } + } + + mt_unlock(&debug_malloc_mutex); + } +} + +static void very_low_dmalloc_describe_location(struct memory_map *m, + int offset, + int indent) +{ + struct memory_map_entry *e; + fprintf(stderr,"%*s ** In memory map %s:\n",indent,"",m->name+2); + for(e=m->entries;e;e=e->next) + { + if(e->offset <= offset && e->offset + e->size * e->count > offset) + { + int num=(offset - e->offset)/e->size; + int off=offset-e->size*num-e->offset; + fprintf(stderr,"%*s Found in member: %s[%d] + %d (offset=%d size=%d)\n", + off, + indent,"", + num, + e->name,e->offset,e->size); + + if(e->recur) + { + very_low_dmalloc_describe_location(e->recur, + off-e->recur_offset, + indent+2); + } + } + } +} + +static void low_dmalloc_describe_location(struct memhdr *mh, int offset) +{ + struct memloc *l; + for(l=mh->locations;l;l=l->next) + { + if(l->location[0]=='M') + { + struct memory_map *m = (struct memory_map *)(l->location - 1); + very_low_dmalloc_describe_location(m, offset,4); + } + } +} + +void dmalloc_describe_location(void *p, int offset) +{ + if(p) + { + struct memhdr *mh; + mt_lock(&debug_malloc_mutex); + if((mh=my_find_memhdr(p,0))) low_dmalloc_describe_location(mh, offset); + mt_unlock(&debug_malloc_mutex); + } +} + +struct memory_map *dmalloc_alloc_mmap(char *name, int line) +{ + struct memory_map *m; + mt_lock(&debug_malloc_mutex); + m=alloc_memory_map(); + strncpy(m->name+2,name,sizeof(m->name)-2); + m->name[sizeof(m->name)-1]=0; + m->name[0]='T'; + m->name[1]='M'; + + if(strlen(m->name)+12<sizeof(m->name)) + sprintf(m->name+strlen(m->name),":%d",line); + + m->entries=0; + mt_unlock(&debug_malloc_mutex); + return m; +} + +void dmalloc_add_mmap_entry(struct memory_map *m, + char *name, + int offset, + int size, + int count, + struct memory_map *recur, + int recur_offset) +{ + struct memory_map_entry *e; + mt_lock(&debug_malloc_mutex); + e=alloc_memory_map_entry(); + strncpy(e->name,name,sizeof(e->name)); + e->name[sizeof(e->name)-1]=0; + e->offset=offset; + e->size=size; + e->count=count?count:1; + e->next=m->entries; + e->recur=recur; + e->recur=recur_offset; + m->entries=e; + mt_unlock(&debug_malloc_mutex); +} + #endif diff --git a/src/program.c b/src/program.c index f9585993ea2827eb8e4c6c74884a103a95cd47de..68703e32b9bb30f1b65da1242f9df4359a6d1ad6 100644 --- a/src/program.c +++ b/src/program.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: program.c,v 1.222 2000/04/06 21:00:20 hubbe Exp $"); +RCSID("$Id: program.c,v 1.223 2000/04/08 02:01:09 hubbe Exp $"); #include "program.h" #include "object.h" #include "dynamic_buffer.h" @@ -595,6 +595,62 @@ void fixate_program(void) } new_program->flags |= PROGRAM_FIXED; + +#ifdef DEBUG_MALLOC + { +#define DBSTR(X) ((X)?(X)->str:"") + int e,v; + struct memory_map *m=dmalloc_alloc_mmap( DBSTR(lex.current_file), + lex.current_line); + for(e=0;e<new_program->num_inherits;e++) + { + struct inherit *i=new_program->inherits+e; + char *tmp; + char buffer[50]; + + for(v=0;v<i->prog->num_variable_index;v++) + { + int d=i->prog->variable_index[v]; + struct identifier *id=i->prog->identifiers+d; + + dmalloc_add_mmap_entry(m, + id->name->str, + OFFSETOF(object,storage) + i->storage_offset + id->func.offset, + sizeof_variable(id->run_time_type), + 1, /* count */ + 0,0); + } + + if(i->name) + { + tmp=i->name->str; + }else if(!(tmp=dmalloc_find_name(i->prog))){ + /* Didn't find a given name, revert to ad-hoc method */ + INT32 line,pos; + + for(pos=0;pos<100;pos++) + { + tmp=get_line(i->prog->program+pos, i->prog, &line); + if(tmp && line) break; + if(pos+1>=(long)i->prog->num_program) break; + } + if(!(tmp && line)) + { + sprintf(buffer,"inherit[%d]",e); + tmp=buffer; + } + } + dmalloc_add_mmap_entry(m, + tmp, + OFFSETOF(object, storage) + i->storage_offset, + i->prog->storage_needed - i->prog->inherits[0].storage_offset, + 1, /* count */ + 0,0); + + } + dmalloc_set_mmap_template(new_program, m); + } +#endif } struct program *low_allocate_program(void) @@ -708,6 +764,11 @@ void low_start_new_program(struct program *p, fake_object->parent_identifier=0; fake_object->prog=p; add_ref(p); + +#ifdef PIKE_DEBUG + fake_object->program_id=p->id; +#endif + #ifdef PIKE_SECURITY fake_object->prot=0; #endif @@ -1383,7 +1444,7 @@ void set_gc_mark_callback(void (*m)(struct object *)) */ void set_gc_check_callback(void (*m)(struct object *)) { - new_program->gc_check=m; + new_program->gc_check_func=m; } int low_reference_inherited_identifier(struct program_state *q, @@ -3074,7 +3135,11 @@ struct program *compile(struct pike_string *prog, if(lex.current_file) { store_linenumber(lex.current_line, lex.current_file); - debug_malloc_name(new_program, lex.current_file->str, lex.current_line); + +#ifdef DEBUG_MALLOC + if(strcmp(lex.current_file->str,"-") || lex.current_line!=1) + debug_malloc_name(new_program, lex.current_file->str, lex.current_line); +#endif } compilation_depth=0; @@ -3469,6 +3534,7 @@ void gc_free_all_unreferenced_programs(void) { free_svalue(& p->constants[e].sval); p->constants[e].sval.type=T_INT; + DO_IF_DMALLOC(p->constants[e].sval.u.refs=(void *)-1); } for(e=0;e<p->num_inherits;e++) @@ -3483,6 +3549,16 @@ void gc_free_all_unreferenced_programs(void) /* FIXME: Is there anything else that needs to be freed here? */ SET_NEXT_AND_FREE(p, free_program); }else{ +#ifdef PIKE_DEBUG + int e,tmp=0; + for(e=0;e<p->num_constants;e++) + { + if(p->constants[e].sval.type == T_PROGRAM && p->constants[e].sval.u.program == p) + tmp++; + } + if(tmp >= p->refs) + fatal("garbage collector failed to free program!!!\n"); +#endif next=p->next; } } diff --git a/src/program.h b/src/program.h index 54b71c2cdbe1581f7f910a34b79964fd2ace4314..ceb71467425c1744aa591a71a3e68776466fade4 100644 --- a/src/program.h +++ b/src/program.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: program.h,v 1.85 2000/03/30 08:43:07 hubbe Exp $ + * $Id: program.h,v 1.86 2000/04/08 02:01:09 hubbe Exp $ */ #ifndef PROGRAM_H #define PROGRAM_H @@ -262,7 +262,7 @@ struct program void (*init)(struct object *); void (*exit)(struct object *); void (*gc_marked)(struct object *); - void (*gc_check)(struct object *); + void (*gc_check_func)(struct object *); #ifdef PIKE_DEBUG unsigned INT32 checksum; #endif diff --git a/src/svalue.c b/src/svalue.c index 7fb1643246000d91f47650d43a11af2989c82b03..962b50f556fa1305c5f0404de5afda2e8590ba1e 100644 --- a/src/svalue.c +++ b/src/svalue.c @@ -23,7 +23,7 @@ #include "queue.h" #include "bignum.h" -RCSID("$Id: svalue.c,v 1.64 2000/03/27 07:54:27 hubbe Exp $"); +RCSID("$Id: svalue.c,v 1.65 2000/04/08 02:01:09 hubbe Exp $"); struct svalue dest_ob_zero = { T_INT, 0 }; @@ -153,7 +153,7 @@ void debug_free_svalues(struct svalue *s,INT32 num, INT32 type_hint DMALLOC_LINE while(--num>=0) { \ DO_IF_DMALLOC(debug_malloc_update_location(s->u.Z, dmalloc_location)); \ Y(s->u.Z); \ - DO_IF_DMALLOC(s->u.Z=0); \ + DO_IF_DMALLOC(s->u.Z=(void *)-1); \ s++; \ }return @@ -1204,7 +1204,7 @@ void check_svalue(struct svalue *s) #endif -TYPE_FIELD gc_check_svalues(struct svalue *s, int num) +TYPE_FIELD real_gc_check_svalues(struct svalue *s, int num) { INT32 e; TYPE_FIELD f; @@ -1272,7 +1272,7 @@ TYPE_FIELD gc_check_svalues(struct svalue *s, int num) } #ifdef PIKE_DEBUG -void gc_xmark_svalues(struct svalue *s, int num) +void real_gc_xmark_svalues(struct svalue *s, int num) { INT32 e; @@ -1298,7 +1298,7 @@ void gc_xmark_svalues(struct svalue *s, int num) } #endif -void gc_check_short_svalue(union anything *u, TYPE_T type) +void real_gc_check_short_svalue(union anything *u, TYPE_T type) { #ifdef PIKE_DEBUG gc_svalue_location=(void *)u; diff --git a/src/svalue.h b/src/svalue.h index a062913934e4a4a1290dd8b5222e346761f87592..d2d314c88f7102a2d3d4cb90edfbafdc35e742df 100644 --- a/src/svalue.h +++ b/src/svalue.h @@ -5,7 +5,7 @@ \*/ /* - * $Id: svalue.h,v 1.48 2000/03/20 21:00:04 hubbe Exp $ + * $Id: svalue.h,v 1.49 2000/04/08 02:01:09 hubbe Exp $ */ #ifndef SVALUE_H #define SVALUE_H @@ -270,8 +270,8 @@ do{ \ #endif -#define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE) { debug_malloc_touch(_s->u.refs); if(--*(_s->u.refs) <=0) { really_free_svalue(_s); DO_IF_DMALLOC(_s->u.refs=0;) }}}while(0) -#define free_short_svalue(X,T) do { union anything *_s=(X); TYPE_T _t=(T); check_type(_t); check_refs2(_s,_t); if(_t<=MAX_REF_TYPE && _s->refs) if(--*(_s->refs) <= 0) { really_free_short_svalue(_s,_t); DO_IF_DMALLOC(_s->refs=0;)} }while(0) +#define free_svalue(X) do { struct svalue *_s=(X); check_type(_s->type); check_refs(_s); if(_s->type<=MAX_REF_TYPE) { debug_malloc_touch(_s->u.refs); if(--*(_s->u.refs) <=0) { really_free_svalue(_s); } DO_IF_DMALLOC(_s->u.refs=(void *)-1;) }}while(0) +#define free_short_svalue(X,T) do { union anything *_s=(X); TYPE_T _t=(T); check_type(_t); check_refs2(_s,_t); if(_t<=MAX_REF_TYPE && _s->refs) if(--*(_s->refs) <= 0) { really_free_short_svalue(_s,_t); } DO_IF_DMALLOC(_s->refs=(void *)-1;) }while(0) #define add_ref_svalue(X) do { struct svalue *_tmp=(X); check_type(_tmp->type); check_refs(_tmp); if(_tmp->type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp->u.refs); _tmp->u.refs[0]++; } }while(0) #define assign_svalue_no_free(X,Y) do { struct svalue _tmp, *_to=(X), *_from=(Y); check_type(_from->type); check_refs(_from); *_to=_tmp=*_from; if(_tmp.type <= MAX_REF_TYPE) { debug_malloc_touch(_tmp.u.refs); _tmp.u.refs[0]++; } }while(0) #define assign_svalue(X,Y) do { struct svalue *_to2=(X), *_from2=(Y); free_svalue(_to2); assign_svalue_no_free(_to2, _from2); }while(0) @@ -335,9 +335,9 @@ void copy_svalues_recursively_no_free(struct svalue *to, struct processing *p); void check_short_svalue(union anything *u, TYPE_T type); void check_svalue(struct svalue *s); -TYPE_FIELD gc_check_svalues(struct svalue *s, int num); -void gc_xmark_svalues(struct svalue *s, int num); -void gc_check_short_svalue(union anything *u, TYPE_T type); +TYPE_FIELD real_gc_check_svalues(struct svalue *s, int num); +void real_gc_xmark_svalues(struct svalue *s, int num); +void real_gc_check_short_svalue(union anything *u, TYPE_T type); void gc_mark_svalues(struct svalue *s, int num); void gc_mark_short_svalue(union anything *u, TYPE_T type); INT32 pike_sizeof(struct svalue *s);