pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:23:   #include "constants.h"   #include "interpret.h"   #include "bignum.h"      #include "gc.h"   #include "main.h"   #include <math.h>      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.169 2001/07/13 11:26:38 grubba Exp $"); + RCSID("$Id: gc.c,v 1.170 2001/08/20 18:08:13 mast Exp $");      /* Run garbage collect approximately every time    * 20 percent of all arrays, objects and programs is    * garbage.    */      #define GC_CONST 20   #define MIN_ALLOC_THRESHOLD 1000   #define MAX_ALLOC_THRESHOLD 10000000   #define MULTIPLIER 0.9
pike.git/src/gc.c:110:    union {    struct { /* Pop frame. */    struct gc_frame *prev; /* Previous frame in rec_list. */    struct gc_frame *next; /* Next pointer in rec_list and kill_list. */    unsigned INT16 cycle; /* Cycle id number. */    } pop;    struct { /* Link frame. */    gc_cycle_check_cb *checkfn;    int weak;    } link; -  TYPE_T free_extra_type; /* Used on free_extra_list. The type of the thing. */ +  int free_extra_type; /* Used on free_extra_list. The type of the thing. */    } u;    unsigned INT16 frameflags;   };      #define GC_POP_FRAME 0x01   #define GC_WEAK_REF 0x02   #define GC_STRONG_REF 0x04   #define GC_OFF_STACK 0x08   #ifdef PIKE_DEBUG   #define GC_LINK_FREED 0x10
pike.git/src/gc.c:254:    fprintf(stderr,"Average frees per gc() : %f\n",objects_freed);    fprintf(stderr,"Second since last gc() : %ld\n",    DO_NOT_WARN((long)TIME(0) - (long)last_gc));    fprintf(stderr,"Projected garbage : %f\n", objects_freed * (double) num_allocs / (double) alloc_threshold);    fprintf(stderr,"Max used gc frames : %u\n", max_tot_gc_frames);    fprintf(stderr,"Live recursed ratio : %g\n", (double) tot_live_rec / tot_cycle_checked);    fprintf(stderr,"Frame rotation ratio : %g\n", (double) tot_frame_rot / tot_cycle_checked);    fprintf(stderr,"in_gc : %d\n", Pike_in_gc);   }    - TYPE_T attempt_to_identify(void *something) + int attempt_to_identify(void *something, void **inblock)   {    struct array *a;    struct object *o;    struct program *p;    struct mapping *m;    struct multiset *mu;    -  +  if (inblock) *inblock = 0; +     a=&empty_array;    do    {    if(a==(struct array *)something) return T_ARRAY;    a=a->next;    }while(a!=&empty_array);    -  for(o=first_object;o;o=o->next) +  for(o=first_object;o;o=o->next) {    if(o==(struct object *)something)    return T_OBJECT; -  +  if (o->storage && o->prog && +  (char *) something >= o->storage && +  (char *) something < o->storage + o->prog->storage_needed) { +  if (inblock) *inblock = (void *) o; +  return T_STORAGE; +  } +  }       for(p=first_program;p;p=p->next)    if(p==(struct program *)something)    return T_PROGRAM;       for(m=first_mapping;m;m=m->next)    if(m==(struct mapping *)something)    return T_MAPPING;    else if (m->data == (struct mapping_data *) something)    return T_MAPPING_DATA;
pike.git/src/gc.c:310:      #define DESCRIBE_MEM 1   #define DESCRIBE_NO_REFS 2   #define DESCRIBE_SHORT 4   #define DESCRIBE_NO_DMALLOC 8      /* type == -1 means that memblock is a char* and should be    * really be printed..    */   void describe_location(void *real_memblock, -  int real_type, +  int type,    void *location,    int indent,    int depth,    int flags)   {    struct program *p; -  void *memblock=0, *descblock; -  int type=real_type; +  void *memblock=0, *descblock, *inblock;    if(!location) return;   /* fprintf(stderr,"**Location of (short) svalue: %p\n",location); */    -  if(real_type!=-1 && real_memblock != (void *) -1) memblock=real_memblock; +  if(type!=-1 && real_memblock != (void *) -1) memblock=real_memblock;      #ifdef DEBUG_MALLOC    if(memblock == 0 || type == -1)    {    extern void *dmalloc_find_memblock_base(void *);    memblock=dmalloc_find_memblock_base(location);    }   #endif       if(type==PIKE_T_UNKNOWN) -  type=attempt_to_identify(memblock); +  type=attempt_to_identify(memblock, &inblock);       if(memblock)    fprintf(stderr,"%*s-> from %s %p offset %"PRINTPTRDIFFT"d\n",    indent,"",    get_name_of_type(type),    memblock,    (char *)location - (char *)memblock);    else    fprintf(stderr,"%*s-> at location %p%s\n",    indent,"",
pike.git/src/gc.c:483:    if(tmp.name)    fprintf(stderr," (%s)",tmp.name->str);    fprintf(stderr,"\n");    }       }    }    break;    }    +  case T_STORAGE: +  fprintf(stderr, "%*s **In storage of object\n", indent, ""); +  break; +     case T_MULTISET:    descblock = ((struct multiset *) memblock)->ind;    /* FALL THROUGH */    case T_ARRAY:    {    struct array *a=(struct array *)descblock;    struct svalue *s=(struct svalue *)location;    fprintf(stderr,"%*s **In index number %"PRINTPTRDIFFT"d\n",indent,"",    s-ITEM(a));    break;
pike.git/src/gc.c:519:    fprintf(stderr, "%*s **In value with index ", indent, "");    print_svalue(stderr, &k->ind);    fputc('\n', stderr);    break;    }    break;    }    }       if(memblock && depth>0) -  describe_something(memblock,type,indent+2,depth-1,flags | DESCRIBE_MEM); +  describe_something(memblock,type,indent+2,depth-1,flags | DESCRIBE_MEM,inblock);      #ifdef DEBUG_MALLOC    /* FIXME: Is the following call correct?    * Shouldn't the second argument be an offset?    */    dmalloc_describe_location(descblock, location, indent);   #endif   }      static void describe_gc_frame(struct gc_frame *l)
pike.git/src/gc.c:597:    }       if (flags & 2)    fatal_after_gc = "Fatal in garbage collector.\n";    else    debug_fatal("Fatal in garbage collector.\n");   }      static void gdb_gc_stop_here(void *a, int weak)   { - #if 1 + #if 0    if (!found_where) fatal("found_where is zero.\n");   #endif    fprintf(stderr,"***One %sref found%s. ",    weak ? "weak " : "",    found_where?found_where:"");    if (found_in) {    if (gc_svalue_location)    describe_location(found_in , found_in_type, gc_svalue_location,0,1,0);    else {    fputc('\n', stderr); -  describe_something(found_in, found_in_type, 2, 0, DESCRIBE_MEM); +  describe_something(found_in, found_in_type, 2, 0, DESCRIBE_MEM, 0);    }    }    fprintf(stderr,"----------end------------\n");   }      void debug_gc_xmark_svalues(struct svalue *s, ptrdiff_t num, char *fromwhere)   {    char *old_found_where = found_where;    if (fromwhere) found_where = fromwhere;    found_in=(void *) -1;    found_in_type=-1;    gc_xmark_svalues(s,num);    found_where=old_found_where;    found_in_type=PIKE_T_UNKNOWN;    found_in=0;   }      void debug_gc_check_svalues2(struct svalue *s, ptrdiff_t num, -  TYPE_T data_type, void *data, char *fromwhere) +  int data_type, void *data, char *fromwhere)   {    char *old_found_where = found_where;    if (fromwhere) found_where = fromwhere;    found_in=data;    found_in_type=data_type;    gc_check_svalues(s,num);    found_where=old_found_where;    found_in_type=PIKE_T_UNKNOWN;    found_in=0;   }      void debug_gc_check_weak_svalues2(struct svalue *s, ptrdiff_t num, -  TYPE_T data_type, void *data, char *fromwhere) +  int data_type, void *data, char *fromwhere)   {    char *old_found_where = found_where;    if (fromwhere) found_where = fromwhere;    found_in=data;    found_in_type=data_type;    gc_check_weak_svalues(s,num);    found_where=old_found_where;    found_in_type=PIKE_T_UNKNOWN;    found_in=0;   }    - void debug_gc_check_short_svalue2(union anything *u, TYPE_T type, -  TYPE_T data_type, void *data, char *fromwhere) + void debug_gc_check_short_svalue2(union anything *u, int type, +  int data_type, void *data, char *fromwhere)   {    char *old_found_where = found_where;    if (fromwhere) found_where = fromwhere;    found_in=data;    found_in_type=data_type;    gc_check_short_svalue(u,type);    found_where=old_found_where;    found_in_type=PIKE_T_UNKNOWN;    found_in=0;   }    - void debug_gc_check_weak_short_svalue2(union anything *u, TYPE_T type, -  TYPE_T data_type, void *data, char *fromwhere) + void debug_gc_check_weak_short_svalue2(union anything *u, int type, +  int data_type, void *data, char *fromwhere)   {    char *old_found_where = found_where;    if (fromwhere) found_where = fromwhere;    found_in=data;    found_in_type=data_type;    gc_check_weak_short_svalue(u,type);    found_where=old_found_where;    found_in_type=PIKE_T_UNKNOWN;    found_in=0;   }    - int debug_low_gc_check(void *x, TYPE_T data_type, void *data, char *fromwhere) + int debug_low_gc_check(void *x, int data_type, void *data, char *fromwhere)   {    int ret;    char *old_found_where = found_where;    if (fromwhere) found_where = fromwhere;    found_in=data;    found_in_type=data_type;    ret=gc_check(x);    found_where=old_found_where;    found_in_type=PIKE_T_UNKNOWN;    found_in=0;
pike.git/src/gc.c:706: Inside #if defined(__ECL)
   return DO_NOT_WARN((unsigned long)x);   }   #else /* !__ECL */   #define SIZE_T_TO_ULONG(x) ((unsigned long)(x))   #endif /* __ECL */      void low_describe_something(void *a,    int t,    int indent,    int depth, -  int flags) +  int flags, +  void *inblock)   {    struct program *p=(struct program *)a;    struct marker *m;       if(depth<0) return;       if (marker_hash_table && (m = find_marker(a))) {    fprintf(stderr,"%*s**Got gc ",indent,"");    describe_marker(m);    }    -  + again:    switch(t)    { -  +  case T_STORAGE: +  if (!inblock) attempt_to_identify (a, &a); +  t = T_OBJECT; +  goto again; +     case T_FUNCTION: -  if(attempt_to_identify(a) != T_OBJECT) +  if(attempt_to_identify(a, 0) != T_OBJECT)    {    fprintf(stderr,"%*s**Builtin function!\n",indent,"");    break;    } -  +  /* FALL THROUGH */    -  +  describe_object:    case T_OBJECT:    p=((struct object *)a)->prog;    if(p && (p->flags & PROGRAM_USES_PARENT))    {    fprintf(stderr,"%*s**Parent identifier: %d\n",indent,"",PARENT_INFO( ((struct object *)a) )->parent_identifier);    }    fprintf(stderr,"%*s**Program id: %ld\n",indent,"",((struct object *)a)->program_id);       if (((struct object *)a)->next == ((struct object *)a))    fprintf(stderr, "%*s**The object is fake.\n",indent,"");
pike.git/src/gc.c:760:    fprintf(stderr,"%*s**The object is destructed.\n",indent,"");    p=id_to_program(((struct object *)a)->program_id);    }    if (p) {    fprintf(stderr,"%*s**Attempting to describe program object was instantiated from:\n",indent,"");   #ifdef DEBUG_MALLOC    if ((int) p == 0x55555555)    fprintf(stderr, "%*s**Zapped program pointer.\n", indent, "");    else   #endif -  low_describe_something(p, T_PROGRAM, indent, depth, flags); +  low_describe_something(p, T_PROGRAM, indent, depth, flags, 0);    }       if(p &&    (p->flags & PROGRAM_USES_PARENT) &&    LOW_PARENT_INFO(((struct object *)a),p)->parent)    {    fprintf(stderr,"%*s**Describing object's parent:\n",indent,""); -  describe_something( PARENT_INFO((struct object *)a)->parent, t, indent+2,depth-1, +  describe_something( PARENT_INFO((struct object *)a)->parent, T_OBJECT, +  indent+2, depth-1,    (flags | DESCRIBE_SHORT | DESCRIBE_NO_REFS ) -  & ~ (DESCRIBE_MEM)); +  & ~ (DESCRIBE_MEM), +  0);    }else{    fprintf(stderr,"%*s**There is no parent (any longer?)\n",indent,"");    }    break;       case T_PROGRAM:    {    struct pike_string *tmp;    INT32 line;    int foo=0;
pike.git/src/gc.c:859:    }    }    break;    }       case T_MAPPING:    fprintf(stderr,"%*s**Describing mapping:\n",indent,"");    debug_dump_mapping((struct mapping *)a);    fprintf(stderr,"%*s**Describing mapping data block:\n",indent,"");    describe_something( ((struct mapping *)a)->data, T_MAPPING_DATA, -  indent+2,-1,flags); +  indent+2,-1,flags, 0);    break;       case T_STRING:    {    struct pike_string *s=(struct pike_string *)a;    fprintf(stderr, "%*s**String length is %"PRINTPTRDIFFT"d:\n",    indent, "", s->len);    if(s->len>77)    {    fprintf(stderr,"%*s** \"%60s ...\"\n",indent,"",s->str);    }else{    fprintf(stderr,"%*s** \"%s\"\n",indent,"",s->str);    }    break;    } -  +  +  case T_PIKE_FRAME: { +  struct pike_frame *f = (struct pike_frame *) a; +  do { +  if (f->current_object) { +  fprintf(stderr, "%*s**Describing the current object:\n", indent, ""); +  describe_something(f->current_object, T_OBJECT, indent+2, depth, flags, 0);    } -  +  if ((f = f->scope)) +  fprintf(stderr, "%*s**Moving on to outer scope frame %p:\n", indent, "", f); +  } while (f); +  break;    }    - void describe_something(void *a, int t, int indent, int depth, int flags) +  default: +  fprintf(stderr, "%*s**Cannot describe block of unknown type %d\n", +  indent, "", t); +  } + } +  + void describe_something(void *a, int t, int indent, int depth, int flags, +  void *inblock)   {    int tmp;    struct program *p=(struct program *)a;    if(!a) return;       if(t==-1)    {    fprintf(stderr,"%*s**Location description: %s\n",indent,"",(char *)a);    return;    }
pike.git/src/gc.c:913:    } else {    fprintf(stderr,"%*s**Location: %p Type: %s Refs: %d\n",indent,"",a,    get_name_of_type(t),    *(INT32 *)a);      #ifdef DEBUG_MALLOC    if(!(flags & DESCRIBE_NO_DMALLOC))    debug_malloc_dump_references(a,indent+2,depth-1,flags);   #endif    -  low_describe_something(a,t,indent,depth,flags); +  low_describe_something(a,t,indent,depth,flags,inblock);    }       fprintf(stderr,"%*s*******************\n",indent,"");    d_flag=tmp;   }      PMOD_EXPORT void describe(void *x)   { -  describe_something(x, attempt_to_identify(x), 0, 2, 0); +  void *inblock; +  int type = attempt_to_identify(x, &inblock); +  describe_something(x, type, 0, 2, 0, inblock);   }      void debug_describe_svalue(struct svalue *s)   {    fprintf(stderr,"Svalue at %p is:\n",s);    switch(s->type)    {    case T_INT:    fprintf(stderr," %"PRINTPIKEINT"d\n",s->u.integer);    break;
pike.git/src/gc.c:957:    {    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);    }    }    } -  describe_something(s->u.refs,s->type,0,2,0); +  describe_something(s->u.refs,s->type,0,2,0,0);   }      void gc_watch(void *a)   {    struct marker *m;    init_gc();    m = get_marker(a);    if (!(m->flags & GC_WATCHED)) {    m->flags |= GC_WATCHED;    fprintf(stderr, "## Watching thing %p.\n", a);
pike.git/src/gc.c:1463:    gc_add_extra_ref(a);    m->flags |= GC_GOT_DEAD_REF;   #ifdef PIKE_DEBUG    delayed_freed++;   #endif    }       return 1;   }    - void gc_delayed_free(void *a, TYPE_T type) + void gc_delayed_free(void *a, int type)   {    struct marker *m;      #ifdef PIKE_DEBUG    if (gc_is_watching && (m = find_marker(a)) && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    fprintf(stderr, "## Watched thing %p found in "    "gc_delayed_free() in pass %d.\n", a, Pike_in_gc);    }    if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_CYCLE &&
pike.git/src/gc.c:2160:    kill_list = NEXT(gc_rec_last);    NEXT(gc_rec_last) = 0;    }   }      void do_gc_recurse_svalues(struct svalue *s, int num)   {    gc_recurse_svalues(s, num);   }    - void do_gc_recurse_short_svalue(union anything *u, TYPE_T type) + void do_gc_recurse_short_svalue(union anything *u, int type)   {    gc_recurse_short_svalue(u, type);   }      int gc_do_free(void *a)   {    struct marker *m;   #ifdef PIKE_DEBUG    if (gc_is_watching && (m = find_marker(a)) && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */