commit eac54a6a7063d4ca67e1cb2236c8cd8dcb7b2546
parent 1a3a9ea745d00a5a2f686839849bf3b9da78cfc7
Author: Oto Havle <havleoto@gmail.com>
Date: Tue, 1 Nov 2011 21:29:33 +0100
Bugfix: old value of dynamic keyed variable now properly rooted
Diffstat:
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/src/kgkd_vars.c b/src/kgkd_vars.c
@@ -96,7 +96,7 @@ void do_set_pass(klisp_State *K, TValue *xparams, TValue ptree,
abnormal passes */
/* TODO: reuse the code for guards in kgcontinuations.c */
-/* GC: this assumes that key is rooted */
+/* GC: this assumes that key, old_value and new_value are rooted */
inline TValue make_bind_continuation(klisp_State *K, TValue key,
TValue old_flag, TValue old_value,
TValue new_flag, TValue new_value)
@@ -167,10 +167,16 @@ void do_bind(klisp_State *K, TValue *xparams, TValue ptree,
/* set the var to the new object */
kset_car(key, new_flag);
kset_cdr(key, new_value);
+ /* Old value must be protected from GC. It is no longer
+ reachable through key and not yet reachable through
+ continuation xparams. Boolean flag needn't be rooted,
+ because is not heap-allocated. */
+ krooted_tvs_push(K, old_value);
/* create a continuation to set the var to the correct value/flag on both
normal return and abnormal passes */
TValue new_cont = make_bind_continuation(K, key, old_flag, old_value,
new_flag, new_value);
+ krooted_tvs_pop(K);
kset_cc(K, new_cont); /* implicit rooting */
TValue env = kmake_empty_environment(K);
krooted_tvs_push(K, env);