From: Mark Date: Sat, 14 Oct 2023 20:03:47 +0000 (-0600) Subject: correct cyclic variable check in cycle detecting stackless iterator (#2111, #2113) X-Git-Tag: remove~23 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=379c252b897975e6a5c6d03e77f2022143dc7f22;p=scryer-prolog.git correct cyclic variable check in cycle detecting stackless iterator (#2111, #2113) --- diff --git a/src/machine/gc.rs b/src/machine/gc.rs index a0a802db..bb90a29c 100644 --- a/src/machine/gc.rs +++ b/src/machine/gc.rs @@ -269,6 +269,20 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { None } + #[inline] + fn is_cyclic(&self, h: usize) -> bool { + if self.heap[h].is_var() { + self.heap[h].get_forwarding_bit() + } else if self.heap[h].is_ref() { + // the cell h in the second branch contains its original + // value whether h is marked or unmarked, meaning the + // is_compound check is well-founded in either case. + self.heap[h].get_forwarding_bit() || self.heap[h].is_compound(self.heap) + } else { + false + } + } + fn forward(&mut self) -> Option { loop { if self.heap[self.current].get_mark_bit() != self.iter_state.mark_phase() { @@ -280,7 +294,7 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { let current = self.current; if let Some(cell) = UMP::forward_attr_var(self) { - if current as u64 != next && self.heap[next as usize].is_compound(self.heap) { + if current as u64 != next && self.is_cyclic(next as usize) { self.iter_state.cycle_detected(); } @@ -299,7 +313,7 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> { let current = self.current; if let Some(cell) = self.forward_var() { - if current as u64 != next && self.heap[next as usize].is_compound(self.heap) { + if current as u64 != next && self.is_cyclic(next as usize) { self.iter_state.cycle_detected(); }