pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:22:   #include "time_stuff.h"   #include "constants.h"   #include "interpret.h"      #include "gc.h"   #include "main.h"   #include <math.h>      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.73 2000/04/19 21:49:27 mast Exp $"); + RCSID("$Id: gc.c,v 1.74 2000/04/20 01:49:42 mast Exp $");      /* Run garbage collect approximate every time we have    * 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:590: Inside #if defined(PIKE_DEBUG)
   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="Reference to object to free in referenced object!\n";    }    }    return 0;    }    -  if (Pike_in_gc != 1) +  if (Pike_in_gc != 2)    fatal("gc check attempted in pass %d.\n", Pike_in_gc);       if(m->saved_refs != -1)    if(m->saved_refs != *(INT32 *)a) {    fprintf(stderr,"**Refs changed in gc() pass %d. Expected %ld, got %ld.\n",    Pike_in_gc, (long)m->saved_refs, (long)*(INT32 *)a);    describe(a);    locate_references(a);    fprintf(stderr,"##### Continuing search for more bugs....\n");    fatal_after_gc="Refs changed in gc()\n";
pike.git/src/gc.c:720: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG      int debug_gc_is_referenced(void *a)   {    struct marker *m;    m=get_marker(a);       if(m->refs + m->xrefs > *(INT32 *)a ||    (!(m->refs < *(INT32 *)a) && m->xrefs) || -  (Pike_in_gc < 3 && m->saved_refs != -1 && m->saved_refs != *(INT32 *)a)) +  (Pike_in_gc < 4 && m->saved_refs != -1 && m->saved_refs != *(INT32 *)a))    {    INT32 refs=m->refs;    INT32 xrefs=m->xrefs;    TYPE_T t=attempt_to_identify(a);    d_flag=0;       fprintf(stderr,"**Something has %ld refs, while gc() found %ld + %ld external.\n",    (long)*(INT32 *)a,    (long)refs,    (long)xrefs);
pike.git/src/gc.c:804: Inside #if defined(PIKE_DEBUG)
   return 0;   }   #endif      int gc_mark(void *a)   {    struct marker *m;    m=get_marker(debug_malloc_pass(a));      #ifdef PIKE_DEBUG -  if (Pike_in_gc != 2) +  if (Pike_in_gc != 3)    fatal("gc mark attempted in pass %d.\n", Pike_in_gc);   #endif       if(m->flags & GC_REFERENCED)    {    return 0;    }else{    m->flags |= GC_REFERENCED;    return 1;    }
pike.git/src/gc.c:856: Inside #if defined(PIKE_DEBUG)
      return (m->flags & (GC_REFERENCED|GC_CHECKED)) == GC_CHECKED;   }   #endif      void do_gc(void)   {    double tmp;    INT32 tmp2;    double multiplier; +  int destroyed, destructed;   #ifdef HAVE_GETHRTIME   #ifdef PIKE_DEBUG    hrtime_t gcstarttime;   #endif   #endif       if(Pike_in_gc) return;    Pike_in_gc=1;    -  /* Make sure there will be no callback to this while we're in the gc. */ +  /* 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 +  * the object list, which causes that list to be reordered and the +  * various gc loops over it might then miss things. */    destruct_objects_to_destruct();       if(gc_evaluator_callback)    {    remove_callback(gc_evaluator_callback);    gc_evaluator_callback=0;    }       tmp2=num_objects;   
pike.git/src/gc.c:899:    multiplier=pow(MULTIPLIER, (double) num_allocs / (double) alloc_threshold);    objects_alloced*=multiplier;    objects_alloced += (double) num_allocs;       objects_freed*=multiplier;    objects_freed += (double) num_objects;          init_gc();    +  Pike_in_gc=2;    /* First we count internal references */    gc_check_all_arrays();    gc_check_all_multisets();    gc_check_all_mappings();    gc_check_all_programs();    gc_check_all_objects();      #ifdef PIKE_DEBUG    if(master_object) gc_external_mark2(master_object,0," &master_object");    {
pike.git/src/gc.c:920: Inside #if defined(PIKE_DEBUG)
   if(builtin_constants)    gc_external_mark2(builtin_constants,0," &builtin_constants");    }   #endif       /* These callbacks are mainly for pass 1, but can also    * do things that are normally associated with pass 2    */    call_callback(& gc_callbacks, (void *)0);    -  Pike_in_gc=2; -  +  Pike_in_gc=3;    /* Next we mark anything with external references */    gc_mark_all_arrays();    run_queue(&gc_mark_queue);    gc_mark_all_multisets();    run_queue(&gc_mark_queue);    gc_mark_all_mappings();    run_queue(&gc_mark_queue);    gc_mark_all_programs();    run_queue(&gc_mark_queue);    gc_mark_all_objects();    run_queue(&gc_mark_queue);       if(d_flag)    gc_mark_all_strings();    -  +    #ifdef PIKE_DEBUG    check_for=(void *)1;   #endif -  Pike_in_gc=3; +  Pike_in_gc=5;    /* 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(); -  gc_free_all_unreferenced_objects(); +  Pike_in_gc=4; +  /* 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=5; +  destructed = gc_free_all_unreferenced_objects();      #ifdef PIKE_DEBUG -  +  if (destroyed != destructed) +  fatal("destroy() called in %d objects in gc, but %d destructed.\n", +  destroyed, destructed);    check_for=0;    if(fatal_after_gc) fatal(fatal_after_gc);   #endif       exit_gc();    -  Pike_in_gc=5; +  Pike_in_gc=6;    destruct_objects_to_destruct();       objects_freed -= (double) num_objects;       tmp=(double)num_objects;    tmp=tmp * GC_CONST/100.0 * (objects_alloced+1.0) / (objects_freed+1.0);       if((int)tmp < alloc_threshold + num_allocs)    {    alloc_threshold=(int)tmp;