]> Repositorios git - scryer-prolog.git/commitdiff
fix copy_term/2 variable copying bug in lists (#923, #2127)
authorMark <[email protected]>
Tue, 21 Nov 2023 19:50:10 +0000 (12:50 -0700)
committerMark <[email protected]>
Tue, 21 Nov 2023 21:52:35 +0000 (14:52 -0700)
src/machine/copier.rs
src/machine/machine_state.rs
src/machine/machine_state_impl.rs
src/machine/mock_wam.rs
src/machine/system_calls.rs
src/toplevel.pl

index be433ba1414a6e9cfc2ca1fc203a70a6d0b40319..c02854ffdcb24212eee874b65720915b8cde5737 100644 (file)
@@ -18,6 +18,7 @@ pub trait CopierTarget: IndexMut<usize, Output = HeapCellValue> {
     fn store(&self, value: HeapCellValue) -> HeapCellValue;
     fn deref(&self, value: HeapCellValue) -> HeapCellValue;
     fn push(&mut self, value: HeapCellValue);
+    fn push_attr_var_queue(&mut self, attr_var_loc: usize);
     fn stack(&mut self) -> &mut Stack;
     fn threshold(&self) -> usize;
 }
@@ -73,7 +74,6 @@ impl<T: CopierTarget> CopyTermState<T> {
                     if h >= self.old_h {
                         *self.value_at_scan() = list_loc_as_cell!(h);
                         self.scan += 1;
-
                         return;
                     }
                 }
@@ -96,14 +96,19 @@ impl<T: CopierTarget> CopyTermState<T> {
             .store(self.target.deref(heap_loc_as_cell!(addr + 1)));
 
         if !cdr.is_var() {
+            // mark addr + 1 as a list back edge in the cdr of the list
             self.trail_list_cell(addr + 1, threshold);
+            self.target[addr + 1].set_mark_bit(true);
+            self.target[addr + 1].set_forwarding_bit(true);
         } else {
             let car = self
                 .target
                 .store(self.target.deref(heap_loc_as_cell!(addr)));
 
             if !car.is_var() {
+                // mark addr as a list back edge in the car of the list
                 self.trail_list_cell(addr, threshold);
+                self.target[addr].set_mark_bit(true);
             }
         }
 
@@ -178,6 +183,7 @@ impl<T: CopierTarget> CopyTermState<T> {
 
             for (threshold, list_loc) in iter {
                 self.target[threshold] = list_loc_as_cell!(self.target.threshold());
+                self.target.push_attr_var_queue(threshold - 1);
                 self.copy_attr_var_list(list_loc);
             }
         }
@@ -263,6 +269,7 @@ impl<T: CopierTarget> CopyTermState<T> {
     }
 
     fn copy_var(&mut self, addr: HeapCellValue) {
+        let index = addr.get_value() as usize;
         let rd = self.target.deref(addr);
         let ra = self.target.store(rd);
 
@@ -271,7 +278,20 @@ impl<T: CopierTarget> CopyTermState<T> {
                 if h >= self.old_h {
                     *self.value_at_scan() = ra;
                     self.scan += 1;
+                    return;
+                }
+            }
+            (HeapCellValueTag::Lis, h) => {
+                if h >= self.old_h && self.target[index].get_mark_bit() {
+                    *self.value_at_scan() = heap_loc_as_cell!(
+                        if ra.get_forwarding_bit() {
+                            h + 1
+                        } else {
+                            h
+                        }
+                    );
 
+                    self.scan += 1;
                     return;
                 }
             }
@@ -356,12 +376,16 @@ impl<T: CopierTarget> CopyTermState<T> {
         }
     }
 
-    fn unwind_trail(&mut self) {
-        for (r, value) in self.trail.drain(0..) {
+    fn unwind_trail(mut self) {
+        for (r, value) in self.trail {
             let index = r.get_value() as usize;
 
             match r.get_tag() {
-                RefTag::AttrVar | RefTag::HeapCell => self.target[index] = value,
+                RefTag::AttrVar | RefTag::HeapCell => {
+                    self.target[index] = value;
+                    self.target[index].set_mark_bit(false);
+                    self.target[index].set_forwarding_bit(false);
+                }
                 RefTag::StackCell => self.target.stack()[index] = value,
             }
         }
index 596eefbd30b6ddf50754f7829b2d68f8a88966a6..3763b2c09bcaa45a1963da1b1de3f9db9699402d 100644 (file)
@@ -289,6 +289,11 @@ impl<'a> CopierTarget for CopyTerm<'a> {
         self.state.heap.push(hcv);
     }
 
+    #[inline(always)]
+    fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
+        self.state.attr_var_init.attr_var_queue.push(attr_var_loc);
+    }
+
     #[inline(always)]
     fn store(&self, value: HeapCellValue) -> HeapCellValue {
         self.state.store(value)
@@ -307,6 +312,7 @@ impl<'a> CopierTarget for CopyTerm<'a> {
 
 #[derive(Debug)]
 pub(super) struct CopyBallTerm<'a> {
+    attr_var_queue: &'a mut Vec<usize>,
     stack: &'a mut Stack,
     heap: &'a mut Heap,
     heap_boundary: usize,
@@ -314,10 +320,16 @@ pub(super) struct CopyBallTerm<'a> {
 }
 
 impl<'a> CopyBallTerm<'a> {
-    pub(super) fn new(stack: &'a mut Stack, heap: &'a mut Heap, stub: &'a mut Heap) -> Self {
+    pub(super) fn new(
+        attr_var_queue: &'a mut Vec<usize>,
+        stack: &'a mut Stack,
+        heap: &'a mut Heap,
+        stub: &'a mut Heap,
+    ) -> Self {
         let hb = heap.len();
 
         CopyBallTerm {
+            attr_var_queue,
             stack,
             heap,
             heap_boundary: hb,
@@ -359,6 +371,11 @@ impl<'a> CopierTarget for CopyBallTerm<'a> {
         self.stub.push(value);
     }
 
+    #[inline(always)]
+    fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
+        self.attr_var_queue.push(attr_var_loc);
+    }
+
     fn store(&self, value: HeapCellValue) -> HeapCellValue {
         read_heap_cell!(value,
             (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => {
index 82a64bf48cc2a75246403ab1d00daa8768b45bc1..edd6b673fbabeb7f5ceb04243eb1cde0dd67d915 100644 (file)
@@ -334,7 +334,12 @@ impl MachineState {
         self.ball.boundary = self.heap.len();
 
         copy_term(
-            CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.ball.stub),
+            CopyBallTerm::new(
+                &mut self.attr_var_init.attr_var_queue,
+                &mut self.stack,
+                &mut self.heap,
+                &mut self.ball.stub,
+            ),
             addr,
             AttrVarPolicy::DeepCopy,
         );
index 94eab6ff2429b2d906a8cd191ee47d76627d05b0..0da42e08d55ad1542f491fbc2eab858f3aea145c 100644 (file)
@@ -159,6 +159,14 @@ impl<'a> CopierTarget for TermCopyingMockWAM<'a> {
         self.wam.machine_st.heap.push(val);
     }
 
+    fn push_attr_var_queue(&mut self, attr_var_loc: usize) {
+        self.wam
+            .machine_st
+            .attr_var_init
+            .attr_var_queue
+            .push(attr_var_loc);
+    }
+
     fn stack(&mut self) -> &mut Stack {
         &mut self.wam.machine_st.stack
     }
index 0c425b969d8b37154a007c476aa2b502a24835d0..e5f77bb47575a679837470ab1344422711a4b2b4 100644 (file)
@@ -827,8 +827,12 @@ impl MachineState {
     ) -> usize {
         let threshold = self.lifted_heap.len() - lh_offset;
 
-        let mut copy_ball_term =
-            CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.lifted_heap);
+        let mut copy_ball_term = CopyBallTerm::new(
+            &mut self.attr_var_init.attr_var_queue,
+            &mut self.stack,
+            &mut self.heap,
+            &mut self.lifted_heap,
+        );
 
         copy_ball_term.push(list_loc_as_cell!(threshold + 1));
         copy_ball_term.push(heap_loc_as_cell!(threshold + 3));
@@ -6789,6 +6793,7 @@ impl Machine {
 
         copy_term(
             CopyBallTerm::new(
+                &mut self.machine_st.attr_var_init.attr_var_queue,
                 &mut self.machine_st.stack,
                 &mut self.machine_st.heap,
                 &mut ball.stub,
index dc7342c047e1b20ada1d11c9b7f2627249dd545f..a9a423c45af5bf6c6c2741e86a4fa479fbdb4ec9 100644 (file)
@@ -452,4 +452,4 @@ print_exception_with_check(E) :-
     % is expected to be printed instead.
     ;  print_exception(E)
     ).
-    
\ No newline at end of file
+