remove need to clone instructions.

This commit is contained in:
Mark Thom
2018-10-04 22:18:29 -06:00
parent 4bd805cc76
commit 054def4cc7
4 changed files with 95 additions and 65 deletions

View File

@@ -10,6 +10,7 @@ use prolog::targets::*;
use std::cell::Cell; use std::cell::Cell;
use std::collections::{HashMap}; use std::collections::{HashMap};
use std::mem;
use std::rc::Rc; use std::rc::Rc;
use std::vec::Vec; use std::vec::Vec;
@@ -235,15 +236,18 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker>
let mut dealloc_index = code.len() - 1; let mut dealloc_index = code.len() - 1;
match code.last_mut() { match code.last_mut() {
Some(&mut Line::Control(ref mut ctrl)) => Some(&mut Line::Control(ref mut ctrl)) => {
match ctrl.clone() { let old_ctrl = mem::replace(ctrl, ControlInstruction::Proceed);
match old_ctrl {
ControlInstruction::CallClause(ct, arity, pvs, false, use_default_cp) => ControlInstruction::CallClause(ct, arity, pvs, false, use_default_cp) =>
*ctrl = ControlInstruction::CallClause(ct, arity, pvs, true, use_default_cp), *ctrl = ControlInstruction::CallClause(ct, arity, pvs, true, use_default_cp),
ControlInstruction::JmpBy(arity, offset, pvs, false) => ControlInstruction::JmpBy(arity, offset, pvs, false) =>
*ctrl = ControlInstruction::JmpBy(arity, offset, pvs, true), *ctrl = ControlInstruction::JmpBy(arity, offset, pvs, true),
ControlInstruction::Proceed => {}, ControlInstruction::Proceed => {},
_ => dealloc_index += 1 _ => dealloc_index += 1
}, }
},
Some(&mut Line::Cut(CutInstruction::Cut(_))) => Some(&mut Line::Cut(CutInstruction::Cut(_))) =>
dealloc_index += 1, dealloc_index += 1,
_ => {} _ => {}

View File

@@ -3,7 +3,6 @@ use prolog_parser::ast::*;
use prolog::instructions::*; use prolog::instructions::*;
use std::collections::{HashMap, VecDeque}; use std::collections::{HashMap, VecDeque};
use std::hash::Hash; use std::hash::Hash;
use std::rc::Rc;
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
enum IntIndex { enum IntIndex {
@@ -141,7 +140,7 @@ impl CodeOffsets {
if con_ind.len() > 1 { if con_ind.len() > 1 {
let index = Self::flatten_index(con_ind, prelude.len()); let index = Self::flatten_index(con_ind, prelude.len());
let instr = IndexingInstruction::SwitchOnConstant(index.len(), Rc::new(index)); let instr = IndexingInstruction::SwitchOnConstant(index.len(), index);
prelude.push_front(Line::from(instr)); prelude.push_front(Line::from(instr));
@@ -161,7 +160,7 @@ impl CodeOffsets {
if str_ind.len() > 1 { if str_ind.len() > 1 {
let index = Self::flatten_index(str_ind, prelude.len()); let index = Self::flatten_index(str_ind, prelude.len());
let instr = IndexingInstruction::SwitchOnStructure(index.len(), Rc::new(index)); let instr = IndexingInstruction::SwitchOnStructure(index.len(), index);
prelude.push_front(Line::from(instr)); prelude.push_front(Line::from(instr));

View File

@@ -493,7 +493,6 @@ impl From<InlinedClauseType> for ClauseType {
} }
} }
#[derive(Clone)]
pub enum ChoiceInstruction { pub enum ChoiceInstruction {
DefaultRetryMeElse(usize), DefaultRetryMeElse(usize),
DefaultTrustMe, DefaultTrustMe,
@@ -502,7 +501,6 @@ pub enum ChoiceInstruction {
TryMeElse(usize) TryMeElse(usize)
} }
#[derive(Clone)]
pub enum CutInstruction { pub enum CutInstruction {
Cut(RegType), Cut(RegType),
GetLevel(RegType), GetLevel(RegType),
@@ -510,7 +508,6 @@ pub enum CutInstruction {
NeckCut NeckCut
} }
#[derive(Clone)]
pub enum IndexedChoiceInstruction { pub enum IndexedChoiceInstruction {
Retry(usize), Retry(usize),
Trust(usize), Trust(usize),
@@ -570,7 +567,6 @@ pub enum ArithmeticInstruction {
Neg(ArithmeticTerm, usize), Neg(ArithmeticTerm, usize),
} }
#[derive(Clone)]
pub enum ControlInstruction { pub enum ControlInstruction {
Allocate(usize), // num_frames. Allocate(usize), // num_frames.
// name, arity, perm_vars after threshold, last call, use default call policy. // name, arity, perm_vars after threshold, last call, use default call policy.
@@ -590,11 +586,10 @@ impl ControlInstruction {
} }
} }
#[derive(Clone)]
pub enum IndexingInstruction { pub enum IndexingInstruction {
SwitchOnTerm(usize, usize, usize, usize), SwitchOnTerm(usize, usize, usize, usize),
SwitchOnConstant(usize, Rc<HashMap<Constant, usize>>), SwitchOnConstant(usize, HashMap<Constant, usize>),
SwitchOnStructure(usize, Rc<HashMap<(ClauseName, usize), usize>>) SwitchOnStructure(usize, HashMap<(ClauseName, usize), usize>)
} }
impl From<IndexingInstruction> for Line { impl From<IndexingInstruction> for Line {
@@ -637,7 +632,6 @@ pub type CompiledFact = Vec<FactInstruction>;
pub type CompiledQuery = Vec<QueryInstruction>; pub type CompiledQuery = Vec<QueryInstruction>;
#[derive(Clone)]
pub enum Line { pub enum Line {
Arithmetic(ArithmeticInstruction), Arithmetic(ArithmeticInstruction),
Choice(ChoiceInstruction), Choice(ChoiceInstruction),

View File

@@ -30,6 +30,20 @@ pub struct IndexStore {
pub(super) modules: ModuleDir pub(super) modules: ModuleDir
} }
enum RefOrOwned<'a, T: 'a> {
Borrowed(&'a T),
Owned(T)
}
impl<'a, T> RefOrOwned<'a, T> {
fn as_ref(&'a self) -> &'a T {
match self {
&RefOrOwned::Borrowed(r) => r,
&RefOrOwned::Owned(ref r) => r
}
}
}
impl IndexStore { impl IndexStore {
#[inline] #[inline]
pub(super) fn new() -> Self { pub(super) fn new() -> Self {
@@ -37,7 +51,7 @@ impl IndexStore {
atom_tbl: TabledData::new(Rc::new("user".to_string())), atom_tbl: TabledData::new(Rc::new("user".to_string())),
code_dir: CodeDir::new(), code_dir: CodeDir::new(),
op_dir: default_op_dir(), op_dir: default_op_dir(),
modules: ModuleDir::new() modules: ModuleDir::new(),
} }
} }
@@ -78,15 +92,59 @@ impl IndexStore {
} }
} }
pub struct CodeRepo {
cached_query: Option<Code>,
pub(super) term_expanders: Code,
pub(super) code: Code
}
impl CodeRepo {
#[inline]
fn new() -> Self {
CodeRepo {
cached_query: None,
term_expanders: Code::new(),
code: Code::new()
}
}
fn lookup_instr<'a>(&'a self, last_call: bool, p: &CodePtr) -> Option<RefOrOwned<'a, Line>>
{
match p {
&CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) =>
if p < self.term_expanders.len() {
Some(RefOrOwned::Borrowed(&self.term_expanders[p]))
} else {
None
},
&CodePtr::Local(LocalCodePtr::TopLevel(_, p)) =>
match &self.cached_query {
&Some(ref cq) => Some(RefOrOwned::Borrowed(&cq[p])),
&None => None
},
&CodePtr::Local(LocalCodePtr::DirEntry(p)) =>
Some(RefOrOwned::Borrowed(&self.code[p])),
&CodePtr::BuiltInClause(ref built_in, _) => {
let call_clause = call_clause!(ClauseType::BuiltIn(built_in.clone()),
built_in.arity(),
0, last_call);
Some(RefOrOwned::Owned(call_clause))
},
&CodePtr::CallN(arity, _) => {
let call_clause = call_clause!(ClauseType::CallN, arity, 0, last_call);
Some(RefOrOwned::Owned(call_clause))
}
}
}
}
pub struct Machine { pub struct Machine {
ms: MachineState, ms: MachineState,
call_policy: Box<CallPolicy>, call_policy: Box<CallPolicy>,
cut_policy: Box<CutPolicy>, cut_policy: Box<CutPolicy>,
code: Code,
pub(super) indices: IndexStore, pub(super) indices: IndexStore,
term_dir: TermDir, term_dir: TermDir,
term_expanders: Code, pub(super) code_repo: CodeRepo
cached_query: Option<Code>
} }
impl Index<LocalCodePtr> for Machine { impl Index<LocalCodePtr> for Machine {
@@ -95,13 +153,13 @@ impl Index<LocalCodePtr> for Machine {
fn index(&self, ptr: LocalCodePtr) -> &Self::Output { fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
match ptr { match ptr {
LocalCodePtr::TopLevel(_, p) => { LocalCodePtr::TopLevel(_, p) => {
match &self.cached_query { match &self.code_repo.cached_query {
&Some(ref cq) => &cq[p], &Some(ref cq) => &cq[p],
&None => panic!("Out-of-bounds top level index.") &None => panic!("Out-of-bounds top level index.")
} }
}, },
LocalCodePtr::DirEntry(p) => &self.code[p], LocalCodePtr::DirEntry(p) => &self.code_repo.code[p],
LocalCodePtr::UserTermExpansion(p) => &self.term_expanders[p] LocalCodePtr::UserTermExpansion(p) => &self.code_repo.term_expanders[p]
} }
} }
} }
@@ -156,11 +214,9 @@ impl Machine {
ms: MachineState::new(), ms: MachineState::new(),
call_policy: Box::new(DefaultCallPolicy {}), call_policy: Box::new(DefaultCallPolicy {}),
cut_policy: Box::new(DefaultCutPolicy {}), cut_policy: Box::new(DefaultCutPolicy {}),
code: Code::new(),
indices: IndexStore::new(), indices: IndexStore::new(),
term_dir: TermDir::new(), term_dir: TermDir::new(),
term_expanders: Code::new(), code_repo: CodeRepo::new()
cached_query: None
}; };
let atom_tbl = wam.indices.atom_tbl.clone(); let atom_tbl = wam.indices.atom_tbl.clone();
@@ -232,7 +288,7 @@ impl Machine {
self.indices.code_dir.insert(key.clone(), idx.clone()); self.indices.code_dir.insert(key.clone(), idx.clone());
} }
self.code.extend(code.into_iter()); self.code_repo.code.extend(code.into_iter());
Ok(()) Ok(())
} }
@@ -269,15 +325,15 @@ impl Machine {
#[inline] #[inline]
pub fn add_module(&mut self, module: Module, code: Code) { pub fn add_module(&mut self, module: Module, code: Code) {
self.indices.modules.insert(module.module_decl.name.clone(), module); self.indices.modules.insert(module.module_decl.name.clone(), module);
self.code.extend(code.into_iter()); self.code_repo.code.extend(code.into_iter());
} }
pub fn code_size(&self) -> usize { pub fn code_size(&self) -> usize {
self.code.len() self.code_repo.code.len()
} }
fn cached_query_size(&self) -> usize { fn cached_query_size(&self) -> usize {
match &self.cached_query { match &self.code_repo.cached_query {
&Some(ref query) => query.len(), &Some(ref query) => query.len(),
_ => 0 _ => 0
} }
@@ -295,50 +351,27 @@ impl Machine {
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, self.ms.flags); let mut cg = CodeGenerator::<DebrayAllocator>::new(false, self.ms.flags);
let code = cg.compile_predicate(&preds.0)?; let code = cg.compile_predicate(&preds.0)?;
Ok(self.term_expanders = code) Ok(self.code_repo.term_expanders = code)
}
fn lookup_instr(&self, p: CodePtr) -> Option<Line> {
match p {
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) =>
if p < self.term_expanders.len() {
Some(self.term_expanders[p].clone())
} else {
None
},
CodePtr::Local(LocalCodePtr::TopLevel(_, p)) =>
match &self.cached_query {
&Some(ref cq) => Some(cq[p].clone()),
&None => None
},
CodePtr::Local(LocalCodePtr::DirEntry(p)) =>
Some(self.code[p].clone()),
CodePtr::BuiltInClause(built_in, _) =>
Some(call_clause!(ClauseType::BuiltIn(built_in.clone()), built_in.arity(),
0, self.ms.last_call)),
CodePtr::CallN(arity, _) =>
Some(call_clause!(ClauseType::CallN, arity, 0, self.ms.last_call))
}
} }
fn execute_instr(&mut self) fn execute_instr(&mut self)
{ {
let instr = match self.lookup_instr(self.ms.p.clone()) { let instr = match self.code_repo.lookup_instr(self.ms.last_call, &self.ms.p) {
Some(instr) => instr, Some(instr) => instr,
None => return None => return
}; };
match instr { match instr.as_ref() {
Line::Arithmetic(ref arith_instr) => &Line::Arithmetic(ref arith_instr) =>
self.ms.execute_arith_instr(arith_instr), self.ms.execute_arith_instr(arith_instr),
Line::Choice(ref choice_instr) => &Line::Choice(ref choice_instr) =>
self.ms.execute_choice_instr(choice_instr, &mut self.call_policy), self.ms.execute_choice_instr(choice_instr, &mut self.call_policy),
Line::Cut(ref cut_instr) => &Line::Cut(ref cut_instr) =>
self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy), self.ms.execute_cut_instr(cut_instr, &mut self.cut_policy),
Line::Control(ref control_instr) => &Line::Control(ref control_instr) =>
self.ms.execute_ctrl_instr(&mut self.indices, &mut self.call_policy, self.ms.execute_ctrl_instr(&mut self.indices, &mut self.call_policy,
&mut self.cut_policy, control_instr), &mut self.cut_policy, control_instr),
Line::Fact(ref fact) => { &Line::Fact(ref fact) => {
for fact_instr in fact { for fact_instr in fact {
if self.failed() { if self.failed() {
break; break;
@@ -349,11 +382,11 @@ impl Machine {
self.ms.p += 1; self.ms.p += 1;
}, },
Line::Indexing(ref indexing_instr) => &Line::Indexing(ref indexing_instr) =>
self.ms.execute_indexing_instr(&indexing_instr), self.ms.execute_indexing_instr(&indexing_instr),
Line::IndexedChoice(ref choice_instr) => &Line::IndexedChoice(ref choice_instr) =>
self.ms.execute_indexed_choice_instr(choice_instr, &mut self.call_policy), self.ms.execute_indexed_choice_instr(choice_instr, &mut self.call_policy),
Line::Query(ref query) => { &Line::Query(ref query) => {
for query_instr in query { for query_instr in query {
if self.failed() { if self.failed() {
break; break;
@@ -395,8 +428,8 @@ impl Machine {
} }
match self.ms.p { match self.ms.p {
CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < self.code.len() => {}, CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < self.code_repo.code.len() => {},
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < self.term_expanders.len() => {}, CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < self.code_repo.term_expanders.len() => {},
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.ms.fail = true, CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.ms.fail = true,
CodePtr::Local(_) => break, CodePtr::Local(_) => break,
_ => {} _ => {}
@@ -483,7 +516,7 @@ impl Machine {
{ {
let mut heap_locs = HashMap::new(); let mut heap_locs = HashMap::new();
self.cached_query = Some(code); self.code_repo.cached_query = Some(code);
self.run_query(&alloc_locs, &mut heap_locs); self.run_query(&alloc_locs, &mut heap_locs);
if self.failed() { if self.failed() {