add global_count inference counter that is always incremented (#2009)
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@@ -1599,9 +1599,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.16"
|
version = "0.2.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2"
|
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -329,6 +329,8 @@ enum SystemClauseType {
|
|||||||
InstallSCCCleaner,
|
InstallSCCCleaner,
|
||||||
#[strum_discriminants(strum(props(Arity = "3", Name = "$install_inference_counter")))]
|
#[strum_discriminants(strum(props(Arity = "3", Name = "$install_inference_counter")))]
|
||||||
InstallInferenceCounter,
|
InstallInferenceCounter,
|
||||||
|
#[strum_discriminants(strum(props(Arity = "1", Name = "$inference_count")))]
|
||||||
|
InferenceCount,
|
||||||
#[strum_discriminants(strum(props(Arity = "1", Name = "$lh_length")))]
|
#[strum_discriminants(strum(props(Arity = "1", Name = "$lh_length")))]
|
||||||
LiftedHeapLength,
|
LiftedHeapLength,
|
||||||
#[strum_discriminants(strum(props(Arity = "3", Name = "$load_library_as_stream")))]
|
#[strum_discriminants(strum(props(Arity = "3", Name = "$load_library_as_stream")))]
|
||||||
@@ -1720,6 +1722,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::CallHeadIsDynamic |
|
&Instruction::CallHeadIsDynamic |
|
||||||
&Instruction::CallInstallSCCCleaner |
|
&Instruction::CallInstallSCCCleaner |
|
||||||
&Instruction::CallInstallInferenceCounter |
|
&Instruction::CallInstallInferenceCounter |
|
||||||
|
&Instruction::CallInferenceCount |
|
||||||
&Instruction::CallLiftedHeapLength |
|
&Instruction::CallLiftedHeapLength |
|
||||||
&Instruction::CallLoadLibraryAsStream |
|
&Instruction::CallLoadLibraryAsStream |
|
||||||
&Instruction::CallModuleExists |
|
&Instruction::CallModuleExists |
|
||||||
@@ -1954,6 +1957,7 @@ fn generate_instruction_preface() -> TokenStream {
|
|||||||
&Instruction::ExecuteHeadIsDynamic |
|
&Instruction::ExecuteHeadIsDynamic |
|
||||||
&Instruction::ExecuteInstallSCCCleaner |
|
&Instruction::ExecuteInstallSCCCleaner |
|
||||||
&Instruction::ExecuteInstallInferenceCounter |
|
&Instruction::ExecuteInstallInferenceCounter |
|
||||||
|
&Instruction::ExecuteInferenceCount |
|
||||||
&Instruction::ExecuteLiftedHeapLength |
|
&Instruction::ExecuteLiftedHeapLength |
|
||||||
&Instruction::ExecuteLoadLibraryAsStream |
|
&Instruction::ExecuteLoadLibraryAsStream |
|
||||||
&Instruction::ExecuteModuleExists |
|
&Instruction::ExecuteModuleExists |
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ macro_rules! try_or_throw {
|
|||||||
|
|
||||||
macro_rules! increment_call_count {
|
macro_rules! increment_call_count {
|
||||||
($s:expr) => {{
|
($s:expr) => {{
|
||||||
if !($s.increment_call_count_fn)(&mut $s) {
|
if !$s.increment_call_count() {
|
||||||
$s.backtrack();
|
$s.backtrack();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -3675,6 +3675,16 @@ impl Machine {
|
|||||||
try_or_throw!(self.machine_st, self.install_inference_counter());
|
try_or_throw!(self.machine_st, self.install_inference_counter());
|
||||||
step_or_fail!(self, self.machine_st.p = self.machine_st.cp);
|
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 => {
|
&Instruction::CallLiftedHeapLength => {
|
||||||
self.lifted_heap_length();
|
self.lifted_heap_length();
|
||||||
step_or_fail!(self, self.machine_st.p += 1);
|
step_or_fail!(self, self.machine_st.p += 1);
|
||||||
|
|||||||
@@ -96,7 +96,6 @@ pub struct MachineState {
|
|||||||
pub(crate) unify_fn: fn(&mut MachineState),
|
pub(crate) unify_fn: fn(&mut MachineState),
|
||||||
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
pub(crate) bind_fn: fn(&mut MachineState, Ref, HeapCellValue),
|
||||||
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
pub(crate) run_cleaners_fn: fn(&mut Machine) -> bool,
|
||||||
pub(crate) increment_call_count_fn: fn(&mut MachineState) -> bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MachineState {
|
impl fmt::Debug for MachineState {
|
||||||
@@ -417,15 +416,17 @@ impl MachineState {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.cwil.global_count += 1;
|
||||||
|
|
||||||
if let Some(&(ref limit, block)) = self.cwil.limits.last() {
|
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.cwil.inference_limit_exceeded = true;
|
||||||
self.block = block;
|
self.block = block;
|
||||||
self.unwind_stack();
|
self.unwind_stack();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
self.cwil.count += 1;
|
self.cwil.local_count += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -967,7 +968,8 @@ impl MachineState {
|
|||||||
#[allow(clippy::upper_case_acronyms)]
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub(crate) struct CWIL {
|
pub(crate) struct CWIL {
|
||||||
count: Integer,
|
local_count: Integer,
|
||||||
|
pub(crate) global_count: Integer,
|
||||||
limits: Vec<(Integer, usize)>,
|
limits: Vec<(Integer, usize)>,
|
||||||
pub(crate) inference_limit_exceeded: bool,
|
pub(crate) inference_limit_exceeded: bool,
|
||||||
}
|
}
|
||||||
@@ -975,22 +977,22 @@ pub(crate) struct CWIL {
|
|||||||
impl CWIL {
|
impl CWIL {
|
||||||
pub(crate) fn new() -> Self {
|
pub(crate) fn new() -> Self {
|
||||||
CWIL {
|
CWIL {
|
||||||
count: Integer::from(0),
|
local_count: Integer::from(0),
|
||||||
|
global_count: Integer::from(0),
|
||||||
limits: vec![],
|
limits: vec![],
|
||||||
inference_limit_exceeded: false,
|
inference_limit_exceeded: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn add_limit(&mut self, limit: usize, block: usize) -> &Integer {
|
pub(crate) fn add_limit(&mut self, mut limit: Integer, block: usize) -> &Integer {
|
||||||
let mut limit = Integer::from(limit);
|
limit += &self.local_count;
|
||||||
limit += &self.count;
|
|
||||||
|
|
||||||
match self.limits.last() {
|
match self.limits.last() {
|
||||||
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
Some((ref inner_limit, _)) if *inner_limit <= limit => {}
|
||||||
_ => self.limits.push((limit, block)),
|
_ => self.limits.push((limit, block)),
|
||||||
};
|
}
|
||||||
|
|
||||||
&self.count
|
&self.local_count
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@@ -1001,12 +1003,12 @@ impl CWIL {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&self.count
|
&self.local_count
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn reset(&mut self) {
|
pub(crate) fn reset(&mut self) {
|
||||||
self.count = Integer::from(0);
|
self.local_count = Integer::from(0);
|
||||||
self.limits.clear();
|
self.limits.clear();
|
||||||
self.inference_limit_exceeded = false;
|
self.inference_limit_exceeded = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,6 @@ impl MachineState {
|
|||||||
unify_fn: MachineState::unify,
|
unify_fn: MachineState::unify,
|
||||||
bind_fn: MachineState::bind,
|
bind_fn: MachineState::bind,
|
||||||
run_cleaners_fn: |_| false,
|
run_cleaners_fn: |_| false,
|
||||||
increment_call_count_fn: |_| true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
use crate::parser::ast::*;
|
use crate::parser::ast::*;
|
||||||
use crate::parser::parser::*;
|
use crate::parser::parser::*;
|
||||||
|
|
||||||
use dashu::integer::Sign;
|
use dashu::integer::{Sign, UBig};
|
||||||
use dashu::integer::UBig;
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use num_order::NumOrd;
|
use num_order::NumOrd;
|
||||||
|
|
||||||
@@ -5516,11 +5515,8 @@ impl Machine {
|
|||||||
let a2 = self.deref_register(2);
|
let a2 = self.deref_register(2);
|
||||||
|
|
||||||
let n = match Number::try_from(a2) {
|
let n = match Number::try_from(a2) {
|
||||||
Ok(Number::Fixnum(bp)) => bp.get_num() as usize,
|
Ok(Number::Fixnum(bp)) => Integer::from(bp.get_num() as usize),
|
||||||
Ok(Number::Integer(n)) => {
|
Ok(Number::Integer(n)) => (*n).clone(),
|
||||||
let value: usize = (&*n).try_into().unwrap();
|
|
||||||
value
|
|
||||||
}
|
|
||||||
_ => {
|
_ => {
|
||||||
let stub = functor_stub(atom!("call_with_inference_limit"), 3);
|
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 bp = cell_as_fixnum!(a1).get_num() as usize;
|
||||||
let a3 = self.deref_register(3);
|
let a3 = self.deref_register(3);
|
||||||
let count = self.machine_st.cwil.add_limit(n, bp);
|
|
||||||
|
|
||||||
let result = count.try_into();
|
let count = self.machine_st.cwil.add_limit(n, bp).clone();
|
||||||
if let Ok(value) = result {
|
self.inference_count(a3, count);
|
||||||
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;
|
|
||||||
|
|
||||||
Ok(())
|
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)]
|
#[inline(always)]
|
||||||
pub(crate) fn module_exists(&mut self) {
|
pub(crate) fn module_exists(&mut self) {
|
||||||
let module = self.deref_register(1);
|
let module = self.deref_register(1);
|
||||||
@@ -5671,7 +5670,6 @@ impl Machine {
|
|||||||
|
|
||||||
if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
|
if bp == self.machine_st.b && self.machine_st.cwil.is_empty() {
|
||||||
self.machine_st.cwil.reset();
|
self.machine_st.cwil.reset();
|
||||||
self.machine_st.increment_call_count_fn = |_| true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user