2003-02-14
2003-02-14 05:31:27 by Martin Stjernholm <mast@lysator.liu.se>
-
0db2c06832e91374c28fef7c000bc15d3ef2b8cd
(53 lines)
(+35/-18)
[
Show
| Annotate
]
Branch: 7.9
Fixed some destruct order bugs. Moved a heavy debug check up one
level.
Rev: src/gc.c:1.207
2:
|| This file is part of Pike. For copyright information see COPYRIGHT.
|| Pike is distributed under GPL, LGPL and MPL. See the file COPYING
|| for more information.
- || $Id: gc.c,v 1.206 2003/02/10 17:10:40 mast Exp $
+ || $Id: gc.c,v 1.207 2003/02/14 05:31:27 mast Exp $
*/
#include "global.h"
33:
#include "block_alloc.h"
- RCSID("$Id: gc.c,v 1.206 2003/02/10 17:10:40 mast Exp $");
+ RCSID("$Id: gc.c,v 1.207 2003/02/14 05:31:27 mast Exp $");
int gc_enabled = 1;
131:
#define GC_WEAK_REF 0x02
#define GC_STRONG_REF 0x04
#define GC_OFF_STACK 0x08
+ #define GC_ON_KILL_LIST 0x10
#ifdef PIKE_DEBUG
- #define GC_LINK_FREED 0x10
- #define GC_FOLLOWED_NONSTRONG 0x20
+ #define GC_LINK_FREED 0x20
+ #define GC_FOLLOWED_NONSTRONG 0x40
#endif
#undef BLOCK_ALLOC_NEXT
178:
* gc_rec_last points at the last frame in the list and new frames are
* linked in after it. A cycle is always treated as one atomic unit,
* e.g. it's either popped whole or not at all. That means that
- * rec_list may contain frames that are no longer on the stack.
+ * rec_list might contain frames that are no longer on the stack.
*
- * A range of frames which always ends at the end of the list, may be
+ * A range of frames which always ends at the end of the list may be
* rotated a number of slots to break a cyclic reference at a chosen
* point. The stack of link frames are rotated simultaneously.
*
1840:
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. */
+ * down to the end gets before the bit from beg down to pos. The beg
+ * pos might be moved further down the stack to avoid mixing cycles or
+ * breaking strong link sequences. */
{
struct gc_frame *l;
-
+ CYCLE_DEBUG_MSG(find_marker(beg->data), "> rotate_rec_list, asked to begin at");
+
#ifdef PIKE_DEBUG
if (Pike_in_gc != GC_PASS_CYCLE)
Pike_fatal("Use of the gc frame stack outside the cycle check pass.\n");
1864:
}
#endif
+ #if 0
if (CYCLE(beg)) {
for (l = beg; CYCLE(PREV(l)) == CYCLE(beg); l = PREV(l))
CHECK_POP_FRAME(l);
- CHECK_POP_FRAME(l);
+
if (CYCLE(l) == CYCLE(pos)) {
/* Breaking something previously marked as a cycle. Clear it
- * since we're no longer sure it's an ambigious cycle. */
+ * since we're no longer sure it's an unambiguous cycle. */
unsigned cycle = CYCLE(l);
for (; l && CYCLE(l) == cycle; l = NEXT(l)) {
CHECK_POP_FRAME(l);
1883:
}
else beg = l; /* Keep the cycle continuous. */
}
+ #endif
-
+ /* Always keep chains of strong refs continuous, or else we risk
+ * breaking the order in a later rotation. */
+ for (; beg->frameflags & GC_STRONG_REF; beg = PREV(beg)) {}
+
CYCLE_DEBUG_MSG(find_marker(beg->data), "> rotate_rec_list, begin at");
{
1957: Inside #if defined(PIKE_DEBUG)
if (m->flags & GC_XREFERENCED)
gc_fatal(x, 1, "Doing cycle check in externally referenced thing "
"missed in mark pass.\n");
- if (gc_debug) {
+ if (weak && gc_rec_last == &rec_list)
+ gc_fatal(x, 1, "weak is %d when on top of stack.\n", weak);
+ if (gc_debug > 1) {
struct array *a;
struct object *o;
struct program *p;
2032:
if (weak >= 0) gc_rec_last->frameflags |= GC_FOLLOWED_NONSTRONG;
#endif
- if (m->frame && !(m->frame->frameflags & GC_OFF_STACK)) {
+ if (m->frame && !(m->frame->frameflags & GC_ON_KILL_LIST)) {
/* A cyclic reference is found. */
#ifdef PIKE_DEBUG
if (gc_rec_last == &rec_list)
2046:
if (!weak) {
struct gc_frame *q;
CYCLE_DEBUG_MSG(m, "gc_cycle_push, search normal");
+ /* Find the last weakly linked thing and the one before the
+ * first strongly linked thing. */
for (q = m->frame, p = NEXT(q);; q = p, p = NEXT(p)) {
CHECK_POP_FRAME(p);
if (p->frameflags & (GC_WEAK_REF|GC_STRONG_REF)) {
2058:
else if (weak < 0) {
CYCLE_DEBUG_MSG(m, "gc_cycle_push, search strong");
+ /* Find the last weakly linked thing and the last one which
+ * isn't strongly linked. */
for (p = NEXT(m->frame);; p = NEXT(p)) {
CHECK_POP_FRAME(p);
if (p->frameflags & GC_WEAK_REF) weak_ref = p;
2081:
else {
struct gc_frame *q;
CYCLE_DEBUG_MSG(m, "gc_cycle_push, search weak");
+ /* Find the thing before the first strongly linked one. */
for (q = m->frame, p = NEXT(q);; q = p, p = NEXT(p)) {
CHECK_POP_FRAME(p);
if (!(p->frameflags & GC_WEAK_REF) && !nonstrong_ref)
2102:
else if (weak < 0) {
/* The backward link is strong. Must break the cycle at the
* last nonstrong link. */
- if (m->frame->frameflags & GC_STRONG_REF)
- nonstrong_ref->frameflags =
- (nonstrong_ref->frameflags & ~GC_WEAK_REF) | GC_STRONG_REF;
- else
- m->frame->frameflags =
- (m->frame->frameflags & ~GC_WEAK_REF) | GC_STRONG_REF;
+
CYCLE_DEBUG_MSG(find_marker(nonstrong_ref->data),
"gc_cycle_push, nonstrong break");
rotate_rec_list(m->frame, nonstrong_ref);
-
+ NEXT(nonstrong_ref)->frameflags =
+ (NEXT(nonstrong_ref)->frameflags & ~GC_WEAK_REF) | GC_STRONG_REF;
}
else if (nonstrong_ref) {
2284:
if (!(pm->flags & GC_GOT_DEAD_REF))
gc_add_extra_ref(p->data);
base = p;
+ p->frameflags |= GC_ON_KILL_LIST;
DO_IF_DEBUG(PREV(p) = (struct gc_frame *)(ptrdiff_t) -1);
CYCLE_DEBUG_MSG(pm, "gc_cycle_pop, put on kill list");
}
2769:
struct gc_frame *next = NEXT(kill_list);
struct object *o = (struct object *) kill_list->data;
#ifdef PIKE_DEBUG
+ if (!(kill_list->frameflags & GC_ON_KILL_LIST))
+ gc_fatal(o, 0, "Kill list element hasn't got the proper flag.\n");
if ((get_marker(kill_list->data)->flags & (GC_LIVE|GC_LIVE_OBJ)) !=
(GC_LIVE|GC_LIVE_OBJ))
- gc_fatal(o, 0, "Invalid thing in kill list.\n");
+ gc_fatal(o, 0, "Invalid object on kill list.\n");
if (o->prog && (o->prog->flags & PROGRAM_USES_PARENT) &&
PARENT_INFO(o)->parent &&
!PARENT_INFO(o)->parent->prog &&