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
commit53872969cc7c6a52ff2d92b9da1bba8000c45522 (patch)
treeb394820faf54dd9db3ee999ee5fc9ff58883eb9a
parent13994ed823c2445bbeecea677fd604744b373c5e (diff)
downloadtxr-53872969cc7c6a52ff2d92b9da1bba8000c45522.tar.gz
txr-53872969cc7c6a52ff2d92b9da1bba8000c45522.tar.bz2
txr-53872969cc7c6a52ff2d92b9da1bba8000c45522.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;
}
}