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
commit13994ed823c2445bbeecea677fd604744b373c5e (patch)
treedccbf9179283db3e7760319a4689a76697d5dba1
parenta7f9a8749ab3eae450c2a447782e9a9c034057ea (diff)
downloadtxr-13994ed823c2445bbeecea677fd604744b373c5e.tar.gz
txr-13994ed823c2445bbeecea677fd604744b373c5e.tar.bz2
txr-13994ed823c2445bbeecea677fd604744b373c5e.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)