summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-05-06 08:26:11 -0700
committerKaz Kylheku <kaz@kylheku.com>2020-05-06 08:26:11 -0700
commita924e5ab8b90b03f614587fc8ece2e302fae6c81 (patch)
tree4de96730bb8fcf0c81d8084cd3b426b9ec610c72
parent6be4b2168d58a9ce47e5a90aa4f54f0061e5d2d4 (diff)
downloadtxr-a924e5ab8b90b03f614587fc8ece2e302fae6c81.tar.gz
txr-a924e5ab8b90b03f614587fc8ece2e302fae6c81.tar.bz2
txr-a924e5ab8b90b03f614587fc8ece2e302fae6c81.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.
-rw-r--r--gc.c8
1 files 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);
}