diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2020-05-06 08:26:11 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2020-05-06 08:26:11 -0700 |
commit | b4fd90ddf5aa2019548997d8fc99c1e7e3c10fa6 (patch) | |
tree | 4de96730bb8fcf0c81d8084cd3b426b9ec610c72 /gc.c | |
parent | 4516a7472d34a74f89b7b5d26db4f26d62bf9f83 (diff) | |
download | txr-b4fd90ddf5aa2019548997d8fc99c1e7e3c10fa6.tar.gz txr-b4fd90ddf5aa2019548997d8fc99c1e7e3c10fa6.tar.bz2 txr-b4fd90ddf5aa2019548997d8fc99c1e7e3c10fa6.zip |
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.
Diffstat (limited to 'gc.c')
-rw-r--r-- | gc.c | 8 |
1 files changed, 4 insertions, 4 deletions
@@ -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); } |