From: Mark Date: Fri, 23 Jun 2023 00:28:10 +0000 (-0600) Subject: backtrack on emission of unsafe register instructions on internal branches X-Git-Tag: v0.9.2~123^2~26 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=9ea6cb4cab4409e0f5cee917d37c3ff9ac0b0fc1;p=scryer-prolog.git backtrack on emission of unsafe register instructions on internal branches --- diff --git a/src/codegen.rs b/src/codegen.rs index 794ec65b..000c0e65 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -103,25 +103,15 @@ impl BranchCodeStack { for (inner_idx, code) in self.stack[idx].iter_mut().enumerate() { if inner_idx + 1 == inner_len { - jump_span -= code.len() + 1; // = jump_span.saturating_sub(code.len() + 1); + jump_span -= code.len() + 1; } else { jump_span -= code.len() + 1; code.push_back(instr!("jmp_by_call", jump_span as usize)); - // saturate at 0 if underflow happens, which only - // happens when jump_span is no longer needed - // anyway. still, we don't want to panic at - // underflow. jump_span -= 1; } } } - - // eliminate terminating jump instruction in last arm of last - // branch. - // self.stack.last_mut() - // .and_then(|branch| branch.last_mut()) - // .map(|code| code.pop_back()); } fn pop_branch(&mut self, depth: usize, settings: CodeGenSettings) -> CodeDeque { @@ -1242,14 +1232,6 @@ impl<'b> CodeGenerator<'b> { code.extend(code_segment.into_iter()); } - /* - for line in &code { - println!("{:?}", line); - } - - println!(""); - */ - Ok(code) } } diff --git a/src/debray_allocator.rs b/src/debray_allocator.rs index 2f8d442e..2cd853c7 100644 --- a/src/debray_allocator.rs +++ b/src/debray_allocator.rs @@ -75,7 +75,17 @@ impl DebrayAllocator { self.branch_stack.push(BranchOccurrences::new(num_branches)); } + pub(crate) fn current_branch_designator(&self) -> BranchDesignator { + let num_branches = self.branch_stack.len(); + let current_branch = self.branch_stack.last() + .map(|occurrences| occurrences.current_branch) + .unwrap_or(0); + + BranchDesignator((num_branches, current_branch)) + } + pub(crate) fn add_branch(&mut self) { + let branch_designator = self.current_branch_designator(); let branch_occurrences = self.branch_stack.last_mut().unwrap(); for var_num in branch_occurrences.subsumed_hits.drain(..) { @@ -83,11 +93,11 @@ impl DebrayAllocator { VarAlloc::Perm(_, ref mut allocation) => { match allocation { PermVarAllocation::Done { shallow_safety, deep_safety, .. } => { - if !shallow_safety.unneeded() { + if !shallow_safety.is_unneeded(branch_designator) { branch_occurrences.shallow_safety.insert(var_num); } - if !deep_safety.unneeded() { + if !deep_safety.is_unneeded(branch_designator) { branch_occurrences.deep_safety.insert(var_num); } } @@ -128,6 +138,8 @@ impl DebrayAllocator { (deep_safety, shallow_safety) }); + let branch_designator = self.current_branch_designator(); + let (deep_safety, shallow_safety) = match self.branch_stack.last_mut() { Some(latest_branch) => { latest_branch.deep_safety.union_with(&deep_safety); @@ -143,10 +155,12 @@ impl DebrayAllocator { VarAlloc::Perm(_, ref mut allocation) => { let shallow_safety = VarSafetyStatus::needed_if( shallow_safety.contains(var_num), + branch_designator, ); let deep_safety = VarSafetyStatus::needed_if( deep_safety.contains(var_num), + branch_designator, ); *allocation = PermVarAllocation::Done { shallow_safety, deep_safety }; @@ -415,10 +429,12 @@ impl DebrayAllocator { pub(crate) fn mark_temp_to_safe_perm(&mut self, var_num: usize) { match &self.var_data.records[var_num].allocation { &VarAlloc::Temp { to_perm_var_num: Some(perm_var_num), .. } => { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[perm_var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { - *deep_safety = VarSafetyStatus::Unneeded; - *shallow_safety = VarSafetyStatus::Unneeded; + *deep_safety = VarSafetyStatus::unneeded(branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); } _ => unreachable!() } @@ -429,14 +445,16 @@ impl DebrayAllocator { } fn mark_safe_var(&mut self, var_num: usize, lvl: Level, term_loc: GenContext) { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { deep_safety, shallow_safety, .. }) => { // GetVariable in head chunk is considered safe. if lvl == Level::Deep { - *deep_safety = VarSafetyStatus::Unneeded; - *shallow_safety = VarSafetyStatus::Unneeded; + *deep_safety = VarSafetyStatus::unneeded(branch_designator); + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); } else if term_loc == GenContext::Head { - *shallow_safety = VarSafetyStatus::Unneeded; + *shallow_safety = VarSafetyStatus::GloballyUnneeded; } else { if let Some(temp_var_num) = self.shallow_temp_mappings.get(&self.arg_c).cloned() { match &mut self.var_data.records[temp_var_num].allocation { @@ -449,7 +467,7 @@ impl DebrayAllocator { } } VarAlloc::Temp { ref mut safety, .. } => { - *safety = VarSafetyStatus::Unneeded; + *safety = VarSafetyStatus::GloballyUnneeded; } _ => { unreachable!() @@ -463,20 +481,22 @@ impl DebrayAllocator { r: RegType, arg_c: usize, ) -> Instruction { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { ref mut shallow_safety, .. }) => { - if !self.in_tail_position || shallow_safety.unneeded() { + if !self.in_tail_position || shallow_safety.is_unneeded(branch_designator) { Target::argument_to_value(r, arg_c) } else { - *shallow_safety = VarSafetyStatus::Unneeded; + *shallow_safety = VarSafetyStatus::unneeded(branch_designator); Target::unsafe_argument_to_value(r, arg_c) } } VarAlloc::Temp { ref mut safety, .. } => { - if safety.unneeded() { + if safety.is_unneeded(branch_designator) { Target::argument_to_value(r, arg_c) } else { - *safety = VarSafetyStatus::Unneeded; + *safety = VarSafetyStatus::GloballyUnneeded; Target::unsafe_argument_to_value(r, arg_c) } } @@ -491,20 +511,22 @@ impl DebrayAllocator { var_num: usize, r: RegType, ) -> Instruction { + let branch_designator = self.current_branch_designator(); + match &mut self.var_data.records[var_num].allocation { VarAlloc::Perm(_, PermVarAllocation::Done { ref mut deep_safety, .. }) => { - if deep_safety.unneeded() { + if deep_safety.is_unneeded(branch_designator) { Target::subterm_to_value(r) } else { - *deep_safety = VarSafetyStatus::Unneeded; + *deep_safety = VarSafetyStatus::unneeded(branch_designator); Target::unsafe_subterm_to_value(r) } } VarAlloc::Temp { ref mut safety, .. } => { - if safety.unneeded() { + if safety.is_unneeded(branch_designator) { Target::subterm_to_value(r) } else { - *safety = VarSafetyStatus::Unneeded; + *safety = VarSafetyStatus::unneeded(branch_designator); Target::unsafe_subterm_to_value(r) } } diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 1b65ef9e..a701dba3 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -839,12 +839,3 @@ impl BranchMap { var_data } } - -#[cfg(test)] -mod tests { - #[test] - fn disjunct_compilation() { - let mut wam = MachineState::new(); - let mut op_dir = default_op_dir(); - } -}