introduce InlineTermStream to avoid arena allocations during call_inline (#1576)

This commit is contained in:
Mark Thom
2022-11-08 23:55:22 +01:00
parent d91ee5b77c
commit 9366a48d6d
3 changed files with 84 additions and 14 deletions

View File

@@ -2428,9 +2428,9 @@ impl Machine {
module_name: HeapCellValue, module_name: HeapCellValue,
key: PredicateKey, key: PredicateKey,
) -> CodeIndex { ) -> CodeIndex {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> = Loader::new( let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new(
self, self,
LiveTermStream::new(ListingSource::User), InlineTermStream {},
); );
let module_name = if module_name.get_tag() == HeapCellValueTag::Atom { let module_name = if module_name.get_tag() == HeapCellValueTag::Atom {
@@ -2448,9 +2448,9 @@ impl Machine {
vars: &[Term], vars: &[Term],
) -> Result<(), SessionError> { ) -> Result<(), SessionError> {
let mut compile = || { let mut compile = || {
let mut loader: Loader<'_, LiveLoadAndMachineState<'_>> = Loader::new( let mut loader: Loader<'_, InlineLoadState<'_>> = Loader::new(
self, self,
LiveTermStream::new(ListingSource::User), InlineTermStream {},
); );
let term = loader.read_term_from_heap(term_loc)?; let term = loader.read_term_from_heap(term_loc)?;

View File

@@ -390,6 +390,64 @@ impl<'a> LoadState<'a> for BootstrappingLoadState<'a> {
} }
} }
pub struct InlineLoadState<'a> {
machine_st: &'a mut MachineState,
pub payload: LoadStatePayload<InlineTermStream>,
}
impl<'a> Deref for InlineLoadState<'a> {
type Target = LoadStatePayload<InlineTermStream>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.payload
}
}
impl<'a> DerefMut for InlineLoadState<'a> {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.payload
}
}
impl<'a> LoadState<'a> for InlineLoadState<'a> {
type TS = InlineTermStream;
type LoaderFieldType = InlineLoadState<'a>;
type Evacuable = ();
#[inline(always)]
fn new(machine_st: &'a mut MachineState, payload: LoadStatePayload<Self::TS>) -> Self::LoaderFieldType {
InlineLoadState { machine_st, payload }
}
fn evacuate(_loader: Loader<'a, Self>) -> Result<Self::Evacuable, SessionError> {
Ok(())
}
#[inline(always)]
fn should_drop_load_state(_loader: &Loader<'a, Self>) -> bool {
false
}
#[inline(always)]
fn reset_machine(_loader: &mut Loader<'a, Self>) {
}
#[inline(always)]
fn machine_st(load_state: &mut Self::LoaderFieldType) -> &mut MachineState {
&mut load_state.machine_st
}
#[inline(always)]
fn err_on_builtin_overwrite(
_loader: &Loader<'a, Self>,
_key: PredicateKey,
) -> Result<(), SessionError> {
Ok(())
}
}
pub struct Loader<'a, LS: LoadState<'a>> { pub struct Loader<'a, LS: LoadState<'a>> {
pub(super) payload: LS::LoaderFieldType, pub(super) payload: LS::LoaderFieldType,
pub(super) wam_prelude: MachinePreludeView<'a>, pub(super) wam_prelude: MachinePreludeView<'a>,
@@ -2389,21 +2447,15 @@ impl Machine {
} }
pub(crate) fn builtin_property(&mut self) { pub(crate) fn builtin_property(&mut self) {
let key = self let (name, arity) = self
.machine_st .machine_st
.read_predicate_key(self.machine_st.registers[1], self.machine_st.registers[2]); .read_predicate_key(self.machine_st.registers[1], self.machine_st.registers[2]);
match ClauseType::from(key.0, key.1, &mut self.machine_st.arena) { if !ClauseType::is_inbuilt(name, arity) { // ClauseType::from(key.0, key.1, &mut self.machine_st.arena) {
ClauseType::BuiltIn(_) | ClauseType::Inlined(..) | ClauseType::CallN(_) => { if let Some(module) = self.indices.modules.get(&(atom!("builtins"))) {
self.machine_st.fail = !module.code_dir.contains_key(&(name, arity));
return; return;
} }
ClauseType::Named(arity, name, _) => {
if let Some(module) = self.indices.modules.get(&(atom!("builtins"))) {
self.machine_st.fail = !module.code_dir.contains_key(&(name, arity));
return;
}
}
_ => {}
} }
self.machine_st.fail = true; self.machine_st.fail = true;

View File

@@ -119,3 +119,21 @@ impl TermStream for LiveTermStream {
&self.listing_src &self.listing_src
} }
} }
pub struct InlineTermStream {
}
impl TermStream for InlineTermStream {
fn next(&mut self, _: &CompositeOpDir) -> Result<Term, CompilationError> {
Err(CompilationError::from(ParserError::UnexpectedEOF))
}
fn eof(&mut self) -> Result<bool, CompilationError> {
Ok(true)
}
fn listing_src(&self) -> &ListingSource {
&ListingSource::User
}
}