diff --git a/racket/src/racket/gc2/fnls.c b/racket/src/racket/gc2/fnls.c index 755d0047ee..c7ce9b0b9b 100644 --- a/racket/src/racket/gc2/fnls.c +++ b/racket/src/racket/gc2/fnls.c @@ -23,39 +23,28 @@ #undef splay_insert #undef splay_delete -static void remove_finalizer(Fnl *fnl, int gen0, GCTYPE *gc) +static void remove_finalizer(Fnl *fnl, int lvl, GCTYPE *gc) { if (fnl->prev) fnl->prev->next = fnl->next; - else { - if (gen0) - gc->gen0_finalizers = fnl->next; - else - gc->finalizers = fnl->next; - } + else + gc->finalizers[lvl] = fnl->next; if (fnl->next) fnl->next->prev = fnl->prev; - if (gen0) - gc->splayed_gen0_finalizers = fnl_splay_delete((intptr_t)fnl->p, gc->splayed_gen0_finalizers); - else - gc->splayed_finalizers = fnl_splay_delete((intptr_t)fnl->p, gc->splayed_finalizers); + gc->splayed_finalizers[lvl] = fnl_splay_delete((intptr_t)fnl->p, gc->splayed_finalizers[lvl]); } -static void add_finalizer(Fnl *fnl, int gen0, GCTYPE *gc) +static void add_finalizer(Fnl *fnl, int lvl, GCTYPE *gc) { - fnl->next = (gen0 ? gc->gen0_finalizers : gc->finalizers); + fnl->next = gc->finalizers[lvl]; + fnl->prev = NULL; if (fnl->next) fnl->next->prev = fnl; - if (gen0) { - gc->gen0_finalizers = fnl; - gc->splayed_gen0_finalizers = fnl_splay_insert((intptr_t)fnl->p, fnl, gc->splayed_gen0_finalizers); - } else { - gc->finalizers = fnl; - gc->splayed_finalizers = fnl_splay_insert((intptr_t)fnl->p, fnl, gc->splayed_finalizers); - } + gc->finalizers[lvl] = fnl; + gc->splayed_finalizers[lvl] = fnl_splay_insert((intptr_t)fnl->p, fnl, gc->splayed_finalizers[lvl]); } void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *data), @@ -64,6 +53,7 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d { GCTYPE *gc = GC_get_GC(); Fnl *fnl; + int lvl; if (!is_finalizable_page(gc, p)) { /* Never collected. Don't finalize it. */ @@ -72,17 +62,18 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d return; } - gc->splayed_gen0_finalizers = fnl_splay((intptr_t)p, gc->splayed_gen0_finalizers); - fnl = gc->splayed_gen0_finalizers; - if (!fnl || (fnl->p != p)) { - gc->splayed_finalizers = fnl_splay((intptr_t)p, gc->splayed_finalizers); - fnl = gc->splayed_finalizers; - if (!fnl || (fnl->p != p)) + for (lvl = 0; lvl < NUM_FNL_LEVELS; lvl++) { + gc->splayed_finalizers[lvl] = fnl_splay((intptr_t)p, gc->splayed_finalizers[lvl]); + fnl = gc->splayed_finalizers[lvl]; + if (!fnl || (fnl->p != p)) { fnl = NULL; - else { - /* since we're mutating this finalizer, move it to the gen0 list and tree */ - remove_finalizer(fnl, 0, gc); - add_finalizer(fnl, 1, gc); + } else { + if (lvl > FNL_LEVEL_GEN_0) { + /* since we're mutating this finalizer, move it to the gen0 set */ + remove_finalizer(fnl, lvl, gc); + add_finalizer(fnl, FNL_LEVEL_GEN_0, gc); + } + break; } } @@ -95,7 +86,7 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d fnl->eager_level = level; } else { /* remove finalizer */ - remove_finalizer(fnl, 1, gc); + remove_finalizer(fnl, FNL_LEVEL_GEN_0, gc); --gc->num_fnls; } return; @@ -143,7 +134,7 @@ void GC_set_finalizer(void *p, int tagged, int level, void (*f)(void *p, void *d } #endif - add_finalizer(fnl, 1, gc); + add_finalizer(fnl, FNL_LEVEL_GEN_0, gc); gc->num_fnls++; } @@ -151,14 +142,16 @@ static void merge_finalizer_trees(GCTYPE *gc) /* For a full GC, move all finalizers to the gen0 list */ { Fnl *fnl, *next; + int lvl; - for (fnl = gc->finalizers; fnl; fnl = next) { - next = fnl->next; - add_finalizer(fnl, 1, gc); + for (lvl = FNL_LEVEL_GEN_1; lvl < NUM_FNL_LEVELS; lvl++) { + for (fnl = gc->finalizers[lvl]; fnl; fnl = next) { + next = fnl->next; + add_finalizer(fnl, FNL_LEVEL_GEN_0, gc); + } + gc->finalizers[lvl] = NULL; + gc->splayed_finalizers[lvl] = NULL; } - - gc->finalizers = NULL; - gc->splayed_finalizers = NULL; } static void reset_finalizer_tree(GCTYPE *gc) @@ -168,9 +161,30 @@ static void reset_finalizer_tree(GCTYPE *gc) { Fnl *fnl, *next; - fnl = gc->gen0_finalizers; - gc->gen0_finalizers = NULL; - gc->splayed_gen0_finalizers = NULL; + if (gc->gc_full) { + GC_ASSERT(!gc->finalizers[FNL_LEVEL_INC_1]); + GC_ASSERT(!gc->splayed_finalizers[FNL_LEVEL_INC_1]); + GC_ASSERT(!gc->finalizers[FNL_LEVEL_INC_2]); + GC_ASSERT(!gc->splayed_finalizers[FNL_LEVEL_INC_2]); + if (gc->finished_incremental) { + fnl = gc->finalizers[FNL_LEVEL_GEN_1]; + for (; fnl; fnl = next) { + next = fnl->next; + add_finalizer(fnl, FNL_LEVEL_INC_3, gc); + } + gc->finalizers[FNL_LEVEL_GEN_1] = gc->finalizers[FNL_LEVEL_INC_3]; + gc->splayed_finalizers[FNL_LEVEL_GEN_1] = gc->splayed_finalizers[FNL_LEVEL_INC_3]; + gc->finalizers[FNL_LEVEL_INC_3] = NULL; + gc->splayed_finalizers[FNL_LEVEL_INC_3] = NULL; + } else { + GC_ASSERT(!gc->finalizers[FNL_LEVEL_INC_3]); + GC_ASSERT(!gc->splayed_finalizers[FNL_LEVEL_INC_3]); + } + } + + fnl = gc->finalizers[FNL_LEVEL_GEN_0]; + gc->finalizers[FNL_LEVEL_GEN_0] = NULL; + gc->splayed_finalizers[FNL_LEVEL_GEN_0] = NULL; for (; fnl; fnl = next) { next = fnl->next; @@ -182,22 +196,8 @@ static void reset_finalizer_tree(GCTYPE *gc) || is_in_generation_half(gc, fnl->f) || is_in_generation_half(gc, fnl->p) || is_in_generation_half(gc, fnl->data)) - add_finalizer(fnl, 1, gc); + add_finalizer(fnl, FNL_LEVEL_GEN_0, gc); else - add_finalizer(fnl, 0, gc); - } -} - -static void reset_gen1_finalizer_tree(GCTYPE *gc) -{ - Fnl *fnl, *next; - - fnl = gc->finalizers; - gc->finalizers = NULL; - gc->splayed_finalizers = NULL; - - for (; fnl; fnl = next) { - next = fnl->next; - add_finalizer(fnl, 0, gc); + add_finalizer(fnl, FNL_LEVEL_GEN_1, gc); } } diff --git a/racket/src/racket/gc2/newgc.c b/racket/src/racket/gc2/newgc.c index 69d71c3280..7b4aad3149 100644 --- a/racket/src/racket/gc2/newgc.c +++ b/racket/src/racket/gc2/newgc.c @@ -102,7 +102,8 @@ enum { AGE_GEN_0 = 0, AGE_GEN_HALF = 1, AGE_GEN_1 = 2, - AGE_VACATED = 3 + AGE_VACATED = 3, /* used for pages to be removed */ + AGE_GEN_INC = 4 /* used for naming a finalizer set */ }; static const char *type_name[PAGE_TYPES] = { @@ -2472,23 +2473,20 @@ static int is_finalizable_page(NewGC *gc, void *p) #include "fnls.c" -inline static void mark_finalizer_structs(NewGC *gc, int old_gen) +inline static void mark_finalizer_structs(NewGC *gc, int lvl) { Fnl *fnl; - set_backtrace_source(gc, &gc->gen0_finalizers, BT_ROOT); - if (old_gen) - gcMARK2(gc->finalizers, gc); - else - gcMARK2(gc->gen0_finalizers, gc); - for(fnl = (old_gen ? gc->finalizers : gc->gen0_finalizers); fnl; fnl = fnl->next) { + set_backtrace_source(gc, &gc->finalizers[lvl], BT_ROOT); + gcMARK2(gc->finalizers[lvl], gc); + for(fnl = gc->finalizers[lvl]; fnl; fnl = fnl->next) { set_backtrace_source(gc, fnl, BT_FINALIZER); gcMARK2(fnl->data, gc); - set_backtrace_source(gc, &gc->gen0_finalizers, BT_ROOT); + set_backtrace_source(gc, &gc->finalizers[lvl], BT_ROOT); gcMARK2(fnl->next, gc); } - if (!old_gen) { + if (lvl == FNL_LEVEL_GEN_0) { set_backtrace_source(gc, &gc->run_queue, BT_ROOT); gcMARK2(gc->run_queue, gc); for(fnl = gc->run_queue; fnl; fnl = fnl->next) { @@ -2509,20 +2507,20 @@ inline static void mark_finalizer_structs(NewGC *gc, int old_gen) gcMARK2(fnl->next, gc); } } -} +} inline static void repair_finalizer_structs(NewGC *gc) { Fnl *fnl; /* repair the base parts of the list */ - gcFIXUP2(gc->gen0_finalizers, gc); + gcFIXUP2(gc->finalizers[FNL_LEVEL_GEN_0], gc); gcFIXUP2(gc->run_queue, gc); gcFIXUP2(gc->last_in_queue, gc); gcFIXUP2(gc->inc_run_queue, gc); gcFIXUP2(gc->inc_last_in_queue, gc); /* then repair the stuff inside them */ - for(fnl = gc->gen0_finalizers; fnl; fnl = fnl->next) { + for(fnl = gc->finalizers[FNL_LEVEL_GEN_0]; fnl; fnl = fnl->next) { gcFIXUP2(fnl->data, gc); gcFIXUP2(fnl->p, gc); gcFIXUP2(fnl->next, gc); @@ -2552,45 +2550,61 @@ static void merge_run_queues(NewGC *gc) } } -inline static void check_finalizers(NewGC *gc, int level, int old_gen) +inline static int check_finalizers(NewGC *gc, int level, int old_gen, int fuel) { - Fnl *work = (old_gen - ? GC_resolve2(gc->finalizers, gc) - : GC_resolve2(gc->gen0_finalizers, gc)); + int lvl = (old_gen + ? (FNL_LEVEL_GEN_1 + level - 1) + : FNL_LEVEL_GEN_0); + Fnl *work = GC_resolve2(gc->finalizers[lvl], gc); Fnl *prev = NULL; + if (!fuel) return 0; + GCDEBUG((DEBUGOUTF, "CFNL: Checking level %i finalizers\n", level)); while(work) { + if (!fuel) { + GC_ASSERT(old_gen); + return 0; + } + if (fuel > 0) { + fuel -= 4; + if (fuel < 0) fuel = 0; + } + if((work->eager_level == level) && !marked(gc, work->p)) { - struct finalizer *next = GC_resolve2(work->next, gc); + struct finalizer *next; GCDEBUG((DEBUGOUTF, "CFNL: Level %i finalizer %p on %p queued for finalization.\n", work->eager_level, work, work->p)); set_backtrace_source(gc, work, BT_FINALIZER); gcMARK2(work->p, gc); - if (prev) - prev->next = next; - else if (old_gen) - gc->finalizers = next; - else - gc->gen0_finalizers = next; - if (next) - next->prev = work->prev; - work->prev = NULL; /* queue is singly-linked */ - work->left = NULL; - work->right = NULL; if (old_gen) { + remove_finalizer(work, lvl, gc); + next = gc->finalizers[lvl]; + if (gc->inc_last_in_queue) gc->inc_last_in_queue = gc->inc_last_in_queue->next = work; else gc->inc_run_queue = gc->inc_last_in_queue = work; } else { + next = GC_resolve2(work->next, gc); + if (prev) + prev->next = next; + else + gc->finalizers[lvl] = next; + if (next) + next->prev = work->prev; + work->prev = NULL; /* queue is singly-linked */ + work->left = NULL; + work->right = NULL; + if (gc->last_in_queue) gc->last_in_queue = gc->last_in_queue->next = work; else gc->run_queue = gc->last_in_queue = work; } + work->next = NULL; --gc->num_fnls; @@ -2600,13 +2614,23 @@ inline static void check_finalizers(NewGC *gc, int level, int old_gen) GCDEBUG((DEBUGOUTF, "CFNL: Not finalizing %p (level %i on %p): %p / %i\n", work, work->eager_level, work->p, pagemap_find_page(gc->page_maps, work->p), marked(work->p))); - p = GC_resolve2(work->p, gc); - if (p != work->p) - work->p = p; - prev = work; - work = GC_resolve2(work->next, gc); + if (old_gen) { + /* Move to next set of finalizers */ + GC_ASSERT(lvl < FNL_LEVEL_INC_3); + remove_finalizer(work, lvl, gc); + add_finalizer(work, lvl+1, gc); + work = gc->finalizers[lvl]; + } else { + p = GC_resolve2(work->p, gc); + if (p != work->p) + work->p = p; + prev = work; + work = GC_resolve2(work->next, gc); + } } } + + return fuel; } /*****************************************************************************/ @@ -3089,10 +3113,14 @@ static int designate_modified_gc(NewGC *gc, void *p) /* Some marking functions, like the one for weak boxes, update the record, so it's ok to make the page writable. */ && (gc->inc_gen1 + /* Finalization in incremental mode can touch otherwise + pages that are otherwise unmodified in the current pass: */ + || gc->fnl_gen1 /* Memory accounting can also modify otherwise unadjusted pages after incrementa mode: */ || (gc->doing_memory_accounting && gc->finished_incremental))) { check_incremental_unprotect(gc, page); + gc->unprotected_page = 1; /* for using fuel */ return 1; } GCPRINT(GCOUTF, "Seg fault (internal error during gc) at %p\n", p); @@ -4199,6 +4227,8 @@ static int propagate_incremental_marks(NewGC *gc, int do_emph, int fuel) { int save_inc, save_check, init_fuel = fuel; + if (!fuel) return 0; + GC_ASSERT(gc->mark_gen1); save_inc = gc->inc_gen1; @@ -4220,6 +4250,10 @@ static int propagate_incremental_marks(NewGC *gc, int do_emph, int fuel) fuel--; fuel -= (gc->copy_count >> 2); fuel -= (gc->traverse_count >> 2); + if (gc->unprotected_page) { + gc->unprotected_page = 0; + fuel -= 100; + } if (fuel < 0) fuel = 0; } @@ -5913,101 +5947,106 @@ extern double scheme_get_inexact_milliseconds(void); #define AS_100M(c) ((c / (1024 * 1024 * 100)) + 1) -static int mark_and_finalize_all(NewGC *gc, int old_gen TIME_FORMAL_ARGS) +static int mark_and_finalize_all(NewGC *gc, int old_gen, int no_full TIME_FORMAL_ARGS) { - int fuel = (INCREMENTAL_COLLECT_FUEL_PER_100M * AS_100M(gc->memory_in_use)) / 2; + int fuel = (old_gen + ? (no_full + ? INCREMENTAL_COLLECT_FUEL_PER_100M / INCREMENTAL_MINOR_REQUEST_DIVISOR + : (INCREMENTAL_COLLECT_FUEL_PER_100M * AS_100M(gc->memory_in_use)) / 2) + : -1); + int reset_gen1; + + /* Propagate marks */ + if (!old_gen) + propagate_marks_plus_ephemerons(gc); + else + fuel = propagate_incremental_marks(gc, 1, fuel); + + /* check finalizers at level 1 */ + fuel = check_finalizers(gc, 1, old_gen, fuel); if (!old_gen) propagate_marks_plus_ephemerons(gc); else - (void)propagate_incremental_marks(gc, 1, -1); - - check_finalizers(gc, 1, old_gen); - if (!old_gen) - propagate_marks_plus_ephemerons(gc); - else { fuel = propagate_incremental_marks(gc, 1, fuel); - if (!fuel) - return 1; - } TIME_STEP("marked"); - if (old_gen) { + if (old_gen || (gc->gc_full && gc->finished_incremental)) { GC_ASSERT(!gc->fnl_gen1); gc->fnl_gen1 = 1; - } + reset_gen1 = 1; + } else + reset_gen1 = 0; if (gc->gc_full) - (void)zero_weak_boxes(gc, 0, 0, 1, -1); - fuel = zero_weak_boxes(gc, 0, 0, old_gen, (old_gen ? fuel : -1)); - if (old_gen && !fuel) { - gc->fnl_gen1 = 0; - return 1; - } + (void)zero_weak_boxes(gc, 0, 0, 1, 1, -1); + fuel = zero_weak_boxes(gc, 0, 0, old_gen, !old_gen, fuel); if (gc->gc_full) - (void)zero_weak_arrays(gc, 0, 1, -1); - fuel = zero_weak_arrays(gc, 0, old_gen, (old_gen ? fuel : -1)); - if (old_gen && !fuel) { - gc->fnl_gen1 = 0; - return 1; - } + (void)zero_weak_arrays(gc, 0, 1, 1, -1); + fuel = zero_weak_arrays(gc, 0, old_gen, !old_gen, fuel); if (gc->gc_full) zero_remaining_ephemerons(gc, 1); - zero_remaining_ephemerons(gc, old_gen); + if (fuel) + zero_remaining_ephemerons(gc, old_gen); TIME_STEP("zeroed"); - - check_finalizers(gc, 2, old_gen); + + fuel = check_finalizers(gc, 2, old_gen, fuel); + if (!old_gen) propagate_marks(gc); else - (void)propagate_incremental_marks(gc, 0, -1); + fuel = propagate_incremental_marks(gc, 0, fuel); + if (gc->gc_full) - (void)zero_weak_boxes(gc, 1, 0, 1, -1); - (void)zero_weak_boxes(gc, 1, 0, old_gen, -1); + (void)zero_weak_boxes(gc, 1, 0, 1, 1, -1); + fuel = zero_weak_boxes(gc, 1, 0, old_gen, !old_gen, fuel); + + fuel = check_finalizers(gc, 3, old_gen, fuel); - check_finalizers(gc, 3, old_gen); if (!old_gen) propagate_marks(gc); else - (void)propagate_incremental_marks(gc, 0, -1); + fuel = propagate_incremental_marks(gc, 0, fuel); - if (gc->GC_post_propagate_hook) + if (fuel && gc->GC_post_propagate_hook) gc->GC_post_propagate_hook(gc); + + if (fuel) { + /* for any new ones that appeared: */ + (void)zero_weak_boxes(gc, 0, 1, old_gen, 0, -1); + (void)zero_weak_boxes(gc, 1, 1, old_gen, 0, -1); + (void)zero_weak_arrays(gc, 1, old_gen, 0, -1); + zero_remaining_ephemerons(gc, old_gen); - /* for any new ones that appeared: */ - (void)zero_weak_boxes(gc, 0, 1, old_gen, -1); - (void)zero_weak_boxes(gc, 1, 1, old_gen, -1); - (void)zero_weak_arrays(gc, 1, old_gen, -1); - zero_remaining_ephemerons(gc, old_gen); - - GC_ASSERT(!gc->weak_arrays); - GC_ASSERT(!gc->bp_weak_arrays); - GC_ASSERT(!gc->weak_boxes[0]); - GC_ASSERT(!gc->weak_boxes[1]); - GC_ASSERT(!gc->bp_weak_boxes[0]); - GC_ASSERT(!gc->bp_weak_boxes[1]); - GC_ASSERT(!gc->ephemerons); - GC_ASSERT(!gc->bp_ephemerons); - if (gc->gc_full) { - GC_ASSERT(!gc->inc_weak_arrays); - GC_ASSERT(!gc->inc_weak_boxes[0]); - GC_ASSERT(!gc->inc_weak_boxes[1]); - GC_ASSERT(!gc->inc_ephemerons); + GC_ASSERT(!gc->weak_arrays); + GC_ASSERT(!gc->bp_weak_arrays); + GC_ASSERT(!gc->weak_boxes[0]); + GC_ASSERT(!gc->weak_boxes[1]); + GC_ASSERT(!gc->bp_weak_boxes[0]); + GC_ASSERT(!gc->bp_weak_boxes[1]); + GC_ASSERT(!gc->ephemerons); + GC_ASSERT(!gc->bp_ephemerons); + if (gc->gc_full) { + GC_ASSERT(!gc->inc_weak_arrays); + GC_ASSERT(!gc->inc_weak_boxes[0]); + GC_ASSERT(!gc->inc_weak_boxes[1]); + GC_ASSERT(!gc->inc_ephemerons); + } } - if (old_gen) + if (reset_gen1) gc->fnl_gen1 = 0; TIME_STEP("finalized"); - return 0; + return !fuel; } -static int mark_and_finalize_all_incremental(NewGC *gc TIME_FORMAL_ARGS) +static int mark_and_finalize_all_incremental(NewGC *gc, int no_full TIME_FORMAL_ARGS) { int save_inc, save_check, more_to_do; @@ -6019,7 +6058,7 @@ static int mark_and_finalize_all_incremental(NewGC *gc TIME_FORMAL_ARGS) gc->inc_gen1 = 1; gc->check_gen1 = 1; - more_to_do = mark_and_finalize_all(gc, 1 TIME_ARGS); + more_to_do = mark_and_finalize_all(gc, 1, no_full TIME_ARGS); gc->inc_gen1 = save_inc; gc->check_gen1 = save_check; @@ -6168,7 +6207,7 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin /* mark and repair the roots for collection */ mark_backpointers(gc); TIME_STEP("backpointered"); - mark_finalizer_structs(gc, 0); + mark_finalizer_structs(gc, FNL_LEVEL_GEN_0); TIME_STEP("pre-rooted"); mark_roots(gc); mark_immobiles(gc); @@ -6183,11 +6222,11 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin /* now propagate/repair the marks we got from these roots, and do the finalizer passes */ - (void)mark_and_finalize_all(gc, 0 TIME_ARGS); + (void)mark_and_finalize_all(gc, 0, no_full TIME_ARGS); if (do_incremental) { if (!gc->all_marked_incremental) { - mark_finalizer_structs(gc, 1); + mark_finalizer_structs(gc, FNL_LEVEL_GEN_1); if (!mark_stack_is_empty(gc->inc_mark_stack)) { int fuel = (no_full ? INCREMENTAL_COLLECT_FUEL_PER_100M / INCREMENTAL_MINOR_REQUEST_DIVISOR @@ -6197,12 +6236,10 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin } else { /* We ran out of incremental marking work, so perform major-GC finalization */ - if (mark_and_finalize_all_incremental(gc TIME_ARGS)) { + if (mark_and_finalize_all_incremental(gc, no_full TIME_ARGS)) { /* More finalizaton work to do */ - reset_gen1_finalizer_tree(gc); } else { BTC_clean_up_gen1(gc); - reset_gen1_finalizer_tree(gc); /* Switch to incrementally reparing pages */ gc->all_marked_incremental = 1; } @@ -6244,10 +6281,10 @@ static void garbage_collect(NewGC *gc, int force_full, int no_full, int switchin repair_heap(gc); TIME_STEP("repaired"); if (check_inc_repair) { - GC_ASSERT(gc->all_marked_incremental); int fuel = (no_full ? INCREMENTAL_REPAIR_FUEL_PER_100M / INCREMENTAL_MINOR_REQUEST_DIVISOR : INCREMENTAL_REPAIR_FUEL_PER_100M * AS_100M(gc->memory_in_use)); + GC_ASSERT(gc->all_marked_incremental); incremental_repair_pages(gc, fuel); TIME_STEP("inc-repaired"); if (!gc->inc_repair_next) diff --git a/racket/src/racket/gc2/newgc.h b/racket/src/racket/gc2/newgc.h index 03323fd128..973eeb3dec 100644 --- a/racket/src/racket/gc2/newgc.h +++ b/racket/src/racket/gc2/newgc.h @@ -149,6 +149,15 @@ typedef mpage **PageMap; #define NUM_MED_PAGE_SIZES (((LOG_APAGE_SIZE - 1) - 3) + 1) +enum { + FNL_LEVEL_GEN_0, + FNL_LEVEL_GEN_1, + FNL_LEVEL_INC_1, + FNL_LEVEL_INC_2, + FNL_LEVEL_INC_3, + NUM_FNL_LEVELS +}; + typedef struct NewGC { Gen0 gen0; Gen_Half gen_half; @@ -221,6 +230,7 @@ typedef struct NewGC { unsigned char during_backpointer :1; unsigned char incremental_requested :1; unsigned char high_fragmentation :1; + unsigned char unprotected_page :1; /* blame the child */ unsigned int doing_memory_accounting :1; @@ -282,10 +292,8 @@ typedef struct NewGC { GC_Immobile_Box *immobile_boxes; - Fnl *finalizers; - Fnl *splayed_finalizers; - Fnl *gen0_finalizers; - Fnl *splayed_gen0_finalizers; + Fnl *finalizers[NUM_FNL_LEVELS]; + Fnl *splayed_finalizers[NUM_FNL_LEVELS]; int num_fnls; void *park[2]; diff --git a/racket/src/racket/gc2/weak.c b/racket/src/racket/gc2/weak.c index d9fcd99a08..e1b0aa5255 100644 --- a/racket/src/racket/gc2/weak.c +++ b/racket/src/racket/gc2/weak.c @@ -155,11 +155,13 @@ static GC_Weak_Array *append_weak_arrays(GC_Weak_Array *wa, GC_Weak_Array *bp_wa return bp_wa; } -static int zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc, int fuel) +static int zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc, int need_resolve, int fuel) { GC_Weak_Array *wa; int i, num_gen0; + if (!fuel) return 0; + if (from_inc) { wa = gc->inc_weak_arrays; num_gen0 = 0; @@ -177,11 +179,13 @@ static int zero_weak_arrays(GCTYPE *gc, int force_zero, int from_inc, int fuel) void *p = data[i]; if (p && (force_zero || !is_marked(gc, p))) data[i] = wa->replace_val; - else + else if (need_resolve) data[i] = GC_resolve2(p, gc); } - if (fuel > 0) - fuel = ((fuel > wa->count) ? (fuel - wa->count) : 0); + if (fuel > 0) { + fuel -= (4 * wa->count); + if (fuel < 0) fuel = 0; + } if (num_gen0 > 0) { if (!is_in_generation_half(gc, wa)) { @@ -348,11 +352,13 @@ static GC_Weak_Box *append_weak_boxes(GC_Weak_Box *wb, GC_Weak_Box *bp_wb, int * return bp_wb; } -static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc, int fuel) +static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc, int need_resolve, int fuel) { GC_Weak_Box *wb; int num_gen0; + if (!fuel) return 0; + if (from_inc) { wb = gc->inc_weak_boxes[is_late]; num_gen0 = 0; @@ -388,9 +394,9 @@ static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc *(p + wb->soffset) = NULL; wb->secondary_erase = NULL; } - } else { + } else if (need_resolve) wb->val = GC_resolve2(wb->val, gc); - } + if (num_gen0 > 0) { if (!is_in_generation_half(gc, wb)) { if (!gc->all_marked_incremental) { @@ -405,6 +411,7 @@ static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc } } } + if (from_inc) { GC_Weak_Box *next; next = wb->inc_next; @@ -416,9 +423,14 @@ static int zero_weak_boxes(GCTYPE *gc, int is_late, int force_zero, int from_inc num_gen0--; if (fuel >= 0) { - if (fuel > 0) - fuel--; - else { + if (fuel > 0) { + if (gc->unprotected_page) { + fuel -= 100; + gc->unprotected_page = 0; + } else + fuel -= 4; + if (fuel < 0) fuel = 0; + } else { GC_ASSERT(from_inc); gc->inc_weak_boxes[is_late] = wb; return 0; diff --git a/racket/src/racket/src/mzclpf_post.inc b/racket/src/racket/src/mzclpf_post.inc index 1a0303a9f0..9b47dc1f48 100644 --- a/racket/src/racket/src/mzclpf_post.inc +++ b/racket/src/racket/src/mzclpf_post.inc @@ -27,7 +27,8 @@ /* We're the first to look at this prefix... */ /* Add it to the chain of prefixes to finish after all other marking: */ - if (gc_mode == GC_CURRENT_MODE_INCREMENTAL) { + if ((gc_mode == GC_CURRENT_MODE_INCREMENTAL) + || (gc_mode == GC_CURRENT_MODE_INCREMENTAL_FINAL)) { pf->next_final = scheme_inc_prefix_finalize; scheme_inc_prefix_finalize = pf; } else {