pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:1:   /*   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information. - || $Id: gc.c,v 1.193 2003/01/11 01:30:21 mast Exp $ + || $Id: gc.c,v 1.194 2003/01/11 03:06:54 mast Exp $   */      #include "global.h"      struct callback *gc_evaluator_callback=0;      #include "array.h"   #include "multiset.h"   #include "mapping.h"   #include "object.h"
pike.git/src/gc.c:24:   #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.193 2003/01/11 01:30:21 mast Exp $"); + RCSID("$Id: gc.c,v 1.194 2003/01/11 03:06:54 mast Exp $");      /* Run garbage collect approximately every time    * 20 percent of all arrays, objects and programs is    * garbage.    */   #define GC_CONST 20      /* Use a decaying average where the slowness factor approximately    * corresponds to the average over the last ten gc rounds.    * (0.9 == 1 - 1/10) */
pike.git/src/gc.c:2431:    if (!p) break;    }    }       CALL_AND_UNSET_ONERROR(tmp);   }      size_t do_gc(void)   {    double tmp; -  size_t num_objs, allocs, freed; +  size_t num_objs, allocs, unreferenced;    ptrdiff_t objs, pre_kill_objs;    double multiplier;   #ifdef PIKE_DEBUG   #ifdef HAVE_GETHRTIME    hrtime_t gcstarttime = 0;   #endif    unsigned destroy_count, obj_count;    ONERROR uwp;   #endif   
pike.git/src/gc.c:2684: Inside #if defined(PIKE_DEBUG), #if 0 /* Temporarily disabled - Hubbe */ and #if defined(DEBUG_MALLOC)
   describe(m->data);    Pike_in_gc = GC_PASS_MIDDLETOUCH;    Pike_fatal("Fatal in garbage collector.\n");    }   #endif   #endif    GC_VERBOSE_DO(fprintf(stderr, "| middletouch\n"));    }   #endif    -  /* Add an extra reference to the stuff gc_internal_* point to, so we -  * know they're still around when gc_free_all_unreferenced_* are -  * about to be called. */ -  if (gc_internal_array != &weak_empty_array) add_ref(gc_internal_array); -  if (gc_internal_multiset) add_ref(gc_internal_multiset); -  if (gc_internal_mapping) add_ref(gc_internal_mapping); -  if (gc_internal_program) add_ref(gc_internal_program); -  if (gc_internal_object) add_ref(gc_internal_object); -  +     /* Thread switches, object alloc/free and reference changes are    * allowed again now. */       Pike_in_gc=GC_PASS_FREE;   #ifdef PIKE_DEBUG    weak_freed = 0;    obj_count = num_objects;   #endif       /* Now we free the unused stuff. The extra refs to gc_internal_*    * added above are removed just before the calls so we'll get the    * correct relative positions in them. */ -  freed = 0; -  if (gc_internal_array != &weak_empty_array) { -  FREE_AND_GET_REFERENCED(gc_internal_array, struct array, free_array); -  freed += 1 + gc_free_all_unreferenced_arrays(); -  } -  if (gc_internal_multiset) { -  FREE_AND_GET_REFERENCED(gc_internal_multiset, struct multiset, free_multiset); -  freed += 1 + gc_free_all_unreferenced_multisets(); -  } -  if (gc_internal_mapping) { -  FREE_AND_GET_REFERENCED(gc_internal_mapping, struct mapping, free_mapping); -  freed += 1 + gc_free_all_unreferenced_mappings(); -  } -  if (gc_internal_program) { -  FREE_AND_GET_REFERENCED(gc_internal_program, struct program, free_program); -  freed += 1 + gc_free_all_unreferenced_programs(); -  } -  if (gc_internal_object) { -  FREE_AND_GET_REFERENCED(gc_internal_object, struct object, free_object); -  freed += 1 + gc_free_all_unreferenced_objects(); -  } +  unreferenced = 0; +  if (gc_internal_array != &weak_empty_array) +  unreferenced += gc_free_all_unreferenced_arrays(); +  if (gc_internal_multiset) +  unreferenced += gc_free_all_unreferenced_multisets(); +  if (gc_internal_mapping) +  unreferenced += gc_free_all_unreferenced_mappings(); +  if (gc_internal_program) +  unreferenced += gc_free_all_unreferenced_programs(); +  if (gc_internal_object) +  unreferenced += gc_free_all_unreferenced_objects();       /* We might occasionally get things to gc_delayed_free that the free    * calls above won't find. They're tracked in this list. */    while (free_extra_list) {    struct gc_frame *next = free_extra_list->back;    union anything u;    u.refs = (INT32 *) free_extra_list->data;    gc_free_extra_ref(u.refs);    free_short_svalue(&u, free_extra_list->u.free_extra_type);    debug_really_free_gc_frame(free_extra_list);    free_extra_list = next;    }    -  GC_VERBOSE_DO(fprintf(stderr, "| free: %d really freed, %u left with live references\n", -  obj_count - num_objects, live_ref)); +  GC_VERBOSE_DO(fprintf(stderr, "| free: %d unreferenced, %d really freed, " +  "%u left with live references\n", +  unreferenced, obj_count - num_objects, live_ref));      #ifdef PIKE_DEBUG    gc_internal_array = (struct array *) (ptrdiff_t) -1;    gc_internal_multiset = (struct multiset *) (ptrdiff_t) -1;    gc_internal_mapping = (struct mapping *) (ptrdiff_t) -1;    gc_internal_program = (struct program *) (ptrdiff_t) -1;    gc_internal_object = (struct object *) (ptrdiff_t) -1;       if(fatal_after_gc) Pike_fatal("%s", fatal_after_gc);   #endif
pike.git/src/gc.c:2790:    INT32 line;    struct pike_string *file = get_program_line (o->prog, &line);    fprintf(stderr, ", prog %s:%d\n", file->str, line);    free_string(file);    }    else fputs(", is destructed\n", stderr);    );    destruct(o);    free_object(o);    gc_free_extra_ref(o); -  freed++; +    #ifdef PIKE_DEBUG    destroy_count++;   #endif    debug_really_free_gc_frame(kill_list);    kill_list = next;    }       GC_VERBOSE_DO(fprintf(stderr, "| kill: %u objects killed, %d things really freed\n",    destroy_count, pre_kill_objs - num_objects));   
pike.git/src/gc.c:2830: Inside #if defined(PIKE_DEBUG)
   GC_VERBOSE_DO(fprintf(stderr, "| posttouch: %u things\n", n));    }    if (gc_extra_refs)    Pike_fatal("Lost track of %d extra refs to things in gc.\n", gc_extra_refs);    if(fatal_after_gc) Pike_fatal("%s", fatal_after_gc);   #endif       Pike_in_gc=0;    exit_gc();    -  /* At this point, freed contains the number of things that were -  * without external references during the check and mark passes. In -  * the process of freeing them, destroy functions might have been -  * called which means anything might have happened. Therefore we use -  * that figure instead of the difference between the number of -  * allocated things to measure the amount of garbage. */ +  /* At this point, unreferenced contains the number of things that +  * were without external references during the check and mark +  * passes. In the process of freeing them, destroy functions might +  * have been called which means anything might have happened. +  * Therefore we use that figure instead of the difference between +  * the number of allocated things to measure the amount of +  * garbage. */    -  objects_freed = objects_freed * multiplier + freed * (1.0 - multiplier); +  objects_freed = objects_freed * multiplier + unreferenced * (1.0 - multiplier);       /* Calculate the new threshold by adjusting the average threshold    * (objects_alloced) with the ratio between the wanted garbage at    * the next gc (GC_CONST/100.0 * num_objs) and the actual average    * garbage (objects_freed). (Where the +1.0's come from I don't    * know. Perhaps they're to avoid division by zero. /mast) */    tmp = (objects_alloced+1.0) * (GC_CONST/100.0 * num_objs) / (objects_freed+1.0);      #if 0    /* Afaics this was to limit the growth of the threshold to avoid
pike.git/src/gc.c:2869:    tmp = (double)MAX_ALLOC_THRESHOLD;       alloc_threshold = (ptrdiff_t)tmp;      #ifdef PIKE_DEBUG    UNSET_ONERROR (uwp);    if(GC_VERBOSE_DO(1 ||) Pike_interpreter.trace_level)    {   #ifdef HAVE_GETHRTIME    fprintf(stderr, -  "done (freed %"PRINTPTRDIFFT"d of %"PRINTPTRDIFFT"d things), %ld ms.\n", -  freed, num_objs, (long)((gethrtime() - gcstarttime)/1000000)); +  "done (%"PRINTPTRDIFFT"d of %"PRINTPTRDIFFT"d was unreferenced), %ld ms.\n", +  unreferenced, num_objs, (long)((gethrtime() - gcstarttime)/1000000));   #else    fprintf(stderr, -  "done (freed %"PRINTPTRDIFFT"d of %"PRINTPTRDIFFT"d things)\n", -  freed, num_objs); +  "done (%"PRINTPTRDIFFT"d of %"PRINTPTRDIFFT"d was unreferenced)\n", +  unreferenced, num_objs);   #endif    }    if (max_gc_frames > max_tot_gc_frames) max_tot_gc_frames = max_gc_frames;    tot_cycle_checked += cycle_checked;    tot_live_rec += live_rec, tot_frame_rot += frame_rot;   #endif      #ifdef ALWAYS_GC    ADD_GC_CALLBACK();   #else    if(d_flag > 3) ADD_GC_CALLBACK();   #endif    -  return freed; +  return unreferenced;   }      /*! @decl mapping(string:int|float) gc_status()    *! @belongs Debug    *!    *! Get statistics from the garbage collector.    *!    *! @returns    *! A mapping with the following content will be returned:    *! @mapping