pike.git / src / gc.c

version» Context lines:

pike.git/src/gc.c:22:   #include "time_stuff.h"   #include "constants.h"   #include "interpret.h"      #include "gc.h"   #include "main.h"   #include <math.h>      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.89 2000/06/11 02:41:01 mast Exp $"); + RCSID("$Id: gc.c,v 1.90 2000/06/11 11:59:47 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:722:    m = find_marker(a);    if (Pike_in_gc == GC_PASS_PRETOUCH) {    if (m) gc_fatal(a, 0, "Object touched twice.\n");    get_marker(a)->flags |= GC_TOUCHED;    }    else if (Pike_in_gc == GC_PASS_POSTTOUCH) {    if (m) {    if (!(m->flags & GC_TOUCHED))    gc_fatal(a, 2, "An existing but untouched marker found "    "for object in linked lists.\n"); -  else if (m->flags & (GC_RECURSING|GC_LIVE_RECURSE|GC_WEAK_REF)) +  else if (m->flags & (GC_RECURSING|GC_LIVE_RECURSE|GC_WEAK_REF|GC_STRONG_REF))    gc_fatal(a, 2, "Marker still got flag from recurse list.\n");    else if (m->flags & GC_REFERENCED)    return;    else if (m->flags & GC_XREFERENCED)    gc_fatal(a, 3, "A thing with external references "    "got missed by mark pass.\n");    else if (!(m->flags & GC_CYCLE_CHECKED))    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 >= m->saved_refs || m->flags & GC_IS_ONLY_WEAK) +  else if (m->weak_refs >= m->saved_refs)    gc_fatal(a, 3, "A thing which had only weak references is "    "still around after gc.\n");    else if (!(m->flags & GC_LIVE))    gc_fatal(a, 3, "A thing to garb is still around.\n");    }    }    else    fatal("debug_gc_touch() used in invalid gc pass.\n");   }   
pike.git/src/gc.c:808: Inside #if defined(PIKE_DEBUG)
   struct marker *m;   #ifdef PIKE_DEBUG    if (!(m = gc_check_debug(a))) return 0;   #else    m = get_marker(a);   #endif    m->weak_refs++;   #ifdef PIKE_DEBUG    if (m->weak_refs > m->refs + 1)    gc_fatal(a, 1, "Thing has gotten more weak refs than internal refs.\n"); -  if (m->weak_refs == m->saved_refs) { -  if (m->flags & GC_IS_ONLY_WEAK) -  gc_fatal(a, 0, "Already counted this as weakly freed.\n"); -  weak_freed++; -  m->flags |= GC_IS_ONLY_WEAK; -  } +  if (m->weak_refs == m->saved_refs) weak_freed++;   #endif    return add_ref(m);   }      static void init_gc(void)   {    init_marker_hash();   }      static void exit_gc(void)
pike.git/src/gc.c:907:   #endif      #ifdef PIKE_DEBUG      void gc_add_extra_ref(void *a)   {    struct marker *m = get_marker(a);    if (m->flags & GC_GOT_EXTRA_REF)    gc_fatal(a, 0, "Thing already got an extra gc ref.\n");    m->flags |= GC_GOT_EXTRA_REF; -  if (m->saved_refs != -1) m->saved_refs++; +     gc_extra_refs++;    ++*(INT32 *) a;   }      void gc_free_extra_ref(void *a)   {    struct marker *m = get_marker(a);    if (!(m->flags & GC_GOT_EXTRA_REF))    gc_fatal(a, 0, "Thing haven't got an extra gc ref.\n");    m->flags &= ~GC_GOT_EXTRA_REF; -  if (m->saved_refs != -1) m->saved_refs--; +     gc_extra_refs--;   }      int debug_gc_is_referenced(void *a)   {    struct marker *m;    if (!a) fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_MARK)    fatal("gc_is_referenced() called in invalid gc pass.\n");   
pike.git/src/gc.c:999: Inside #if defined(PIKE_DEBUG)
   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->saved_refs)    gc_fatal(a, 0, "More weak references than references.\n");    if (m->weak_refs > m->refs)    gc_fatal(a, 0, "More weak references than internal references.\n");    -  if (m->weak_refs >= *(INT32 *) a) { -  if (!(m->flags & GC_IS_ONLY_WEAK)) -  gc_fatal(a, 0, "Got only weak refs but flag isn't set by real_gc_check_weak().\n"); -  return 1; +  return m->weak_refs >= *(INT32 *) a;   } -  else return 0; - } +       #endif /* PIKE_DEBUG */      int gc_mark(void *a)   {    struct marker *m;      #ifdef PIKE_DEBUG    if (!a) fatal("Got null pointer.\n");    if (Pike_in_gc != GC_PASS_MARK)
pike.git/src/gc.c:1044:   static void break_cycle (struct marker *beg, struct marker *pos)   {    /* There's a cycle from beg to gc_rec_last which should be broken at    * pos. Do it by removing the things from beg down to pos, to let    * them be handled again after gc_rec_last. (It's possible to be    * smarter here and put those things after gc_rec_last to avoid    * recursing through them again, but then it becomes tricky to know    * where the "stack top" is.) */       struct marker *p, *q; -  int cycle = beg->cycle; +    #ifdef GC_CYCLE_DEBUG    fprintf(stderr, "%*sbreak cycle: %8p, [%8p] ",    gc_cycle_indent, "", beg->data, gc_rec_last);    describe_marker(beg);   #endif   #ifdef PIKE_DEBUG    if (beg == pos)    gc_fatal(beg->data, 0, "Cycle already broken at requested position.\n");   #endif    -  if (cycle) { +  if (beg->cycle) {   #ifdef PIKE_DEBUG -  if (pos->cycle == cycle || gc_rec_last->cycle == cycle) +  if (pos->cycle == beg->cycle || gc_rec_last->cycle == beg->cycle)    gc_fatal(pos->data, 0, "Same cycle on both sides of broken link.\n");   #endif    for (p = &rec_list; p->link->cycle != beg->cycle; p = p->link) {}    }    else    for (p = &rec_list; p->link != beg; p = p->link) {}       q = p->link;    p->link = pos;       while (q != pos) { -  q->flags &= ~(GC_CYCLE_CHECKED|GC_RECURSING|GC_WEAK_REF|GC_FOLLOWED_NONSTRONG); +  q->flags &= ~(GC_CYCLE_CHECKED|GC_RECURSING| +  GC_WEAK_REF|GC_STRONG_REF|GC_FOLLOWED_NONSTRONG);    q->cycle = 0;   #ifdef GC_CYCLE_DEBUG    fprintf(stderr, "%*sreset marker: "    "%8p, ", gc_cycle_indent, "", q->data);    describe_marker(q);   #endif   #ifdef PIKE_DEBUG    if (q->flags & (GC_GOT_DEAD_REF|GC_GOT_EXTRA_REF))    gc_fatal(q->data, 0, "Didn't expect an extra ref at reset.\n");    p = q->link;
pike.git/src/gc.c:1121: Inside #if defined(PIKE_DEBUG)
   if(o == (struct object *) x) goto on_gc_internal_lists;    for(p = gc_internal_program; p; p = p->next)    if(p == (struct program *) x) goto on_gc_internal_lists;    for(m = gc_internal_mapping; m; m = m->next)    if(m == (struct mapping *) x) goto on_gc_internal_lists;    for(l = gc_internal_multiset; l; l = l->next)    if(l == (struct multiset *) x) goto on_gc_internal_lists;    gc_fatal(x, 0, "gc_cycle_check() called for thing not on gc_internal lists.\n");    on_gc_internal_lists:    } -  if (weak < 0 && gc_rec_last->flags & GC_FOLLOWED_NONSTRONG) -  gc_fatal(x, 0, "Followed strong link too late.\n"); -  if (weak >= 0) gc_rec_last->flags |= GC_FOLLOWED_NONSTRONG; +    #endif       if (gc_rec_last->flags & GC_LIVE_RECURSE) {   #ifdef PIKE_DEBUG    if (!(gc_rec_last->flags & GC_LIVE))    gc_fatal(x, 0, "Doing live recursion from a dead thing.\n");   #endif       if (m->flags & GC_CYCLE_CHECKED) {    if (!(m->flags & GC_LIVE)) {
pike.git/src/gc.c:1161: Inside #if defined(GC_CYCLE_DEBUG)
   int flags;   #ifdef GC_CYCLE_DEBUG    fprintf(stderr, "%*sgc_cycle_push, live rec done: %8p, [%8p] ",    gc_cycle_indent, "", x, gc_rec_last);    describe_marker(m);   #endif    do {    gc_rec_last->flags &= ~GC_LIVE_RECURSE;   #ifdef GC_CYCLE_DEBUG    gc_cycle_indent -= 2; -  fprintf(stderr, "%*sgc_cycle_push, unwinding: " +  fprintf(stderr, "%*sgc_cycle_push, unwinding live: "    "%8p, ", gc_cycle_indent, "", gc_rec_last->data);    describe_marker(gc_rec_last);   #endif    gc_rec_last = (struct marker *)    dequeue_lifo(&gc_mark_queue, (queue_call) gc_set_rec_last);   #ifdef PIKE_DEBUG    if (!gc_rec_last)    fatal("Expected a gc_set_rec_last entry in gc_mark_queue.\n");   #endif    } while (gc_rec_last->flags & GC_LIVE_RECURSE);
pike.git/src/gc.c:1187:    }       return 0;    }       if (!(gc_rec_last->flags & GC_RECURSING))    /* The upward thing has been removed from rec_list, so we should    * ignore it and not do any recursion from it. */    return 0;    + #ifdef PIKE_DEBUG +  if (weak < 0 && gc_rec_last->flags & GC_FOLLOWED_NONSTRONG) +  gc_fatal(x, 0, "Followed strong link too late.\n"); +  if (weak >= 0) gc_rec_last->flags |= GC_FOLLOWED_NONSTRONG; + #endif +     if (m->flags & GC_RECURSING) { /* A cycle is found. */    if (m != gc_rec_last) {    struct marker *p, *weak_ref = 0, *nonstrong_ref = 0;    if (!weak) {    struct marker *q;    for (q = m, p = m->link; p; q = p, p = p->link) {    if (p->flags & (GC_WEAK_REF|GC_STRONG_REF)) {    if (p->flags & GC_WEAK_REF) weak_ref = p;    else if (!nonstrong_ref) nonstrong_ref = q;    }
pike.git/src/gc.c:1439: Inside #if defined(PIKE_DEBUG)
   if (m->flags & (GC_REFERENCED))    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    gc_cycle_indent -= 2;   #endif    -  if (!(m->flags & GC_RECURSING)) { +  if (!(m->flags & GC_RECURSING) || m->flags & GC_LIVE_RECURSE) {    m->flags &= ~GC_LIVE_RECURSE;   #ifdef GC_CYCLE_DEBUG    fprintf(stderr, "%*sgc_cycle_pop, pop ignored: %8p, [%8p] ",    gc_cycle_indent, "", a, gc_rec_last);    describe_marker(m);   #endif    return 0;    }      #ifdef PIKE_DEBUG    if (m->flags & GC_GOT_DEAD_REF)    gc_fatal(a, 0, "Didn't expect a dead extra ref.\n");   #endif       if (m->cycle) {    /* Part of a cycle. Leave for now so we pop the whole cycle at once. */ -  m->flags &= ~GC_WEAK_REF; +  m->flags &= ~(GC_WEAK_REF|GC_STRONG_REF);   #ifdef GC_CYCLE_DEBUG    fprintf(stderr, "%*sgc_cycle_pop, in cycle: %8p, [%8p] ",    gc_cycle_indent, "", a, gc_rec_last);    describe_marker(m);   #endif    if (!(gc_rec_last->flags & GC_RECURSING))    for (gc_rec_last = &rec_list;    gc_rec_last->link != m && gc_rec_last->link->cycle != m->cycle;    gc_rec_last = gc_rec_last->link) {}    if (gc_rec_last->cycle != m->cycle)    /* Time to pop the cycle. */    pop_cycle_to_kill_list();    return 0;    }       else {    struct marker *p;    ADD_REF_IF_DEAD(m); -  m->flags &= ~(GC_RECURSING|GC_WEAK_REF); +  m->flags &= ~(GC_RECURSING|GC_WEAK_REF|GC_STRONG_REF);    if (gc_rec_last->flags & GC_RECURSING) p = gc_rec_last;    else p = &rec_list;    for (; p->link != m; p = p->link) {   #ifdef PIKE_DEBUG    if (!p->link || m->link) -  gc_fatal(a, 0, "Thing not in cycle not last on rec_list.\n"); +  gc_fatal(a, 0, "Thing not in cycle isn't last on rec_list.\n");   #endif    }    p->link = 0;   #ifdef GC_CYCLE_DEBUG    fprintf(stderr, "%*sgc_cycle_pop: %8p, [%8p] ",    gc_cycle_indent, "", a, gc_rec_last);    describe_marker(m);   #endif    return 1;    }