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.143 2000/12/01 08:09:47 hubbe Exp $"); + RCSID("$Id: gc.c,v 1.144 2000/12/14 07:24:37 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:1230:    /* Make sure the thing doesn't run out of refs, since we can't    * handle cascading frees now. We'll do it in the free pass    * instead. */    gc_add_extra_ref(a);    m->flags |= GC_GOT_DEAD_REF;    }       return 1;   }    + void gc_delayed_free(void *a) + { +  struct marker *m; +  + #ifdef PIKE_DEBUG +  if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_CYCLE && +  Pike_in_gc != GC_PASS_ZAP_WEAK) +  fatal("gc_delayed_free() called in invalid gc pass.\n"); +  if (gc_debug) { +  if (!(m = find_marker(a))) +  gc_fatal(a, 0, "gc_delayed_free() got unknown object (missed by pretouch pass).\n"); +  } +  else m = get_marker(a); +  if (*(INT32 *) a != 1) +  fatal("gc_delayed_free() called for thing that haven't got a single ref.\n"); +  if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED)) +  gc_fatal(a, 1, "gc_delayed_free() got a thing marked as referenced.\n"); +  debug_malloc_touch(a); + #else +  m = get_marker(a); + #endif +  +  gc_add_extra_ref(a); +  m->flags |= GC_GOT_DEAD_REF; + } +    int gc_mark(void *a)   {    struct marker *m = get_marker(debug_malloc_pass(a));      #ifdef PIKE_DEBUG    if (!a) fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_ZAP_WEAK)    fatal("gc mark attempted in invalid pass.\n");    if (!*(INT32 *) a)    gc_fatal(a, 0, "Marked a thing without refs.\n");
pike.git/src/gc.c:2019:    /* 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);       GC_VERBOSE_DO(fprintf(stderr, "| check: %u references checked, counted %lu weak refs\n",    checked, SIZE_T_TO_ULONG(gc_ext_weak_refs)));       Pike_in_gc=GC_PASS_MARK;    -  /* Anything after and including gc_internal_foo in the linked lists +  /* Anything after and including gc_internal_* in the linked lists    * are considered to lack external references. The mark pass move    * externally referenced things in front of these pointers. */    gc_internal_array = empty_array.next;    gc_internal_multiset = first_multiset;    gc_internal_mapping = first_mapping;    gc_internal_program = first_program;    gc_internal_object = first_object;       /* Next we mark anything with external references. Note that we can    * follow the same reference several times, e.g. with shared mapping
pike.git/src/gc.c:2144:    gc_zap_ext_weak_refs_in_objects();    gc_zap_ext_weak_refs_in_programs();    GC_VERBOSE_DO(    fprintf(stderr,    "| zap weak: freed %ld external weak refs, %lu internal still around,\n"    "| %d things really freed\n",    PTRDIFF_T_TO_LONG(to_free - gc_ext_weak_refs),    SIZE_T_TO_ULONG(gc_ext_weak_refs), obj_count - num_objects));    }    +  /* Add an extra reference to the stuff gc_internal_* point to, so we +  * know they're still around when gc_free_all_unreferenced_* is +  * about to be called. */ +  if (gc_internal_array != &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 */ +  /* 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. */ +  if (gc_internal_array != &empty_array) { +  FREE_AND_GET_REFERENCED(gc_internal_array, struct array, free_array);    gc_free_all_unreferenced_arrays(); -  +  } +  if (gc_internal_multiset) { +  FREE_AND_GET_REFERENCED(gc_internal_multiset, struct multiset, free_multiset);    gc_free_all_unreferenced_multisets(); -  +  } +  if (gc_internal_mapping) { +  FREE_AND_GET_REFERENCED(gc_internal_mapping, struct mapping, free_mapping);    gc_free_all_unreferenced_mappings(); -  +  } +  if (gc_internal_program) { +  FREE_AND_GET_REFERENCED(gc_internal_program, struct program, free_program);    gc_free_all_unreferenced_programs(); -  +  } +  if (gc_internal_object) { +  FREE_AND_GET_REFERENCED(gc_internal_object, struct object, free_object);    gc_free_all_unreferenced_objects(); -  +  }       GC_VERBOSE_DO(fprintf(stderr, "| free: %d really freed, %u left with live references\n",    obj_count - num_objects, live_ref));    -  gc_internal_array = &empty_array; -  gc_internal_multiset = 0; -  gc_internal_mapping = 0; -  gc_internal_program = 0; -  gc_internal_object = 0; -  +    #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) fatal("%s", fatal_after_gc);   #endif       /* Pike code may run again now. */       Pike_in_gc=GC_PASS_KILL;    /* Destruct the live objects in cycles, but first warn about any bad    * cycles. */    pre_kill_objs = num_objects;    if (last_cycle) {