From 8902bcb5ab30033fd4292d3a164b273e3930f4c6 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 16 Feb 2020 16:30:36 -0700 Subject: [PATCH] use raw_block.rs for the heap backend --- src/prolog/machine/dynamic_database.rs | 2 +- src/prolog/machine/heap.rs | 253 ++++++++++++++++++----- src/prolog/machine/machine_errors.rs | 4 +- src/prolog/machine/machine_indices.rs | 14 +- src/prolog/machine/machine_state.rs | 51 +++-- src/prolog/machine/machine_state_impl.rs | 56 ++--- src/prolog/machine/mod.rs | 12 +- src/prolog/machine/raw_block.rs | 8 +- src/prolog/machine/stack.rs | 2 + src/prolog/machine/system_calls.rs | 101 +++++---- src/prolog/machine/term_expansion.rs | 2 +- src/prolog/read.rs | 6 +- 12 files changed, 347 insertions(+), 164 deletions(-) diff --git a/src/prolog/machine/dynamic_database.rs b/src/prolog/machine/dynamic_database.rs index f76601bf..44871b4c 100644 --- a/src/prolog/machine/dynamic_database.rs +++ b/src/prolog/machine/dynamic_database.rs @@ -134,7 +134,7 @@ impl Machine { self.machine_st = machine_st; if let EvalSession::Error(err) = result { - let h = self.machine_st.heap.h; + let h = self.machine_st.heap.h(); let stub = MachineError::functor_stub(src, 1); let err = MachineError::session_error(h, err); let err = self.machine_st.error_form(err, stub); diff --git a/src/prolog/machine/heap.rs b/src/prolog/machine/heap.rs index da3cc218..b3d406e3 100644 --- a/src/prolog/machine/heap.rs +++ b/src/prolog/machine/heap.rs @@ -1,99 +1,252 @@ -use prolog_parser::ast::*; +use core::marker::PhantomData; + +use crate::prolog_parser::ast::*; use crate::prolog::machine::machine_indices::*; +use crate::prolog::machine::raw_block::*; use std::mem; use std::ops::{Index, IndexMut}; +use std::ptr; + +pub(crate) struct StandardHeapTraits {} + +impl RawBlockTraits for StandardHeapTraits { + #[inline] + fn init_size() -> usize { + 256 * mem::size_of::() + } + + #[inline] + fn align() -> usize { + mem::align_of::() + } +} -pub struct Heap { - heap: Vec, - pub h: usize, +pub(crate) struct HeapTemplate { + buf: RawBlock, + _marker: PhantomData, } -impl Heap { - pub fn with_capacity(cap: usize) -> Self { - Heap { - heap: Vec::with_capacity(cap), - h: 0, +pub(crate) type Heap = HeapTemplate; + +impl Drop for HeapTemplate { + fn drop(&mut self) { + self.clear(); + self.buf.deallocate(); + } +} + +pub(crate) +struct HeapIntoIterator { + offset: usize, + buf: RawBlock, +} + +impl Drop for HeapIntoIterator { + fn drop(&mut self) { + let mut heap = + HeapTemplate { buf: self.buf.take(), _marker: PhantomData }; + + heap.truncate(self.offset / mem::size_of::()); + heap.buf.deallocate(); + } +} + +impl Iterator for HeapIntoIterator { + type Item = HeapCellValue; + + fn next(&mut self) -> Option { + let ptr = self.buf.base as usize + self.offset; + self.offset += mem::size_of::(); + + if ptr < self.buf.top as usize { + unsafe { + Some(ptr::read(ptr as *const HeapCellValue)) + } + } else { + None } } +} - #[inline] - pub fn push(&mut self, val: HeapCellValue) { - self.heap.push(val); - self.h += 1; +pub(crate) +struct HeapIterator<'a, T: RawBlockTraits> { + offset: usize, + buf: &'a RawBlock, +} + +impl<'a, T: RawBlockTraits> HeapIterator<'a, T> { + pub(crate) + fn new(buf: &'a RawBlock, offset: usize) -> Self { + HeapIterator { buf, offset } } +} - #[inline] - pub(crate) fn take(&mut self) -> Self { - let h = self.h; - self.h = 0; +impl<'a, T: RawBlockTraits> Iterator for HeapIterator<'a, T> { + type Item = &'a HeapCellValue; + + fn next(&mut self) -> Option { + let ptr = self.buf.base as usize + self.offset; + self.offset += mem::size_of::(); - Heap { - heap: mem::replace(&mut self.heap, vec![]), - h, + if ptr < self.buf.top as usize { + unsafe { + Some(&*(ptr as *const _)) + } + } else { + None } } +} +pub(crate) +struct HeapIteratorMut<'a, T: RawBlockTraits> { + offset: usize, + buf: &'a mut RawBlock, +} + +impl<'a, T: RawBlockTraits> HeapIteratorMut<'a, T> { + pub(crate) + fn new(buf: &'a mut RawBlock, offset: usize) -> Self { + HeapIteratorMut { buf, offset } + } +} + +impl<'a, T: RawBlockTraits> Iterator for HeapIteratorMut<'a, T> { + type Item = &'a mut HeapCellValue; + + fn next(&mut self) -> Option { + let ptr = self.buf.base as usize + self.offset; + self.offset += mem::size_of::(); + + if ptr < self.buf.top as usize { + unsafe { + Some(&mut *(ptr as *mut _)) + } + } else { + None + } + } +} + +impl HeapTemplate { #[inline] - pub fn truncate(&mut self, h: usize) { - self.h = h; - self.heap.truncate(h); + pub(crate) + fn new() -> Self { + HeapTemplate { buf: RawBlock::new(), _marker: PhantomData } } #[inline] - pub fn last(&self) -> Option<&HeapCellValue> { - self.heap.last() + pub(crate) + fn push(&mut self, val: HeapCellValue) { + unsafe { + let new_top = self.buf.new_block(mem::size_of::()); + ptr::write(self.buf.top as *mut _, val); + self.buf.top = new_top; + } } #[inline] - pub fn len(&self) -> usize { - self.heap.len() + pub(crate) + fn take(&mut self) -> HeapTemplate { + unsafe { + HeapTemplate { + buf: mem::transmute::, RawBlock>(self.buf.take()), + _marker: PhantomData, + } + } + } + + #[inline] + pub(crate) + fn truncate(&mut self, h: usize) { + let new_top = h * mem::size_of::() + self.buf.base as usize; + let mut h = new_top; + + unsafe { + while h as *const _ < self.buf.top { + let val = h as *mut HeapCellValue; + ptr::drop_in_place(val); + h += mem::size_of::(); + } + } + + self.buf.top = new_top as *const _; } - pub fn append(&mut self, vals: Vec) { - let n = vals.len(); + #[inline] + pub(crate) + fn h(&self) -> usize { + (self.buf.top as usize - self.buf.base as usize) / mem::size_of::() + } - self.heap.extend(vals.into_iter()); - self.h += n; + pub(crate) + fn append(&mut self, vals: Vec) { + for val in vals { + self.push(val); + } } - pub fn clear(&mut self) { - self.heap.clear(); - self.h = 0; + pub(crate) + fn clear(&mut self) { + if !self.buf.base.is_null() { + self.truncate(0); + self.buf.top = self.buf.base; + } } - pub fn to_list>(&mut self, values: Iter) -> usize { - let head_addr = self.h; + pub(crate) + fn to_list>(&mut self, values: Iter) -> usize { + let head_addr = self.h(); for value in values { - let h = self.h; + let h = self.h(); self.push(HeapCellValue::Addr(Addr::Lis(h + 1))); self.push(HeapCellValue::Addr(value)); } self.push(HeapCellValue::Addr(Addr::Con(Constant::EmptyList))); + head_addr } - pub fn extend>(&mut self, iter: Iter) { + /* Create an iterator starting from the passed offset. */ + pub(crate) + fn iter_from<'a>(&'a self, offset: usize) -> HeapIterator<'a, T> { + HeapIterator::new(&self.buf, offset * mem::size_of::()) + } + + pub(crate) + fn iter_mut_from<'a>(&'a mut self, offset: usize) -> HeapIteratorMut<'a, T> { + HeapIteratorMut::new(&mut self.buf, offset * mem::size_of::()) + } + + pub(crate) + fn into_iter(mut self) -> HeapIntoIterator { + HeapIntoIterator { buf: self.buf.take(), offset: 0 } + } + + pub(crate) + fn extend>(&mut self, iter: Iter) { for hcv in iter { self.push(hcv); } } - pub fn to_local_code_ptr(&self, addr: &Addr) -> Option { + pub(crate) + fn to_local_code_ptr(&self, addr: &Addr) -> Option { let extract_integer = |s: usize| -> Option { - match self.heap[s].as_addr(s) { + match self[s].as_addr(s) { Addr::Con(Constant::Integer(n)) => n.to_usize(), _ => None } }; - + match addr { Addr::Str(s) => { - match &self.heap[*s] { + match &self[*s] { HeapCellValue::NamedStr(arity, ref name, _) => { match (name.as_str(), *arity) { ("dir_entry", 1) => { @@ -128,16 +281,24 @@ impl Heap { } } -impl Index for Heap { +impl Index for HeapTemplate { type Output = HeapCellValue; + #[inline] fn index(&self, index: usize) -> &Self::Output { - &self.heap[index] + unsafe { + let ptr = self.buf.base as usize + index * mem::size_of::(); + &*(ptr as *const HeapCellValue) + } } } -impl IndexMut for Heap { +impl IndexMut for HeapTemplate { + #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { - &mut self.heap[index] + unsafe { + let ptr = self.buf.base as usize + index * mem::size_of::(); + &mut *(ptr as *mut HeapCellValue) + } } } diff --git a/src/prolog/machine/machine_errors.rs b/src/prolog/machine/machine_errors.rs index 5596d71b..c084c645 100644 --- a/src/prolog/machine/machine_errors.rs +++ b/src/prolog/machine/machine_errors.rs @@ -485,7 +485,7 @@ impl MachineState { let location = err.location; let err_len = err.len(); - let h = self.heap.h; + let h = self.heap.h(); let mut stub = vec![ HeapCellValue::NamedStr(2, clause_name!("error"), None), HeapCellValue::Addr(Addr::HeapCell(h + 3)), @@ -512,7 +512,7 @@ impl MachineState { } pub(super) fn throw_exception(&mut self, err: MachineStub) { - let h = self.heap.h; + let h = self.heap.h(); self.ball.boundary = 0; self.ball.stub.truncate(0); diff --git a/src/prolog/machine/machine_indices.rs b/src/prolog/machine/machine_indices.rs index 0d1aac8b..44e086b1 100644 --- a/src/prolog/machine/machine_indices.rs +++ b/src/prolog/machine/machine_indices.rs @@ -6,7 +6,8 @@ use crate::prolog::fixtures::*; use crate::prolog::forms::*; use crate::prolog::machine::code_repo::CodeRepo; use crate::prolog::machine::Ball; -use crate::prolog::machine::heap::Heap; +use crate::prolog::machine::heap::*; +use crate::prolog::machine::raw_block::RawBlockTraits; use crate::prolog::instructions::*; use crate::prolog::rug::Integer; @@ -350,14 +351,16 @@ pub enum LocalCodePtr { } impl LocalCodePtr { - pub fn assign_if_local(&mut self, cp: CodePtr) { + pub(crate) + fn assign_if_local(&mut self, cp: CodePtr) { match cp { CodePtr::Local(local) => *self = local, _ => {} } } - pub fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool { + pub(crate) + fn is_reset_cont_marker(&self, code_repo: &CodeRepo, last_call: bool) -> bool { match code_repo.lookup_instr(last_call, &CodePtr::Local(*self)) { Some(line) => { match line.as_ref() { @@ -375,8 +378,9 @@ impl LocalCodePtr { false } - pub fn as_functor(&self, heap: &mut Heap) -> Addr { - let addr = Addr::HeapCell(heap.h); + pub(crate) + fn as_functor(&self, heap: &mut HeapTemplate) -> Addr { + let addr = Addr::HeapCell(heap.h()); match self { LocalCodePtr::DirEntry(p) => { diff --git a/src/prolog/machine/machine_state.rs b/src/prolog/machine/machine_state.rs index ab7c9b04..5eb4dccc 100644 --- a/src/prolog/machine/machine_state.rs +++ b/src/prolog/machine/machine_state.rs @@ -20,15 +20,15 @@ use std::mem; use std::ops::{Index, IndexMut}; pub struct Ball { - pub(super) boundary: usize, // ball.0 - pub(super) stub: MachineStub, // ball.1 + pub(super) boundary: usize, + pub(super) stub: Heap, } impl Ball { pub(super) fn new() -> Self { Ball { boundary: 0, - stub: MachineStub::new(), + stub: Heap::new(), } } @@ -43,20 +43,18 @@ impl Ball { Ball { boundary, - stub: mem::replace(&mut self.stub, vec![]), + stub: self.stub.take(), } } - pub(super) fn copy_and_align(&self, h: usize) -> MachineStub { + pub(super) fn copy_and_align(&self, h: usize) -> Heap { let diff = self.boundary as i64 - h as i64; - let mut stub = vec![]; - - for index in 0..self.stub.len() { - let heap_value = self.stub[index].clone(); + let mut stub = Heap::new(); + for heap_value in self.stub.iter_from(0).cloned() { stub.push(match heap_value { HeapCellValue::Addr(addr) => HeapCellValue::Addr(addr - diff), - _ => heap_value, + heap_value => heap_value, }); } @@ -91,7 +89,7 @@ impl<'a> IndexMut for CopyTerm<'a> { // the ordinary, heap term copier, used by duplicate_term. impl<'a> CopierTarget for CopyTerm<'a> { fn threshold(&self) -> usize { - self.state.heap.h + self.state.heap.h() } fn push(&mut self, hcv: HeapCellValue) { @@ -115,16 +113,17 @@ pub(super) struct CopyBallTerm<'a> { stack: &'a mut Stack, heap: &'a mut Heap, heap_boundary: usize, - stub: &'a mut MachineStub, + stub: &'a mut Heap, } impl<'a> CopyBallTerm<'a> { pub(super) fn new( stack: &'a mut Stack, heap: &'a mut Heap, - stub: &'a mut MachineStub, + stub: &'a mut Heap, ) -> Self { - let hb = heap.len(); + let hb = heap.h(); + CopyBallTerm { stack, heap, @@ -161,7 +160,7 @@ impl<'a> IndexMut for CopyBallTerm<'a> { // the ordinary, heap term copier, used by duplicate_term. impl<'a> CopierTarget for CopyBallTerm<'a> { fn threshold(&self) -> usize { - self.heap_boundary + self.stub.len() + self.heap_boundary + self.stub.h() } fn push(&mut self, value: HeapCellValue) { @@ -253,7 +252,7 @@ pub struct MachineState { pub(super) hb: usize, pub(super) block: usize, // an offset into the OR stack. pub(super) ball: Ball, - pub(super) lifted_heap: Vec, + pub(super) lifted_heap: Heap, pub(super) interms: Vec, // intermediate numbers. pub(super) last_call: bool, pub(crate) heap_locs: HeapVarDict, @@ -268,7 +267,7 @@ impl MachineState { let mut iter = addrs.iter(); while let Some(addr) = iter.next() { - match addr { + match addr { &Addr::Con(Constant::String(n, ref s)) if self.flags.double_quotes.is_chars() => { if s.len() < n { @@ -278,7 +277,7 @@ impl MachineState { if iter.next().is_some() { return Err(MachineError::type_error(ValidType::Character, addr.clone())); } - } + } &Addr::Con(Constant::Char(c)) => { chars.push(c); } @@ -368,7 +367,7 @@ impl MachineState { } } - let h = self.heap.h; + let h = self.heap.h(); let stub = MachineError::functor_stub(name.clone(), arity); let err = MachineError::module_resolution_error(h, module_name, name, arity); @@ -412,7 +411,7 @@ fn try_in_situ( Ok(()) } else { let stub = MachineError::functor_stub(name.clone(), arity); - let h = machine_st.heap.h; + let h = machine_st.heap.h(); let key = ExistenceError::Procedure(name, arity); Err(machine_st.error_form(MachineError::existence_error(h, key), stub)) @@ -455,7 +454,7 @@ pub(crate) trait CallPolicy: Any { attr_var_init_bindings_b, ); - machine_st.hb = machine_st.heap.h; + machine_st.hb = machine_st.heap.h(); machine_st.p += 1; Ok(()) @@ -491,7 +490,7 @@ pub(crate) trait CallPolicy: Any { machine_st.attr_var_init.backtrack(attr_var_init_queue_b, attr_var_init_bindings_b); - machine_st.hb = machine_st.heap.h; + machine_st.hb = machine_st.heap.h(); machine_st.p += offset; Ok(()) @@ -530,7 +529,7 @@ pub(crate) trait CallPolicy: Any { machine_st.stack.truncate(machine_st.b); machine_st.b = machine_st.stack.index_or_frame(b).prelude.b; - machine_st.hb = machine_st.heap.h; + machine_st.hb = machine_st.heap.h(); machine_st.p += offset; Ok(()) @@ -570,7 +569,7 @@ pub(crate) trait CallPolicy: Any { machine_st.stack.truncate(machine_st.b); machine_st.b = machine_st.stack.index_or_frame(b).prelude.b; - machine_st.hb = machine_st.heap.h; + machine_st.hb = machine_st.heap.h(); machine_st.p += 1; Ok(()) @@ -716,7 +715,7 @@ pub(crate) trait CallPolicy: Any { machine_st.unify(addr, Addr::HeapCell(offset.heap_loc)); } Err(e) => { - let h = machine_st.heap.h; + let h = machine_st.heap.h(); let stub = MachineError::functor_stub(clause_name!("read"), 1); let err = MachineError::syntax_error(h, e); let err = machine_st.error_form(err, stub); @@ -967,7 +966,7 @@ impl CWILCallPolicy { } fn increment(&mut self, machine_st: &MachineState) -> CallResult { - if self.inference_limit_exceeded || machine_st.ball.stub.len() > 0 { + if self.inference_limit_exceeded || machine_st.ball.stub.h() > 0 { return Ok(()); } diff --git a/src/prolog/machine/machine_state_impl.rs b/src/prolog/machine/machine_state_impl.rs index a305ab72..e18cee94 100644 --- a/src/prolog/machine/machine_state_impl.rs +++ b/src/prolog/machine/machine_state_impl.rs @@ -60,7 +60,7 @@ impl MachineState { cp: LocalCodePtr::default(), attr_var_init: AttrVarInitializer::new(0, 0), fail: false, - heap: Heap::with_capacity(1024), + heap: Heap::new(), mode: MachineMode::Write, stack: Stack::new(), registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used. @@ -69,7 +69,7 @@ impl MachineState { hb: 0, block: 0, ball: Ball::new(), - lifted_heap: Vec::with_capacity(1024), + lifted_heap: Heap::new(), interms: vec![Number::default(); 256], last_call: false, heap_locs: HeapVarDict::new(), @@ -78,7 +78,7 @@ impl MachineState { } } - pub(crate) fn with_capacity(capacity: usize) -> Self { + pub(crate) fn with_small_heap() -> Self { MachineState { s: 0, p: CodePtr::default(), @@ -89,7 +89,7 @@ impl MachineState { cp: LocalCodePtr::default(), attr_var_init: AttrVarInitializer::new(0, 0), fail: false, - heap: Heap::with_capacity(capacity), + heap: Heap::new(), mode: MachineMode::Write, stack: Stack::new(), registers: vec![Addr::HeapCell(0); MAX_ARITY + 1], // self.registers[0] is never used. @@ -98,7 +98,7 @@ impl MachineState { hb: 0, block: 0, ball: Ball::new(), - lifted_heap: Vec::with_capacity(capacity), + lifted_heap: Heap::new(), interms: vec![Number::default(); 0], last_call: false, heap_locs: HeapVarDict::new(), @@ -109,7 +109,7 @@ impl MachineState { #[allow(dead_code)] pub fn print_heap(&self, start: usize) { - for h in start .. self.heap.h { + for h in start .. self.heap.h() { println!("{} : {}", h, self.heap[h]); } } @@ -1377,7 +1377,7 @@ impl MachineState { fn get_char_list(&mut self, offset: usize, s: Rc) { if let Some(c) = s[offset ..].chars().next() { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::Char(c)))); self.heap.push(HeapCellValue::Addr(Addr::Con(Constant::String( @@ -1413,7 +1413,7 @@ impl MachineState { addr @ Addr::AttrVar(_) | addr @ Addr::StackCell(..) | addr @ Addr::HeapCell(_) => { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::Lis(h + 1))); self.bind(addr.as_var().unwrap(), Addr::HeapCell(h)); @@ -1444,7 +1444,7 @@ impl MachineState { } } Addr::AttrVar(_) | Addr::HeapCell(_) | Addr::StackCell(_, _) => { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::Str(h + 1))); self.heap @@ -1481,7 +1481,7 @@ impl MachineState { match self.mode { MachineMode::Read => self[reg] = self.heap[self.s].as_addr(self.s), MachineMode::Write => { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self[reg] = Addr::HeapCell(h); @@ -1500,7 +1500,7 @@ impl MachineState { } MachineMode::Write => { let addr = self.deref(self[reg].clone()); - let h = self.heap.h; + let h = self.heap.h(); if let Addr::HeapCell(hc) = addr { if hc < h { @@ -1540,7 +1540,7 @@ impl MachineState { match self.mode { MachineMode::Read => self.s += n, MachineMode::Write => { - let h = self.heap.h; + let h = self.heap.h(); for i in h..h + n { self.heap.push(HeapCellValue::Addr(Addr::HeapCell(i))); @@ -1633,9 +1633,9 @@ impl MachineState { &QueryInstruction::PutConstant(_, ref constant, reg) => { self[reg] = Addr::Con(constant.clone()) } - &QueryInstruction::PutList(_, reg) => self[reg] = Addr::Lis(self.heap.h), + &QueryInstruction::PutList(_, reg) => self[reg] = Addr::Lis(self.heap.h()), &QueryInstruction::PutStructure(ref ct, arity, reg) => { - let h = self.heap.h; + let h = self.heap.h(); self.heap .push(HeapCellValue::NamedStr(arity, ct.name(), ct.spec())); @@ -1648,7 +1648,7 @@ impl MachineState { if addr.is_protected(e) { self.registers[arg] = self.store(addr); } else { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self.bind(Ref::HeapCell(h), addr); @@ -1666,7 +1666,7 @@ impl MachineState { self.registers[arg] = self[norm].clone(); } RegType::Temp(_) => { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self[norm] = Addr::HeapCell(h); @@ -1679,7 +1679,7 @@ impl MachineState { } &QueryInstruction::SetLocalValue(reg) => { let addr = self.deref(self[reg].clone()); - let h = self.heap.h; + let h = self.heap.h(); if let Addr::HeapCell(hc) = addr { if hc < h { @@ -1693,7 +1693,7 @@ impl MachineState { self.bind(Ref::HeapCell(h), addr); } &QueryInstruction::SetVariable(reg) => { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self[reg] = Addr::HeapCell(h); } @@ -1702,7 +1702,7 @@ impl MachineState { self.heap.push(HeapCellValue::Addr(heap_val)); } &QueryInstruction::SetVoid(n) => { - let h = self.heap.h; + let h = self.heap.h(); for i in h..h + n { self.heap.push(HeapCellValue::Addr(Addr::HeapCell(i))); @@ -1715,7 +1715,7 @@ impl MachineState { self.ball.reset(); let addr = self[temp_v!(1)].clone(); - self.ball.boundary = self.heap.h; + self.ball.boundary = self.heap.h(); copy_term( CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.ball.stub), @@ -2411,16 +2411,16 @@ impl MachineState { let spec = fetch_atom_op_spec(name.clone(), spec, op_dir); let f_a = if name.as_str() == "." && arity == 2 { - Addr::Lis(self.heap.h) + Addr::Lis(self.heap.h()) } else { - let h = self.heap.h; + let h = self.heap.h(); self.heap .push(HeapCellValue::NamedStr(arity as usize, name, spec)); Addr::Str(h) }; for _ in 0..arity { - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); } @@ -2631,7 +2631,7 @@ impl MachineState { } pub(super) fn copy_term(&mut self, attr_var_policy: AttrVarPolicy) { - let old_h = self.heap.h; + let old_h = self.heap.h(); let a1 = self[temp_v!(1)].clone(); let a2 = self[temp_v!(2)].clone(); @@ -2904,7 +2904,7 @@ impl MachineState { or_frame.prelude.b = self.b; or_frame.prelude.bp = self.p.local() + 1; or_frame.prelude.tr = self.tr; - or_frame.prelude.h = self.heap.h; + or_frame.prelude.h = self.heap.h(); or_frame.prelude.b0 = self.b0; or_frame.prelude.attr_var_init_queue_b = @@ -2918,7 +2918,7 @@ impl MachineState { self.stack.index_or_frame_mut(b)[i-1] = self.registers[i].clone(); } - self.hb = self.heap.h; + self.hb = self.heap.h(); self.p += offset; } &IndexedChoiceInstruction::Retry(l) => try_or_fail!(self, call_policy.retry(self, l)), @@ -2943,7 +2943,7 @@ impl MachineState { or_frame.prelude.b = self.b; or_frame.prelude.bp = self.p.local() + offset; or_frame.prelude.tr = self.tr; - or_frame.prelude.h = self.heap.h; + or_frame.prelude.h = self.heap.h(); or_frame.prelude.b0 = self.b0; or_frame.prelude.attr_var_init_queue_b = self.attr_var_init.attr_var_queue.len(); @@ -2956,7 +2956,7 @@ impl MachineState { self.stack.index_or_frame_mut(b)[i-1] = self.registers[i].clone(); } - self.hb = self.heap.h; + self.hb = self.heap.h(); self.p += 1; } &ChoiceInstruction::DefaultRetryMeElse(offset) => { diff --git a/src/prolog/machine/mod.rs b/src/prolog/machine/mod.rs index d2abfef2..e1f0265b 100644 --- a/src/prolog/machine/mod.rs +++ b/src/prolog/machine/mod.rs @@ -5,7 +5,7 @@ use crate::prolog::clause_types::*; use crate::prolog::forms::*; use crate::prolog::heap_print::*; use crate::prolog::instructions::*; -use crate::prolog::machine::heap::Heap; +use crate::prolog::machine::heap::*; use crate::prolog::read::*; mod attributed_variables; @@ -335,7 +335,7 @@ impl Machine { { let mut wam = Machine { machine_st: MachineState::new(), - inner_heap: Heap::with_capacity(256 * 256), + inner_heap: Heap::new(), policies: MachinePolicies::new(), indices: IndexStore::new(), code_repo: CodeRepo::new(), @@ -491,7 +491,7 @@ impl Machine { } fn throw_session_error(&mut self, err: SessionError, key: PredicateKey) { - let h = self.machine_st.heap.h; + let h = self.machine_st.heap.h(); let err = MachineError::session_error(h, err); let stub = MachineError::functor_stub(key.0, key.1); @@ -692,7 +692,7 @@ impl Machine { } fn sink_to_snapshot(&mut self) -> MachineState { - let mut snapshot = MachineState::with_capacity(0); + let mut snapshot = MachineState::with_small_heap(); snapshot.hb = self.machine_st.hb; snapshot.e = self.machine_st.e; @@ -711,7 +711,7 @@ impl Machine { snapshot.block = self.machine_st.block; snapshot.ball = self.machine_st.ball.take(); - snapshot.lifted_heap = mem::replace(&mut self.machine_st.lifted_heap, vec![]); + snapshot.lifted_heap = self.machine_st.lifted_heap.take(); snapshot } @@ -738,7 +738,7 @@ impl Machine { self.machine_st.block = snapshot.block; self.machine_st.ball = snapshot.ball.take(); - self.machine_st.lifted_heap = mem::replace(&mut snapshot.lifted_heap, vec![]); + self.machine_st.lifted_heap = snapshot.lifted_heap.take(); } pub(super) fn run_query(&mut self) { diff --git a/src/prolog/machine/raw_block.rs b/src/prolog/machine/raw_block.rs index 3539425f..b9e7f7ed 100644 --- a/src/prolog/machine/raw_block.rs +++ b/src/prolog/machine/raw_block.rs @@ -5,9 +5,13 @@ use std::mem; use std::ptr; pub(crate) trait RawBlockTraits { - fn init_size() -> usize; + fn init_size() -> usize; fn align() -> usize; - fn base_offset(base: *const u8) -> *const u8; + + #[inline] + fn base_offset(base: *const u8) -> *const u8 { + base + } } pub(crate) struct RawBlock { diff --git a/src/prolog/machine/stack.rs b/src/prolog/machine/stack.rs index 2916b27b..9984dfe1 100644 --- a/src/prolog/machine/stack.rs +++ b/src/prolog/machine/stack.rs @@ -141,6 +141,7 @@ pub struct OrFrame { impl Index for OrFrame { type Output = Addr; + #[inline] fn index(&self, index: usize) -> &Self::Output { let prelude_offset = prelude_size::(); let index_offset = index * mem::size_of::(); @@ -155,6 +156,7 @@ impl Index for OrFrame { } impl IndexMut for OrFrame { + #[inline] fn index_mut(&mut self, index: usize) -> &mut Self::Output { let prelude_offset = prelude_size::(); let index_offset = index * mem::size_of::(); diff --git a/src/prolog/machine/system_calls.rs b/src/prolog/machine/system_calls.rs index 0fc09b97..1eb3f912 100644 --- a/src/prolog/machine/system_calls.rs +++ b/src/prolog/machine/system_calls.rs @@ -283,7 +283,7 @@ impl MachineState { let var_atom = clause_name!(var.to_string(), indices.atom_tbl); let var_atom = Constant::Atom(var_atom, None); - let h = self.heap.h; + let h = self.heap.h(); let spec = fetch_atom_op_spec(clause_name!("="), None, &indices.op_dir); self.heap.push(HeapCellValue::NamedStr(2, clause_name!("="), spec)); @@ -307,7 +307,7 @@ impl MachineState { // reset the input stream after an input failure. *current_input_stream = readline::input_stream(); - let h = self.heap.h; + let h = self.heap.h(); let syntax_error = MachineError::syntax_error(h, err); let stub = MachineError::functor_stub(clause_name!("read_term"), 2); @@ -328,9 +328,13 @@ impl MachineState { } fn copy_findall_solution(&mut self, lh_offset: usize, copy_target: Addr) -> usize { - let threshold = self.lifted_heap.len() - lh_offset; - let mut copy_ball_term = - CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut self.lifted_heap); + let threshold = self.lifted_heap.h() - lh_offset; + + let mut copy_ball_term = CopyBallTerm::new( + &mut self.stack, + &mut self.heap, + &mut self.lifted_heap, + ); copy_ball_term.push(HeapCellValue::Addr(Addr::Lis(threshold + 1))); copy_ball_term.push(HeapCellValue::Addr(Addr::HeapCell(threshold + 3))); @@ -356,10 +360,10 @@ impl MachineState { { match self.store(self.deref(self[temp_v!(1)].clone())) { Addr::Con(Constant::Usize(lh_offset)) => { - if lh_offset >= self.lifted_heap.len() { + if lh_offset >= self.lifted_heap.h() { self.lifted_heap.truncate(lh_offset); } else { - let threshold = self.lifted_heap.len() - lh_offset; + let threshold = self.lifted_heap.h() - lh_offset; self.lifted_heap .push(HeapCellValue::Addr(addr_constr(threshold))); } @@ -466,7 +470,7 @@ impl MachineState { }); let err = ParserError::UnexpectedChar(c, line_num, col_num); - let h = self.heap.h; + let h = self.heap.h(); let err = MachineError::syntax_error(h, err); return Err(self.error_form(err, stub)); @@ -480,7 +484,7 @@ impl MachineState { match parser.read_term(composite_op!(&indices.op_dir)) { Err(err) => { - let h = self.heap.h; + let h = self.heap.h(); let err = MachineError::syntax_error(h, err); return Err(self.error_form(err, stub)); @@ -500,7 +504,7 @@ impl MachineState { _ => { let err = ParserError::ParseBigInt(0, 0); - let h = self.heap.h; + let h = self.heap.h(); let err = MachineError::syntax_error(h, err); return Err(self.error_form(err, stub)); @@ -893,7 +897,7 @@ impl MachineState { } &SystemClauseType::LiftedHeapLength => { let a1 = self[temp_v!(1)].clone(); - let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.len())); + let lh_len = Addr::Con(Constant::Usize(self.lifted_heap.h())); self.unify(a1, lh_len); } @@ -960,7 +964,7 @@ impl MachineState { match indices.global_variables.get_mut(&key) { Some((ref mut ball, None)) => { - let h = self.heap.h; + let h = self.heap.h(); let stub = ball.copy_and_align(h); self.heap.extend(stub.into_iter()); @@ -984,7 +988,7 @@ impl MachineState { match indices.global_variables.get_mut(&key) { Some((ref mut ball, ref mut offset @ None)) => { - let h = self.heap.h; + let h = self.heap.h(); let stub = ball.copy_and_align(h); self.heap.extend(stub.into_iter()); @@ -1108,15 +1112,15 @@ impl MachineState { let copy_target = self[temp_v!(2)].clone(); let old_threshold = self.copy_findall_solution(lh_offset, copy_target); - let new_threshold = self.lifted_heap.len() - lh_offset; + let new_threshold = self.lifted_heap.h() - lh_offset; self.lifted_heap[old_threshold] = HeapCellValue::Addr(Addr::HeapCell(new_threshold)); - for index in old_threshold + 1..self.lifted_heap.len() { - match &mut self.lifted_heap[index] { + for addr in self.lifted_heap.iter_mut_from(old_threshold + 1) { + match addr { &mut HeapCellValue::Addr(ref mut addr) => { - *addr -= self.heap.len() + lh_offset + *addr -= self.heap.h() + lh_offset } _ => {} } @@ -1433,7 +1437,7 @@ impl MachineState { Ok(()) => {} Err(e) => { // 8.14.3.3 l) - let e = MachineError::session_error(self.heap.h, e); + let e = MachineError::session_error(self.heap.h(), e); let stub = MachineError::functor_stub(clause_name!("op"), 3); let permission_error = self.error_form(e, stub); @@ -1464,7 +1468,7 @@ impl MachineState { Addr::AttrVar(h) => h + 1, attr_var @ Addr::HeapCell(_) | attr_var @ Addr::StackCell(..) => { // create an AttrVar in the heap. - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::AttrVar(h))); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h + 1))); @@ -1545,7 +1549,7 @@ impl MachineState { addrs.push(self.stack.index_and_frame(e)[index].clone()); } - let chunk = Addr::HeapCell(self.heap.h); + let chunk = Addr::HeapCell(self.heap.h()); self.heap.push(HeapCellValue::NamedStr( 1 + num_cells, @@ -1563,27 +1567,34 @@ impl MachineState { match self.store(self.deref(lh_offset)) { Addr::Con(Constant::Usize(lh_offset)) => { - if lh_offset >= self.lifted_heap.len() { + if lh_offset >= self.lifted_heap.h() { let solutions = self[temp_v!(2)].clone(); let diff = self[temp_v!(3)].clone(); self.unify(solutions, Addr::Con(Constant::EmptyList)); self.unify(diff, Addr::Con(Constant::EmptyList)); } else { - let h = self.heap.h; + let h = self.heap.h(); + let mut last_index = h; - for index in lh_offset..self.lifted_heap.len() { - match self.lifted_heap[index].clone() { + for value in self.lifted_heap.iter_from(lh_offset) { + last_index = self.heap.h(); + + match value.clone() { HeapCellValue::Addr(addr) => { - self.heap.push(HeapCellValue::Addr(addr + h)) + self.heap.push(HeapCellValue::Addr(addr + h)); + } + value => { + self.heap.push(value); } - value => self.heap.push(value), } } - if let Some(HeapCellValue::Addr(addr)) = self.heap.last().cloned() { - let diff = self[temp_v!(3)].clone(); - self.unify(diff, addr); + if last_index < self.heap.h() { + if let HeapCellValue::Addr(addr) = self.heap[last_index].clone() { + let diff = self[temp_v!(3)].clone(); + self.unify(diff, addr); + } } self.lifted_heap.truncate(lh_offset); @@ -1600,18 +1611,20 @@ impl MachineState { match self.store(self.deref(lh_offset)) { Addr::Con(Constant::Usize(lh_offset)) => { - if lh_offset >= self.lifted_heap.len() { + if lh_offset >= self.lifted_heap.h() { let solutions = self[temp_v!(2)].clone(); self.unify(solutions, Addr::Con(Constant::EmptyList)); } else { - let h = self.heap.h; + let h = self.heap.h(); - for index in lh_offset..self.lifted_heap.len() { - match self.lifted_heap[index].clone() { + for addr in self.lifted_heap.iter_from(lh_offset).cloned() { + match addr { HeapCellValue::Addr(addr) => { self.heap.push(HeapCellValue::Addr(addr + h)) } - value => self.heap.push(value), + value => { + self.heap.push(value); + } } } @@ -1825,7 +1838,7 @@ impl MachineState { let value = self[temp_v!(2)].clone(); let mut ball = Ball::new(); - let h = self.heap.h; + let h = self.heap.h(); ball.boundary = h; copy_term( @@ -2004,11 +2017,11 @@ impl MachineState { &SystemClauseType::Fail => self.fail = true, &SystemClauseType::GetBall => { let addr = self.store(self.deref(self[temp_v!(1)].clone())); - let h = self.heap.h; + let h = self.heap.h(); - if self.ball.stub.len() > 0 { + if self.ball.stub.h() > 0 { let stub = self.ball.copy_and_align(h); - self.heap.append(stub); + self.heap.extend(stub.into_iter()); } else { self.fail = true; return Ok(()); @@ -2168,7 +2181,7 @@ impl MachineState { &SystemClauseType::ResetContinuationMarker => { self[temp_v!(3)] = Addr::Con(Constant::Atom(clause_name!("none"), None)); - let h = self.heap.h; + let h = self.heap.h(); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); self[temp_v!(4)] = Addr::HeapCell(h); @@ -2215,7 +2228,7 @@ impl MachineState { let value = self[temp_v!(2)].clone(); let mut ball = Ball::new(); - ball.boundary = self.heap.h; + ball.boundary = self.heap.h(); copy_term( CopyBallTerm::new(&mut self.stack, &mut self.heap, &mut ball.stub), value, @@ -2234,7 +2247,7 @@ impl MachineState { let value = self[temp_v!(2)].clone(); let mut ball = Ball::new(); - let h = self.heap.h; + let h = self.heap.h(); ball.boundary = h; copy_term( @@ -2324,7 +2337,7 @@ impl MachineState { } else { let arity = arity.to_usize().unwrap(); let stub = MachineError::functor_stub(name.clone(), arity); - let h = self.heap.h; + let h = self.heap.h(); let err = MachineError::existence_error( h, @@ -2339,7 +2352,7 @@ impl MachineState { None => { let arity = arity.to_usize().unwrap(); let stub = MachineError::functor_stub(name.clone(), arity); - let h = self.heap.h; + let h = self.heap.h(); let err = MachineError::existence_error( h, @@ -2352,7 +2365,7 @@ impl MachineState { } }; - let mut h = self.heap.h; + let mut h = self.heap.h(); let mut functors = vec![]; walk_code( diff --git a/src/prolog/machine/term_expansion.rs b/src/prolog/machine/term_expansion.rs index 9c91e555..c1425955 100644 --- a/src/prolog/machine/term_expansion.rs +++ b/src/prolog/machine/term_expansion.rs @@ -369,7 +369,7 @@ impl MachineState { hook: CompileTimeHook, ) -> Option { let term_write_result = write_term_to_heap(term, self); - let h = self.heap.h; + let h = self.heap.h(); self[temp_v!(1)] = Addr::HeapCell(term_write_result.heap_loc); self.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); diff --git a/src/prolog/read.rs b/src/prolog/read.rs index ee753b4a..d45a7414 100644 --- a/src/prolog/read.rs +++ b/src/prolog/read.rs @@ -120,7 +120,7 @@ impl MachineState { } fn push_stub_addr(machine_st: &mut MachineState) { - let h = machine_st.heap.h; + let h = machine_st.heap.h(); machine_st.heap.push(HeapCellValue::Addr(Addr::HeapCell(h))); } @@ -145,13 +145,13 @@ pub struct TermWriteResult { } pub(crate) fn write_term_to_heap(term: &Term, machine_st: &mut MachineState) -> TermWriteResult { - let heap_loc = machine_st.heap.h; + let heap_loc = machine_st.heap.h(); let mut queue = SubtermDeque::new(); let mut var_dict = HeapVarDict::new(); for term in breadth_first_iter(term, true) { - let h = machine_st.heap.h; + let h = machine_st.heap.h(); match &term { &TermRef::Cons(lvl, ..) => { -- 2.54.0