improve efficiency of call/N, replace '$call_with_default_policy' with

'$call_with_inference_counting'
This commit is contained in:
Mark Thom
2022-06-12 22:17:44 -06:00
parent a68394b6f2
commit 987bbdecf5
12 changed files with 1116 additions and 621 deletions

View File

@@ -2039,12 +2039,15 @@ impl MachineState {
)
}
pub(super) fn setup_call_n(&mut self, arity: usize) -> Result<PredicateKey, MachineStub> {
let addr = self.store(self.deref(self.registers[arity]));
let (name, narity) = read_heap_cell!(addr,
pub(crate) fn setup_call_n_init_goal_info(
&mut self,
goal: HeapCellValue,
arity: usize,
) -> Result<(Atom, usize, usize), MachineStub> {
Ok(read_heap_cell!(goal,
(HeapCellValueTag::Str, s) => {
let (name, narity) = cell_as_atom_cell!(self.heap[s]).get_name_and_arity();
let (name, narity) = cell_as_atom_cell!(self.heap[s])
.get_name_and_arity();
if narity + arity > MAX_ARITY {
let stub = functor_stub(atom!("call"), arity + 1);
@@ -2052,34 +2055,48 @@ impl MachineState {
return Err(self.error_form(err, stub));
}
for i in (1..arity).rev() {
self.registers[i + narity] = self.registers[i];
}
for i in 1..narity + 1 {
self.registers[i] = self.heap[s + i];
}
(name, narity)
(name, narity, s)
}
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);
(name, 0)
if name == atom!("[]") {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.type_error(ValidType::Callable, goal);
return Err(self.error_form(err, stub));
}
(name, 0, 0)
}
(HeapCellValueTag::Char, c) => {
(self.atom_tbl.build_with(&c.to_string()), 0)
(self.atom_tbl.build_with(&c.to_string()), 0, 0)
}
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar, _h) => {
(HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.instantiation_error();
return Err(self.error_form(err, stub));
}
_ => {
let stub = functor_stub(atom!("call"), arity + 1);
let err = self.type_error(ValidType::Callable, addr);
let err = self.type_error(ValidType::Callable, goal);
return Err(self.error_form(err, stub));
}
);
))
}
pub(crate) fn setup_call_n(&mut self, arity: usize) -> Result<PredicateKey, MachineStub> {
let addr = self.store(self.deref(self.registers[arity]));
let (name, narity, s) = self.setup_call_n_init_goal_info(addr, arity)?;
if narity > 0 {
for i in (1..arity).rev() {
self.registers[i + narity] = self.registers[i];
}
for i in 1..narity + 1 {
self.registers[i] = self.heap[s + i];
}
}
Ok((name, arity + narity - 1))
}