Branch: Tag:

2000-04-23

2000-04-23 03:01:26 by Martin Stjernholm <mast@lysator.liu.se>

GC fixes. Made the gc quite a bit more whiny when -d is used.

Rev: src/array.c:1.68
Rev: src/array.h:1.19
Rev: src/gc.c:1.79
Rev: src/gc.h:1.38
Rev: src/mapping.c:1.79
Rev: src/mapping.h:1.24
Rev: src/multiset.c:1.20
Rev: src/multiset.h:1.10
Rev: src/object.c:1.120
Rev: src/object.h:1.45
Rev: src/program.c:1.232
Rev: src/program.h:1.87
Rev: src/svalue.c:1.72
Rev: src/threads.h:1.89

29:      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.78 2000/04/22 02:23:56 hubbe Exp $"); + RCSID("$Id: gc.c,v 1.79 2000/04/23 03:01:25 mast Exp $");      /* Run garbage collect approximate every time we have    * 20 percent of all arrays, objects and programs is
42:   #define MULTIPLIER 0.9   #define MARKER_CHUNK_SIZE 1023    - INT32 num_objects =0; + INT32 num_objects = 1; /* Account for empty_array. */   INT32 num_allocs =0;   INT32 alloc_threshold = MIN_ALLOC_THRESHOLD;   int Pike_in_gc = 0;
129: Inside #if defined(PIKE_DEBUG)
  static int found_in_type=0;   void *gc_svalue_location=0;   char *fatal_after_gc=0; + static int gc_debug = 0;      #define DESCRIBE_MEM 1   #define DESCRIBE_NO_REFS 2
387:    fprintf(stderr,"%*s**Parent identifier: %d\n",indent,"",((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,""); +  +  if(!p) +  { +  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,""); +  low_describe_something(p, T_PROGRAM, indent, depth, flags); +  } +     if( ((struct object *)a)->parent)    {    fprintf(stderr,"%*s**Describing object's parent:\n",indent,"");
396:    }else{    fprintf(stderr,"%*s**There is no parent (any longer?)\n",indent,"");    } -  if(!p) -  { -  fprintf(stderr,"%*s**The object is destructed.\n",indent,""); -  p=id_to_program(((struct object *)a)->program_id); +  break;    -  if(!p) break; -  } -  fprintf(stderr,"%*s**Attempting to describe program object was instantiated from:\n",indent,""); -  +     case T_PROGRAM:    {    char *tmp;
566:    describe_something(s->u.refs,s->type,0,2,0);   }    + void debug_gc_touch(void *a) + { +  struct marker *m; +  if (!a) fatal("real_gc_check(): Got null pointer.\n"); +  +  m = find_marker(a); +  if (Pike_in_gc == GC_PASS_PRETOUCH) { +  if (m) { +  fprintf(stderr,"**Object touched twice.\n"); +  describe(a); +  fatal("Object touched twice.\n"); +  } +  get_marker(a)->flags |= GC_TOUCHED; +  } +  else if (Pike_in_gc == GC_PASS_POSTTOUCH) { +  if (m) { +  if (!(m->flags & GC_TOUCHED)) { +  fprintf(stderr,"**An existing but untouched marker found for object in linked lists. flags: %x.\n", m->flags); +  describe(a); +  fatal("An existing but untouched marker found for object in linked lists.\n"); +  } +  if ((m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED) { +  fprintf(stderr,"**An object to garb is still around. flags: %x.\n", m->flags); +  fprintf(stderr," has %ld references, while gc() found %ld + %ld external.\n",(long)*(INT32 *)a,(long)m->refs,(long)m->xrefs); +  describe(a); +  locate_references(a); +  fprintf(stderr,"##### Continuing search for more bugs....\n"); +  fatal_after_gc="An object to garb is still around.\n"; +  } +  } +  } +  else +  fatal("debug_gc_touch() used in invalid gc pass.\n"); + } +    #endif /* PIKE_DEBUG */      INT32 real_gc_check(void *a)   { -  struct marker *m=get_marker(a); +  struct marker *m;      #ifdef PIKE_DEBUG -  +  if (!a) fatal("real_gc_check(): Got null pointer.\n");    if(check_for)    {    if(check_for == a)
580: Inside #if defined(PIKE_DEBUG)
   gdb_gc_stop_here(a);    }    -  if(check_for == (void *)1 && gc_do_free(a)) +  m=get_marker(a); +  if(check_for == (void *)1 && +  m && (m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED)    { -  struct marker *m=get_marker(a); +     int t=attempt_to_identify(a);    if(t != T_STRING && t != T_UNKNOWN)    {
601:    return 0;    }    -  if (Pike_in_gc /100 != 1) -  fatal("gc check attempted in pass %d.\n", Pike_in_gc); +  if (Pike_in_gc != GC_PASS_CHECK) +  fatal("gc check attempted in invalid pass.\n");    -  +  m = get_marker(a); +     if(m->saved_refs != -1)    if(m->saved_refs != *(INT32 *)a) {    fprintf(stderr,"**Refs changed in gc() pass %d. Expected %ld, got %ld.\n",
669: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG   void locate_references(void *a)   { +  int tmp, orig_in_gc = Pike_in_gc;    void *orig_check_for=check_for;    if(!Pike_in_gc)    init_gc(); -  +  Pike_in_gc = GC_PASS_LOCATE;    -  +  /* Disable debug, this may help reduce recursion bugs */ +  tmp=d_flag; +  d_flag=0; +     fprintf(stderr,"**Looking for references:\n");       check_for=a;
717: Inside #if defined(PIKE_DEBUG)
   }   #endif    +  Pike_in_gc = orig_in_gc;    if(!Pike_in_gc)    exit_gc(); -  +  d_flag=tmp;   }   #endif   
727: Inside #if defined(PIKE_DEBUG)
  int debug_gc_is_referenced(void *a)   {    struct marker *m; -  m=get_marker(a); +  if (!a) fatal("real_gc_check(): Got null pointer.\n");    -  +  m=get_marker(a);    if(m->refs + m->xrefs > *(INT32 *)a ||    (!(m->refs < *(INT32 *)a) && m->xrefs) || -  (Pike_in_gc < 300 && m->saved_refs != -1 && m->saved_refs != *(INT32 *)a)) +  (Pike_in_gc >= GC_PASS_CHECK && Pike_in_gc <= GC_PASS_MARK && +  m->saved_refs != -1 && m->saved_refs != *(INT32 *)a))    {    INT32 refs=m->refs;    INT32 xrefs=m->xrefs;
744: Inside #if defined(PIKE_DEBUG)
   (long)xrefs);       if(m->saved_refs != *(INT32 *)a) -  fprintf(stderr,"**In pass one it had %ld refs!!!\n",(long)m->saved_refs); +  fprintf(stderr,"**In check pass it had %ld refs!!!\n",(long)m->saved_refs);       describe_something(a, t, 0,2,0);   
764: Inside #if defined(PIKE_DEBUG)
  int gc_external_mark3(void *a, void *in, char *where)   {    struct marker *m; +  if (!a) fatal("real_gc_check(): Got null pointer.\n");       if(check_for)    {
783: Inside #if defined(PIKE_DEBUG)
   return 1;    }    -  if(check_for == (void *)1 && gc_do_free(a)) +  m=get_marker(a); +  if(check_for == (void *)1 && +  m && (m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED)    { -  struct marker *m=get_marker(a); +     int t=attempt_to_identify(a);    if(t != T_STRING && t != T_UNKNOWN)    {
816:   int gc_mark(void *a)   {    struct marker *m; -  m=get_marker(debug_malloc_pass(a)); +       #ifdef PIKE_DEBUG -  if (Pike_in_gc /100 != 2) -  fatal("gc mark attempted in pass %d.\n", Pike_in_gc); +  if (!a) fatal("real_gc_check(): Got null pointer.\n"); +  if (Pike_in_gc != GC_PASS_MARK) +  fatal("gc mark attempted in invalid pass.\n");   #endif    -  +  m = get_marker(debug_malloc_pass(a));    if(m->flags & GC_REFERENCED)    {    return 0;
836: Inside #if defined(PIKE_DEBUG)
  int debug_gc_do_free(void *a)   {    struct marker *m; +  if (!a) fatal("real_gc_check(): Got null pointer.\n");    -  m=get_marker(debug_malloc_pass(a)); +  m=find_marker(debug_malloc_pass(a)); +  if (!m) return 0; /* Object created after mark pass. */       if( (m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED &&    (m->flags & GC_XREFERENCED) )
849: Inside #if defined(PIKE_DEBUG)
   {    fprintf(stderr,    "**gc_is_referenced failed, object has %ld references,\n" -  "** while gc() found %ld + %ld external. (type=%d, flags=%d)\n", +  "** while gc() found %ld + %ld external. (type=%d, flags=%x)\n",    (long)*(INT32 *)a,(long)refs,(long)xrefs,t,m->flags);    describe_something(a, t, 4,1,0);   
879:   #endif       if(Pike_in_gc) return; -  Pike_in_gc=10; /* before pass 1 */ +  init_gc(); +  Pike_in_gc=GC_PASS_PREPARE; + #ifdef PIKE_DEBUG +  gc_debug = d_flag; + #endif       /* Make sure there will be no callback to this while we're in the    * gc. That can be fatal since this function links objects back to
915:    objects_freed*=multiplier;    objects_freed += (double) num_objects;    + #ifdef PIKE_DEBUG +  if (gc_debug) { +  INT32 n; +  Pike_in_gc = GC_PASS_PRETOUCH; +  n = gc_touch_all_arrays(); +  n += gc_touch_all_multisets(); +  n += gc_touch_all_mappings(); +  n += gc_touch_all_programs(); +  n += gc_touch_all_objects(); +  if (n != num_objects) +  fatal("Object count wrong before gc; expected %d, got %d.\n", num_objects, n); +  } + #endif    -  init_gc(); -  -  Pike_in_gc=100; /* pass one */ +  Pike_in_gc=GC_PASS_CHECK;    /* First we count internal references */    gc_check_all_arrays();    gc_check_all_multisets();
935:    }   #endif    -  /* These callbacks are mainly for pass 1, but can also -  * do things that are normally associated with pass 2 +  /* These callbacks are mainly for the check pass, but can also +  * do things that are normally associated with the mark pass    */    call_callback(& gc_callbacks, (void *)0);    -  Pike_in_gc=200; /* pass two */ +  Pike_in_gc=GC_PASS_MARK;    /* Next we mark anything with external references */    gc_mark_all_arrays();    run_queue(&gc_mark_queue);
959: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    check_for=(void *)1;   #endif -  Pike_in_gc=350; /* pass 3.5 */ +  Pike_in_gc=GC_PASS_FREE;    /* Now we free the unused stuff */ -  -  +     gc_free_all_unreferenced_arrays();    gc_free_all_unreferenced_multisets();    gc_free_all_unreferenced_mappings();    gc_free_all_unreferenced_programs(); -  Pike_in_gc=300; +  Pike_in_gc=GC_PASS_DESTROY; /* Pike code allowed in this pass. */    /* This is intended to happen before the freeing done above. But    * it's put here for the time being, since the problem of non-object    * objects getting external references from destroy code isn't    * solved yet. */    destroyed = gc_destroy_all_unreferenced_objects(); -  Pike_in_gc=350; +  Pike_in_gc=GC_PASS_FREE;    destructed = gc_free_all_unreferenced_objects();      #ifdef PIKE_DEBUG
984:    if(fatal_after_gc) fatal(fatal_after_gc);   #endif    -  exit_gc(); -  -  Pike_in_gc=400; +  Pike_in_gc=GC_PASS_DESTRUCT;    destruct_objects_to_destruct();    -  + #ifdef PIKE_DEBUG +  if (gc_debug) { +  INT32 n; +  Pike_in_gc=GC_PASS_POSTTOUCH; +  n = gc_touch_all_arrays(); +  n += gc_touch_all_multisets(); +  n += gc_touch_all_mappings(); +  n += gc_touch_all_programs(); +  n += gc_touch_all_objects(); +  if (n != num_objects) +  fatal("Object count wrong after gc; expected %d, got %d.\n", num_objects, n); +  if(fatal_after_gc) fatal(fatal_after_gc); +  } + #endif +  +  Pike_in_gc=0; +  exit_gc(); +     objects_freed -= (double) num_objects;       tmp=(double)num_objects;
1026:   #else    if(d_flag > 3) ADD_GC_CALLBACK();   #endif -  Pike_in_gc=0; +    }      
1057:       f_aggregate_mapping(14);   } -  +