2000-09-03
2000-09-03 23:09:38 by Martin Stjernholm <mast@lysator.liu.se>
-
22aa2f7505171b0133fa7db32535764c3995ed7b
(185 lines)
(+126/-59)
[
Show
| Annotate
]
Branch: 7.9
More debug to check markers being correlated with their data. More dmalloc
tracking.
Rev: src/gc.c:1.128
Rev: src/gc.h:1.64
30:
#include "block_alloc.h"
- RCSID("$Id: gc.c,v 1.127 2000/08/27 15:21:50 mast Exp $");
+ RCSID("$Id: gc.c,v 1.128 2000/09/03 23:09:38 mast Exp $");
/* Run garbage collect approximately every time
* 20 percent of all arrays, objects and programs is
62:
* o Strong references are used in special cases like parent object
* references. There can never be a cycle consisting only of strong
* references. (This means the gc will never destruct a parent
- * object before all childs has been destructed.)
+ * object before all children have been destructed.)
*
* The gc tries to detect and warn about cases where there are live
* objects with no well defined order between them. There are cases
70:
*
* Things that aren't live objects but are referenced from them are
* still intact during this destruct pass, so it's entirely possible
- * to save these things by adding external references to them.
- * However, it's not possible for live objects to save themselves or
- * other live objects; all live objects that didn't have external
- * references at the start of the gc pass will be destructed
- * regardless of added references.
+ * to save them by adding external references to them. However, it's
+ * not possible for live objects to save themselves or other live
+ * objects; all live objects that didn't have external references at
+ * the start of the gc pass will be destructed regardless of added
+ * references.
*
* Things that have only weak external references at the start of the
* gc pass will be freed. That's done before the live object destruct
225:
(X)->frame = 0;
#endif
+ #ifdef PIKE_DEBUG
+ #undef get_marker
+ #define get_marker debug_get_marker
+ #undef find_marker
+ #define find_marker debug_find_marker
+ #endif
+
PTR_HASH_ALLOC(marker,MARKER_CHUNK_SIZE)
#ifdef PIKE_DEBUG
-
+ #undef get_marker
+ #define get_marker(X) ((struct marker *) debug_malloc_pass(debug_get_marker(X)))
+ #undef find_marker
+ #define find_marker(X) ((struct marker *) debug_malloc_pass(debug_find_marker(X)))
+
int gc_in_cycle_check = 0;
static unsigned weak_freed, checked, marked, cycle_checked, live_ref;
static unsigned max_gc_frames, num_gc_frames = 0;
273: Inside #if defined(PIKE_DEBUG)
for(m=first_mapping;m;m=m->next)
if(m==(struct mapping *)something)
return T_MAPPING;
+ else if (m->data == (struct mapping_data *) something)
+ return T_MAPPING_DATA;
for(mu=first_multiset;mu;mu=mu->next)
if(mu==(struct multiset *)something)
589:
found_in=0;
}
- int debug_gc_check(void *x, TYPE_T t, void *data)
+ int debug_low_gc_check(void *x, TYPE_T t, void *data)
{
int ret;
found_in=data;
847:
{
struct marker *m;
if (!a) fatal("Got null pointer.\n");
-
+
m = find_marker(a);
- if (Pike_in_gc == GC_PASS_PRETOUCH) {
- if (m) gc_fatal(a, 0, "Object touched twice.\n");
- get_marker(a)->flags |= GC_TOUCHED;
- }
- else if (Pike_in_gc == GC_PASS_POSTTOUCH) {
+
+ switch (Pike_in_gc) {
+ case GC_PASS_PRETOUCH:
+ if (m && !(m->flags & GC_PRETOUCHED))
+ gc_fatal(a, 1, "Thing got an existing but untouched marker.\n");
+ get_marker(a)->flags |= GC_PRETOUCHED;
+ break;
+
+ case GC_PASS_MIDDLETOUCH:
+ if (!m)
+ gc_fatal(a, 1, "Found a thing without marker.\n");
+ else if (!(m->flags & GC_PRETOUCHED))
+ gc_fatal(a, 1, "Thing got an existing but untouched marker.\n");
+ m->flags |= GC_MIDDLETOUCHED;
+ break;
+
+ case GC_PASS_POSTTOUCH:
if (!*(INT32 *) a)
gc_fatal(a, 1, "Found a thing without refs.\n");
if (m) {
- if (!(m->flags & GC_TOUCHED))
+ if (!(m->flags & (GC_PRETOUCHED|GC_MIDDLETOUCHED)))
gc_fatal(a, 2, "An existing but untouched marker found "
"for object in linked lists.\n");
else if (m->flags & GC_LIVE_RECURSE ||
890:
gc_fatal(a, 3, "A thing to garb is still around.\n");
}
}
- }
- else
+ break;
+
+ default:
fatal("debug_gc_touch() used in invalid gc pass.\n");
}
-
+ }
static INLINE struct marker *gc_check_debug(void *a, int weak)
{
1090: Inside #if defined(PIKE_DEBUG)
if (gc_debug) {
m = find_marker(a);
- if ((!m || !(m->flags & GC_TOUCHED)) &&
+ if ((!m || !(m->flags & GC_PRETOUCHED)) &&
!safe_debug_findstring((struct pike_string *) a))
gc_fatal(a, 0, "Doing gc_is_referenced() on invalid object.\n");
if (!m) m = get_marker(a);
1164: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
if (!a) fatal("Got null pointer.\n");
- if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_CYCLE &&
- Pike_in_gc != GC_PASS_ZAP_WEAK)
+ if (Pike_in_gc != GC_PASS_MARK && Pike_in_gc != GC_PASS_ZAP_WEAK)
fatal("gc_do_weak_free() called in invalid gc pass.\n");
if (gc_debug) {
if (!(m = find_marker(a)))
1183:
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;
}
}
1195:
#endif
m->weak_refs--;
gc_ext_weak_refs--;
+ #ifdef PIKE_DEBUG
+ m->flags |= GC_WEAK_FREED;
+ #endif
return 1;
}
return 0;
1421: Inside #if defined(PIKE_DEBUG)
if (m->data != x) fatal("Got wrong marker.\n");
if (Pike_in_gc != GC_PASS_CYCLE)
fatal("GC cycle push attempted in invalid pass.\n");
- if (gc_debug && !(m->flags & GC_TOUCHED))
+ if (gc_debug && !(m->flags & GC_PRETOUCHED))
gc_fatal(x, 0, "gc_cycle_push() called for untouched thing.\n");
if ((!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED) &&
*(INT32 *) x)
1812: Inside #if defined(PIKE_DEBUG)
if (!(m->flags & GC_NOT_REFERENCED) || m->flags & GC_MARKED)
gc_fatal(a, 0, "gc_do_free() called for referenced thing.\n");
if (gc_debug &&
- (m->flags & (GC_TOUCHED|GC_MARKED|GC_IS_REFERENCED)) == GC_TOUCHED)
+ (m->flags & (GC_PRETOUCHED|GC_MARKED|GC_IS_REFERENCED)) == GC_PRETOUCHED)
gc_fatal(a, 0, "gc_do_free() called without prior call to "
"gc_mark() or gc_is_referenced().\n");
}
1884: Inside #if defined(PIKE_DEBUG)
#ifdef PIKE_DEBUG
gc_debug = d_flag;
#endif
+ gc_debug = 1;
destruct_objects_to_destruct();
1929: Inside #if defined(PIKE_DEBUG)
n += gc_touch_all_mappings();
n += gc_touch_all_programs();
n += gc_touch_all_objects();
+ gc_touch_all_strings();
if (n != (unsigned) num_objects)
fatal("Object count wrong before gc; expected %d, got %d.\n", num_objects, n);
GC_VERBOSE_DO(fprintf(stderr, "| pretouch: %u things\n", n));
1984:
run_queue(&gc_mark_queue);
gc_mark_all_objects();
run_queue(&gc_mark_queue);
- /* if(gc_debug) */
- /* gc_mark_all_strings(); */
+ if(gc_debug) gc_mark_all_strings();
GC_VERBOSE_DO(fprintf(stderr,
"| mark: %u markers referenced,\n"
2015:
fatal("Recurse list not empty or inconsistent after cycle check pass.\n");
#endif
+ #ifdef PIKE_DEBUG
+ if (gc_debug) {
+ unsigned n;
+ size_t i;
+ struct marker *m;
+ Pike_in_gc=GC_PASS_MIDDLETOUCH;
+ n = gc_touch_all_arrays();
+ n += gc_touch_all_multisets();
+ n += gc_touch_all_mappings();
+ n += gc_touch_all_programs();
+ n += gc_touch_all_objects();
+ gc_touch_all_strings();
+ if (n != (unsigned) num_objects)
+ fatal("Object count wrong in gc; expected %d, got %d.\n", num_objects, n);
+ get_marker(rec_list.data)->flags |= GC_MIDDLETOUCHED;
+ #ifdef DEBUG_MALLOC
+ PTR_HASH_LOOP(marker, i, m)
+ if (!(m->flags & (GC_MIDDLETOUCHED|GC_WEAK_FREED)) &&
+ dmalloc_is_invalid_memory_block(m->data)) {
+ fprintf(stderr, "Found a stray marker after middletouch pass: ");
+ describe_marker(m);
+ fprintf(stderr, "Describing marker location(s):\n");
+ debug_malloc_dump_references(m, 2, 1, 0);
+ fprintf(stderr, "Describing thing for marker:\n");
+ describe(m->data);
+ fatal("Fatal in garbage collector.\n");
+ }
+ #endif
+ GC_VERBOSE_DO(fprintf(stderr, "| middletouch\n"));
+ }
+ #endif
+
GC_VERBOSE_DO(fprintf(stderr,
"| cycle: %u internal things visited, %u cycle ids used,\n"
"| %u weak references freed, %d things really freed,\n"
2133: Inside #if defined(PIKE_DEBUG)
n += gc_touch_all_mappings();
n += gc_touch_all_programs();
n += gc_touch_all_objects();
+ // gc_touch_all_strings();
if (n != (unsigned) num_objects)
fatal("Object count wrong after gc; expected %d, got %d.\n", num_objects, n);
GC_VERBOSE_DO(fprintf(stderr, "| posttouch: %u things\n", n));