From b20f57e55eea53a570c1fb59961173035f00f8dc Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 10 Nov 2016 21:55:58 -0800 Subject: Fix some gc-unsafe mutations found by inspection. * eval.c (force): When replacing the promise by a forced value, we must use the set macro. Only the deref assignments which store symbols are safe, not the one storing ret. * lib.c (alist_nremove, alist_nremove1): We must use the set macro here instead of assigning through deref. Even though these assignments preserve the direction of the list (they just splice out nodes), it's possible that the list already contains a "wrong-way" reference (old generation to new) and that the node making this reference is appropriately marked to be processed properly in the next GC cycle. If we remove *that* node, we then cause its predecessor to point to the new generation node and that predecessor could be old generation. --- eval.c | 2 +- lib.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eval.c b/eval.c index 06df270d..a0c610c9 100644 --- a/eval.c +++ b/eval.c @@ -4469,7 +4469,7 @@ static val force(val promise) deref(pstate) = promise_inprogress_s; ret = funcall(deref(pval)); deref(pstate) = promise_forced_s; - deref(pval) = ret; + set(pval, ret); return ret; } else if (deref(pstate) == promise_inprogress_s) { val form = second(cdr(cd)); diff --git a/lib.c b/lib.c index aee22096..b4452cbb 100644 --- a/lib.c +++ b/lib.c @@ -7249,7 +7249,7 @@ val alist_nremove(val list, val keys) while (deref(plist)) { if (memqual(car(car(deref(plist))), keys)) - deref(plist) = cdr(deref(plist)); + set(plist, cdr(deref(plist))); else plist = cdr_l(deref(plist)); } @@ -7268,7 +7268,7 @@ val alist_nremove1(val list, val key) while (deref(plist)) { if (equal(car(car(deref(plist))), key)) - deref(plist) = cdr(deref(plist)); + set(plist, cdr(deref(plist))); else plist = cdr_l(deref(plist)); } -- cgit v1.2.3