summaryrefslogtreecommitdiffstats
path: root/lib.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-08-29 07:29:09 -0700
committerKaz Kylheku <kaz@kylheku.com>2021-08-29 07:29:09 -0700
commit13da0e5ed3d3d4be6d1f9cc9d786ff4e0f2edd68 (patch)
tree7ae339fc0501087c3c3c4c5c45c3d0c592afb995 /lib.c
parent9f142b398f53ab7844a0fdfc5b562e8bbccfebe2 (diff)
downloadtxr-13da0e5ed3d3d4be6d1f9cc9d786ff4e0f2edd68.tar.gz
txr-13da0e5ed3d3d4be6d1f9cc9d786ff4e0f2edd68.tar.bz2
txr-13da0e5ed3d3d4be6d1f9cc9d786ff4e0f2edd68.zip
seq_iter: fix gc issues.
* lib.h (struct seq_iter_ops): New operation, mark. (seq_iter_ops_init): Default the mark operation to seq_iter_mark_op. (seq_iter_ops_init_nomark): New macro. * lib.c (seq_iter_mark_op): New static function. (si_range_cnum_ops, si_range_chr_ops, si_rev_range_cnum_ops, si_rev_range_chr_ops, si_chr_ops): Initialize with seq_iter_ops_init_nomark so that the iterator has no mark operation. All other iterator types have the above new static function as their mark op. (seq_iter_mark): Simplified: if the iterator has a mark op, call it. (seq_next, iter_step): If the iterator has a mark op, that means that the seq_get operation is likely replacing one heap object with another, and so mut(iter) must be called to inform the garbage collector of the assignment.
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c47
1 files changed, 22 insertions, 25 deletions
diff --git a/lib.c b/lib.c
index 7a1b9493..af9a9703 100644
--- a/lib.c
+++ b/lib.c
@@ -861,6 +861,11 @@ static void seq_iter_rewind(seq_iter_t *it, val self)
}
}
+static void seq_iter_mark_op(struct seq_iter *it)
+{
+ gc_mark(it->ui.iter);
+}
+
struct seq_iter_ops si_null_ops = seq_iter_ops_init(seq_iter_get_nil,
seq_iter_peek_nil);
@@ -877,12 +882,12 @@ struct seq_iter_ops si_tree_ops = seq_iter_ops_init(seq_iter_get_tree,
seq_iter_peek_tree);
struct seq_iter_ops si_range_cnum_ops =
- seq_iter_ops_init(seq_iter_get_range_cnum,
- seq_iter_peek_range_cnum);
+ seq_iter_ops_init_nomark(seq_iter_get_range_cnum,
+ seq_iter_peek_range_cnum);
struct seq_iter_ops si_range_chr_ops =
- seq_iter_ops_init(seq_iter_get_range_chr,
- seq_iter_peek_range_chr);
+ seq_iter_ops_init_nomark(seq_iter_get_range_chr,
+ seq_iter_peek_range_chr);
struct seq_iter_ops si_range_bignum_ops =
seq_iter_ops_init(seq_iter_get_range_bignum,
@@ -893,12 +898,12 @@ struct seq_iter_ops si_range_str_ops =
seq_iter_peek_range_str);
struct seq_iter_ops si_rev_range_cnum_ops =
- seq_iter_ops_init(seq_iter_get_rev_range_cnum,
- seq_iter_peek_rev_range_cnum);
+ seq_iter_ops_init_nomark(seq_iter_get_rev_range_cnum,
+ seq_iter_peek_rev_range_cnum);
struct seq_iter_ops si_rev_range_chr_ops =
- seq_iter_ops_init(seq_iter_get_rev_range_chr,
- seq_iter_peek_rev_range_chr);
+ seq_iter_ops_init_nomark(seq_iter_get_rev_range_chr,
+ seq_iter_peek_rev_range_chr);
struct seq_iter_ops si_rev_range_bignum_ops =
seq_iter_ops_init(seq_iter_get_rev_range_bignum,
@@ -908,8 +913,8 @@ struct seq_iter_ops si_rev_range_str_ops =
seq_iter_ops_init(seq_iter_get_rev_range_str,
seq_iter_peek_range_str);
-struct seq_iter_ops si_chr_ops = seq_iter_ops_init(seq_iter_get_chr,
- seq_iter_peek_chr);
+struct seq_iter_ops si_chr_ops = seq_iter_ops_init_nomark(seq_iter_get_chr,
+ seq_iter_peek_chr);
struct seq_iter_ops si_num_ops = seq_iter_ops_init(seq_iter_get_num,
seq_iter_peek_num);
@@ -1127,20 +1132,8 @@ static void seq_iter_mark(val seq_iter)
gc_mark(si->inf.obj);
- switch (si->inf.kind) {
- case SEQ_LISTLIKE:
- case SEQ_HASHLIKE:
- case SEQ_TREELIKE:
- gc_mark(si->ui.iter);
- break;
- case SEQ_NOTSEQ:
- if (cobjp(si->inf.obj) && obj_struct_p(si->inf.obj))
- gc_mark(si->ui.iter);
- break;
- case SEQ_NIL:
- case SEQ_VECLIKE:
- break;
- }
+ if (si->ops->mark)
+ si->ops->mark(si);
}
static struct cobj_ops seq_iter_ops = cobj_ops_init(eq,
@@ -1165,7 +1158,9 @@ val seq_next(val iter, val end_val)
struct seq_iter *si = coerce(struct seq_iter *,
cobj_handle(self, iter, seq_iter_cls));
val item = nil;
- return if3(seq_get(si, &item), item, end_val);
+ val ret = if3(seq_get(si, &item), item, end_val);
+ mut(iter);
+ return ret;
}
val seq_reset(val iter, val obj)
@@ -1300,6 +1295,8 @@ val iter_step(val iter)
struct seq_iter *si = coerce(struct seq_iter *, iter->co.handle);
val item = nil;
(void) seq_get(si, &item);
+ if (si->ops->mark)
+ mut(iter);
return iter;
}
if (obj_struct_p(iter)) {