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.166 2001/07/05 00:09:41 mast Exp $"); + RCSID("$Id: gc.c,v 1.167 2001/07/05 01:44:55 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. */    } 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:149:    gc_fatal((frame)->data, 0, \    "Pop frame pointers are inconsistent.\n"); \   } while (0)   #else   #define CHECK_POP_FRAME(frame) do {} while (0)   #endif      static struct gc_frame rec_list = {0, 0, {{0, 0, 0}}, GC_POP_FRAME};   static struct gc_frame *gc_rec_last = &rec_list, *gc_rec_top = 0;   static struct gc_frame *kill_list = 0; + static struct gc_frame *free_extra_list = 0; /* See note in gc_delayed_free. */      static unsigned last_cycle;   size_t gc_ext_weak_refs;      /* gc_frame objects are used as frames in a recursion stack during the    * cycle check pass. gc_rec_top points to the current top of the    * stack. When a thing is recursed, a pop frame is first pushed on the    * stack and then the gc_cycle_check_* function fills in with link    * frames for every reference the thing contains.    *
pike.git/src/gc.c:1456:    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) + void gc_delayed_free(void *a, TYPE_T 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_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);    delayed_freed++;   #else    m = get_marker(a);   #endif    -  +  if (m->flags & GC_MARKED) { +  /* Note that we can get marked things here, e.g. if the index in a +  * mapping with weak indices is removed in the zap weak pass, the +  * value will be zapped too, but it will still have a mark from +  * the mark pass. This means that the stuff referenced by the +  * value will only be refcount garbed, which can leave cyclic +  * garbage for the next gc round. +  * +  * Since the value has been marked we won't find it in the free +  * pass, so we have to keep special track of it. :P */ +  struct gc_frame *l = alloc_gc_frame(); +  l->data = a; +  l->u.free_extra_type = type; +  l->back = free_extra_list; +  l->frameflags = 0; +  free_extra_list = l; +  } +     gc_add_extra_ref(a);    m->flags |= GC_GOT_DEAD_REF;   }      #ifdef PIKE_DEBUG   void gc_mark_enqueue(queue_call call, void *data)   {    struct marker *m;    if (gc_is_watching && (m = find_marker(data)) && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */
pike.git/src/gc.c:2520:    }    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();    }    +  /* 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));      #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;