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) (report-errs)

View File

@ -2974,6 +2974,14 @@ static void propagate_marks(NewGC *gc)
propagate_marks_worker(gc, mark_table, p); 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 #ifdef MZ_USE_PLACES
static void promote_marked_gen0_big_pages(NewGC *gc) { static void promote_marked_gen0_big_pages(NewGC *gc) {
mpage *page; 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 /* now propagate/repair the marks we got from these roots, and do the
finalizer passes */ finalizer passes */
propagate_marks(gc); propagate_marks_plus_ephemerons(gc);
mark_ready_ephemerons(gc);
propagate_marks(gc);
check_finalizers(gc, 1); check_finalizers(gc, 1);
mark_ready_ephemerons(gc); propagate_marks_plus_ephemerons(gc);
propagate_marks(gc);
check_finalizers(gc, 2); check_finalizers(gc, 2);
mark_ready_ephemerons(gc); propagate_marks_plus_ephemerons(gc);
propagate_marks(gc);
if(gc->gc_full) zero_weak_finalizers(gc); if(gc->gc_full) zero_weak_finalizers(gc);
do_ordered_level3(gc); propagate_marks(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; 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; GC_Ephemeron *waiting = NULL, *next, *eph;
int did_one = 0;
for (eph = gc->ephemerons; eph; eph = next) { for (eph = gc->ephemerons; eph; eph = next) {
next = eph->next; next = eph->next;
if (is_marked(gc, eph->key)) { if (is_marked(gc, eph->key)) {
gcMARK2(eph->val, gc); gcMARK2(eph->val, gc);
gc->num_last_seen_ephemerons++; gc->num_last_seen_ephemerons++;
did_one = 1;
} else { } else {
eph->next = waiting; eph->next = waiting;
waiting = eph; waiting = eph;
} }
} }
gc->ephemerons = waiting; gc->ephemerons = waiting;
return did_one;
} }
static void zero_remaining_ephemerons(GCTYPE *gc) static void zero_remaining_ephemerons(GCTYPE *gc)