From 73dd8cc697918d02ac3639fde96ed5ff94d30911 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 24 Oct 2010 18:13:38 -0600 Subject: [PATCH] fix gc handling of ephemeron chains --- collects/tests/racket/will.rktl | 18 ++++++++++++++++++ src/racket/gc2/newgc.c | 18 +++++++++++------- src/racket/gc2/weak.c | 6 +++++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/collects/tests/racket/will.rktl b/collects/tests/racket/will.rktl index feda49fcab..c648e59476 100644 --- a/collects/tests/racket/will.rktl +++ b/collects/tests/racket/will.rktl @@ -146,7 +146,25 @@ (custodian-shutdown-all c1) (sync (system-idle-evt)) (test #t values done)) + +;; ---------------------------------------- +(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) diff --git a/src/racket/gc2/newgc.c b/src/racket/gc2/newgc.c index b8aac8f4fc..1509c3f1a7 100644 --- a/src/racket/gc2/newgc.c +++ b/src/racket/gc2/newgc.c @@ -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); diff --git a/src/racket/gc2/weak.c b/src/racket/gc2/weak.c index 1adf2fbaca..9f47efcf4f 100644 --- a/src/racket/gc2/weak.c +++ b/src/racket/gc2/weak.c @@ -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)