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

View File

@@ -3,7 +3,6 @@ use prolog_parser::ast::*;
use prolog::instructions::*;
use std::collections::{HashMap, VecDeque};
use std::hash::Hash;
use std::rc::Rc;
#[derive(Clone, Copy)]
enum IntIndex {
@@ -141,7 +140,7 @@ impl CodeOffsets {
if con_ind.len() > 1 {
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));
@@ -161,7 +160,7 @@ impl CodeOffsets {
if str_ind.len() > 1 {
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));

View File

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

View File

@@ -30,6 +30,20 @@ pub struct IndexStore {
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 {
#[inline]
pub(super) fn new() -> Self {
@@ -37,7 +51,7 @@ impl IndexStore {
atom_tbl: TabledData::new(Rc::new("user".to_string())),
code_dir: CodeDir::new(),
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 {
ms: MachineState,
call_policy: Box<CallPolicy>,
cut_policy: Box<CutPolicy>,
code: Code,
pub(super) indices: IndexStore,
term_dir: TermDir,
term_expanders: Code,
cached_query: Option<Code>
pub(super) code_repo: CodeRepo
}
impl Index<LocalCodePtr> for Machine {
@@ -95,13 +153,13 @@ impl Index<LocalCodePtr> for Machine {
fn index(&self, ptr: LocalCodePtr) -> &Self::Output {
match ptr {
LocalCodePtr::TopLevel(_, p) => {
match &self.cached_query {
match &self.code_repo.cached_query {
&Some(ref cq) => &cq[p],
&None => panic!("Out-of-bounds top level index.")
}
},
LocalCodePtr::DirEntry(p) => &self.code[p],
LocalCodePtr::UserTermExpansion(p) => &self.term_expanders[p]
LocalCodePtr::DirEntry(p) => &self.code_repo.code[p],
LocalCodePtr::UserTermExpansion(p) => &self.code_repo.term_expanders[p]
}
}
}
@@ -156,11 +214,9 @@ impl Machine {
ms: MachineState::new(),
call_policy: Box::new(DefaultCallPolicy {}),
cut_policy: Box::new(DefaultCutPolicy {}),
code: Code::new(),
indices: IndexStore::new(),
term_dir: TermDir::new(),
term_expanders: Code::new(),
cached_query: None
code_repo: CodeRepo::new()
};
let atom_tbl = wam.indices.atom_tbl.clone();
@@ -232,7 +288,7 @@ impl Machine {
self.indices.code_dir.insert(key.clone(), idx.clone());
}
self.code.extend(code.into_iter());
self.code_repo.code.extend(code.into_iter());
Ok(())
}
@@ -269,15 +325,15 @@ impl Machine {
#[inline]
pub fn add_module(&mut self, module: Module, code: Code) {
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 {
self.code.len()
self.code_repo.code.len()
}
fn cached_query_size(&self) -> usize {
match &self.cached_query {
match &self.code_repo.cached_query {
&Some(ref query) => query.len(),
_ => 0
}
@@ -295,50 +351,27 @@ impl Machine {
let mut cg = CodeGenerator::<DebrayAllocator>::new(false, self.ms.flags);
let code = cg.compile_predicate(&preds.0)?;
Ok(self.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))
}
Ok(self.code_repo.term_expanders = code)
}
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,
None => return
};
match instr {
Line::Arithmetic(ref arith_instr) =>
match instr.as_ref() {
&Line::Arithmetic(ref 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),
Line::Cut(ref cut_instr) =>
&Line::Cut(ref cut_instr) =>
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,
&mut self.cut_policy, control_instr),
Line::Fact(ref fact) => {
&Line::Fact(ref fact) => {
for fact_instr in fact {
if self.failed() {
break;
@@ -349,11 +382,11 @@ impl Machine {
self.ms.p += 1;
},
Line::Indexing(ref indexing_instr) =>
&Line::Indexing(ref 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),
Line::Query(ref query) => {
&Line::Query(ref query) => {
for query_instr in query {
if self.failed() {
break;
@@ -395,8 +428,8 @@ impl Machine {
}
match self.ms.p {
CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < self.code.len() => {},
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < self.term_expanders.len() => {},
CodePtr::Local(LocalCodePtr::DirEntry(p)) if p < self.code_repo.code.len() => {},
CodePtr::Local(LocalCodePtr::UserTermExpansion(p)) if p < self.code_repo.term_expanders.len() => {},
CodePtr::Local(LocalCodePtr::UserTermExpansion(_)) => self.ms.fail = true,
CodePtr::Local(_) => break,
_ => {}
@@ -483,7 +516,7 @@ impl Machine {
{
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);
if self.failed() {