From: Mark Date: Thu, 12 Oct 2023 17:22:57 +0000 (-0600) Subject: fix bugs in marker algorithm iterator X-Git-Tag: remove~31 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=8aadc99f1d06f500603b318f7be35885e358719c;p=scryer-prolog.git fix bugs in marker algorithm iterator --- diff --git a/src/heap_iter.rs b/src/heap_iter.rs index d36855da..ab3b962a 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -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, - cell: HeapCellValue, + start: usize, ) -> StacklessPreOrderHeapIter { - StacklessPreOrderHeapIter::::new(heap, cell) + StacklessPreOrderHeapIter::::new(heap, start) +} + + +pub(crate) fn cycle_detecting_stackless_preorder_iter( + heap: &mut Heap, + start: usize, +) -> StacklessPreOrderHeapIter { + StacklessPreOrderHeapIter::::new(heap, start) } + #[inline(always)] pub(crate) fn stackful_preorder_iter<'a, ElideLists: ListElisionPolicy>( heap: &'a mut Vec, @@ -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) diff --git a/src/machine/gc.rs b/src/machine/gc.rs index 5b4895bd..0d37dfec 100644 --- a/src/machine/gc.rs +++ b/src/machine/gc.rs @@ -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) -> Option where Self: Sized; + fn invert_marker(iter: &mut StacklessPreOrderHeapIter) 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(iter: &mut StacklessPreOrderHeapIter) { + 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) -> Option { + iter.forward_var() + } + + #[inline] + fn invert_marker(iter: &mut StacklessPreOrderHeapIter) { + 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, +} + +impl UnmarkPolicy for CycleDetectorUMP { #[inline(always)] fn forward_attr_var(iter: &mut StacklessPreOrderHeapIter) -> Option { iter.forward_var() } -} -struct MarkerUMP {} + #[inline] + fn invert_marker(iter: &mut StacklessPreOrderHeapIter) { + 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) -> Option { 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) {} + + #[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, - orig_heap_len: usize, + pub(crate) heap: &'a mut [HeapCellValue], start: usize, current: usize, next: u64, - _marker: PhantomData, + 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, 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, 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 { + 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 { - 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 { 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 { 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::::new(heap, cell); +pub fn mark_cells(heap: &mut Heap, start: usize) { + let mut iter = StacklessPreOrderHeapIter::::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); diff --git a/src/types.rs b/src/types.rs index cf2159ba..043bd221 100644 --- a/src/types.rs +++ b/src/types.rs @@ -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,