]> Repositorios git - scryer-prolog.git/commitdiff
fix bugs & incompleteness of cycle-detecting stackless iterator (#2111)
authorMark <[email protected]>
Sat, 14 Oct 2023 19:00:58 +0000 (13:00 -0600)
committerMark <[email protected]>
Sat, 14 Oct 2023 19:00:58 +0000 (13:00 -0600)
src/machine/gc.rs

index 5b1ccca3ee2f4d41584480b3dacb1ff1ccf91347..a0a802db59c8b45066cc52589c046861c576b8fa 100644 (file)
@@ -17,6 +17,7 @@ pub(crate) trait UnmarkPolicy {
     ) -> bool where Self: Sized {
         iter.backward()
     }
+    fn detect_list_tail_cycle(_iter: &mut StacklessPreOrderHeapIter<Self>) where Self: Sized {}
 }
 
 pub(crate) struct IteratorUMP {
@@ -87,12 +88,18 @@ impl UnmarkPolicy for CycleDetectorUMP {
     fn list_head_cycle_detecting_backward(
         iter: &mut StacklessPreOrderHeapIter<Self>,
     ) -> bool {
-        if !iter.iter_state.cycle_detected && iter.iter_state.mark_phase && iter.detect_list_cycle() {
-            iter.iter_state.cycle_detected = true;
+        if !iter.iter_state.cycle_detected && iter.iter_state.mark_phase {
+            iter.iter_state.cycle_detected = iter.detect_list_cycle();
         }
 
         iter.backward()
     }
+
+    fn detect_list_tail_cycle(iter: &mut StacklessPreOrderHeapIter<Self>) {
+        if iter.iter_state.mark_phase && !iter.iter_state.cycle_detected {
+            iter.iter_state.cycle_detected = iter.detect_list_cycle();
+        }
+    }
 }
 
 struct MarkerUMP {}
@@ -273,7 +280,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_ref() {
+                            if current as u64 != next && self.heap[next as usize].is_compound(self.heap) {
                                 self.iter_state.cycle_detected();
                             }
 
@@ -292,7 +299,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_ref() {
+                            if current as u64 != next && self.heap[next as usize].is_compound(self.heap) {
                                 self.iter_state.cycle_detected();
                             }
 
@@ -347,6 +354,11 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
                             if self.heap[last_cell_loc-1].get_mark_bit() == self.iter_state.mark_phase() {
                                 // the conjunction leading here is a necessary but not sufficient
                                 // condition of the presence of a cycle at the list head.
+
+                                if last_cell_loc == self.current {
+                                    UMP::detect_list_tail_cycle(self);
+                                }
+
                                 self.backward();
 
                                 if UMP::list_head_cycle_detecting_backward(self) {