move bump allocation logic to its own module
This commit is contained in:
@@ -19,6 +19,7 @@ pub mod machine_errors;
|
|||||||
pub mod machine_indices;
|
pub mod machine_indices;
|
||||||
pub(super) mod machine_state;
|
pub(super) mod machine_state;
|
||||||
pub mod modules;
|
pub mod modules;
|
||||||
|
mod raw_vec;
|
||||||
mod stack;
|
mod stack;
|
||||||
pub(super) mod term_expansion;
|
pub(super) mod term_expansion;
|
||||||
pub mod toplevel;
|
pub mod toplevel;
|
||||||
|
|||||||
100
src/prolog/machine/raw_vec.rs
Normal file
100
src/prolog/machine/raw_vec.rs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use std::alloc;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
pub(crate) trait RawVecTraits {
|
||||||
|
fn init_size() -> usize;
|
||||||
|
fn align() -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) struct RawVec<T: RawVecTraits> {
|
||||||
|
pub(crate) size: usize,
|
||||||
|
pub(crate) base: *const u8,
|
||||||
|
pub(crate) top: *const u8,
|
||||||
|
_marker: PhantomData<T>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: RawVecTraits> RawVec<T> {
|
||||||
|
pub(crate)
|
||||||
|
fn new() -> Self {
|
||||||
|
let mut vec = RawVec { size: 0,
|
||||||
|
base: ptr::null(),
|
||||||
|
top: ptr::null(),
|
||||||
|
_marker: PhantomData };
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
vec.grow();
|
||||||
|
}
|
||||||
|
|
||||||
|
vec
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
unsafe fn grow(&mut self) {
|
||||||
|
if self.size == 0 {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(T::init_size(), T::align());
|
||||||
|
|
||||||
|
self.base = alloc::alloc(layout) as *const _;
|
||||||
|
self.size = T::init_size();
|
||||||
|
|
||||||
|
self.top = self.base.offset(T::align() as isize);
|
||||||
|
} else {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(T::init_size(), T::align());
|
||||||
|
let top_dist = self.top as usize - self.base as usize;
|
||||||
|
|
||||||
|
self.base = alloc::realloc(self.base as *mut _, layout, self.size*2) as *const _;
|
||||||
|
self.top = (self.base as usize + top_dist) as *const _;
|
||||||
|
self.size *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn empty_vec() -> Self {
|
||||||
|
RawVec { size: 0,
|
||||||
|
base: ptr::null(),
|
||||||
|
top: ptr::null(),
|
||||||
|
_marker: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
fn take(&mut self) -> Self {
|
||||||
|
mem::replace(self, Self::empty_vec())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn free_space(&self) -> usize {
|
||||||
|
debug_assert!(self.top >= self.base,
|
||||||
|
"self.top = {:?} < {:?} = self.base",
|
||||||
|
self.top, self.base);
|
||||||
|
|
||||||
|
self.size - (self.top as usize - self.base as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate)
|
||||||
|
unsafe fn new_block(&mut self, block_size: usize) -> *const u8 {
|
||||||
|
loop {
|
||||||
|
if self.free_space() >= block_size {
|
||||||
|
return (self.top as usize + block_size) as *const _;
|
||||||
|
} else {
|
||||||
|
self.grow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate)
|
||||||
|
fn deallocate(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
let layout = alloc::Layout::from_size_align_unchecked(self.size, T::align());
|
||||||
|
|
||||||
|
alloc::dealloc(self.base as *mut u8, layout);
|
||||||
|
|
||||||
|
self.top = ptr::null();
|
||||||
|
self.base = ptr::null();
|
||||||
|
self.size = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,25 @@
|
|||||||
use crate::prolog::machine::machine_indices::*;
|
use crate::prolog::machine::machine_indices::*;
|
||||||
|
use crate::prolog::machine::raw_vec::*;
|
||||||
|
|
||||||
use core::marker::PhantomData;
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use std::alloc;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
const STACK_ALIGN: usize = mem::align_of::<Addr>();
|
struct StackTraits {}
|
||||||
const INIT_STACK_SIZE: usize = 10 * 1024 * 1024;
|
|
||||||
|
impl RawVecTraits for StackTraits {
|
||||||
|
#[inline]
|
||||||
|
fn init_size() -> usize {
|
||||||
|
10 * 1024 * 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn align() -> usize {
|
||||||
|
mem::align_of::<Addr>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const fn prelude_size<Prelude>() -> usize {
|
const fn prelude_size<Prelude>() -> usize {
|
||||||
let size = mem::size_of::<Prelude>();
|
let size = mem::size_of::<Prelude>();
|
||||||
@@ -18,16 +29,14 @@ const fn prelude_size<Prelude>() -> usize {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Stack {
|
pub struct Stack {
|
||||||
size: usize,
|
buf: RawVec<StackTraits>,
|
||||||
base: *const u8,
|
|
||||||
top: *const u8,
|
|
||||||
_marker: PhantomData<Addr>,
|
_marker: PhantomData<Addr>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for Stack {
|
impl Drop for Stack {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.drop_in_place();
|
self.drop_in_place();
|
||||||
self.deallocate();
|
self.buf.deallocate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,80 +187,28 @@ impl OrFrame {
|
|||||||
|
|
||||||
impl Stack {
|
impl Stack {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut stack = Stack { size: 0, base: ptr::null(), top: ptr::null(),
|
Stack { buf: RawVec::new(), _marker: PhantomData }
|
||||||
_marker: PhantomData };
|
|
||||||
|
|
||||||
unsafe { stack.grow(); }
|
|
||||||
stack
|
|
||||||
}
|
|
||||||
|
|
||||||
fn empty_stack() -> Self {
|
|
||||||
Stack { size: 0, base: ptr::null(), top: ptr::null(),
|
|
||||||
_marker: PhantomData }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn take(&mut self) -> Stack {
|
|
||||||
mem::replace(self, Stack::empty_stack())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn free_space(&self) -> usize {
|
|
||||||
debug_assert!(self.top >= self.base,
|
|
||||||
"self.top = {:?} < {:?} = self.base",
|
|
||||||
self.top, self.base);
|
|
||||||
|
|
||||||
self.size - (self.top as usize - self.base as usize)
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn grow(&mut self) {
|
|
||||||
if self.size == 0 {
|
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(INIT_STACK_SIZE, STACK_ALIGN);
|
|
||||||
|
|
||||||
self.base = alloc::alloc(layout) as *const _;
|
|
||||||
self.top = self.base as *const _;
|
|
||||||
self.size = INIT_STACK_SIZE;
|
|
||||||
|
|
||||||
self.top = self.top.offset(mem::align_of::<Addr>() as isize);
|
|
||||||
} else {
|
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(self.size, STACK_ALIGN);
|
|
||||||
let top_dist = self.top as usize - self.base as usize;
|
|
||||||
|
|
||||||
self.base = alloc::realloc(self.base as *mut _, layout, self.size*2) as *const _;
|
|
||||||
self.top = (self.base as usize + top_dist) as *const _;
|
|
||||||
self.size *= 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
unsafe fn new_frame_ptr(&mut self, frame_size: usize) -> *const u8 {
|
|
||||||
loop {
|
|
||||||
if self.free_space() >= frame_size {
|
|
||||||
return (self.top as usize + frame_size) as *const _;
|
|
||||||
} else {
|
|
||||||
self.grow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate_and_frame(&mut self, num_cells: usize) -> usize {
|
pub fn allocate_and_frame(&mut self, num_cells: usize) -> usize {
|
||||||
let frame_size = AndFrame::size_of(num_cells);
|
let frame_size = AndFrame::size_of(num_cells);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let new_top = self.new_frame_ptr(frame_size);
|
let new_top = self.buf.new_block(frame_size);
|
||||||
|
|
||||||
for idx in 0 .. num_cells {
|
for idx in 0 .. num_cells {
|
||||||
let offset = prelude_size::<AndFramePrelude>() + idx * mem::size_of::<Addr>();
|
let offset = prelude_size::<AndFramePrelude>() + idx * mem::size_of::<Addr>();
|
||||||
ptr::write((self.top as usize + offset) as *mut Addr, Addr::StackCell(0,0));
|
ptr::write((self.buf.top as usize + offset) as *mut Addr, Addr::StackCell(0,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let and_frame = &mut *(self.top as *mut AndFrame);
|
let and_frame = &mut *(self.buf.top as *mut AndFrame);
|
||||||
|
|
||||||
and_frame.prelude.univ_prelude.is_or_frame = 0;
|
and_frame.prelude.univ_prelude.is_or_frame = 0;
|
||||||
and_frame.prelude.univ_prelude.num_cells = num_cells;
|
and_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||||
|
|
||||||
let e = self.top as usize - self.base as usize;
|
let e = self.buf.top as usize - self.buf.base as usize;
|
||||||
self.top = new_top;
|
self.buf.top = new_top;
|
||||||
|
|
||||||
e
|
e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,20 +217,21 @@ impl Stack {
|
|||||||
let frame_size = OrFrame::size_of(num_cells);
|
let frame_size = OrFrame::size_of(num_cells);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let new_top = self.new_frame_ptr(frame_size);
|
let new_top = self.buf.new_block(frame_size);
|
||||||
|
|
||||||
for idx in 0 .. num_cells {
|
for idx in 0 .. num_cells {
|
||||||
let offset = prelude_size::<OrFramePrelude>() + idx * mem::size_of::<Addr>();
|
let offset = prelude_size::<OrFramePrelude>() + idx * mem::size_of::<Addr>();
|
||||||
ptr::write((self.top as usize + offset) as *mut Addr, Addr::StackCell(0,0));
|
ptr::write((self.buf.top as usize + offset) as *mut Addr, Addr::StackCell(0,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
let or_frame = &mut *(self.top as *mut OrFrame);
|
let or_frame = &mut *(self.buf.top as *mut OrFrame);
|
||||||
|
|
||||||
or_frame.prelude.univ_prelude.is_or_frame = 1;
|
or_frame.prelude.univ_prelude.is_or_frame = 1;
|
||||||
or_frame.prelude.univ_prelude.num_cells = num_cells;
|
or_frame.prelude.univ_prelude.num_cells = num_cells;
|
||||||
|
|
||||||
let b = self.top as usize - self.base as usize;
|
let b = self.buf.top as usize - self.buf.base as usize;
|
||||||
self.top = new_top;
|
self.buf.top = new_top;
|
||||||
|
|
||||||
b
|
b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -281,7 +239,7 @@ impl Stack {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn index_and_frame(&self, e: usize) -> &AndFrame {
|
pub fn index_and_frame(&self, e: usize) -> &AndFrame {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.base as usize + e;
|
let ptr = self.buf.base as usize + e;
|
||||||
&*(ptr as *const AndFrame)
|
&*(ptr as *const AndFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,7 +247,7 @@ impl Stack {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
|
pub fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.base as usize + e;
|
let ptr = self.buf.base as usize + e;
|
||||||
&mut *(ptr as *mut AndFrame)
|
&mut *(ptr as *mut AndFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -297,7 +255,7 @@ impl Stack {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn index_or_frame(&self, b: usize) -> &OrFrame {
|
pub fn index_or_frame(&self, b: usize) -> &OrFrame {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.base as usize + b;
|
let ptr = self.buf.base as usize + b;
|
||||||
&*(ptr as *const OrFrame)
|
&*(ptr as *const OrFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -305,20 +263,13 @@ impl Stack {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame {
|
pub fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame {
|
||||||
unsafe {
|
unsafe {
|
||||||
let ptr = self.base as usize + b;
|
let ptr = self.buf.base as usize + b;
|
||||||
&mut *(ptr as *mut OrFrame)
|
&mut *(ptr as *mut OrFrame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deallocate(&mut self) {
|
pub fn take(&mut self) -> Self {
|
||||||
unsafe {
|
Stack { buf: self.buf.take(), _marker: PhantomData }
|
||||||
let layout = alloc::Layout::from_size_align_unchecked(self.size, STACK_ALIGN);
|
|
||||||
alloc::dealloc(self.base as *mut u8, layout);
|
|
||||||
|
|
||||||
self.top = ptr::null();
|
|
||||||
self.base = ptr::null();
|
|
||||||
self.size = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn truncate(&mut self, b: usize) {
|
pub fn truncate(&mut self, b: usize) {
|
||||||
@@ -330,11 +281,11 @@ impl Stack {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn inner_truncate(&mut self, b: usize) {
|
fn inner_truncate(&mut self, b: usize) {
|
||||||
let mut b = b + self.base as usize;
|
let mut b = b + self.buf.base as usize;
|
||||||
let base = b;
|
let base = b;
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
while b as *const _ < self.top {
|
while b as *const _ < self.buf.top {
|
||||||
let univ_prelude = ptr::read(b as *const FramePrelude);
|
let univ_prelude = ptr::read(b as *const FramePrelude);
|
||||||
|
|
||||||
let offset = if univ_prelude.is_or_frame == 0 {
|
let offset = if univ_prelude.is_or_frame == 0 {
|
||||||
@@ -360,8 +311,8 @@ impl Stack {
|
|||||||
b = offset;
|
b = offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if base < self.top as usize {
|
if base < self.buf.top as usize {
|
||||||
self.top = base as *const _;
|
self.buf.top = base as *const _;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,10 +320,10 @@ impl Stack {
|
|||||||
pub fn drop_in_place(&mut self) {
|
pub fn drop_in_place(&mut self) {
|
||||||
self.truncate(mem::align_of::<Addr>());
|
self.truncate(mem::align_of::<Addr>());
|
||||||
|
|
||||||
debug_assert!(if self.top.is_null() {
|
debug_assert!(if self.buf.top.is_null() {
|
||||||
self.top == self.base
|
self.buf.top == self.buf.base
|
||||||
} else {
|
} else {
|
||||||
self.top as usize == self.base as usize + mem::align_of::<Addr>()
|
self.buf.top as usize == self.buf.base as usize + mem::align_of::<Addr>()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user