From c90dd80ece7d2073a5b0d4906dbee77420d93c19 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 13 Nov 2022 20:51:40 -0700 Subject: [PATCH] revise UnsafeVarMarker (#1545) --- src/codegen.rs | 47 +--------------- src/fixtures.rs | 147 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 124 insertions(+), 70 deletions(-) diff --git a/src/codegen.rs b/src/codegen.rs index ec69f277..6abed278 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -49,48 +49,6 @@ impl<'a> ConjunctInfo<'a> { fn perm_var_offset(&self) -> usize { self.has_deep_cut as usize } - - fn mark_unsafe_vars(&self, mut unsafe_var_marker: UnsafeVarMarker, code: &mut Code) { - if code.is_empty() { - return; - } - - let mut code_index = 0; - - for phase in 0.. { - while code[code_index].is_query_instr() { - let query_instr = &mut code[code_index]; - - if !unsafe_var_marker.mark_safe_vars(query_instr) { - unsafe_var_marker.mark_phase(query_instr, phase); - } - - code_index += 1; - } - - if code_index + 1 < code.len() { - code_index += 1; - } else { - break; - } - } - - code_index = 0; - - for phase in 0.. { - while code[code_index].is_query_instr() { - let query_instr = &mut code[code_index]; - unsafe_var_marker.mark_unsafe_vars(query_instr, phase); - code_index += 1; - } - - if code_index + 1 < code.len() { - code_index += 1; - } else { - break; - } - } - } } #[derive(Clone, Copy, Debug)] @@ -989,7 +947,8 @@ impl<'b> CodeGenerator<'b> { let iter = ChunkedIterator::from_rule_body(p1, clauses); self.compile_seq(iter, &conjunct_info, &mut code, false)?; - conjunct_info.mark_unsafe_vars(unsafe_var_marker, &mut code); + unsafe_var_marker.mark_unsafe_instrs(&mut code); + self.compile_cleanup(&mut code, &conjunct_info, clauses.last().unwrap_or(p1)); Ok(code) @@ -1013,7 +972,7 @@ impl<'b> CodeGenerator<'b> { } } - UnsafeVarMarker::from_safe_vars(safe_vars) + UnsafeVarMarker::from_fact_vars(safe_vars) } pub(crate) fn compile_fact(&mut self, term: &Term) -> Result { diff --git a/src/fixtures.rs b/src/fixtures.rs index 43c3ace8..3857d294 100644 --- a/src/fixtures.rs +++ b/src/fixtures.rs @@ -253,68 +253,163 @@ impl<'a> VariableFixtures<'a> { #[derive(Debug)] pub(crate) struct UnsafeVarMarker { - pub(crate) unsafe_vars: IndexMap, - pub(crate) safe_vars: IndexSet, + pub(crate) unsafe_perm_vars: IndexMap, + pub(crate) unsafe_temp_vars: IndexSet, + pub(crate) safe_perm_vars: IndexSet, + pub(crate) safe_temp_vars: IndexSet, } impl UnsafeVarMarker { pub(crate) fn new() -> Self { UnsafeVarMarker { - unsafe_vars: IndexMap::new(), - safe_vars: IndexSet::new(), + unsafe_perm_vars: IndexMap::new(), + unsafe_temp_vars: IndexSet::new(), + safe_perm_vars: IndexSet::new(), + safe_temp_vars: IndexSet::new(), } } - pub(crate) fn from_safe_vars(safe_vars: IndexSet) -> Self { - UnsafeVarMarker { - unsafe_vars: IndexMap::new(), - safe_vars, + pub(crate) fn from_fact_vars(safe_vars: IndexSet) -> Self { + let mut unsafe_var_marker = Self::new(); + + for r in safe_vars { + unsafe_var_marker.mark_var_as_safe(r); } + + unsafe_var_marker + } + + fn mark_var_as_safe(&mut self, r: RegType) { + match r { + RegType::Temp(t) => { + self.safe_temp_vars.insert(t); + } + RegType::Perm(p) => { + self.safe_perm_vars.insert(p); + } + }; } - pub(crate) fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool { + fn mark_var_as_unsafe(&mut self, r: RegType, phase: usize) { + match r { + RegType::Temp(t) => { + self.unsafe_temp_vars.insert(t); + } + RegType::Perm(p) => { + self.unsafe_perm_vars.insert(p, phase); + } + } + } + + fn mark_safe_vars(&mut self, query_instr: &Instruction) -> bool { match query_instr { &Instruction::PutVariable(r @ RegType::Temp(_), _) | &Instruction::SetVariable(r) => { - self.safe_vars.insert(r); + self.mark_var_as_safe(r); true } _ => false, } } - pub(crate) fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) { + fn mark_phase(&mut self, query_instr: &Instruction, phase: usize) { match query_instr { &Instruction::PutValue(r @ RegType::Perm(_), _) | &Instruction::SetValue(r) => { - let p = self.unsafe_vars.entry(r).or_insert(0); - *p = phase; + self.mark_var_as_unsafe(r, phase); } _ => {} } } - pub(crate) fn mark_unsafe_vars(&mut self, query_instr: &mut Instruction, phase: usize) { + fn mark_unsafe_perm_vars(&mut self, query_instr: &mut Instruction, phase: usize) { match query_instr { - &mut Instruction::PutValue(RegType::Perm(i), arg) => { - if let Some(p) = self.unsafe_vars.swap_remove(&RegType::Perm(i)) { - if p == phase { - *query_instr = Instruction::PutUnsafeValue(i, arg); - self.safe_vars.insert(RegType::Perm(i)); + &mut Instruction::PutValue(RegType::Perm(p), arg) => { + if let Some(ph) = self.unsafe_perm_vars.swap_remove(&p) { + if ph == phase { + *query_instr = Instruction::PutUnsafeValue(p, arg); + self.safe_perm_vars.insert(p); } else { - self.unsafe_vars.insert(RegType::Perm(i), p); + self.unsafe_perm_vars.insert(p, ph); } } } - &mut Instruction::SetValue(r) => { - if !self.safe_vars.contains(&r) { - *query_instr = Instruction::SetLocalValue(r); + &mut Instruction::SetValue(r @ RegType::Perm(p)) if !self.safe_perm_vars.contains(&p) => { + *query_instr = Instruction::SetLocalValue(r); - self.safe_vars.insert(r); - self.unsafe_vars.remove(&r); - } + self.safe_perm_vars.insert(p); + self.unsafe_perm_vars.remove(&p); } _ => {} } } + + fn mark_unsafe_temp_vars(&mut self, query_instr: &mut Instruction) { + match query_instr { + &mut Instruction::SetValue(r @ RegType::Temp(t)) if !self.safe_temp_vars.contains(&t) => { + *query_instr = Instruction::SetLocalValue(r); + + self.safe_temp_vars.insert(t); + self.unsafe_temp_vars.remove(&t); + } + _ => { + } + } + } + + fn clear_temp_vars(&mut self) { + self.safe_temp_vars.clear(); + self.unsafe_temp_vars.clear(); + } + + pub(crate) fn mark_unsafe_instrs(&mut self, code: &mut Code) { + if code.is_empty() { + return; + } + + let mut code_index = 0; + + for phase in 0.. { + while code[code_index].is_query_instr() { + let query_instr = &mut code[code_index]; + + if !self.mark_safe_vars(query_instr) { + self.mark_phase(query_instr, phase); + self.mark_unsafe_temp_vars(query_instr); + } + + code_index += 1; + } + + while code_index < code.len() && !code[code_index].is_query_instr() { + code_index += 1; + } + + self.clear_temp_vars(); + + if code_index >= code.len() { + break; + } + } + + code_index = 0; + + for phase in 0.. { + while code[code_index].is_query_instr() { + let query_instr = &mut code[code_index]; + self.mark_unsafe_perm_vars(query_instr, phase); + code_index += 1; + } + + // ensure phase->instruction assignments match those of + // the previous for loop. + while code_index < code.len() && !code[code_index].is_query_instr() { + code_index += 1; + } + + if code_index >= code.len() { + break; + } + } + } } -- 2.54.0