fix bugs & incompleteness of cycle-detecting stackless iterator (#2111)

This commit is contained in:
Mark
2023-10-14 13:00:58 -06:00
parent 62e6ca02f9
commit 307cb56ef5

View File

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