limit hash lookups to metacall
This commit is contained in:
@@ -28,16 +28,12 @@ impl<'a> CodeDirs<'a> {
|
||||
let module_name = p.module_name();
|
||||
|
||||
match module_name {
|
||||
ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") =>
|
||||
self.code_dir,
|
||||
_ =>
|
||||
&self.modules.get(&module_name).unwrap().code_dir
|
||||
ClauseName::BuiltIn("user") | ClauseName::BuiltIn("builtin") => self.code_dir,
|
||||
_ => &self.modules.get(&module_name).unwrap().code_dir
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr)
|
||||
-> Option<(usize, ClauseName)>
|
||||
{
|
||||
pub(super) fn get(&self, name: ClauseName, arity: usize, p: &CodePtr) -> Option<CodeIndex> {
|
||||
let code_dir = self.get_current_code_dir(p);
|
||||
code_dir.get(&(name, arity)).cloned()
|
||||
}
|
||||
@@ -215,54 +211,46 @@ pub struct MachineState {
|
||||
pub(crate) type CallResult = Result<(), Vec<HeapCellValue>>;
|
||||
|
||||
pub(crate) trait CallPolicy: Any {
|
||||
fn context_call<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
name: ClauseName, arity: usize, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
if lco {
|
||||
self.try_execute(machine_st, code_dirs, name, arity)
|
||||
} else {
|
||||
self.try_call(machine_st, code_dirs, name, arity)
|
||||
}
|
||||
}
|
||||
|
||||
fn try_call<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
name: ClauseName, arity: usize)
|
||||
fn context_call(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex, lco: bool)
|
||||
-> CallResult
|
||||
{
|
||||
let compiled_tl_index = code_dirs.get(name, arity, &machine_st.p);
|
||||
if lco {
|
||||
self.try_execute(machine_st, arity, idx)
|
||||
} else {
|
||||
self.try_call(machine_st, arity, idx)
|
||||
}
|
||||
}
|
||||
|
||||
match compiled_tl_index {
|
||||
Some(compiled_tl_index) => {
|
||||
let module_name = compiled_tl_index.1.clone();
|
||||
fn try_call(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex) -> CallResult
|
||||
{
|
||||
if idx.is_undefined() {
|
||||
machine_st.fail = true;
|
||||
} else {
|
||||
let compiled_tl_index = idx.0.get();
|
||||
let module_name = idx.1;
|
||||
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index.0, module_name);
|
||||
},
|
||||
None => machine_st.fail = true
|
||||
};
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn try_execute<'a>(&mut self, machine_st: &mut MachineState, code_dirs: CodeDirs<'a>,
|
||||
name: ClauseName, arity: usize)
|
||||
fn try_execute<'a>(&mut self, machine_st: &mut MachineState, arity: usize, idx: CodeIndex)
|
||||
-> CallResult
|
||||
{
|
||||
let compiled_tl_index = code_dirs.get(name, arity, &machine_st.p);
|
||||
{
|
||||
if idx.is_undefined() {
|
||||
machine_st.fail = true;
|
||||
} else {
|
||||
let compiled_tl_index = idx.0.get();
|
||||
let module_name = idx.1;
|
||||
|
||||
match compiled_tl_index {
|
||||
Some(compiled_tl_index) => {
|
||||
let module_name = compiled_tl_index.1.clone();
|
||||
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index.0, module_name);
|
||||
},
|
||||
None => machine_st.fail = true
|
||||
};
|
||||
machine_st.num_of_args = arity;
|
||||
machine_st.b0 = machine_st.b;
|
||||
machine_st.p = CodePtr::DirEntry(compiled_tl_index, module_name);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -396,7 +384,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
{
|
||||
match ct {
|
||||
&ClauseType::AcyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
@@ -422,21 +410,26 @@ pub(crate) trait CallPolicy: Any {
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::CallN =>
|
||||
&ClauseType::CallN => {
|
||||
if let Some((name, arity)) = machine_st.setup_call_n(arity) {
|
||||
self.context_call(machine_st, code_dirs, name, arity, lco)
|
||||
} else {
|
||||
Ok(())
|
||||
},
|
||||
if let Some(idx) = code_dirs.get(name, arity, &machine_st.p.clone()) {
|
||||
return self.context_call(machine_st, arity, idx, lco);
|
||||
} else {
|
||||
machine_st.fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Compare => {
|
||||
let a1 = machine_st[temp_v!(1)].clone();
|
||||
let a2 = machine_st[temp_v!(2)].clone();
|
||||
let a3 = machine_st[temp_v!(3)].clone();
|
||||
|
||||
let c = Addr::Con(match machine_st.compare_term_test(&a2, &a3) {
|
||||
Ordering::Greater => atom!(">", machine_st.atom_tbl),
|
||||
Ordering::Equal => atom!("=", machine_st.atom_tbl),
|
||||
Ordering::Less => atom!("<", machine_st.atom_tbl)
|
||||
Ordering::Greater => atom!(">"),
|
||||
Ordering::Equal => atom!("="),
|
||||
Ordering::Less => atom!("<")
|
||||
});
|
||||
|
||||
machine_st.unify(a1, c);
|
||||
@@ -454,7 +447,7 @@ pub(crate) trait CallPolicy: Any {
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
&ClauseType::CyclicTerm => {
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
let addr = machine_st[temp_v!(1)].clone();
|
||||
machine_st.fail = !machine_st.is_cyclic_term(addr);
|
||||
return_from_clause!(lco, machine_st)
|
||||
},
|
||||
@@ -522,12 +515,12 @@ pub(crate) trait CallPolicy: Any {
|
||||
if !lco {
|
||||
machine_st.cp = machine_st.p.clone() + 1;
|
||||
}
|
||||
|
||||
|
||||
machine_st.goto_throw();
|
||||
Ok(())
|
||||
},
|
||||
&ClauseType::Named(ref name) | &ClauseType::Op(ref name, _) =>
|
||||
self.context_call(machine_st, code_dirs, name.clone(), arity, lco),
|
||||
&ClauseType::Named(_, ref idx) | &ClauseType::Op(_, _, ref idx) =>
|
||||
self.context_call(machine_st, arity, idx.clone(), lco),
|
||||
&ClauseType::CallWithInferenceLimit => {
|
||||
machine_st.goto_ptr(CodePtr::DirEntry(393, clause_name!("builtin")), 3, lco);
|
||||
Ok(())
|
||||
|
||||
@@ -909,11 +909,14 @@ impl MachineState {
|
||||
self.registers[arity - 1] = pred;
|
||||
|
||||
if let Some((name, arity)) = self.setup_call_n(arity - 1) {
|
||||
try_or_fail!(self, call_policy.try_execute(self, code_dirs, name, arity));
|
||||
if let Some(idx) = code_dirs.get(name, arity, &self.p.clone()) {
|
||||
try_or_fail!(self, call_policy.try_execute(self, arity, idx));
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.fail = true;
|
||||
}
|
||||
|
||||
self.fail = true;
|
||||
}
|
||||
|
||||
pub(super) fn goto_throw(&mut self) {
|
||||
|
||||
@@ -25,8 +25,8 @@ pub struct Machine {
|
||||
call_policy: Box<CallPolicy>,
|
||||
cut_policy: Box<CutPolicy>,
|
||||
code: Code,
|
||||
code_dir: CodeDir,
|
||||
pub op_dir: OpDir,
|
||||
pub(super) code_dir: CodeDir,
|
||||
pub(super) op_dir: OpDir,
|
||||
term_dir: TermDir,
|
||||
modules: HashMap<ClauseName, Module>,
|
||||
cached_query: Option<Code>
|
||||
@@ -87,7 +87,7 @@ impl Machine {
|
||||
let name = name.defrock_brackets();
|
||||
|
||||
match self.code_dir.get(&(name.clone(), arity)).cloned() {
|
||||
Some((_, ref mod_name)) if mod_name == &module_name => {
|
||||
Some(CodeIndex (_, ref mod_name)) if mod_name == &module_name => {
|
||||
self.code_dir.remove(&(name.clone(), arity));
|
||||
|
||||
// remove or respecify ops.
|
||||
@@ -179,7 +179,7 @@ impl Machine {
|
||||
-> EvalSession
|
||||
{
|
||||
match self.code_dir.get(&(name.clone(), arity)) {
|
||||
Some(&(_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
|
||||
Some(&CodeIndex (_, ref mod_name)) if mod_name == &clause_name!("builtin") =>
|
||||
return EvalSession::from(EvalError::ImpermissibleEntry(format!("{}/{}", name, arity))),
|
||||
_ => {}
|
||||
};
|
||||
@@ -188,7 +188,12 @@ impl Machine {
|
||||
|
||||
self.code.extend(code.into_iter());
|
||||
self.term_dir.insert((name.clone(), arity), pred);
|
||||
self.code_dir.insert((name, arity), (offset, clause_name!("user")));
|
||||
|
||||
let entry = self.code_dir.entry((name, arity))
|
||||
.or_insert(CodeIndex::from((offset, clause_name!("user"))));
|
||||
|
||||
entry.0.set(offset);
|
||||
entry.1 = clause_name!("user");
|
||||
|
||||
EvalSession::EntrySuccess
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user