2000-06-12
2000-06-12 19:32:40 by Martin Stjernholm <mast@lysator.liu.se>
-
932633dfc44cacee098a89e62626fb0d4bc10bfc
(81 lines)
(+37/-44)
[
Show
| Annotate
]
Branch: 7.9
Fixed a bug when setting GC_DONT_POP in forward references.
Removed the saved_refs debug checks; they won't work since things may
be freed in check, mark and cycle check passes that we don't have
direct control over. E.g. check_mapping_for_destruct is run during the
check pass, and if an index is a destructed object then the value will
be freed, which can cause a cascading free by refcount garbing.
Rev: src/gc.c:1.93
29:
#include "block_alloc.h"
- RCSID("$Id: gc.c,v 1.92 2000/06/12 13:51:58 mast Exp $");
+ RCSID("$Id: gc.c,v 1.93 2000/06/12 19:32:40 mast Exp $");
/* Run garbage collect approximately every time
* 20 percent of all arrays, objects and programs is
79:
* will be freed. That's done before the live object destruct pass.
*/
- /* #define GC_VERBOSE */
- /* #define GC_CYCLE_DEBUG */
+ #define GC_VERBOSE
+ #define GC_CYCLE_DEBUG
#if defined(GC_VERBOSE) && !defined(PIKE_DEBUG)
#undef GC_VERBOSE
145:
#ifdef PIKE_DEBUG
#define INIT_BLOCK(X) \
(X)->flags=(X)->refs=(X)->weak_refs=(X)->xrefs=0; \
- (X)->saved_refs=-1; \
+
(X)->cycle = (unsigned INT16) -1; \
(X)->link = (struct marker *) -1;
#else
410:
{
if (m)
fprintf(stderr, "marker at %p: flags=0x%04x, refs=%d, weak=%d, "
- "xrefs=%d, saved=%d, cycle=%d, link=%p\n",
+ "xrefs=%d, cycle=%d, link=%p\n",
m, m->flags, m->refs, m->weak_refs,
- m->xrefs, m->saved_refs, m->cycle, m->link);
+ m->xrefs, m->cycle, m->link);
else
fprintf(stderr, "no marker\n");
}
767:
"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)
+ 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))
799:
if (!*(INT32 *)a)
gc_fatal(a, 1, "GC check on thing without refs.\n");
- if(m->saved_refs != -1 && m->saved_refs != *(INT32 *)a)
- gc_fatal(a, 1, "Refs changed in gc.\n");
- m->saved_refs = *(INT32 *)a;
+
if (m->refs + m->xrefs >= *(INT32 *) a)
/* m->refs will be incremented by the caller. */
gc_fatal(a, 1, "Thing is getting more internal refs than refs.\n");
828: Inside #if defined(PIKE_DEBUG)
struct marker *m;
#ifdef PIKE_DEBUG
if (!(m = gc_check_debug(a))) return 0;
+ if (m->weak_refs == -1)
+ gc_fatal(a, 1, "Thing has already reached threshold for weak free.\n");
+ if (m->weak_refs > m->refs + 1)
+ gc_fatal(a, 1, "Thing has gotten more weak refs than internal refs.\n");
+ m->weak_refs++;
+ if (m->weak_refs >= *(INT32 *) a)
+ m->weak_refs = -1;
#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) weak_freed++;
+
#endif
return add_ref(m);
}
923: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
- void debug_gc_check_count_free(void *a)
- {
- struct marker *m;
- if (Pike_in_gc == GC_PASS_CHECK && (m = find_marker(a))) {
- if(m->saved_refs == -1)
- m->saved_refs = *(INT32 *)a - 1;
- else {
- if (m->saved_refs != *(INT32 *)a)
- gc_fatal(a, 1, "Refs changed in gc.\n");
- m->saved_refs--;
- }
- }
- }
-
+
void gc_add_extra_ref(void *a)
{
struct marker *m = get_marker(a);
1007: Inside #if defined(PIKE_DEBUG)
m=get_marker(a);
m->xrefs++;
m->flags|=GC_XREFERENCED;
- if(m->refs + m->xrefs > *(INT32 *)a ||
- (Pike_in_gc == GC_PASS_CHECK &&
- m->saved_refs != -1 && m->saved_refs != *(INT32 *)a))
+ if(m->refs + m->xrefs > *(INT32 *)a)
gc_fatal(a, 1, "Ref counts are wrong.\n");
return 0;
}
1028: Inside #if defined(PIKE_DEBUG)
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)
+ gc_fatal(a, 0, "Thing got only weak refs but real_gc_check_weak() missed it.\n");
- return m->weak_refs >= *(INT32 *) a;
+ return m->weak_refs == -1;
}
#endif /* PIKE_DEBUG */
1196:
if (weak >= 0) gc_rec_last->flags |= GC_FOLLOWED_NONSTRONG;
#endif
- if (m->flags & GC_RECURSING) { /* A cycle is found. */
+ if (m->flags & GC_RECURSING) { /* A cyclic reference is found. */
+ #ifdef PIKE_DEBUG
+ if (m == &rec_list || gc_rec_last == &rec_list)
+ gc_fatal(x, 0, "Cyclic ref involves dummy rec_list marker.\n");
+ #endif
+
if (m != gc_rec_last) {
struct marker *p, *weak_ref = 0, *nonstrong_ref = 0;
if (!weak) {
1276:
/* It might be a reference to a marker that has been swapped
* further down the list by break_cycle(). In that case we
* must mark this path to stay on the list. */
+ struct marker *q = 0;
CYCLE_DEBUG_MSG(m, "gc_cycle_push, forward ref");
- for (p = rec_list.link; !(p->flags & GC_DONT_POP); p = p->link)
- if (p == gc_rec_last) goto dont_stay_on_list;
- for (;; p = p->link) {
+ for (p = rec_list.link; p != gc_rec_last; p = p->link)
+ if (p->flags & GC_DONT_POP) q = p;
+ if (q)
+ for (p = q->link;; p = p->link) {
p->flags |= GC_DONT_POP;
CYCLE_DEBUG_MSG(p, "gc_cycle_push, mark for don't pop");
if (p == gc_rec_last) break;
}
- dont_stay_on_list:
+
}
}
}
1400:
#endif
if (m->flags & GC_DONT_POP) {
+ #ifdef PIKE_DEBUG
+ if (!m->link)
+ gc_fatal(a, 0, "Found GC_DONT_POP marker on top of stack.\n");
+ #endif
CYCLE_DEBUG_MSG(m, "gc_cycle_pop, keep on stack");
return;
}