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.122 2000/08/16 10:35:48 grubba Exp $"); + RCSID("$Id: gc.c,v 1.123 2000/08/16 22:03:40 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:69:    * that are missed by this detection, though.    *    * Things that aren't live objects but are referenced from them are    * still intact during this destruct pass, so it's entirely possible    * to save these things by adding external references to them.    * However, it's not possible for live objects to save themselves or    * other live objects; all live objects that didn't have external    * references at the start of the gc pass will be destructed    * regardless of added references.    * -  * Things that have only weak references at the start of the gc pass -  * will be freed. That's done before the live object destruct pass. +  * Things that have only weak external references at the start of the +  * gc pass will be freed. That's done before the live object destruct +  * pass. Internal weak references are however still intact.    */      /* #define GC_VERBOSE */   /* #define GC_CYCLE_DEBUG */      /* #define GC_STACK_DEBUG */      #if defined(GC_VERBOSE) && !defined(PIKE_DEBUG)   #undef GC_VERBOSE   #endif
pike.git/src/gc.c:871:    gc_fatal(a, 2, "A thing was missed by "    "both mark and cycle check pass.\n");    else if (!(m->flags & GC_IS_REFERENCED))    gc_fatal(a, 2, "An unreferenced thing "    "got missed by gc_is_referenced().\n");    else if (!(m->flags & GC_DO_FREE))    gc_fatal(a, 2, "An unreferenced thing "    "got missed by gc_do_free().\n");    else if (m->flags & GC_GOT_EXTRA_REF)    gc_fatal(a, 2, "A thing still got an extra ref.\n"); -  else if (m->weak_refs == -1) -  gc_fatal(a, 3, "A thing which had only weak references is " -  "still around after gc.\n"); +     else if (!(m->flags & GC_LIVE)) {    if (m->weak_refs > 0)    gc_fatal(a, 3, "A thing to garb is still around. "    "It's probably one with only external weak refs.\n"); -  +  else if (m->weak_refs < 0) +  gc_fatal(a, 3, "A thing which had only weak references is " +  "still around after gc.\n");    else    gc_fatal(a, 3, "A thing to garb is still around.\n");    }    }    }    else    fatal("debug_gc_touch() used in invalid gc pass.\n");   }      static INLINE struct marker *gc_check_debug(void *a, int weak)
pike.git/src/gc.c:945:    return ret;   }      INT32 real_gc_check_weak(void *a)   {    struct marker *m;    INT32 ret;      #ifdef PIKE_DEBUG    if (!(m = gc_check_debug(a, 1))) return 0; -  if (m->weak_refs == -1) +  if (m->weak_refs < 0)    gc_fatal(a, 1, "Thing has already reached threshold for weak free.\n");    if (m->weak_refs >= *(INT32 *) a)    gc_fatal(a, 1, "Thing has gotten more weak refs than refs.\n");    if (m->weak_refs > m->refs + 1)    gc_fatal(a, 1, "Thing has gotten more weak refs than internal refs.\n");   #else    m = get_marker(a);   #endif       m->weak_refs++;
pike.git/src/gc.c:1173: Inside #if defined(PIKE_DEBUG)
   else m = get_marker(a);    debug_malloc_touch(a);       if (m->weak_refs > m->refs)    gc_fatal(a, 0, "More weak references than internal references.\n");   #else    m = get_marker(a);   #endif       if (Pike_in_gc != GC_PASS_ZAP_WEAK) { -  if (m->weak_refs == -1) { +  if (m->weak_refs < 0) {    gc_ext_weak_refs--;    return 1;    }    }    else    if (!(m->flags & GC_MARKED)) {   #ifdef PIKE_DEBUG    if (m->weak_refs <= 0)    gc_fatal(a, 0, "Too many weak refs cleared to thing with external "    "weak refs.\n");
pike.git/src/gc.c:1202:   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"); -  if (m->weak_refs == -1) +  if (m->weak_refs < 0)    gc_fatal(a, 0, "Marking thing scheduled for weak free.\n");    if (Pike_in_gc == GC_PASS_ZAP_WEAK && !(m->flags & GC_MARKED))    gc_fatal(a, 0, "gc_mark() called for thing in zap weak pass "    "that wasn't marked before.\n");   #endif       if (Pike_in_gc == GC_PASS_ZAP_WEAK)    /* Things are visited in the zap weak pass through the mark    * functions to free refs to internal things that only got weak    * external references. That happens only when a thing also have
pike.git/src/gc.c:1502:    }      #ifdef PIKE_DEBUG    if (weak < 0 && gc_rec_last->frameflags & GC_FOLLOWED_NONSTRONG)    gc_fatal(x, 0, "Followed strong link too late.\n");    if (weak >= 0) gc_rec_last->frameflags |= GC_FOLLOWED_NONSTRONG;   #endif       if (weak > 0) {   #ifdef PIKE_DEBUG -  if (m->weak_refs <= 0) +  if (m->weak_refs == 0)    gc_fatal(x, 0, "Followed weak ref to thing that should have none left.\n"); -  m->weak_refs--; +  /* We only keep m->weak_refs accurate in debug mode for the sake +  * of the checks in debug_gc_touch(); nothing else should trust it +  * to be valid after the mark pass. */ +  m->weak_refs--; /* Might already be negative. */   #endif    gc_ext_weak_refs--;    }       if (m->frame && !(m->frame->frameflags & GC_OFF_STACK)) {    /* A cyclic reference is found. */   #ifdef PIKE_DEBUG    if (gc_rec_last == &rec_list)    gc_fatal(x, 0, "Cyclic ref involves dummy rec_list marker.\n");    CHECK_POP_FRAME(gc_rec_last);
pike.git/src/gc.c:2066:    gc_internal_array = &empty_array;    gc_internal_multiset = 0;    gc_internal_mapping = 0;    gc_internal_program = 0;    gc_internal_object = 0;      #ifdef PIKE_DEBUG    if(fatal_after_gc) fatal(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) {    objs -= num_objects;    warn_bad_cycles();    objs += num_objects;    }   #ifdef PIKE_DEBUG