2000-07-11
2000-07-11 03:45:10 by Martin Stjernholm <mast@lysator.liu.se>
-
6d30f5d60a3fe5b4774c46237a2575b5bfe5cf65
(81 lines)
(+72/-9)
[
Show
| Annotate
]
Branch: 7.9
Fixed bug in gc where things which got only weak refs externally but
non-weak internal cyclic refs didn't get gc'd.
Rev: src/array.c:1.77
Rev: src/gc.c:1.105
Rev: src/gc.h:1.54
Rev: src/mapping.c:1.92
Rev: src/multiset.c:1.24
Rev: src/object.c:1.135
Rev: src/program.c:1.249
Rev: src/queue.c:1.5
Rev: src/queue.h:1.4
Rev: src/svalue.c:1.83
Rev: src/testsuite.in:1.312
29:
#include "block_alloc.h"
- RCSID("$Id: gc.c,v 1.104 2000/07/07 15:33:29 mast Exp $");
+ RCSID("$Id: gc.c,v 1.105 2000/07/11 03:45:09 mast Exp $");
/* Run garbage collect approximately every time
* 20 percent of all arrays, objects and programs is
102:
struct marker *gc_rec_last = &rec_list;
static struct marker *kill_list = 0;
static unsigned last_cycle;
+ size_t gc_ext_weak_refs;
/* rec_list is a linked list of the markers currently being recursed
* through in the cycle check pass. gc_rec_last points at the
770:
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))
+ 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
gc_fatal(a, 3, "A thing to garb is still around.\n");
}
}
-
+ }
else
fatal("debug_gc_touch() used in invalid gc pass.\n");
}
847:
#endif
m->weak_refs++;
+ gc_ext_weak_refs++;
if (m->weak_refs >= *(INT32 *) a)
m->weak_refs = -1;
1022: Inside #if defined(PIKE_DEBUG)
struct marker *m;
if (!a) fatal("Got null pointer.\n");
- if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_CYCLE)
+ if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_CYCLE &&
+ !(Pike_in_gc == GC_PASS_FREE && gc_ext_weak_refs))
fatal("gc_do_weak_free() called in invalid gc pass.\n");
if (gc_debug) {
if (!(m = find_marker(a)))
1034: Inside #if defined(PIKE_DEBUG)
if (m->weak_refs > m->refs)
gc_fatal(a, 0, "More weak references than internal references.\n");
- return m->weak_refs == -1;
+ if (Pike_in_gc != GC_PASS_FREE) {
+ if (m->weak_refs == -1) {
+ gc_ext_weak_refs--;
+ return 1;
}
-
+ }
+ else
+ if (!(m->flags & GC_MARKED)) {
+ if (m->weak_refs <= 0)
+ gc_fatal(a, 0, "Too many weak refs cleared to thing with external "
+ "weak refs.\n");
+ m->weak_refs--;
+ gc_ext_weak_refs--;
+ return 1;
+ }
+ return 0;
+ }
#endif /* PIKE_DEBUG */
1045: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
if (!a) fatal("Got null pointer.\n");
- if (Pike_in_gc != GC_PASS_MARK)
+ if (Pike_in_gc != GC_PASS_MARK &&
+ !(Pike_in_gc == GC_PASS_FREE && gc_ext_weak_refs))
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)
+ gc_fatal(a, 0, "Marking thing scheduled for weak free.\n");
+ if (Pike_in_gc == GC_PASS_FREE && !(m->flags & GC_MARKED))
+ gc_fatal(a, 0, "gc_mark() called for thing in free pass "
+ "that wasn't marked before.\n");
#endif
- if(m->flags & GC_MARKED)
- {
+ if (Pike_in_gc == GC_PASS_FREE)
+ /* Things are visited in the free 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 internal
+ * cyclic non-weak refs. */
+ if (m->flags & GC_FREE_VISITED)
return 0;
- }else{
+ else {
+ m->flags |= GC_FREE_VISITED;
+ return 1;
+ }
+
+ else if (m->flags & GC_MARKED) {
+ #ifdef PIKE_DEBUG
+ if (m->weak_refs != 0)
+ gc_fatal(a, 0, "weak_refs changed in marker already visited by gc_mark().\n");
+ #endif
+ return 0;
+ }
+ else {
+ if (m->weak_refs) {
+ gc_ext_weak_refs -= m->weak_refs;
+ m->weak_refs = 0;
+ }
m->flags = (m->flags & ~GC_NOT_REFERENCED) | GC_MARKED;
DO_IF_DEBUG(marked++);
return 1;
1212:
if (weak < 0) gc_rec_last->flags |= GC_FOLLOWED_STRONG;
#endif
+ if (weak > 0) {
+ #ifdef PIKE_DEBUG
+ if (m->weak_refs <= 0)
+ gc_fatal(x, 0, "Followed weak ref to thing that should have none left.\n");
+ m->weak_refs--;
+ #endif
+ gc_ext_weak_refs--;
+ }
+
if (m->flags & GC_IN_REC_LIST) { /* A cyclic reference is found. */
#ifdef PIKE_DEBUG
if (m == &rec_list || gc_rec_last == &rec_list)
1670:
#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();
1835: Inside #if defined(PIKE_DEBUG)
}
if (gc_extra_refs)
fatal("Lost track of %d extra refs to things in gc.\n", gc_extra_refs);
+ if (gc_ext_weak_refs)
+ fatal("Still got %u external weak references to internal things in gc.\n",
+ gc_ext_weak_refs);
#endif
Pike_in_gc=0;