diff --git a/racket/src/racket/sgc/sgc.c b/racket/src/racket/sgc/sgc.c index 06732d9915..9ea81694bd 100644 --- a/racket/src/racket/sgc/sgc.c +++ b/racket/src/racket/sgc/sgc.c @@ -4014,16 +4014,27 @@ static void push_collect_ignore(uintptr_t s, uintptr_t e, } } +static void mark_chunks_finalization_data(MemoryChunk *c) +{ + for (; c; c = c->next) { + Finalizer *fn = c->finalizers; + + if (fn) { + /* Mark data associated with finalization callback: */ + uintptr_t p = PTR_TO_INT(&fn->data); + PUSH_COLLECT(p, p + PTR_SIZE, 0); + } + } + + collect(); +} + static void mark_chunks_for_finalizations(MemoryChunk *c) { for (; c; c = c->next) { Finalizer *fn = c->finalizers; if (fn) { - /* Always mark data associated with finalization: */ - uintptr_t p = PTR_TO_INT(&fn->data); - PUSH_COLLECT(p, p + PTR_SIZE, 0); - /* If not eager, mark data reachable from finalized block: */ if (!fn->eager_level && !c->marked && !c->atomic) { if (fn->ignore_self) @@ -4038,6 +4049,27 @@ static void mark_chunks_for_finalizations(MemoryChunk *c) collect(); } +static void mark_common_finalization_data(BlockOfMemory **blocks, int atomic) +{ + int i; + + for (i = 0; i < NUM_COMMON_SIZE; i++) { + BlockOfMemory *block = blocks[i]; + for (; block; block = block->next) { + Finalizer *fn = block->finalizers; + for (; fn ; fn = fn->next) { + uintptr_t p; + + /* Mark data associated with finalization: */ + p = PTR_TO_INT(&fn->data); + PUSH_COLLECT(p, p + PTR_SIZE, 0); + } + } + } + + collect(); +} + static void mark_common_for_finalizations(BlockOfMemory **blocks, int atomic) { int i; @@ -4048,10 +4080,6 @@ static void mark_common_for_finalizations(BlockOfMemory **blocks, int atomic) Finalizer *fn = block->finalizers; for (; fn ; fn = fn->next) { uintptr_t p; - - /* Always mark data associated with finalization: */ - p = PTR_TO_INT(&fn->data); - PUSH_COLLECT(p, p + PTR_SIZE, 0); /* If not eager, mark data reachable from finalized block: */ if (!fn->eager_level) { @@ -4281,6 +4309,14 @@ static void do_disappear_and_finals() collect(); if (GC_push_last_roots_again) { GC_push_last_roots_again(); collect(); } + /* Mark reachable from finalized callback data: */ + for (j = 0; j < num_common_sets; j++) { + mark_chunks_finalization_data(*(common_sets[j]->othersptr)); + mark_common_finalization_data(common_sets[j]->blocks, common_sets[j]->atomic); + } + collect(); + if (GC_push_last_roots_again) { GC_push_last_roots_again(); collect(); } + /* Queue unreachable eager finalizable, level 1: */ /* DO NOT COLLECT FROM collect_stack UNTIL AFTER THIS LOOP */ /* (Otherwise, some ready eager finalizations may not be queued.) */