refine code generation, scale back unsafe variable instructions for conjunctive queries

This commit is contained in:
Mark Thom
2017-05-17 16:32:46 -06:00
parent 5fa9881556
commit 5efee09434
2 changed files with 47 additions and 64 deletions

View File

@@ -133,15 +133,6 @@ pub struct Rule {
pub clauses: Vec<TermOrCut> pub clauses: Vec<TermOrCut>
} }
impl Rule {
pub fn last_clause(&self) -> &TermOrCut {
match self.clauses.last() {
None => &self.head.1,
Some(clause) => clause
}
}
}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum TermRef<'a> { pub enum TermRef<'a> {
AnonVar(Level), AnonVar(Level),

View File

@@ -225,7 +225,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
(vs, has_deep_cut) (vs, has_deep_cut)
} }
fn add_conditional_call(compiled_query: &mut Code, term: &Term, pvs: usize) fn add_conditional_call(compiled_query: &mut Code, term: &Term, pvs: usize)
{ {
match term { match term {
@@ -277,17 +277,17 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
vec![Line::Cut(CutInstruction::Cut(Terminal::Terminal))], vec![Line::Cut(CutInstruction::Cut(Terminal::Terminal))],
&TermOrCutRef::Term(term) if i + 1 < terms.len() => { &TermOrCutRef::Term(term) if i + 1 < terms.len() => {
let num_vars = vs.vars_above_threshold(i + 1); let num_vars = vs.vars_above_threshold(i + 1);
self.compile_internal_query(term, self.compile_query_line(term,
GenContext::Mid(chunk_num), GenContext::Mid(chunk_num),
num_vars, num_vars,
is_exposed) is_exposed)
}, },
&TermOrCutRef::Term(term) => { &TermOrCutRef::Term(term) => {
let num_vars = vs.vars_above_threshold(i + 1); let num_vars = vs.vars_above_threshold(i + 1);
self.compile_internal_query(term, self.compile_query_line(term,
GenContext::Last(chunk_num), GenContext::Last(chunk_num),
num_vars, num_vars,
is_exposed) is_exposed)
} }
}; };
@@ -317,15 +317,15 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
} }
fn compile_neck_cut_or(&mut self, fn compile_neck_cut_or(&mut self,
p1: &'a TermOrCut, p1: &'a TermOrCut,
clauses: &'a [TermOrCut],
body: &mut Code, body: &mut Code,
perm_vars: usize, perm_vars: usize,
is_exposed: bool) is_exposed: bool,
at_end: bool)
{ {
match p1 { match p1 {
&TermOrCut::Cut => { &TermOrCut::Cut => {
let term = if clauses.is_empty() { let term = if at_end {
Terminal::Terminal Terminal::Terminal
} else { } else {
Terminal::Non Terminal::Non
@@ -359,7 +359,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate)); body.insert(dealloc_index, Line::Control(ControlInstruction::Deallocate));
} }
} }
pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Code pub fn compile_rule<'b: 'a>(&mut self, rule: &'b Rule) -> Code
{ {
let iter = ChunkedIterator::from_rule(rule); let iter = ChunkedIterator::from_rule(rule);
@@ -367,40 +367,34 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
vs = self.marker.drain_var_data(vs); vs = self.marker.drain_var_data(vs);
let &Rule { head: (ref p0, ref p1), ref clauses } = rule; let &Rule { head: (ref p0, ref p1), ref clauses } = rule;
let mut body = Vec::new(); let mut code = Vec::new();
self.marker.advance(GenContext::Head, p0); self.marker.advance(GenContext::Head, p0);
let perm_vars = self.compile_seq_prelude(clauses.len(), &vs, deep_cuts, &mut body); let perm_vars = self.compile_seq_prelude(clauses.len(), &vs, deep_cuts, &mut code);
if p0.is_clause() { if p0.is_clause() {
body.push(Line::Fact(self.compile_target(p0, GenContext::Head, false))); code.push(Line::Fact(self.compile_target(p0, GenContext::Head, false)));
} }
let clauses_slice = if clauses.len() > 1 { self.compile_neck_cut_or(p1, &mut code, perm_vars, false, clauses.len() == 0);
&clauses[1 .. ] self.compile_seq(clauses, &vs, &mut code, false);
} else {
&[]
};
self.compile_neck_cut_or(p1, clauses_slice, &mut body, perm_vars, false); if perm_vars > 0 {
self.compile_seq(clauses, &vs, &mut body, false); let index = if let &Line::Control(_) = code.last().unwrap() {
code.len() - 2
} else {
code.len() - 1
};
if clauses.len() > 0 { if let &mut Line::Query(ref mut query) = &mut code[index] {
let mut index = body.len() - 1;
if let &Line::Control(_) = body.last().unwrap() {
index -= 1;
}
if let &mut Line::Query(ref mut query) = &mut body[index] {
vs.mark_unsafe_vars_in_rule(p0, query); vs.mark_unsafe_vars_in_rule(p0, query);
} }
} }
Self::compile_cleanup(&mut body, clauses.len(), rule.last_clause()); Self::compile_cleanup(&mut code, clauses.len(), clauses.last().unwrap_or(p1));
body code
} }
fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact) fn mark_unsafe_fact_vars(&self, fact: &mut CompiledFact)
@@ -452,12 +446,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
code code
} }
fn compile_internal_query(&mut self, fn compile_query_line(&mut self,
term: &'a Term, term: &'a Term,
term_loc: GenContext, term_loc: GenContext,
index: usize, index: usize,
is_exposed: bool) is_exposed: bool)
-> Code -> Code
{ {
self.marker.advance(term_loc, term); self.marker.advance(term_loc, term);
@@ -487,23 +481,21 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<'a, TermMarker>
deep_cuts, deep_cuts,
&mut code); &mut code);
let query_slice = if query.len() > 1 { self.compile_neck_cut_or(p1, &mut code, perm_vars, true, query.len() == 1);
&query[1 .. ] self.compile_seq(&query[1 .. ], &vs, &mut code, true);
} else {
&[] if perm_vars > 0 {
}; let index = if let &Line::Control(_) = code.last().unwrap() {
code.len() - 2
self.compile_neck_cut_or(p1, query_slice, &mut code, perm_vars, true); } else {
self.compile_seq(query_slice, &vs, &mut code, true); code.len() - 1
for line in code.iter_mut() {
match line {
&mut Line::Query(ref mut query) =>
vs.mark_unsafe_vars_in_query(query),
_ => {}
}; };
}
if let &mut Line::Query(ref mut query) = &mut code[index] {
vs.mark_unsafe_vars_in_query(query);
}
}
Self::compile_cleanup(&mut code, query.len() - 1, query.last().unwrap()); Self::compile_cleanup(&mut code, query.len() - 1, query.last().unwrap());
code code