From b4fd90ddf5aa2019548997d8fc99c1e7e3c10fa6 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Wed, 6 May 2020 08:26:11 -0700 Subject: gc: fight spurious retention. I've noticed that the January 9, 2020 commit "gc: obtain stack top using alloca" triggers spurious retention when compiling with HAVE_VALGRIND. The finalization test case tests/012/fini.tl breaks because the expected finalizers are not called. Changing the (sys:gc) call to two calls to (sys:gc 1) makes it pass. The culprit seems to be the inlining of the complex function sweep into gc. It has local variables for which spaces has to be reserved, which are not used until after mark() is called; likely the values in those spaces are picked up by the stack scan. Let's make sure that functions called out of gc() are not inlined. * gc.c (mark, sweep, prepare_finals, call_finals): Mark NOTINLINE. --- gc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gc.c b/gc.c index ce4d5ef7..4f9e6f60 100644 --- a/gc.c +++ b/gc.c @@ -519,7 +519,7 @@ static void mark_mem_region(val *low, val *high) mark_obj_maybe(*low); } -static void mark(val *gc_stack_top) +NOINLINE static void mark(val *gc_stack_top) { val **rootloc; @@ -625,7 +625,7 @@ static int sweep_one(obj_t *block) return 1; } -static int_ptr_t sweep(void) +NOINLINE static int_ptr_t sweep(void) { int_ptr_t free_count = 0; heap_t **pph; @@ -731,7 +731,7 @@ static int is_reachable(val obj) return (t & REACHABLE) != 0; } -static void prepare_finals(void) +NOINLINE static void prepare_finals(void) { struct fin_reg *f; @@ -807,7 +807,7 @@ static int is_unreachable_final(struct fin_reg *f, val ctx) return !f->reachable; } -static void call_finals(void) +NOINLINE static void call_finals(void) { (void) call_finalizers_impl(nil, is_unreachable_final); } -- cgit v1.2.3