summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-07-29 07:51:02 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-07-29 07:51:02 -0700
commitc366eb1fb657f3db0b4002efa373d692b38cc647 (patch)
treedccbf9179283db3e7760319a4689a76697d5dba1
parented115c18a07c85a8b1de0666157c908290cc38c7 (diff)
downloadtxr-c366eb1fb657f3db0b4002efa373d692b38cc647.tar.gz
txr-c366eb1fb657f3db0b4002efa373d692b38cc647.tar.bz2
txr-c366eb1fb657f3db0b4002efa373d692b38cc647.zip
gc: problem in several object copying functions.
The functions copy-cons, copy-tree, copy-fun and copy-tnode have a problem. They copy the original object bitwise with a structure assignment, and then make some adjustments. The problem is that this inappropriately copies the object's metadata related to gc, such as its generation number or finalization count. To fix this, we introduce a copy_obj function, which is a companion to make_obj. This performs a shallow copy of an object without incorrectly propagating inappropriate metadata. * gc.c, gc.h (copy_obj): New function. * lib.c (copy_fun, copy_cons, copy_tree): Use copy_obj, instead of make_obj plus structure assignment. * tree.c (copy_tnode): Likewise.
-rw-r--r--gc.c11
-rw-r--r--gc.h1
-rw-r--r--lib.c13
-rw-r--r--tree.c4
4 files changed, 16 insertions, 13 deletions
diff --git a/gc.c b/gc.c
index adaf526e..0069dae3 100644
--- a/gc.c
+++ b/gc.c
@@ -269,6 +269,17 @@ val make_obj(void)
abort();
}
+val copy_obj(val orig)
+{
+ val copy = make_obj();
+ *copy = *orig;
+#if CONFIG_GEN_GC
+ copy->t.fincount = 0;
+ copy->t.gen = 0;
+#endif
+ return copy;
+}
+
static void finalize(val obj)
{
switch (convert(type_t, obj->t.type)) {
diff --git a/gc.h b/gc.h
index 309a8912..00c616e9 100644
--- a/gc.h
+++ b/gc.h
@@ -30,6 +30,7 @@ void gc_late_init(void);
val prot1(val *loc);
void protect(val *, ...);
val make_obj(void);
+val copy_obj(val);
void gc(void);
int gc_state(int);
int gc_inprogress(void);
diff --git a/lib.c b/lib.c
index 1a12e678..5de9f170 100644
--- a/lib.c
+++ b/lib.c
@@ -7494,8 +7494,7 @@ val copy_fun(val ofun)
val self = lit("copy-fun");
type_check(self, ofun, FUN);
{
- val nfun = make_obj();
- nfun->f = ofun->f;
+ val nfun = copy_obj(ofun);
if (nfun->f.env)
nfun->f.env = if3(nfun->f.functype == FVM,
@@ -9692,9 +9691,7 @@ val copy_cons(val cell)
case CONS:
case LCONS:
{
- val obj = make_obj();
- *obj = *cell;
- return obj;
+ return copy_obj(cell);
}
default:
type_mismatch(lit("copy-cons: ~s is not a cons"), cell, nao);
@@ -9708,11 +9705,7 @@ val copy_tree(val tree)
} else {
val car = copy_tree(tree->c.car);
val cdr = copy_tree(tree->c.cdr);
- val copy = make_obj();
- *copy = *tree;
- copy->c.car = car;
- copy->c.cdr = cdr;
- return copy;
+ return cons(car, cdr);
}
}
diff --git a/tree.c b/tree.c
index a0a0faf8..53496e3e 100644
--- a/tree.c
+++ b/tree.c
@@ -140,9 +140,7 @@ val set_key(val node, val nkey)
val copy_tnode(val node)
{
- val obj = (type_check(lit("copy-tnode"), node, TNOD), make_obj());
- obj->tn = node->tn;
- return obj;
+ return (type_check(lit("copy-tnode"), node, TNOD), copy_obj(node));
}
static ucnum tn_size(val node)