summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-07-29 07:56:44 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-29 07:56:44 -0700
commit83c9d17a081fe20da7641e65164963fb4383ec01 (patch)
treeb394820faf54dd9db3ee999ee5fc9ff58883eb9a
parentc366eb1fb657f3db0b4002efa373d692b38cc647 (diff)
downloadtxr-83c9d17a081fe20da7641e65164963fb4383ec01.tar.gz
txr-83c9d17a081fe20da7641e65164963fb4383ec01.tar.bz2
txr-83c9d17a081fe20da7641e65164963fb4383ec01.zip
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.
-rw-r--r--eval.c19
1 files 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;
}
}