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.184 2002/06/11 17:30:38 mast Exp $"); + RCSID("$Id: gc.c,v 1.185 2002/08/15 14:49:21 marcus 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:657:       if (flags & 2)    fatal_after_gc = "Fatal in garbage collector.\n";    else    debug_fatal("Fatal in garbage collector.\n");   }      static void gdb_gc_stop_here(void *a, int weak)   {   #if 0 -  if (!found_where) fatal("found_where is zero.\n"); +  if (!found_where) Pike_fatal("found_where is zero.\n");   #endif    fprintf(stderr,"***One %sref found%s. ",    weak ? "weak " : "",    found_where?found_where:"");    if (found_in) {    if (gc_svalue_location)    describe_location(found_in , found_in_type, gc_svalue_location,0,1,0);    else {    fputc('\n', stderr);    describe_something(found_in, found_in_type, 2, 0, DESCRIBE_MEM, 0);
pike.git/src/gc.c:1116:   void debug_gc_touch(void *a)   {    struct marker *m;       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_touch() in pass %d.\n", a, Pike_in_gc);    }    -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");       switch (Pike_in_gc) {    case GC_PASS_PRETOUCH:    m = find_marker(a);    if (m && !(m->flags & (GC_PRETOUCHED|GC_WATCHED)))    gc_fatal(a, 1, "Thing got an existing but untouched marker.\n");    m = get_marker(a);    m->flags |= GC_PRETOUCHED;    m->saved_refs = *(INT32 *) a;    break;
pike.git/src/gc.c:1188:    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");    }    }    break;       default: -  fatal("debug_gc_touch() used in invalid gc pass.\n"); +  Pike_fatal("debug_gc_touch() used in invalid gc pass.\n");    }   }      static INLINE struct marker *gc_check_debug(void *a, int weak)   {    struct marker *m;    -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");    if(Pike_in_gc == GC_PASS_LOCATE)    {    if(check_for == a)    {    gdb_gc_stop_here(a, weak);    }    return 0;    }       if (Pike_in_gc != GC_PASS_CHECK) -  fatal("gc check attempted in invalid pass.\n"); +  Pike_fatal("gc check attempted in invalid pass.\n");       m = get_marker(a);       if (!*(INT32 *)a)    gc_fatal(a, 1, "GC check on thing without refs.\n");    if (m->saved_refs == -1) m->saved_refs = *(INT32 *)a;    else if (m->saved_refs != *(INT32 *)a)    gc_fatal(a, 1, "Refs changed in gc check pass.\n");    if (m->refs + m->xrefs >= *(INT32 *) a)    /* m->refs will be incremented by the caller. */
pike.git/src/gc.c:1453: Inside #if defined(PIKE_DEBUG)
  int debug_gc_is_referenced(void *a)   {    struct marker *m;       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_is_referenced() in pass %d.\n", a, Pike_in_gc);    }    -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_MARK) -  fatal("gc_is_referenced() called in invalid gc pass.\n"); +  Pike_fatal("gc_is_referenced() called in invalid gc pass.\n");       if (gc_debug) {    m = find_marker(a);    if ((!m || !(m->flags & GC_PRETOUCHED)) &&    !safe_debug_findstring((struct pike_string *) a))    gc_fatal(a, 0, "Doing gc_is_referenced() on invalid object.\n");    if (!m) m = get_marker(a);    }    else m = get_marker(a);   
pike.git/src/gc.c:1483: Inside #if defined(PIKE_DEBUG)
  int gc_external_mark3(void *a, void *in, char *where)   {    struct marker *m;       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_external_mark3() in pass %d.\n", a, Pike_in_gc);    }    -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");       if(Pike_in_gc == GC_PASS_LOCATE)    {    if(a==check_for)    {    char *tmp=found_where;    void *tmp2=found_in;       if(where) found_where=where;    if(in) found_in=in;       gdb_gc_stop_here(a, 0);       found_where=tmp;    found_in=tmp2;    }    return 0;    }       if (Pike_in_gc != GC_PASS_CHECK) -  fatal("gc_external_mark() called in invalid gc pass.\n"); +  Pike_fatal("gc_external_mark() called in invalid gc pass.\n");       m=get_marker(a);    m->xrefs++;    m->flags|=GC_XREFERENCED;    if(Pike_in_gc == GC_PASS_CHECK &&    (m->refs + m->xrefs > *(INT32 *)a ||    (m->saved_refs != -1 && m->saved_refs != *(INT32 *)a)))    gc_fatal(a, 1, "Ref counts are wrong.\n");    return 0;   }
pike.git/src/gc.c:1544:   int gc_do_weak_free(void *a)   {    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_do_weak_free() in pass %d.\n", a, Pike_in_gc);    } -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_ZAP_WEAK) -  fatal("gc_do_weak_free() called in invalid gc pass.\n"); +  Pike_fatal("gc_do_weak_free() called in invalid gc pass.\n");    if (gc_debug) {    if (!(m = find_marker(a)))    gc_fatal(a, 0, "gc_do_weak_free() got unknown object.\n");    }    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
pike.git/src/gc.c:1609:    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"); +  Pike_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"); +  Pike_fatal("gc_delayed_free() called for thing that haven't got a single ref.\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
pike.git/src/gc.c:1668:   int gc_mark(void *a)   {    struct marker *m = get_marker(debug_malloc_pass(a));      #ifdef PIKE_DEBUG    if (gc_is_watching && m && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    fprintf(stderr, "## Watched thing %p found in "    "gc_mark() in pass %d.\n", a, Pike_in_gc);    } -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_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"); +  Pike_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 < 0)    gc_fatal(a, 0, "Marking thing scheduled for weak free.\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:1773:    fputc('\n', stderr);   #endif    gc_rec_top = l;    return l;   }      void gc_cycle_run_queue()   {   #ifdef PIKE_DEBUG    if (Pike_in_gc != GC_PASS_CYCLE) -  fatal("Use of the gc frame stack outside the cycle check pass.\n"); +  Pike_fatal("Use of the gc frame stack outside the cycle check pass.\n");   #endif    while (gc_rec_top) {   #ifdef GC_STACK_DEBUG    fprintf(stderr, "dequeue %p [%p]: ", gc_rec_top, gc_rec_top->back);    describe_gc_frame(gc_rec_top);    fputc('\n', stderr);   #endif    if (gc_rec_top->frameflags & GC_POP_FRAME) {    struct gc_frame *l = gc_rec_top->back;    gc_cycle_pop(gc_rec_top->data);
pike.git/src/gc.c:1817:   #endif      static void rotate_rec_list (struct gc_frame *beg, struct gc_frame *pos)   /* Rotates the marker list and the cycle stack so the bit from pos    * down to the end gets before the bit from beg down to pos. */   {    struct gc_frame *l;      #ifdef PIKE_DEBUG    if (Pike_in_gc != GC_PASS_CYCLE) -  fatal("Use of the gc frame stack outside the cycle check pass.\n"); +  Pike_fatal("Use of the gc frame stack outside the cycle check pass.\n");    CHECK_POP_FRAME(beg);    CHECK_POP_FRAME(pos);    if (beg == pos)    gc_fatal(beg->data, 0, "Cycle already broken at requested position.\n");    if (NEXT(gc_rec_last))    gc_fatal(gc_rec_last->data, 0, "gc_rec_last not at end.\n");   #endif      #ifdef GC_STACK_DEBUG    fprintf(stderr,"Stack before:\n");
pike.git/src/gc.c:1916: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG    if (gc_is_watching && m && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    fprintf(stderr, "## Watched thing %p found in "    "gc_cycle_push() in pass %d.\n", x, Pike_in_gc);    }       debug_malloc_touch(x);    -  if (!x) fatal("Got null pointer.\n"); -  if (m->data != x) fatal("Got wrong marker.\n"); +  if (!x) Pike_fatal("Got null pointer.\n"); +  if (m->data != x) Pike_fatal("Got wrong marker.\n");    if (Pike_in_gc != GC_PASS_CYCLE) -  fatal("GC cycle push attempted in invalid pass.\n"); +  Pike_fatal("GC cycle push attempted in invalid pass.\n");    if (gc_debug && !(m->flags & GC_PRETOUCHED))    gc_fatal(x, 0, "gc_cycle_push() called for untouched thing.\n");    if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED) &&    *(INT32 *) x)    gc_fatal(x, 1, "Got a referenced marker to gc_cycle_push.\n");    if (m->flags & GC_XREFERENCED)    gc_fatal(x, 1, "Doing cycle check in externally referenced thing "    "missed in mark pass.\n");    if (gc_debug) {    struct array *a;
pike.git/src/gc.c:1978:       else {    /* We'll get here eventually in the normal recursion. Pop off    * the remaining live recurse frames for the last thing. */    CYCLE_DEBUG_MSG(m, "gc_cycle_push, no live recurse");    last->flags &= ~GC_LIVE_RECURSE;    while (1) {    struct gc_frame *l = gc_rec_top;   #ifdef PIKE_DEBUG    if (!gc_rec_top) -  fatal("Expected a gc_cycle_pop entry in gc_rec_top.\n"); +  Pike_fatal("Expected a gc_cycle_pop entry in gc_rec_top.\n");   #endif    gc_rec_top = l->back;    if (l->frameflags & GC_POP_FRAME) {    gc_rec_last = PREV(l);    debug_really_free_gc_frame(l);    break;    }    debug_really_free_gc_frame(l);    }   #ifdef GC_CYCLE_DEBUG
pike.git/src/gc.c:2149:    /* Should normally not recurse now, but got to do that anyway if we    * must mark live things. */    if (!(last->flags & GC_LIVE) || m->flags & GC_LIVE) {    CYCLE_DEBUG_MSG(m, "gc_cycle_push, no recurse");    return 0;    }      live_recurse:   #ifdef PIKE_DEBUG    if (m->flags & GC_LIVE) -  fatal("Shouldn't live recurse when there's nothing to do.\n"); +  Pike_fatal("Shouldn't live recurse when there's nothing to do.\n");   #endif    m->flags |= GC_LIVE|GC_LIVE_RECURSE;    debug_malloc_touch(x);       if (m->flags & GC_GOT_DEAD_REF) {    /* A thing previously popped as dead is now being marked live.    * Have to remove the extra ref added by gc_cycle_pop(). */    gc_free_extra_ref(x);    if (!--*(INT32 *) x) {   #ifdef PIKE_DEBUG
pike.git/src/gc.c:2192:   {    struct marker *m = find_marker(a);    struct gc_frame *here, *base, *p;      #ifdef PIKE_DEBUG    if (gc_is_watching && m && m->flags & GC_WATCHED) {    /* This is useful to set breakpoints on. */    fprintf(stderr, "## Watched thing %p found in "    "gc_cycle_pop() in pass %d.\n", a, Pike_in_gc);    } -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_CYCLE) -  fatal("GC cycle pop attempted in invalid pass.\n"); +  Pike_fatal("GC cycle pop attempted in invalid pass.\n");    if (!(m->flags & GC_CYCLE_CHECKED))    gc_fatal(a, 0, "Marker being popped doesn't have GC_CYCLE_CHECKED.\n");    if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED) &&    *(INT32 *) a)    gc_fatal(a, 1, "Got a referenced marker to gc_cycle_pop.\n");    if (m->flags & GC_XREFERENCED)    gc_fatal(a, 1, "Doing cycle check in externally referenced thing "    "missed in mark pass.\n");   #endif   #ifdef GC_CYCLE_DEBUG
pike.git/src/gc.c:2307:      int gc_do_free(void *a)   {    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_do_free() in pass %d.\n", a, Pike_in_gc);    } -  if (!a) fatal("Got null pointer.\n"); +  if (!a) Pike_fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_FREE) -  fatal("gc free attempted in invalid pass.\n"); +  Pike_fatal("gc free attempted in invalid pass.\n");   #endif       m=find_marker(debug_malloc_pass(a));    if (!m) return 0; /* Object created after cycle pass. */      #ifdef PIKE_DEBUG    if (*(INT32 *) a > !!(m->flags & GC_GOT_EXTRA_REF)) {    if (!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED)    gc_fatal(a, 0, "gc_do_free() called for referenced thing.\n");    if (gc_debug &&
pike.git/src/gc.c:2433: Inside #if defined(PIKE_DEBUG)
     #ifdef PIKE_DEBUG    if(GC_VERBOSE_DO(1 ||) t_flag) {    fprintf(stderr,"Garbage collecting ... ");    GC_VERBOSE_DO(fprintf(stderr, "\n"));   #ifdef HAVE_GETHRTIME    gcstarttime = gethrtime();   #endif    }    if(num_objects < 0) -  fatal("Panic, less than zero objects!\n"); +  Pike_fatal("Panic, less than zero objects!\n");   #endif       last_gc=TIME(0);       multiplier=pow(MULTIPLIER, (double) num_allocs / (double) alloc_threshold);    objects_alloced*=multiplier;    objects_alloced += (double) num_allocs;       objects_freed*=multiplier;   
pike.git/src/gc.c:2460: Inside #if defined(PIKE_DEBUG)
   if (gc_debug) {    unsigned n;    Pike_in_gc = GC_PASS_PRETOUCH;    n = gc_touch_all_arrays();    n += gc_touch_all_multisets();    n += gc_touch_all_mappings();    n += gc_touch_all_programs();    n += gc_touch_all_objects();    gc_touch_all_strings();    if (n != (unsigned) num_objects) -  fatal("Object count wrong before gc; expected %d, got %d.\n", num_objects, n); +  Pike_fatal("Object count wrong before gc; expected %d, got %d.\n", num_objects, n);    GC_VERBOSE_DO(fprintf(stderr, "| pretouch: %u things\n", n));    }   #endif       Pike_in_gc=GC_PASS_CHECK;    gc_ext_weak_refs = 0;    /* First we count internal references */    gc_check_all_arrays();    gc_check_all_multisets();    gc_check_all_mappings();
pike.git/src/gc.c:2550:    * but the permuting destruct order tests in the testsuite won't be    * really effective unless objects are handled first. :P */    gc_cycle_check_all_objects();    gc_cycle_check_all_arrays();    gc_cycle_check_all_multisets();    gc_cycle_check_all_mappings();    gc_cycle_check_all_programs();      #ifdef PIKE_DEBUG    if (gc_rec_top) -  fatal("gc_rec_top not empty at end of cycle check pass.\n"); +  Pike_fatal("gc_rec_top not empty at end of cycle check pass.\n");    if (NEXT(&rec_list) || gc_rec_last != &rec_list || gc_rec_top) -  fatal("Recurse list not empty or inconsistent after cycle check pass.\n"); +  Pike_fatal("Recurse list not empty or inconsistent after cycle check pass.\n");    if (gc_ext_weak_refs != orig_ext_weak_refs) -  fatal("gc_ext_weak_refs changed from %"PRINTSIZET"u " +  Pike_fatal("gc_ext_weak_refs changed from %"PRINTSIZET"u "    "to %"PRINTSIZET"u in cycle check pass.\n",    orig_ext_weak_refs, gc_ext_weak_refs);   #endif       GC_VERBOSE_DO(fprintf(stderr,    "| cycle: %u internal things visited, %u cycle ids used,\n"    "| %u weak references freed, %d more things to free,\n"    "| %u live recursed frames, %u frame rotations,\n"    "| space for %u gc frames used\n",    cycle_checked, last_cycle, weak_freed,
pike.git/src/gc.c:2610: Inside #if defined(PIKE_DEBUG)
   size_t i;    struct marker *m;    Pike_in_gc=GC_PASS_MIDDLETOUCH;    n = gc_touch_all_arrays();    n += gc_touch_all_multisets();    n += gc_touch_all_mappings();    n += gc_touch_all_programs();    n += gc_touch_all_objects();    gc_touch_all_strings();    if (n != (unsigned) num_objects) -  fatal("Object count wrong in gc; expected %d, got %d.\n", num_objects, n); +  Pike_fatal("Object count wrong in gc; expected %d, got %d.\n", num_objects, n);    get_marker(rec_list.data)->flags |= GC_MIDDLETOUCHED;   #if 0 /* Temporarily disabled - Hubbe */   #ifdef DEBUG_MALLOC    PTR_HASH_LOOP(marker, i, m)    if (!(m->flags & (GC_MIDDLETOUCHED|GC_WEAK_FREED)) &&    dmalloc_is_invalid_memory_block(m->data)) {    fprintf(stderr, "Found a stray marker after middletouch pass: ");    describe_marker(m);    fprintf(stderr, "Describing marker location(s):\n");    debug_malloc_dump_references(m, 2, 1, 0);    fprintf(stderr, "Describing thing for marker:\n");    Pike_in_gc = 0;    describe(m->data);    Pike_in_gc = GC_PASS_MIDDLETOUCH; -  fatal("Fatal in garbage collector.\n"); +  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. */
pike.git/src/gc.c:2697:    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;    -  if(fatal_after_gc) fatal("%s", fatal_after_gc); +  if(fatal_after_gc) Pike_fatal("%s", fatal_after_gc);   #endif       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;
pike.git/src/gc.c:2766: Inside #if defined(PIKE_DEBUG)
   if (gc_debug) {    unsigned n;    Pike_in_gc=GC_PASS_POSTTOUCH;    n = gc_touch_all_arrays();    n += gc_touch_all_multisets();    n += gc_touch_all_mappings();    n += gc_touch_all_programs();    n += gc_touch_all_objects();    /* gc_touch_all_strings(); */    if (n != (unsigned) num_objects) -  fatal("Object count wrong after gc; expected %d, got %d.\n", num_objects, n); +  Pike_fatal("Object count wrong after gc; expected %d, got %d.\n", num_objects, n);    GC_VERBOSE_DO(fprintf(stderr, "| posttouch: %u things\n", n));    }    if (gc_extra_refs) -  fatal("Lost track of %d extra refs to things in gc.\n", gc_extra_refs); -  if(fatal_after_gc) fatal("%s", fatal_after_gc); +  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();       /* It's possible that more things got allocated in the kill pass    * than were freed. The count before that is a better measurement    * then. */    if (pre_kill_objs < num_objects) objs -= pre_kill_objs;    else objs -= num_objects;