2000-09-15
2000-09-15 00:30:55 by Martin Stjernholm <mast@lysator.liu.se>
-
2b8ddee80b18724ea3e066a3a394d4c516c4d579
(54 lines)
(+32/-22)
[
Show
| Annotate
]
Branch: 7.9
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;