]> Repositorios git - scryer-prolog.git/commitdiff
fix bugs in marker algorithm iterator
authorMark <[email protected]>
Thu, 12 Oct 2023 17:22:57 +0000 (11:22 -0600)
committerMark <[email protected]>
Fri, 13 Oct 2023 20:38:50 +0000 (14:38 -0600)
src/heap_iter.rs
src/machine/gc.rs
src/types.rs

index d36855dafe980abe68cbb3e05b7f4e0c2f46c146..ab3b962afd97c21e9f8a95ece454289df1a5a4ce 100644 (file)
@@ -1,5 +1,4 @@
-#[cfg(test)]
-pub(crate) use crate::machine::gc::{IteratorUMP, StacklessPreOrderHeapIter};
+pub(crate) use crate::machine::gc::{CycleDetectorUMP, IteratorUMP, StacklessPreOrderHeapIter};
 
 use crate::atom_table::*;
 use crate::machine::heap::*;
@@ -504,15 +503,23 @@ impl<'a, ElideLists: ListElisionPolicy> Iterator for StackfulPreOrderHeapIter<'a
     }
 }
 
-#[cfg(test)]
 #[inline(always)]
 pub(crate) fn stackless_preorder_iter(
     heap: &mut Vec<HeapCellValue>,
-    cell: HeapCellValue,
+    start: usize,
 ) -> StacklessPreOrderHeapIter<IteratorUMP> {
-    StacklessPreOrderHeapIter::<IteratorUMP>::new(heap, cell)
+    StacklessPreOrderHeapIter::<IteratorUMP>::new(heap, start)
+}
+
+
+pub(crate) fn cycle_detecting_stackless_preorder_iter(
+    heap: &mut Heap,
+    start: usize,
+) -> StacklessPreOrderHeapIter<CycleDetectorUMP> {
+    StacklessPreOrderHeapIter::<CycleDetectorUMP>::new(heap, start)
 }
 
+
 #[inline(always)]
 pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>(
     heap: &'a mut Vec<HeapCellValue>,
@@ -663,9 +670,9 @@ pub(crate) type RightistPostOrderHeapIter<'a> =
 #[inline]
 pub(crate) fn stackless_post_order_iter<'a>(
     heap: &'a mut Heap,
-    cell: HeapCellValue,
+    start: usize,
 ) -> RightistPostOrderHeapIter<'a> {
-    PostOrderIterator::new(stackless_preorder_iter(heap, cell))
+    PostOrderIterator::new(stackless_preorder_iter(heap, start))
 }
 
 #[cfg(test)]
@@ -685,8 +692,10 @@ mod tests {
             .heap
             .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
 
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -718,8 +727,10 @@ mod tests {
             ]
         ));
 
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         for _ in 0..20 {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 5);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -762,7 +773,7 @@ mod tests {
         ));
 
         for _ in 0..200000 {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -793,7 +804,7 @@ mod tests {
         {
             wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -814,7 +825,7 @@ mod tests {
         wam.machine_st.heap.push(empty_list_as_cell!());
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -849,7 +860,7 @@ mod tests {
         wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -883,8 +894,10 @@ mod tests {
             put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
         let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
             assert_eq!(
@@ -898,8 +911,7 @@ mod tests {
         assert_eq!(wam.machine_st.heap[0], pstr_cell);
         assert_eq!(wam.machine_st.heap[1], heap_loc_as_cell!(1));
 
-        wam.machine_st.heap.pop();
-        wam.machine_st.heap.push(pstr_loc_as_cell!(2));
+        wam.machine_st.heap[1] = pstr_loc_as_cell!(3);
 
         let pstr_second_var_cell =
             put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
@@ -907,36 +919,40 @@ mod tests {
         let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                heap_loc_as_cell!(3),
+                heap_loc_as_cell!(4),
             );
 
             assert!(iter.next().is_none());
         }
 
         assert_eq!(wam.machine_st.heap[0], pstr_cell);
-        assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(2));
-        assert_eq!(wam.machine_st.heap[2], pstr_second_cell);
-        assert_eq!(wam.machine_st.heap[3], heap_loc_as_cell!(3));
+        assert_eq!(wam.machine_st.heap[1], pstr_loc_as_cell!(3));
+        assert_eq!(wam.machine_st.heap[2], pstr_loc_as_cell!(0));
+        assert_eq!(wam.machine_st.heap[3], pstr_second_cell);
+        assert_eq!(wam.machine_st.heap[4], heap_loc_as_cell!(4));
 
         wam.machine_st.heap.pop();
-        wam.machine_st.heap.push(pstr_loc_as_cell!(4));
+        wam.machine_st.heap.push(pstr_loc_as_cell!(5));
         wam.machine_st.heap.push(pstr_offset_as_cell!(0));
         wam.machine_st
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(2)));
 
+        wam.machine_st.heap[2] = heap_loc_as_cell!(4);
+
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(4));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 2);
 
             let pstr_offset_cell = pstr_offset_as_cell!(0);
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), fixnum_as_cell!(Fixnum::build_with(2)));
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
 
@@ -946,19 +962,19 @@ mod tests {
         assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
+            pstr_loc_as_cell!(3)
         );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(4)
+            unmark_cell_bits!(wam.machine_st.heap[4]),
+            pstr_loc_as_cell!(5)
         );
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[4]),
+            unmark_cell_bits!(wam.machine_st.heap[5]),
             pstr_offset_as_cell!(0)
         );
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[5]),
+            unmark_cell_bits!(wam.machine_st.heap[6]),
             fixnum_as_cell!(Fixnum::build_with(2))
         );
 
@@ -974,31 +990,31 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(0i64)));
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 6);
             let pstr_offset_cell = pstr_offset_as_cell!(0);
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_loc_as_cell!(4));
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_offset_cell);
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), fixnum_as_cell!(Fixnum::build_with(0)));
 
             assert_eq!(iter.next(), None);
         }
 
         all_cells_unmarked(&wam.machine_st.heap);
 
-        wam.machine_st.heap.pop();
-        wam.machine_st
-            .heap
-            .push(fixnum_as_cell!(Fixnum::build_with(1i64)));
+        wam.machine_st.heap[5] = fixnum_as_cell!(Fixnum::build_with(1i64));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 6);
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_loc_as_cell!(4));
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1008,13 +1024,17 @@ mod tests {
                 unmark_cell_bits!(iter.next().unwrap()),
                 pstr_offset_as_cell!(0)
             );
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                fixnum_as_cell!(Fixnum::build_with(1))
+            );
 
             assert_eq!(iter.next(), None);
-
-            assert_eq!(iter.heap[4], pstr_offset_as_cell!(0));
-            assert_eq!(iter.heap[5], fixnum_as_cell!(Fixnum::build_with(1i64)));
         }
 
+        assert_eq!(wam.machine_st.heap[4], pstr_offset_as_cell!(0));
+        assert_eq!(wam.machine_st.heap[5], fixnum_as_cell!(Fixnum::build_with(1i64)));
+
         all_cells_unmarked(&wam.machine_st.heap);
 
         wam.machine_st.heap.clear();
@@ -1030,7 +1050,7 @@ mod tests {
         wam.machine_st.heap.extend(functor);
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1067,26 +1087,13 @@ mod tests {
                 atom_as_cell!(f_atom, 3)
             );
 
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(a_atom)
-            );
-
             assert_eq!(iter.next(), None);
         }
 
         all_cells_unmarked(&wam.machine_st.heap);
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1133,7 +1140,7 @@ mod tests {
         assert_eq!(wam.machine_st.heap[4], empty_list_as_cell!());
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1165,7 +1172,7 @@ mod tests {
         wam.machine_st.heap[4] = list_loc_as_cell!(1);
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1203,19 +1210,6 @@ mod tests {
                 atom_as_cell!(f_atom, 3)
             );
 
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(a_atom)
-            );
-
             assert_eq!(iter.next(), None);
         }
 
@@ -1227,12 +1221,12 @@ mod tests {
         wam.machine_st.heap.push(heap_loc_as_cell!(2));
         wam.machine_st.heap.push(heap_loc_as_cell!(3));
         wam.machine_st.heap.push(heap_loc_as_cell!(3));
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 4);
 
             assert_eq!(iter.next().unwrap(), heap_loc_as_cell!(3));
-
             assert_eq!(iter.next(), None);
         }
 
@@ -1263,7 +1257,7 @@ mod tests {
         wam.machine_st.heap.push(list_loc_as_cell!(1));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
             assert_eq!(
@@ -1272,9 +1266,6 @@ mod tests {
             );
 
             assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
-            // this is what happens! this next line! We would like it not to happen though.
-            assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
-
             assert_eq!(iter.next(), None);
         }
 
@@ -1310,9 +1301,10 @@ mod tests {
 
         wam.machine_st.heap.push(attr_var_as_cell!(11)); // linked from 7.
         wam.machine_st.heap.push(heap_loc_as_cell!(12));
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 13);
 
             assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
 
@@ -1351,6 +1343,7 @@ mod tests {
         let clpz_atom = atom!("clpz");
         let p_atom = atom!("p");
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
 
         wam.machine_st.heap.push(heap_loc_as_cell!(13)); // 12
@@ -1365,9 +1358,10 @@ mod tests {
         wam.machine_st.heap.push(empty_list_as_cell!()); // 21
         wam.machine_st.heap.push(atom_as_cell!(p_atom, 1)); // 22
         wam.machine_st.heap.push(heap_loc_as_cell!(23)); // 23
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 24);
 
             assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
 
@@ -1502,10 +1496,9 @@ mod tests {
         wam.machine_st.heap.clear();
 
         {
-            let mut iter = stackless_preorder_iter(
-                &mut wam.machine_st.heap,
-                fixnum_as_cell!(Fixnum::build_with(0)),
-            );
+            wam.machine_st.heap.push(fixnum_as_cell!(Fixnum::build_with(0)));
+
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1517,8 +1510,6 @@ mod tests {
 
         all_cells_unmarked(&wam.machine_st.heap);
 
-        assert_eq!(wam.machine_st.heap.len(), 0);
-
         wam.machine_st.heap.clear();
 
         wam.machine_st.heap.push(str_loc_as_cell!(1));
@@ -1528,7 +1519,7 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(1));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1540,7 +1531,7 @@ mod tests {
                 atom_as_cell!(atom!("y"))
             );
 
-            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(1));
+            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), heap_loc_as_cell!(0));
 
             assert!(iter.next().is_none());
         }
@@ -1552,9 +1543,10 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(atom!("g"), 2));
         wam.machine_st.heap.push(str_loc_as_cell!(0));
         wam.machine_st.heap.push(atom_as_cell!(atom!("y")));
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1587,7 +1579,7 @@ mod tests {
         wam.machine_st.heap.push(empty_list_as_cell!());
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(7));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 7);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1645,9 +1637,10 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(atom!("f"), 2));
         wam.machine_st.heap.push(heap_loc_as_cell!(1));
         wam.machine_st.heap.push(heap_loc_as_cell!(1));
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
 
         {
-            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+            let mut iter = stackless_preorder_iter(&mut wam.machine_st.heap, 3);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -1674,38 +1667,68 @@ mod tests {
         wam.machine_st.heap.clear();
 
         // representation of one of the heap terms as in issue #1384.
-        /*
-                wam.machine_st.heap.push(list_loc_as_cell!(7));
-                wam.machine_st.heap.push(heap_loc_as_cell!(0));
-                wam.machine_st.heap.push(list_loc_as_cell!(3));
-                wam.machine_st.heap.push(list_loc_as_cell!(5));
-                wam.machine_st.heap.push(empty_list_as_cell!());
-                wam.machine_st.heap.push(heap_loc_as_cell!(2));
-                wam.machine_st.heap.push(heap_loc_as_cell!(2));
-                wam.machine_st.heap.push(empty_list_as_cell!());
-                wam.machine_st.heap.push(heap_loc_as_cell!(3));
-
-                {
-                    let mut iter = stackless_preorder_iter(
-                        &mut wam.machine_st.heap,
-                        heap_loc_as_cell!(0),
-                    );
+        wam.machine_st.heap.push(list_loc_as_cell!(7)); // 0
+        wam.machine_st.heap.push(heap_loc_as_cell!(0)); // 1
+        wam.machine_st.heap.push(list_loc_as_cell!(3)); // 2
+        wam.machine_st.heap.push(list_loc_as_cell!(5)); // 3
+        wam.machine_st.heap.push(empty_list_as_cell!()); // 4
+        wam.machine_st.heap.push(heap_loc_as_cell!(2)); // 5
+        wam.machine_st.heap.push(heap_loc_as_cell!(2)); // 6
+        wam.machine_st.heap.push(empty_list_as_cell!()); // 7
+        wam.machine_st.heap.push(heap_loc_as_cell!(3)); // 8
 
-                    while let Some(_) = iter.next() {
-                        print_heap_terms(iter.heap.iter(), 0);
-                        println!("");
-                    }
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-                    /*
-                    assert_eq!(
-                        unmark_cell_bits!(iter.next().unwrap()),
-                        atom_as_cell!(atom!("f"), 2)
-                    );
+        {
+            let mut iter = stackless_preorder_iter(
+                &mut wam.machine_st.heap,
+                9,
+            );
 
-                    assert!(iter.next().is_none());
-                    */
-                }
-        */
+            /*
+            while let Some(_) = iter.next() {
+                print_heap_terms(iter.heap.iter(), 0);
+                println!("");
+            }
+            */
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                list_loc_as_cell!(7)
+            );
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                list_loc_as_cell!(5)
+            );
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                heap_loc_as_cell!(2)
+            );
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                list_loc_as_cell!(3)
+            );
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                empty_list_as_cell!()
+            );
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                heap_loc_as_cell!(2)
+            );
+
+            assert_eq!(
+                unmark_cell_bits!(iter.next().unwrap()),
+                empty_list_as_cell!()
+            );
+
+            assert_eq!(iter.next(), None);
+        }
     }
 
     #[test]
@@ -2797,8 +2820,10 @@ mod tests {
             .heap
             .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
 
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         {
-            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 3);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -2828,8 +2853,10 @@ mod tests {
             ]
         ));
 
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
+
         for _ in 0..20 {
-            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 5);
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), str_loc_as_cell!(0));
 
@@ -2860,7 +2887,7 @@ mod tests {
             wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
             let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+                stackless_post_order_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -2876,8 +2903,7 @@ mod tests {
             wam.machine_st.heap.push(heap_loc_as_cell!(1));
             wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-            let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -2903,7 +2929,7 @@ mod tests {
 
         {
             let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+                stackless_post_order_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -2936,7 +2962,7 @@ mod tests {
 
         {
             let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+                stackless_post_order_iter(&mut wam.machine_st.heap, 0);
 
             // the cycle will be iterated twice before being detected.
             assert_eq!(
@@ -2965,7 +2991,7 @@ mod tests {
 
         {
             let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+                stackless_post_order_iter(&mut wam.machine_st.heap, 0);
 
             // cut the iteration short to check that all cells are
             // unmarked and unforwarded by the Drop instance of
@@ -2999,9 +3025,11 @@ mod tests {
             put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
         let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
         {
             let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+                stackless_post_order_iter(&mut wam.machine_st.heap, 2);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -3013,6 +3041,7 @@ mod tests {
             assert_eq!(iter.next(), None);
         }
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
         wam.machine_st.heap.push(pstr_loc_as_cell!(2));
 
@@ -3021,9 +3050,10 @@ mod tests {
 
         let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
         {
-            let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 4);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -3048,9 +3078,10 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(0)));
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
         {
-            let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 7);
             let mut pstr_loc_cell = pstr_loc_as_cell!(0);
 
             pstr_loc_cell.set_forwarding_bit(true);
@@ -3058,11 +3089,7 @@ mod tests {
             // assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(0i64)));
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                pstr_offset_as_cell!(0)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                pstr_offset_as_cell!(0)
+                heap_loc_as_cell!(3)
             );
 
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
@@ -3073,28 +3100,27 @@ mod tests {
 
         all_cells_unmarked(&wam.machine_st.heap);
 
+        wam.machine_st.heap.pop();
         wam.machine_st.heap.pop();
         wam.machine_st
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(1)));
 
+        wam.machine_st.heap.push(pstr_loc_as_cell!(0));
+
         {
-            let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 7);
 
             //assert_eq!(iter.next().unwrap(), fixnum_as_cell!(Fixnum::build_with(1)));
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                pstr_offset_as_cell!(0)
+                heap_loc_as_cell!(3)
             );
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                pstr_offset_as_cell!(0)
+                pstr_second_cell
             );
-
-            assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_second_cell);
             assert_eq!(unmark_cell_bits!(iter.next().unwrap()), pstr_cell);
-
             assert_eq!(iter.next(), None);
         }
 
@@ -3110,9 +3136,10 @@ mod tests {
 
         wam.machine_st.heap.extend(functor);
 
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
+
         {
-            let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 9);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -3142,18 +3169,6 @@ mod tests {
                 list_loc_as_cell!(3)
             );
 
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(a_atom)
-            );
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
                 atom_as_cell!(f_atom, 3)
@@ -3172,8 +3187,7 @@ mod tests {
         wam.machine_st.heap[4] = list_loc_as_cell!(1);
 
         {
-            let mut iter =
-                stackless_post_order_iter(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+            let mut iter = stackless_post_order_iter(&mut wam.machine_st.heap, 0);
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
@@ -3195,24 +3209,14 @@ mod tests {
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(b_atom)
-            );
-            assert_eq!(
-                unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(a_atom)
+                atom_as_cell!(f_atom, 3)
             );
 
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
-                atom_as_cell!(f_atom, 3)
+                list_loc_as_cell!(1)
             );
 
-            assert_eq!(iter.next().unwrap(), list_loc_as_cell!(1));
-
             assert_eq!(
                 unmark_cell_bits!(iter.next().unwrap()),
                 list_loc_as_cell!(3)
index 5b4895bd8e3405474f27fad334052ef7bff8ea46..0d37dfec7e446bf4cadca56c39c7657481930edd 100644 (file)
@@ -5,44 +5,94 @@ use crate::types::*;
 #[cfg(test)]
 use crate::heap_iter::{FocusedHeapIter, HeapOrStackTag, IterStackLoc};
 
-use core::marker::PhantomData;
-
 pub(crate) trait UnmarkPolicy {
-    fn unmark(heap: &mut [HeapCellValue], current: usize);
-    fn mark(heap: &mut [HeapCellValue], current: usize);
     fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue>
     where
         Self: Sized;
+    fn invert_marker(iter: &mut StacklessPreOrderHeapIter<Self>) where Self: Sized;
+    fn cycle_detected(&mut self) where Self: Sized;
+    fn mark_phase(&self) -> bool;
+    fn report_list(&mut self, list_loc: usize);
+}
+
+pub(crate) struct IteratorUMP {
+    mark_phase: bool,
 }
 
-pub(crate) struct IteratorUMP;
+fn invert_marker<UMP: UnmarkPolicy>(iter: &mut StacklessPreOrderHeapIter<UMP>) {
+    if iter.heap[iter.start].get_forwarding_bit() {
+        while !iter.backward() {}
+    }
+
+    iter.heap[iter.start].set_forwarding_bit(true);
+
+    iter.next = iter.heap[iter.start].get_value();
+    iter.current = iter.start;
+
+    while let Some(_) = iter.forward() {}
+}
 
 impl UnmarkPolicy for IteratorUMP {
     #[inline(always)]
-    fn unmark(heap: &mut [HeapCellValue], current: usize) {
-        heap[current].set_mark_bit(false);
+    fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
+        iter.forward_var()
+    }
+
+    #[inline]
+    fn invert_marker(iter: &mut StacklessPreOrderHeapIter<Self>) {
+        iter.iter_state.mark_phase = false;
+        invert_marker(iter);
     }
 
     #[inline(always)]
-    fn mark(_heap: &mut [HeapCellValue], _current: usize) {}
+    fn cycle_detected(&mut self) {}
+
+    #[inline]
+    fn mark_phase(&self) -> bool {
+        self.mark_phase
+    }
 
+    #[inline(always)]
+    fn report_list(&mut self, _list_loc: usize) {}
+}
+
+pub(crate) struct CycleDetectorUMP {
+    mark_phase: bool,
+    cycle_detected: bool,
+    list_locs: Vec<usize>,
+}
+
+impl UnmarkPolicy for CycleDetectorUMP {
     #[inline(always)]
     fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
         iter.forward_var()
     }
-}
 
-struct MarkerUMP {}
+    #[inline]
+    fn invert_marker(iter: &mut StacklessPreOrderHeapIter<Self>) {
+        iter.iter_state.mark_phase = false;
+        invert_marker(iter);
+    }
 
-impl UnmarkPolicy for MarkerUMP {
-    #[inline(always)]
-    fn unmark(_heap: &mut [HeapCellValue], _current: usize) {}
+    #[inline]
+    fn cycle_detected(&mut self) {
+        self.cycle_detected = true;
+    }
 
     #[inline(always)]
-    fn mark(heap: &mut [HeapCellValue], current: usize) {
-        heap[current].set_mark_bit(true);
+    fn mark_phase(&self) -> bool {
+        self.mark_phase
+    }
+
+    #[inline]
+    fn report_list(&mut self, list_loc: usize) {
+        self.list_locs.push(list_loc);
     }
+}
 
+struct MarkerUMP {}
+
+impl UnmarkPolicy for MarkerUMP {
     #[inline(always)]
     fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter<Self>) -> Option<HeapCellValue> {
         if iter.heap[iter.current + 1].get_forwarding_bit() {
@@ -60,16 +110,28 @@ impl UnmarkPolicy for MarkerUMP {
         iter.heap[iter.current].set_forwarding_bit(true); // forward the attr vars list.
         None
     }
+
+    fn invert_marker(_iter: &mut StacklessPreOrderHeapIter<Self>) {}
+
+    #[inline(always)]
+    fn mark_phase(&self) -> bool {
+        true
+    }
+
+    #[inline(always)]
+    fn cycle_detected(&mut self) {}
+
+    #[inline(always)]
+    fn report_list(&mut self, _list_loc: usize) {}
 }
 
 #[derive(Debug)]
 pub(crate) struct StacklessPreOrderHeapIter<'a, UMP: UnmarkPolicy> {
-    pub(crate) heap: &'a mut Vec<HeapCellValue>,
-    orig_heap_len: usize,
+    pub(crate) heap: &'a mut [HeapCellValue],
     start: usize,
     current: usize,
     next: u64,
-    _marker: PhantomData<UMP>,
+    iter_state: UMP,
 }
 
 #[cfg(test)]
@@ -82,79 +144,96 @@ impl<'a> FocusedHeapIter for StacklessPreOrderHeapIter<'a, IteratorUMP> {
 
 impl<'a, UMP: UnmarkPolicy> Drop for StacklessPreOrderHeapIter<'a, UMP> {
     fn drop(&mut self) {
+        UMP::invert_marker(self);
+
         if self.current == self.start {
-            self.heap.truncate(self.orig_heap_len);
             return;
         }
 
         while !self.backward() {}
-
-        self.heap.truncate(self.orig_heap_len);
     }
 }
 
 impl<'a> StacklessPreOrderHeapIter<'a, MarkerUMP> {
-    pub(crate) fn new(heap: &'a mut Vec<HeapCellValue>, cell: HeapCellValue) -> Self {
-        let orig_heap_len = heap.len();
-        let start = orig_heap_len;
+    pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
+        heap[start].set_forwarding_bit(true);
+        let next = heap[start].get_value();
 
-        heap.push(cell);
+        Self {
+            heap,
+            start,
+            current: start,
+            next,
+            iter_state: MarkerUMP {},
+        }
+    }
+}
 
+impl<'a> StacklessPreOrderHeapIter<'a, CycleDetectorUMP> {
+    pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
         heap[start].set_forwarding_bit(true);
         let next = heap[start].get_value();
 
         Self {
             heap,
-            orig_heap_len,
             start,
             current: start,
             next,
-            _marker: PhantomData,
+            iter_state: CycleDetectorUMP {
+                mark_phase: true,
+                cycle_detected: false,
+                list_locs: vec![],
+            },
         }
     }
-}
 
-impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> {
-    #[cfg(test)]
-    pub(crate) fn new(heap: &'a mut Vec<HeapCellValue>, cell: HeapCellValue) -> Self {
-        let orig_heap_len = heap.len();
-        let start = orig_heap_len + 1;
+    #[inline]
+    pub(crate) fn found_cycle(&self) -> bool {
+        self.iter_state.cycle_detected
+    }
 
-        heap.push(cell);
-        heap.push(heap_loc_as_cell!(orig_heap_len));
+    #[inline]
+    pub(crate) fn list_locs(mut self) -> Vec<usize> {
+        std::mem::replace(&mut self.iter_state.list_locs, vec![])
+    }
+}
 
+impl<'a> StacklessPreOrderHeapIter<'a, IteratorUMP> {
+    pub(crate) fn new(heap: &'a mut [HeapCellValue], start: usize) -> Self {
         heap[start].set_forwarding_bit(true);
         let next = heap[start].get_value();
 
         Self {
             heap,
-            orig_heap_len,
             start,
             current: start,
             next,
-            _marker: PhantomData,
+            iter_state: IteratorUMP {
+                mark_phase: true,
+            },
         }
     }
 }
 
 impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
-    fn backward_and_return(&mut self) -> Option<HeapCellValue> {
-        let current = self.current;
+    fn backward_and_return(&mut self) -> HeapCellValue {
+        let mut current = self.heap[self.current];
+        current.set_value(self.next);
 
         if self.backward() {
             // set the f and m bits on the heap cell at start
             // so we invoke backward() and return None next call.
 
             self.heap[self.current].set_forwarding_bit(true);
-            self.heap[self.current].set_mark_bit(true);
+            self.heap[self.current].set_mark_bit(self.iter_state.mark_phase());
         }
 
-        Some(self.heap[current])
+        current
     }
 
     fn forward_var(&mut self) -> Option<HeapCellValue> {
         if self.heap[self.next as usize].get_forwarding_bit() {
-            return self.backward_and_return();
+            return Some(self.backward_and_return());
         }
 
         let temp = self.heap[self.next as usize].get_value();
@@ -168,31 +247,38 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
 
     fn forward(&mut self) -> Option<HeapCellValue> {
         loop {
-            if !self.heap[self.current].get_mark_bit() {
-                self.heap[self.current].set_mark_bit(true);
+            if self.heap[self.current].get_mark_bit() != self.iter_state.mark_phase() {
+                self.heap[self.current].set_mark_bit(self.iter_state.mark_phase());
 
                 match self.heap[self.current].get_tag() {
                     HeapCellValueTag::AttrVar => {
+                        let next = self.next;
+
                         if let Some(cell) = UMP::forward_attr_var(self) {
                             return Some(cell);
                         }
 
-                        if self.heap[self.next as usize].get_mark_bit() {
-                            return Some(attr_var_as_cell!(self.current));
+                        if self.heap[self.next as usize].get_mark_bit() == self.iter_state.mark_phase() {
+                            let tag = HeapCellValueTag::AttrVar;
+                            return Some(HeapCellValue::build_with(tag, next));
                         }
                     }
                     HeapCellValueTag::Var => {
+                        let next = self.next;
+
                         if let Some(cell) = self.forward_var() {
                             return Some(cell);
                         }
 
-                        if self.heap[self.next as usize].get_mark_bit() {
-                            return Some(heap_loc_as_cell!(self.current));
+                        if self.heap[self.next as usize].get_mark_bit() == self.iter_state.mark_phase() {
+                            let tag = HeapCellValueTag::Var;
+                            return Some(HeapCellValue::build_with(tag, next));
                         }
                     }
                     HeapCellValueTag::Str => {
                         if self.heap[self.next as usize + 1].get_forwarding_bit() {
-                            return self.backward_and_return();
+                            self.iter_state.cycle_detected();
+                            return Some(self.backward_and_return());
                         }
 
                         let h = self.next as usize;
@@ -216,43 +302,40 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
                         let last_cell_loc = self.next as usize + 1;
 
                         if self.heap[last_cell_loc].get_forwarding_bit() {
-                            return self.backward_and_return();
+                            self.iter_state.cycle_detected();
+                            return Some(self.backward_and_return());
                         }
 
-                        self.heap[last_cell_loc].set_forwarding_bit(true);
-
                         self.next = self.heap[last_cell_loc].get_value();
                         self.heap[last_cell_loc].set_value(self.current as u64);
                         self.current = last_cell_loc;
 
+                        self.heap[last_cell_loc].set_forwarding_bit(true);
+
+                        if self.heap[last_cell_loc].get_mark_bit() == self.iter_state.mark_phase() {
+                            if self.heap[last_cell_loc-1].get_mark_bit() == self.iter_state.mark_phase() {
+                                self.iter_state.report_list(last_cell_loc - 1);
+                            }
+                        }
+
                         return Some(list_loc_as_cell!(last_cell_loc - 1));
                     }
                     HeapCellValueTag::PStrLoc => {
                         let h = self.next as usize;
-                        let cell = self.heap[h];
 
                         if self.heap[h + 1].get_forwarding_bit() {
-                            return self.backward_and_return();
+                            self.iter_state.cycle_detected();
+                            return Some(self.backward_and_return());
                         }
 
-                        if self.heap[h].get_tag() == HeapCellValueTag::PStr {
-                            let last_cell_loc = h + 1;
-                            self.heap[last_cell_loc].set_forwarding_bit(true);
-
-                            self.next = self.heap[last_cell_loc].get_value();
-                            self.heap[last_cell_loc].set_value(self.current as u64);
-                            self.current = last_cell_loc;
-                        } else {
-                            debug_assert!(self.heap[h].get_tag() == HeapCellValueTag::PStrOffset);
+                        let cell = self.heap[h];
 
-                            self.next = self.heap[h].get_value();
-                            self.heap[h].set_value(self.current as u64);
-                            self.current = h;
+                        let last_cell_loc = h + 1;
+                        self.heap[last_cell_loc].set_forwarding_bit(true);
 
-                            if self.heap[h].get_mark_bit() {
-                                continue;
-                            }
-                        }
+                        self.next = self.heap[last_cell_loc].get_value();
+                        self.heap[last_cell_loc].set_value(self.current as u64);
+                        self.current = last_cell_loc;
 
                         return Some(cell);
                     }
@@ -260,13 +343,11 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
                         let h = self.next as usize;
                         let cell = self.heap[h];
 
-                        // mark the Fixnum offset.
-                        UMP::mark(self.heap, self.current + 1);
-
                         let last_cell_loc = h + 1;
 
                         if self.heap[last_cell_loc].get_forwarding_bit() {
-                            return self.backward_and_return();
+                            self.iter_state.cycle_detected();
+                            return Some(self.backward_and_return());
                         }
 
                         if self.heap[h].get_tag() == HeapCellValueTag::PStr {
@@ -290,7 +371,7 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
                         let arity = AtomCell::from_bytes(cell.into_bytes()).get_arity();
 
                         if arity == 0 {
-                            return self.backward_and_return();
+                            return Some(self.backward_and_return());
                         } else if self.backward() {
                             return None;
                         }
@@ -301,7 +382,7 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
                         }
                     }
                     _ => {
-                        return self.backward_and_return();
+                        return Some(self.backward_and_return());
                     }
                 }
             } else {
@@ -316,15 +397,13 @@ impl<'a, UMP: UnmarkPolicy> StacklessPreOrderHeapIter<'a, UMP> {
         while !self.heap[self.current].get_forwarding_bit() {
             let temp = self.heap[self.current].get_value();
 
-            UMP::unmark(self.heap, self.current);
-
             self.heap[self.current].set_value(self.next);
+
             self.next = self.current as u64;
             self.current = temp as usize;
         }
 
         self.heap[self.current].set_forwarding_bit(false);
-        UMP::unmark(self.heap, self.current);
 
         if self.current == self.start {
             return true;
@@ -351,8 +430,8 @@ impl<'a, UMP: UnmarkPolicy> Iterator for StacklessPreOrderHeapIter<'a, UMP> {
     }
 }
 
-pub fn mark_cells(heap: &mut Heap, cell: HeapCellValue) {
-    let mut iter = StacklessPreOrderHeapIter::<MarkerUMP>::new(heap, cell);
+pub fn mark_cells(heap: &mut Heap, start: usize) {
+    let mut iter = StacklessPreOrderHeapIter::<MarkerUMP>::new(heap, start);
     while let Some(_) = iter.forward() {}
 }
 
@@ -369,62 +448,76 @@ mod tests {
         let a_atom = atom!("a");
         let b_atom = atom!("b");
 
+        wam.machine_st.heap.push(str_loc_as_cell!(1));
+
         wam.machine_st
             .heap
             .extend(functor!(f_atom, [atom(a_atom), atom(b_atom)]));
 
-        mark_cells(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[0]),
-            atom_as_cell!(f_atom, 2)
+            str_loc_as_cell!(1)
         );
+
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[1]),
-            atom_as_cell!(a_atom)
+            atom_as_cell!(f_atom, 2)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[2]),
+            atom_as_cell!(a_atom)
+        );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[3]),
             atom_as_cell!(b_atom)
         );
 
         wam.machine_st.heap.clear();
 
+        wam.machine_st.heap.push(str_loc_as_cell!(1));
+
         wam.machine_st.heap.extend(functor!(
             f_atom,
             [
                 atom(a_atom),
                 atom(b_atom),
                 atom(a_atom),
-                cell(str_loc_as_cell!(0))
+                cell(str_loc_as_cell!(1))
             ]
         ));
 
-        mark_cells(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[0]),
-            atom_as_cell!(f_atom, 4)
+            str_loc_as_cell!(1)
         );
+
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[1]),
-            atom_as_cell!(a_atom)
+            atom_as_cell!(f_atom, 4)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[2]),
-            atom_as_cell!(b_atom)
+            atom_as_cell!(a_atom)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[3]),
-            atom_as_cell!(a_atom)
+            atom_as_cell!(b_atom)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[4]),
-            str_loc_as_cell!(0)
+            atom_as_cell!(a_atom)
+        );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[5]),
+            str_loc_as_cell!(1)
         );
 
         for cell in &mut wam.machine_st.heap {
@@ -432,9 +525,9 @@ mod tests {
         }
 
         // make the structure doubly cyclic.
-        wam.machine_st.heap[2] = str_loc_as_cell!(0);
+        wam.machine_st.heap[2] = str_loc_as_cell!(1);
 
-        mark_cells(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -452,7 +545,7 @@ mod tests {
             ]
         ));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -485,7 +578,7 @@ mod tests {
 
         wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -503,7 +596,7 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(b_atom));
         wam.machine_st.heap.push(empty_list_as_cell!());
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -537,7 +630,7 @@ mod tests {
         // now make the list cyclic.
         wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -569,7 +662,7 @@ mod tests {
         // make the list doubly cyclic.
         wam.machine_st.heap[3] = heap_loc_as_cell!(0);
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -586,7 +679,7 @@ mod tests {
         wam.machine_st.heap.push(stream_cell);
         wam.machine_st.heap.push(empty_list_as_cell!());
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -617,7 +710,7 @@ mod tests {
         wam.machine_st.heap.push(heap_loc_as_cell!(3));
         wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -644,18 +737,20 @@ mod tests {
         // two-part complete string, then a three-part cyclic string
         // involving an uncompacted list of chars.
 
-        let pstr_var_cell =
-            put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
+        wam.machine_st.heap.push(pstr_loc_as_cell!(1));
+
+        let pstr_var_cell = put_partial_string(&mut wam.machine_st.heap, "abc ", &wam.machine_st.atom_tbl);
         let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_loc_as_cell!(1));
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            heap_loc_as_cell!(1)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            heap_loc_as_cell!(2)
         );
 
         wam.machine_st.heap.pop();
@@ -664,25 +759,25 @@ mod tests {
             cell.set_mark_bit(false);
         }
 
-        wam.machine_st.heap.push(pstr_loc_as_cell!(2));
+        wam.machine_st.heap.push(pstr_loc_as_cell!(3));
 
         let pstr_second_var_cell =
             put_partial_string(&mut wam.machine_st.heap, "def", &wam.machine_st.atom_tbl);
         let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize];
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            pstr_loc_as_cell!(3)
         );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            heap_loc_as_cell!(3)
+            unmark_cell_bits!(wam.machine_st.heap[4]),
+            heap_loc_as_cell!(4)
         );
 
         for cell in &mut wam.machine_st.heap {
@@ -690,142 +785,138 @@ mod tests {
         }
 
         wam.machine_st.heap.pop();
-        wam.machine_st.heap.push(pstr_loc_as_cell!(4));
-        wam.machine_st.heap.push(pstr_offset_as_cell!(0));
+        wam.machine_st.heap.push(pstr_loc_as_cell!(5));
+        wam.machine_st.heap.push(pstr_offset_as_cell!(1));
         wam.machine_st
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(2)));
+        wam.machine_st.heap.push(pstr_loc_as_cell!(5));
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(4));
+        mark_cells(&mut wam.machine_st.heap, 7);
 
-        all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+        all_cells_marked_and_unforwarded(&wam.machine_st.heap[1 ..]);
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
-        );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(4)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            pstr_loc_as_cell!(3)
         );
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[4]),
-            pstr_offset_as_cell!(0)
+            pstr_loc_as_cell!(5)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[5]),
-            fixnum_as_cell!(Fixnum::build_with(2))
-        );
-
-        for cell in &mut wam.machine_st.heap {
-            cell.set_mark_bit(false);
-        }
-
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(3));
-
-        all_cells_marked_and_unforwarded(&wam.machine_st.heap);
-
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
-        );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(4)
+            pstr_offset_as_cell!(1)
         );
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[4]),
-            pstr_offset_as_cell!(0)
+            unmark_cell_bits!(wam.machine_st.heap[6]),
+            fixnum_as_cell!(Fixnum::build_with(2))
         );
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[5]),
-            fixnum_as_cell!(Fixnum::build_with(2))
+            unmark_cell_bits!(wam.machine_st.heap[7]),
+            pstr_loc_as_cell!(5)
         );
 
         for cell in &mut wam.machine_st.heap {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(2));
+        wam.machine_st.heap[7] = heap_loc_as_cell!(2);
 
-        all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+        mark_cells(&mut wam.machine_st.heap, 7);
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
-        );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(4)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            pstr_loc_as_cell!(3)
         );
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[4]),
-            pstr_offset_as_cell!(0)
+            pstr_loc_as_cell!(5)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[5]),
+            pstr_offset_as_cell!(1)
+        );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[6]),
             fixnum_as_cell!(Fixnum::build_with(2))
         );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[7]),
+            heap_loc_as_cell!(2)
+        );
 
         for cell in &mut wam.machine_st.heap {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(1));
+        wam.machine_st.heap[7] = pstr_loc_as_cell!(1);
 
-        all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+        mark_cells(&mut wam.machine_st.heap, 7);
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
-        );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(4)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            pstr_loc_as_cell!(3)
         );
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[4]),
-            pstr_offset_as_cell!(0)
+            pstr_loc_as_cell!(5)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[5]),
+            pstr_offset_as_cell!(1)
+        );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[6]),
             fixnum_as_cell!(Fixnum::build_with(2))
         );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[7]),
+            pstr_loc_as_cell!(1)
+        );
 
         for cell in &mut wam.machine_st.heap {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(0));
+        wam.machine_st.heap[7] = heap_loc_as_cell!(0);
 
-        all_cells_marked_and_unforwarded(&wam.machine_st.heap);
+        mark_cells(&mut wam.machine_st.heap, 7);
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
-        );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        all_cells_marked_and_unforwarded(&wam.machine_st.heap[1..]);
+
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(4)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            pstr_loc_as_cell!(3)
         );
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[4]),
-            pstr_offset_as_cell!(0)
+            pstr_loc_as_cell!(5)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[5]),
+            pstr_offset_as_cell!(1)
+        );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[6]),
             fixnum_as_cell!(Fixnum::build_with(2))
         );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[7]),
+            heap_loc_as_cell!(0)
+        );
 
         wam.machine_st.heap.truncate(4);
 
@@ -836,45 +927,46 @@ mod tests {
         wam.machine_st
             .heap
             .push(atom_as_cell!(atom!("irrelevant stuff")));
-        wam.machine_st.heap.push(pstr_offset_as_cell!(0));
+        wam.machine_st.heap.push(pstr_offset_as_cell!(1));
         wam.machine_st
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(2)));
 
-        wam.machine_st.heap[3] = pstr_loc_as_cell!(5);
+        // this is at index 7
+        wam.machine_st.heap.push(pstr_loc_as_cell!(5));
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(5));
+        mark_cells(&mut wam.machine_st.heap, 7);
 
-        assert!(wam.machine_st.heap[0].get_mark_bit());
+        assert!(!wam.machine_st.heap[0].get_mark_bit());
         assert!(wam.machine_st.heap[1].get_mark_bit());
         assert!(wam.machine_st.heap[2].get_mark_bit());
         assert!(wam.machine_st.heap[3].get_mark_bit());
-        assert!(!wam.machine_st.heap[4].get_mark_bit());
+        assert!(wam.machine_st.heap[4].get_mark_bit());
         assert!(wam.machine_st.heap[5].get_mark_bit());
         assert!(wam.machine_st.heap[6].get_mark_bit());
 
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[0]), pstr_cell);
-        assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[1]),
-            pstr_loc_as_cell!(2)
-        );
-        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[2]), pstr_second_cell);
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[1]), pstr_cell);
         assert_eq!(
-            unmark_cell_bits!(wam.machine_st.heap[3]),
-            pstr_loc_as_cell!(5)
+            unmark_cell_bits!(wam.machine_st.heap[2]),
+            pstr_loc_as_cell!(3)
         );
+        assert_eq!(unmark_cell_bits!(wam.machine_st.heap[3]), pstr_second_cell);
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[4]),
             atom_as_cell!(atom!("irrelevant stuff"))
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[5]),
-            pstr_offset_as_cell!(0)
+            pstr_offset_as_cell!(1)
         );
         assert_eq!(
             unmark_cell_bits!(wam.machine_st.heap[6]),
             fixnum_as_cell!(Fixnum::build_with(2))
         );
+        assert_eq!(
+            unmark_cell_bits!(wam.machine_st.heap[7]),
+            pstr_loc_as_cell!(5)
+        );
 
         wam.machine_st.heap.clear();
 
@@ -896,7 +988,9 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(2)));
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(7));
+        wam.machine_st.heap.push(pstr_loc_as_cell!(7));
+
+        mark_cells(&mut wam.machine_st.heap, 9);
 
         assert!(!wam.machine_st.heap[0].get_mark_bit());
         assert!(wam.machine_st.heap[1].get_mark_bit());
@@ -943,7 +1037,9 @@ mod tests {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(5));
+        wam.machine_st.heap[9] = heap_loc_as_cell!(5);
+
+        mark_cells(&mut wam.machine_st.heap, 9);
 
         assert!(!wam.machine_st.heap[0].get_mark_bit());
         assert!(wam.machine_st.heap[1].get_mark_bit());
@@ -994,7 +1090,9 @@ mod tests {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(4));
+        wam.machine_st.heap[9] = pstr_loc_as_cell!(4);
+
+        mark_cells(&mut wam.machine_st.heap, 9);
 
         assert!(!wam.machine_st.heap[0].get_mark_bit());
         assert!(wam.machine_st.heap[1].get_mark_bit());
@@ -1045,7 +1143,9 @@ mod tests {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(2));
+        mark_cells(&mut wam.machine_st.heap, 9);
+
+        wam.machine_st.heap[9] = heap_loc_as_cell!(2);
 
         assert!(!wam.machine_st.heap[0].get_mark_bit());
         assert!(wam.machine_st.heap[1].get_mark_bit());
@@ -1096,7 +1196,9 @@ mod tests {
             cell.set_mark_bit(false);
         }
 
-        mark_cells(&mut wam.machine_st.heap, pstr_loc_as_cell!(1));
+        wam.machine_st.heap[9] = pstr_loc_as_cell!(1);
+
+        mark_cells(&mut wam.machine_st.heap, 9);
 
         assert!(!wam.machine_st.heap[0].get_mark_bit());
         assert!(wam.machine_st.heap[1].get_mark_bit());
@@ -1161,7 +1263,7 @@ mod tests {
         wam.machine_st.heap.push(pstr_loc_as_cell!(0));
         wam.machine_st.heap.push(empty_list_as_cell!());
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(4));
+        mark_cells(&mut wam.machine_st.heap, 4);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1207,7 +1309,7 @@ mod tests {
         wam.machine_st.heap.push(pstr_loc_as_cell!(0));
         wam.machine_st.heap.push(heap_loc_as_cell!(4));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(4));
+        mark_cells(&mut wam.machine_st.heap, 4);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1250,7 +1352,7 @@ mod tests {
         wam.machine_st.heap.push(heap_loc_as_cell!(3));
         wam.machine_st.heap.push(heap_loc_as_cell!(3));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1278,7 +1380,7 @@ mod tests {
         wam.machine_st.heap.push(list_loc_as_cell!(1));
         wam.machine_st.heap.push(list_loc_as_cell!(1));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1313,7 +1415,7 @@ mod tests {
         wam.machine_st.heap.push(attr_var_as_cell!(11)); // linked from 7.
         wam.machine_st.heap.push(heap_loc_as_cell!(12));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1394,7 +1496,7 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(p_atom, 1)); // 22
         wam.machine_st.heap.push(heap_loc_as_cell!(23)); // 23
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1506,7 +1608,7 @@ mod tests {
         wam.machine_st.heap.push(heap_loc_as_cell!(5));
         wam.machine_st.heap.push(list_loc_as_cell!(5));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&mut wam.machine_st.heap[0..24]);
 
@@ -1628,7 +1730,7 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(0)));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         assert_eq!(wam.machine_st.heap.len(), 1);
 
@@ -1647,7 +1749,7 @@ mod tests {
         wam.machine_st.heap.push(str_loc_as_cell!(4));
         wam.machine_st.heap.push(empty_list_as_cell!());
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(7));
+        mark_cells(&mut wam.machine_st.heap, 7);
 
         assert_eq!(wam.machine_st.heap.len(), 10);
 
@@ -1699,8 +1801,9 @@ mod tests {
         wam.machine_st.heap.push(atom_as_cell!(atom!("f"), 2));
         wam.machine_st.heap.push(heap_loc_as_cell!(1));
         wam.machine_st.heap.push(heap_loc_as_cell!(1));
+        wam.machine_st.heap.push(str_loc_as_cell!(0));
 
-        mark_cells(&mut wam.machine_st.heap, str_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 3);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1729,7 +1832,9 @@ mod tests {
         wam.machine_st.heap.push(empty_list_as_cell!());
         wam.machine_st.heap.push(heap_loc_as_cell!(2));
 
-        mark_cells(&mut wam.machine_st.heap, list_loc_as_cell!(5));
+        wam.machine_st.heap.push(list_loc_as_cell!(5));
+
+        mark_cells(&mut wam.machine_st.heap, 7);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
@@ -1775,8 +1880,9 @@ mod tests {
         wam.machine_st.heap.push(heap_loc_as_cell!(2));
         wam.machine_st.heap.push(empty_list_as_cell!()); // C = [[]|B].
         wam.machine_st.heap.push(heap_loc_as_cell!(3));
+        wam.machine_st.heap.push(heap_loc_as_cell!(0));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 9);
 
         assert!(wam.machine_st.heap[0].get_mark_bit());
         assert!(!wam.machine_st.heap[1].get_mark_bit());
@@ -1841,7 +1947,7 @@ mod tests {
             .heap
             .push(fixnum_as_cell!(Fixnum::build_with(4)));
 
-        mark_cells(&mut wam.machine_st.heap, heap_loc_as_cell!(0));
+        mark_cells(&mut wam.machine_st.heap, 0);
 
         all_cells_marked_and_unforwarded(&wam.machine_st.heap);
 
index cf2159ba0e3de5183a5669f569a3d7fec3cca61b..043bd221b7ecec787316381d7c30a8aff52b59ba 100644 (file)
@@ -430,6 +430,7 @@ impl HeapCellValue {
             HeapCellValueTag::Cons
             | HeapCellValueTag::F64
             | HeapCellValueTag::Fixnum
+            | HeapCellValueTag::CutPoint
             | HeapCellValueTag::Char
             | HeapCellValueTag::CStr => true,
             HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0,