fix gc handling of ephemeron chains

This commit is contained in:
Matthew Flatt 2010-10-24 18:13:38 -06:00
parent dee93e6259
commit 73dd8cc697
3 changed files with 34 additions and 8 deletions

View File

@ -149,4 +149,22 @@
;; ----------------------------------------
(let ([something (gensym)])
(define e-chain
(let loop ([n 100] [e #f])
(if (zero? n)
e
(loop (sub1 n)
(make-ephemeron something e)))))
(collect-garbage)
(test 100 'epehemeron-chain
(let loop ([e e-chain])
(if e
(add1 (loop (ephemeron-value e)))
0)))
;; ensure that `something' is retained:
(test #t symbol? (list-ref (list something) (random 1))))
;; ----------------------------------------
(report-errs)

View File

@ -2974,6 +2974,14 @@ static void propagate_marks(NewGC *gc)
propagate_marks_worker(gc, mark_table, p);
}
}
static void propagate_marks_plus_ephemerons(NewGC *gc)
{
do {
propagate_marks(gc);
} while (mark_ready_ephemerons(gc));
}
#ifdef MZ_USE_PLACES
static void promote_marked_gen0_big_pages(NewGC *gc) {
mpage *page;
@ -4162,17 +4170,13 @@ static void garbage_collect(NewGC *gc, int force_full, int switching_master)
/* now propagate/repair the marks we got from these roots, and do the
finalizer passes */
propagate_marks(gc);
mark_ready_ephemerons(gc);
propagate_marks(gc);
propagate_marks_plus_ephemerons(gc);
check_finalizers(gc, 1);
mark_ready_ephemerons(gc);
propagate_marks(gc);
propagate_marks_plus_ephemerons(gc);
check_finalizers(gc, 2);
mark_ready_ephemerons(gc);
propagate_marks(gc);
propagate_marks_plus_ephemerons(gc);
if(gc->gc_full) zero_weak_finalizers(gc);
do_ordered_level3(gc); propagate_marks(gc);

View File

@ -283,21 +283,25 @@ void init_ephemerons(GCTYPE *gc) {
gc->num_last_seen_ephemerons = 0;
}
static void mark_ready_ephemerons(GCTYPE *gc)
static int mark_ready_ephemerons(GCTYPE *gc)
{
GC_Ephemeron *waiting = NULL, *next, *eph;
int did_one = 0;
for (eph = gc->ephemerons; eph; eph = next) {
next = eph->next;
if (is_marked(gc, eph->key)) {
gcMARK2(eph->val, gc);
gc->num_last_seen_ephemerons++;
did_one = 1;
} else {
eph->next = waiting;
waiting = eph;
}
}
gc->ephemerons = waiting;
return did_one;
}
static void zero_remaining_ephemerons(GCTYPE *gc)