From 83c9d17a081fe20da7641e65164963fb4383ec01 Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 29 Jul 2021 07:56:44 -0700 Subject: gc: problem in environment-copying functions. * eval.c (copy_env, deep_copy_env): These functions are not following a protocol for object construction that is correct under generational GC. They are allocating a new object with make_obj first, and then calling functions to copy the constituent elements to populate into the object with a direct assignment. This direct assignment is wrong; the set macro is required. A better fix, rather than using the set macro, is to copy the constituent parts first, holding them in local variables, then allocate the new object, and finally, without doing any other memory allocating operations, assign the constituent parts into the new object. --- eval.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/eval.c b/eval.c index d933cb45..6b2ac391 100644 --- a/eval.c +++ b/eval.c @@ -133,11 +133,13 @@ val copy_env(val oenv) type_check(lit("copy-env"), oenv, ENV); { + val vb = copy_alist(oenv->e.vbindings); + val fb = copy_alist(oenv->e.fbindings); val nenv = make_obj(); nenv->e.type = ENV; - nenv->e.vbindings = copy_alist(oenv->e.vbindings); - nenv->e.fbindings = copy_alist(oenv->e.fbindings); + nenv->e.vbindings = vb; + nenv->e.fbindings = fb; nenv->e.up_env = oenv->e.up_env; return nenv; } @@ -148,13 +150,16 @@ val deep_copy_env(val oenv) type_check(lit("deep-copy-env"), oenv, ENV); { + val vb = copy_alist(oenv->e.vbindings); + val fb = copy_alist(oenv->e.fbindings); + val up_env = if2(oenv->e.up_env != nil, + deep_copy_env(oenv->e.up_env)); val nenv = make_obj(); - nenv->e.type = ENV; - nenv->e.vbindings = copy_alist(oenv->e.vbindings); - nenv->e.fbindings = copy_alist(oenv->e.fbindings); - nenv->e.up_env = if2(oenv->e.up_env != nil, - deep_copy_env(oenv->e.up_env)); + nenv->e.type = ENV; + nenv->e.vbindings = vb; + nenv->e.fbindings = fb; + nenv->e.up_env = up_env; return nenv; } } -- cgit v1.2.3