add global_count inference counter that is always incremented (#2009)

This commit is contained in:
Mark
2023-11-20 16:24:31 -07:00
parent 1e5bb2d3da
commit 54166b91eb
6 changed files with 47 additions and 34 deletions

4
Cargo.lock generated
View File

@@ -1599,9 +1599,9 @@ dependencies = [
[[package]]
name = "num-traits"
version = "0.2.16"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
dependencies = [
"autocfg",
]

View File

@@ -329,6 +329,8 @@ enum SystemClauseType {
InstallSCCCleaner,
#[strum_discriminants(strum(props(Arity = "3", Name = "$install_inference_counter")))]
InstallInferenceCounter,
#[strum_discriminants(strum(props(Arity = "1", Name = "$inference_count")))]
InferenceCount,
#[strum_discriminants(strum(props(Arity = "1", Name = "$lh_length")))]
LiftedHeapLength,
#[strum_discriminants(strum(props(Arity = "3", Name = "$load_library_as_stream")))]
@@ -1720,6 +1722,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::CallHeadIsDynamic |
&Instruction::CallInstallSCCCleaner |
&Instruction::CallInstallInferenceCounter |
&Instruction::CallInferenceCount |
&Instruction::CallLiftedHeapLength |
&Instruction::CallLoadLibraryAsStream |
&Instruction::CallModuleExists |
@@ -1954,6 +1957,7 @@ fn generate_instruction_preface() -> TokenStream {
&Instruction::ExecuteHeadIsDynamic |
&Instruction::ExecuteInstallSCCCleaner |
&Instruction::ExecuteInstallInferenceCounter |
&Instruction::ExecuteInferenceCount |
&Instruction::ExecuteLiftedHeapLength |
&Instruction::ExecuteLoadLibraryAsStream |
&Instruction::ExecuteModuleExists |

View File

@@ -36,7 +36,7 @@ macro_rules! try_or_throw {
macro_rules! increment_call_count {
($s:expr) => {{
if !($s.increment_call_count_fn)(&mut $s) {
if !$s.increment_call_count() {
$s.backtrack();
continue;
}
@@ -3675,6 +3675,16 @@ impl Machine {
try_or_throw!(self.machine_st, self.install_inference_counter());
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallInferenceCount => {
let global_count = self.machine_st.cwil.global_count.clone();
self.inference_count(self.machine_st.registers[1], global_count);
step_or_fail!(self, self.machine_st.p += 1);
}
&Instruction::ExecuteInferenceCount => {
let global_count = self.machine_st.cwil.global_count.clone();
self.inference_count(self.machine_st.registers[1], global_count);
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
}
&Instruction::CallLiftedHeapLength => {
self.lifted_heap_length();
step_or_fail!(self, self.machine_st.p += 1);

View File

@@ -96,7 +96,6 @@ pub struct MachineState {
pub(crate) unify_fn: fn(&mut MachineState),
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
pub(crate) increment_call_count_fn: fn(&mut MachineState) -> bool,
}
impl fmt::Debug for MachineState {
@@ -417,15 +416,17 @@ impl MachineState {
return true;
}
self.cwil.global_count += 1;
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
if self.cwil.count == *limit {
if self.cwil.local_count == *limit {
self.cwil.inference_limit_exceeded = true;
self.block = block;
self.unwind_stack();
return false;
} else {
self.cwil.count += 1;
self.cwil.local_count += 1;
}
}
@@ -967,7 +968,8 @@ impl MachineState {
#[allow(clippy::upper_case_acronyms)]
#[derive(Debug)]
pub(crate) struct CWIL {
count: Integer,
local_count: Integer,
pub(crate) global_count: Integer,
limits: Vec<(Integer, usize)>,
pub(crate) inference_limit_exceeded: bool,
}
@@ -975,22 +977,22 @@ pub(crate) struct CWIL {
impl CWIL {
pub(crate) fn new() -> Self {
CWIL {
count: Integer::from(0),
local_count: Integer::from(0),
global_count: Integer::from(0),
limits: vec![],
inference_limit_exceeded: false,
}
}
pub(crate) fn add_limit(&mut self, limit: usize, block: usize) -> &Integer {
let mut limit = Integer::from(limit);
limit += &self.count;
pub(crate) fn add_limit(&mut self, mut limit: Integer, block: usize) -> &Integer {
limit += &self.local_count;
match self.limits.last() {
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
_ => self.limits.push((limit, block)),
};
}
&self.count
&self.local_count
}
#[inline(always)]
@@ -1001,12 +1003,12 @@ impl CWIL {
}
}
&self.count
&self.local_count
}
#[inline(always)]
pub(crate) fn reset(&mut self) {
self.count = Integer::from(0);
self.local_count = Integer::from(0);
self.limits.clear();
self.inference_limit_exceeded = false;
}

View File

@@ -60,7 +60,6 @@ impl MachineState {
unify_fn: MachineState::unify,
bind_fn: MachineState::bind,
run_cleaners_fn: |_| false,
increment_call_count_fn: |_| true,
}
}

View File

@@ -1,8 +1,7 @@
use crate::parser::ast::*;
use crate::parser::parser::*;
use dashu::integer::Sign;
use dashu::integer::UBig;
use dashu::integer::{Sign, UBig};
use lazy_static::lazy_static;
use num_order::NumOrd;
@@ -5516,11 +5515,8 @@ impl Machine {
let a2 = self.deref_register(2);
let n = match Number::try_from(a2) {
Ok(Number::Fixnum(bp)) => bp.get_num() as usize,
Ok(Number::Integer(n)) => {
let value: usize = (&*n).try_into().unwrap();
value
}
Ok(Number::Fixnum(bp)) => Integer::from(bp.get_num() as usize),
Ok(Number::Integer(n)) => (*n).clone(),
_ => {
let stub = functor_stub(atom!("call_with_inference_limit"), 3);
@@ -5531,21 +5527,24 @@ impl Machine {
let bp = cell_as_fixnum!(a1).get_num() as usize;
let a3 = self.deref_register(3);
let count = self.machine_st.cwil.add_limit(n, bp);
let result = count.try_into();
if let Ok(value) = result {
self.machine_st.unify_fixnum(Fixnum::build_with(value), a3);
} else {
let count = arena_alloc!(count.clone(), &mut self.machine_st.arena);
self.machine_st.unify_big_int(count, a3);
}
self.machine_st.increment_call_count_fn = MachineState::increment_call_count;
let count = self.machine_st.cwil.add_limit(n, bp).clone();
self.inference_count(a3, count);
Ok(())
}
#[inline(always)]
pub(crate) fn inference_count(&mut self, count_var: HeapCellValue, count: Integer) {
if let Some(value) = <&Integer as TryInto<i64>>::try_into(&count).ok() {
self.machine_st
.unify_fixnum(Fixnum::build_with(value), count_var);
} else {
let count = arena_alloc!(count, &mut self.machine_st.arena);
self.machine_st.unify_big_int(count, count_var);
}
}
#[inline(always)]
pub(crate) fn module_exists(&mut self) {
let module = self.deref_register(1);
@@ -5671,7 +5670,6 @@ impl Machine {
if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
self.machine_st.cwil.reset();
self.machine_st.increment_call_count_fn = |_| true;
}
}