Branch: Tag:

2000-09-15

2000-09-15 00:30:55 by Martin Stjernholm <mast@lysator.liu.se>

Another attempt on the infamous "Still got external weak references to
internal things in gc" bug: Postpone destruction of things that are weakly
freed during the mark and cycle check passes.

Rev: src/gc.c:1.134
Rev: src/gc.h:1.66

30:      #include "block_alloc.h"    - RCSID("$Id: gc.c,v 1.133 2000/09/14 15:25:36 mast Exp $"); + RCSID("$Id: gc.c,v 1.134 2000/09/15 00:30:55 mast Exp $");      /* Run garbage collect approximately every time    * 20 percent of all arrays, objects and programs is
1207:   #endif       if (Pike_in_gc != GC_PASS_ZAP_WEAK) { -  if (m->weak_refs < 0) { -  gc_ext_weak_refs--; - #ifdef PIKE_DEBUG -  m->flags |= GC_WEAK_FREED; - #endif -  return 1; +  if (m->weak_refs < 0) +  goto should_free;    } -  } +     else    if (!(m->flags & GC_MARKED)) {   #ifdef PIKE_DEBUG
1223:    "weak refs.\n");   #endif    m->weak_refs--; +  goto should_free; +  } +  return 0; +  + should_free:    gc_ext_weak_refs--;   #ifdef PIKE_DEBUG    m->flags |= GC_WEAK_FREED;   #endif -  +  +  if (*(INT32 *) a == 1) { +  /* 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;   } -  return 0; - } +       int gc_mark(void *a)   {
1778: Inside #if defined(PIKE_DEBUG)
  #ifdef PIKE_DEBUG    if (pm->frame != p)    gc_fatal(p->data, 0, "Bogus marker for thing being popped.\n"); -  if (pm->flags & GC_GOT_DEAD_REF) -  gc_fatal(p->data, 0, "Didn't expect a dead extra ref.\n"); +    #endif    p->frameflags &= ~(GC_WEAK_REF|GC_STRONG_REF);    if (pm->flags & GC_LIVE_OBJ) { -  /* This extra ref is taken away in the kill pass. */ +  /* This extra ref is taken away in the kill pass. Don't add one +  * if it got an extra ref already due to weak free. */ +  if (!(pm->flags & GC_GOT_DEAD_REF))    gc_add_extra_ref(p->data);    base = p;    DO_IF_DEBUG(PREV(p) = (struct gc_frame *)(ptrdiff_t) -1);
1795:    * is done to not refcount garb the cycles themselves    * recursively, which in bad cases can consume a lot of C    * stack. */ - #ifdef PIKE_DEBUG -  if (pm->flags & GC_GOT_DEAD_REF) -  gc_fatal(pm->data, 0, -  "A thing already got an extra dead cycle ref.\n"); - #endif +  if (!(pm->flags & GC_GOT_DEAD_REF)) {    gc_add_extra_ref(pm->data);    pm->flags |= GC_GOT_DEAD_REF;    } -  +  } + #ifdef PIKE_DEBUG +  else +  if (pm->flags & GC_GOT_DEAD_REF) +  gc_fatal(p->data, 0, "Didn't expect a dead extra ref.\n"); + #endif    NEXT(base) = NEXT(p);    CYCLE_DEBUG_MSG(pm, "gc_cycle_pop, pop off");    pm->frame = 0;