From: Mark Thom Date: Tue, 12 Feb 2019 04:21:13 +0000 (-0700) Subject: bracket verify_attributes/3 interrupts with allocation and deallocation of stack... X-Git-Tag: v0.8.110~261 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=e36485533d32771b59552aaaeaae130a3ba1ed71;p=scryer-prolog.git bracket verify_attributes/3 interrupts with allocation and deallocation of stack frames. --- diff --git a/src/prolog/and_stack.rs b/src/prolog/and_stack.rs index 520fe452..b1a5d5a4 100644 --- a/src/prolog/and_stack.rs +++ b/src/prolog/and_stack.rs @@ -8,6 +8,7 @@ pub struct Frame { pub global_index: usize, pub e: usize, pub cp: LocalCodePtr, + pub special_form_cp: LocalCodePtr, perms: Vec } @@ -17,9 +18,15 @@ impl Frame { global_index, e: e, cp: cp, + special_form_cp: LocalCodePtr::default(), perms: (1 .. n+1).map(|i| Addr::StackCell(fr, i)).collect() } } + + #[inline] + pub fn len(&self) -> usize { + self.perms.len() + } } pub struct AndStack(Vec); diff --git a/src/prolog/debray_allocator.rs b/src/prolog/debray_allocator.rs index 9efb17e6..a95bf480 100644 --- a/src/prolog/debray_allocator.rs +++ b/src/prolog/debray_allocator.rs @@ -34,6 +34,7 @@ impl DebrayAllocator { } } + #[inline] fn is_in_use(&self, r: usize) -> bool { let in_use_range = r <= self.arity && r >= self.arg_c; in_use_range || self.in_use.contains(&r) diff --git a/src/prolog/machine/attributed_variables.rs b/src/prolog/machine/attributed_variables.rs index 685af0e6..78320678 100644 --- a/src/prolog/machine/attributed_variables.rs +++ b/src/prolog/machine/attributed_variables.rs @@ -4,10 +4,9 @@ pub static VERIFY_ATTRS: &str = include_str!("attributed_variables.pl"); pub(super) type Bindings = Vec<(usize, Addr)>; -pub(super) struct AttrVarInitializer { +pub(super) struct AttrVarInitializer { pub(super) bindings: Bindings, - cp_stack: Vec, - pub(super) registers: Registers, + pub(super) cp: LocalCodePtr, pub(super) verify_attrs_loc: usize } @@ -15,20 +14,13 @@ impl AttrVarInitializer { pub(super) fn new(p: usize) -> Self { AttrVarInitializer { bindings: vec![], + cp: LocalCodePtr::default(), verify_attrs_loc: p, - cp_stack: vec![], - registers: vec![Addr::HeapCell(0); MAX_ARITY + 1] } } - #[inline] - pub(super) fn pop_code_ptr(&mut self) -> CodePtr { - self.cp_stack.pop().unwrap() - } - #[inline] pub(super) fn reset(&mut self) { - self.cp_stack.clear(); self.bindings.clear(); } } @@ -37,7 +29,7 @@ impl MachineState { pub(super) fn push_attr_var_binding(&mut self, h: usize, addr: Addr) { if self.attr_var_init.bindings.is_empty() { - self.attr_var_init.cp_stack.push(self.p.clone() + 1); + self.attr_var_init.cp = self.p.local() + 1; self.p = CodePtr::VerifyAttrInterrupt(self.attr_var_init.verify_attrs_loc); } @@ -54,18 +46,32 @@ impl MachineState { (var_list_addr, value_list_addr) } + pub(super) + fn calculate_register_threshold(&self) -> usize { + let mut count = 0; + + for r in 1 .. MAX_ARITY + 1 { + if let &Addr::HeapCell(0) = &self[RegType::Temp(r)] { + break; + } + + count += 1; + } + + count + } + pub(super) fn verify_attributes(&mut self) { /* STEP 1: Undo bindings in machine. STEP 2: Write the list of bindings to two lists in the heap, one for vars, one for values. - STEP 3: Swap the machine's Registers for attr_var_init's Registers. - STEP 4: Pass the addresses of the lists to iterate in the attr_vars special form. + STEP 3: Pass the addresses of the lists to iterate in the attr_vars special form. Call verify_attributes/3 wherever applicable. - STEP 5: Redo the bindings. - STEP 6: Call the goals. - STEP 7: Pop the top of AttrVarInitializer::cp_stack to self.p. - STEP 8: Swap the AttrVarInitializer's Registers back for the machine's Registers. + STEP 4: Redo the bindings. + STEP 5: Call the goals. + STEP 6: Pop the top of AttrVarInitializer::cp_stack to self.p. + STEP 7: Swap the AttrVarInitializer's Registers back for the machine's Registers. */ // STEP 1. @@ -75,10 +81,8 @@ impl MachineState { // STEP 2. let (var_list_addr, value_list_addr) = self.populate_var_and_value_lists(); - // STEP 3. - mem::swap(&mut self.registers, &mut self.attr_var_init.registers); - // STEP 4. + // STEP 3. self[temp_v!(1)] = var_list_addr; self[temp_v!(2)] = value_list_addr; } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index 95834df9..6bea1cc2 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -2175,7 +2175,7 @@ impl MachineState { self.e = self.and_stack.len() - 1; } - fn deallocate(&mut self) { + pub(super) fn deallocate(&mut self) { let e = self.e; self.cp = self.and_stack[e].cp.clone(); diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index 6143ccee..f01a2bb0 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -586,6 +586,17 @@ impl MachineState { CodePtr::Local(_) => break, CodePtr::VerifyAttrInterrupt(p) => { + let rs = self.calculate_register_threshold(); + + self.allocate(rs); // store temp vars in perm vars slots. + + let e = self.e; + self.and_stack[e].special_form_cp = self.attr_var_init.cp; + + for i in 1 .. self.and_stack[e].len() + 1 { + self.and_stack[e][i] = self[RegType::Temp(i)].clone(); + } + self.verify_attributes(); self.num_of_args = 2; diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index c531b931..ef299842 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -450,9 +450,15 @@ impl MachineState { CWILCallPolicy.") }, &SystemClauseType::RestoreCodePtrFromSpecialFormCP => { - self.p = self.attr_var_init.pop_code_ptr(); - mem::swap(&mut self.registers, &mut self.attr_var_init.registers); + let e = self.e; + + for i in 1 .. self.and_stack[e].len() + 1 { + self[RegType::Temp(i)] = self.and_stack[e][i].clone(); + } + self.p = CodePtr::Local(self.and_stack[e].special_form_cp); + self.deallocate(); + return Ok(()); }, &SystemClauseType::RestoreCutPolicy => { diff --git a/src/prolog/write.rs b/src/prolog/write.rs index 87a6adaf..98f4ddb4 100644 --- a/src/prolog/write.rs +++ b/src/prolog/write.rs @@ -13,6 +13,23 @@ fn error_string(e: &String) -> String { format!("error: exception thrown: {}", e) } +impl fmt::Display for LocalCodePtr { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + LocalCodePtr::DirEntry(p) => + write!(f, "LocalCodePtr::DirEntry({})", p), + LocalCodePtr::InSituDirEntry(p) => + write!(f, "LocalCodePtr::InSituDirEntry({})", p), + LocalCodePtr::TopLevel(cn, p) => + write!(f, "LocalCodePtr::TopLevel({}, {})", cn, p), + LocalCodePtr::UserGoalExpansion(p) => + write!(f, "LocalCodePtr::UserGoalExpansion({})", p), + LocalCodePtr::UserTermExpansion(p) => + write!(f, "LocalCodePtr::UserTermExpansion({})", p), + } + } +} + impl fmt::Display for IndexPtr { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self {