revert arithmetic code

This commit is contained in:
Mark Thom
2019-12-08 00:17:55 -07:00
parent f16c2a6e99
commit 2be7070e1a
6 changed files with 429 additions and 73 deletions

View File

@@ -1,6 +1,5 @@
use prolog_parser::ast::*; use prolog_parser::ast::*;
use crate::prolog::allocator::Allocator;
use crate::prolog::clause_types::*; use crate::prolog::clause_types::*;
use crate::prolog::fixtures::*; use crate::prolog::fixtures::*;
use crate::prolog::forms::*; use crate::prolog::forms::*;
@@ -70,7 +69,7 @@ impl<'a> ArithInstructionIterator<'a> {
pub enum ArithTermRef<'a> { pub enum ArithTermRef<'a> {
Constant(&'a Constant), Constant(&'a Constant),
Op(ClauseName, usize), // name, arity. Op(ClauseName, usize), // name, arity.
Var(Level, &'a Cell<VarReg>, Rc<Var>), Var(&'a Cell<VarReg>, Rc<Var>),
} }
impl<'a> Iterator for ArithInstructionIterator<'a> { impl<'a> Iterator for ArithInstructionIterator<'a> {
@@ -97,8 +96,8 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
} }
} }
TermIterState::Constant(_, _, c) => return Some(Ok(ArithTermRef::Constant(c))), TermIterState::Constant(_, _, c) => return Some(Ok(ArithTermRef::Constant(c))),
TermIterState::Var(lvl, cell, var) => { TermIterState::Var(_, cell, var) => {
return Some(Ok(ArithTermRef::Var(lvl, cell, var.clone()))) return Some(Ok(ArithTermRef::Var(cell, var.clone())))
} }
_ => return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))), _ => return Some(Err(ArithmeticError::NonEvaluableFunctor(atom!("'.'"), 2))),
}; };
@@ -108,10 +107,10 @@ impl<'a> Iterator for ArithInstructionIterator<'a> {
} }
} }
pub struct ArithmeticEvaluator { pub struct ArithmeticEvaluator<'a> {
bindings: &'a AllocVarDict,
interm: Vec<ArithmeticTerm>, interm: Vec<ArithmeticTerm>,
interm_c: usize, interm_c: usize,
arg_c: usize
} }
pub trait ArithmeticTermIter<'a> { pub trait ArithmeticTermIter<'a> {
@@ -128,12 +127,12 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term {
} }
} }
impl ArithmeticEvaluator { impl<'a> ArithmeticEvaluator<'a> {
pub fn new(target_int: usize, arg_c: usize) -> Self { pub fn new(bindings: &'a AllocVarDict, target_int: usize) -> Self {
ArithmeticEvaluator { ArithmeticEvaluator {
bindings,
interm: Vec::new(), interm: Vec::new(),
interm_c: target_int, interm_c: target_int,
arg_c
} }
} }
@@ -284,33 +283,27 @@ impl ArithmeticEvaluator {
Ok(()) Ok(())
} }
pub fn eval<'a, Iter, TermMarker>( pub fn eval<Iter>(&mut self, src: Iter) -> Result<ArithCont, ArithmeticError>
&mut self,
marker: &mut TermMarker,
src: Iter,
term_loc: GenContext,
) -> Result<ArithCont, ArithmeticError>
where where
Iter: ArithmeticTermIter<'a>, Iter: ArithmeticTermIter<'a>,
TermMarker: Allocator<'a>
{ {
let mut code = vec![]; let mut code = vec![];
for term_ref in src.iter()? { for term_ref in src.iter()? {
match term_ref? { match term_ref? {
ArithTermRef::Constant(c) => self.push_constant(c)?, ArithTermRef::Constant(c) => self.push_constant(c)?,
ArithTermRef::Var(lvl, cell, name) => { ArithTermRef::Var(cell, name) => {
match marker.bindings().get(&name) { let r = if cell.get().norm().reg_num() == 0 {
Some(&VarData::Temp(_, t, _)) if t != 0 => {}, match self.bindings.get(&name) {
Some(&VarData::Perm(p)) if p != 0 => {}, Some(&VarData::Temp(_, t, _)) if t != 0 => RegType::Temp(t),
_ => return Err(ArithmeticError::UninstantiatedVar), Some(&VarData::Perm(p)) if p != 0 => RegType::Perm(p),
} _ => return Err(ArithmeticError::UninstantiatedVar),
}
} else {
cell.get().norm()
};
let mut target = vec![]; self.interm.push(ArithmeticTerm::Reg(r));
marker.mark_var(name.clone(), lvl, cell, term_loc, &mut target);
code.extend(target.into_iter().map(Line::Query));
self.interm.push(ArithmeticTerm::Reg(cell.get().norm()));
} }
ArithTermRef::Op(name, arity) => { ArithTermRef::Op(name, arity) => {
code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?)); code.push(Line::Arithmetic(self.instr_from_clause(name, arity)?));
@@ -318,22 +311,8 @@ impl ArithmeticEvaluator {
} }
} }
if let GenContext::Last(_) = term_loc {
self.tempify_perm_reg();
}
Ok((code, self.interm.pop())) Ok((code, self.interm.pop()))
} }
fn tempify_perm_reg(&mut self) {
if let Some(interm) = self.interm.pop() {
if let ArithmeticTerm::Reg(RegType::Perm(_)) = interm {
self.interm.push(ArithmeticTerm::Reg(RegType::Temp(self.arg_c)));
} else {
self.interm.push(interm);
}
}
}
} }
// integer division rounding function -- 9.1.3.1. // integer division rounding function -- 9.1.3.1.

View File

@@ -360,10 +360,8 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
self.mark_non_callable(name.clone(), 2, term_loc, vr, code); self.mark_non_callable(name.clone(), 2, term_loc, vr, code);
} }
self.marker.reset_arg(2); let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1)?;
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2)?;
let (mut lcode, at_1) = self.call_arith_eval(terms[0].as_ref(), 1, term_loc, 1)?;
let (mut rcode, at_2) = self.call_arith_eval(terms[1].as_ref(), 2, term_loc, 2)?;
code.append(&mut lcode); code.append(&mut lcode);
code.append(&mut rcode); code.append(&mut rcode);
@@ -498,14 +496,12 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
} }
fn call_arith_eval( fn call_arith_eval(
&mut self, &self,
term: &'a Term, term: &'a Term,
target_int: usize, target_int: usize,
term_loc: GenContext,
arg_c: usize
) -> Result<ArithCont, ArithmeticError> { ) -> Result<ArithCont, ArithmeticError> {
let mut evaluator = ArithmeticEvaluator::new(target_int, arg_c); let mut evaluator = ArithmeticEvaluator::new(self.marker.bindings(), target_int);
evaluator.eval(&mut self.marker, term, term_loc) evaluator.eval(term)
} }
fn compile_is_call( fn compile_is_call(
@@ -515,17 +511,20 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
term_loc: GenContext, term_loc: GenContext,
use_default_call_policy: bool, use_default_call_policy: bool,
) -> Result<(), ParserError> { ) -> Result<(), ParserError> {
self.marker.reset_arg(2); let (mut acode, at) = self.call_arith_eval(terms[1].as_ref(), 1)?;
code.append(&mut acode);
Ok(match terms[0].as_ref() { Ok(match terms[0].as_ref() {
&Term::Var(ref vr, ref name) => { &Term::Var(ref vr, ref name) => {
let mut target = vec![]; let mut target = vec![];
self.marker.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
code.extend(target.into_iter().map(Line::Query)); self.marker.reset_arg(2);
self.marker
.mark_var(name.clone(), Level::Shallow, vr, term_loc, &mut target);
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?; if !target.is_empty() {
code.extend(acode.into_iter()); code.extend(target.into_iter().map(Line::Query));
}
if use_default_call_policy { if use_default_call_policy {
code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1)))) code.push(is_call_by_default!(temp_v!(1), at.unwrap_or(interm!(1))))
@@ -534,9 +533,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
} }
} }
&Term::Constant(_, ref c @ Constant::Integer(_)) => { &Term::Constant(_, ref c @ Constant::Integer(_)) => {
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
code.extend(acode.into_iter());
code.push(Line::Query(put_constant!( code.push(Line::Query(put_constant!(
Level::Shallow, Level::Shallow,
c.clone(), c.clone(),
@@ -550,9 +546,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
} }
} }
&Term::Constant(_, ref c @ Constant::Float(_)) => { &Term::Constant(_, ref c @ Constant::Float(_)) => {
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
code.extend(acode.into_iter());
code.push(Line::Query(put_constant!( code.push(Line::Query(put_constant!(
Level::Shallow, Level::Shallow,
c.clone(), c.clone(),
@@ -566,9 +559,6 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
} }
} }
&Term::Constant(_, ref c @ Constant::Rational(_)) => { &Term::Constant(_, ref c @ Constant::Rational(_)) => {
let (acode, at) = self.call_arith_eval(terms[1].as_ref(), 1, term_loc, 2)?;
code.extend(acode.into_iter());
code.push(Line::Query(put_constant!( code.push(Line::Query(put_constant!(
Level::Shallow, Level::Shallow,
c.clone(), c.clone(),
@@ -584,7 +574,7 @@ impl<'a, TermMarker: Allocator<'a>> CodeGenerator<TermMarker> {
_ => code.push(fail!()), _ => code.push(fail!()),
}) })
} }
#[inline] #[inline]
fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) { fn compile_unblocked_cut(&mut self, code: &mut Code, cell: &'a Cell<VarReg>) {
let r = self.marker.get(Rc::new(String::from("!"))); let r = self.marker.get(Rc::new(String::from("!")));

View File

@@ -421,7 +421,7 @@ pub(crate) trait CallPolicy: Any {
machine_st.e = machine_st.stack.index_or_frame(b).prelude.e; machine_st.e = machine_st.stack.index_or_frame(b).prelude.e;
machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp; machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp;
machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.clone() + offset; machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.local() + offset;
let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let old_tr = machine_st.stack.index_or_frame(b).prelude.tr;
let curr_tr = machine_st.tr; let curr_tr = machine_st.tr;
@@ -467,7 +467,7 @@ pub(crate) trait CallPolicy: Any {
machine_st.e = machine_st.stack.index_or_frame(b).prelude.e; machine_st.e = machine_st.stack.index_or_frame(b).prelude.e;
machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp; machine_st.cp = machine_st.stack.index_or_frame(b).prelude.cp;
machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.clone() + 1; machine_st.stack.index_or_frame_mut(b).prelude.bp = machine_st.p.local() + 1;
let old_tr = machine_st.stack.index_or_frame(b).prelude.tr; let old_tr = machine_st.stack.index_or_frame(b).prelude.tr;
let curr_tr = machine_st.tr; let curr_tr = machine_st.tr;

View File

@@ -2081,7 +2081,7 @@ impl MachineState {
self.stack.truncate_to_frame(self.b); self.stack.truncate_to_frame(self.b);
} }
} }
pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool { pub(crate) fn is_cyclic_term(&self, addr: Addr) -> bool {
let mut seen = IndexSet::new(); let mut seen = IndexSet::new();
let mut fail = false; let mut fail = false;
@@ -3105,7 +3105,7 @@ impl MachineState {
and_frame.prelude.e = self.e; and_frame.prelude.e = self.e;
and_frame.prelude.cp = self.cp; and_frame.prelude.cp = self.cp;
self.e = e; self.e = e;
self.p += 1; self.p += 1;
} }
@@ -3113,7 +3113,7 @@ impl MachineState {
pub(super) fn deallocate(&mut self) { pub(super) fn deallocate(&mut self) {
let e = self.e; let e = self.e;
let frame = self.stack.index_and_frame(e); let frame = self.stack.index_and_frame(e);
self.cp = frame.prelude.cp; self.cp = frame.prelude.cp;
self.e = frame.prelude.e; self.e = frame.prelude.e;
@@ -3240,7 +3240,7 @@ impl MachineState {
or_frame.prelude.e = self.e; or_frame.prelude.e = self.e;
or_frame.prelude.cp = self.cp; or_frame.prelude.cp = self.cp;
or_frame.prelude.b = self.b; or_frame.prelude.b = self.b;
or_frame.prelude.bp = self.p.clone() + 1; or_frame.prelude.bp = self.p.local() + 1;
or_frame.prelude.tr = self.tr; or_frame.prelude.tr = self.tr;
or_frame.prelude.pstr_tr = self.pstr_tr; or_frame.prelude.pstr_tr = self.pstr_tr;
or_frame.prelude.h = self.heap.h; or_frame.prelude.h = self.heap.h;
@@ -3279,7 +3279,7 @@ impl MachineState {
or_frame.prelude.e = self.e; or_frame.prelude.e = self.e;
or_frame.prelude.cp = self.cp; or_frame.prelude.cp = self.cp;
or_frame.prelude.b = self.b; or_frame.prelude.b = self.b;
or_frame.prelude.bp = self.p.clone() + offset; or_frame.prelude.bp = self.p.local() + offset;
or_frame.prelude.tr = self.tr; or_frame.prelude.tr = self.tr;
or_frame.prelude.pstr_tr = self.pstr_tr; or_frame.prelude.pstr_tr = self.pstr_tr;
or_frame.prelude.h = self.heap.h; or_frame.prelude.h = self.heap.h;

View File

@@ -739,7 +739,7 @@ impl MachineState {
let b = self.b; let b = self.b;
self.b0 = self.stack.index_or_frame(b).prelude.b0; self.b0 = self.stack.index_or_frame(b).prelude.b0;
self.p = self.stack.index_or_frame(b).prelude.bp.clone(); self.p = CodePtr::Local(self.stack.index_or_frame(b).prelude.bp);
if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p { if let CodePtr::Local(LocalCodePtr::TopLevel(_, p)) = self.p {
self.fail = p == 0; self.fail = p == 0;

387
src/prolog/machine/stack.rs Normal file
View File

@@ -0,0 +1,387 @@
use crate::prolog::machine::machine_indices::*;
use core::marker::PhantomData;
use std::alloc;
use std::mem;
use std::ops::{Index, IndexMut};
use std::ptr;
const STACK_ALIGN: usize = mem::align_of::<Addr>();
const INIT_STACK_SIZE: usize = 10 * 1024 * 1024;
const fn prelude_size<Prelude>() -> usize {
let size = mem::size_of::<Prelude>();
let align = mem::align_of::<Addr>();
(size & !(align - 1)) + align
}
/* The Stack is dropped manually at the discretion of the WAM, despite
having no Drop implementation. That's because it needs to know whether
the top frame is an AND frame or an OR frame. The WAM can
tell it. */
pub struct Stack {
size: usize,
base: *const u8,
top: *const u8,
_marker: PhantomData<Addr>,
}
impl Drop for Stack {
fn drop(&mut self) {
self.drop_in_place();
self.deallocate();
}
}
#[derive(Clone, Copy)]
pub struct FramePrelude {
is_or_frame: u8,
pub num_cells: usize,
}
pub struct AndFramePrelude {
pub univ_prelude: FramePrelude,
pub e: usize,
pub cp: LocalCodePtr,
pub interrupt_cp: LocalCodePtr,
}
pub struct AndFrame {
pub prelude: AndFramePrelude,
_marker: PhantomData<Addr>,
}
impl AndFrame {
pub fn size_of(num_cells: usize) -> usize {
prelude_size::<AndFramePrelude>() + num_cells * mem::size_of::<Addr>()
}
}
impl Index<usize> for AndFrame {
type Output = Addr;
fn index(&self, index: usize) -> &Self::Output {
let prelude_offset = prelude_size::<AndFramePrelude>();
let index_offset = (index - 1) * mem::size_of::<Addr>();
unsafe {
let ptr = mem::transmute::<&AndFrame, *const u8>(self);
let ptr = ptr as usize + prelude_offset + index_offset;
&*(ptr as *const Addr)
}
}
}
impl IndexMut<usize> for AndFrame {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let prelude_offset = prelude_size::<AndFramePrelude>();
let index_offset = (index - 1) * mem::size_of::<Addr>();
unsafe {
let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
let ptr = ptr as usize + prelude_offset + index_offset;
&mut *(ptr as *mut Addr)
}
}
}
impl Drop for AndFrame {
fn drop(&mut self) {
let prelude_offset = prelude_size::<AndFramePrelude>();
unsafe {
let ptr = mem::transmute::<&mut AndFrame, *const u8>(self);
let ptr = ptr as usize + prelude_offset;
for idx in 0 .. self.prelude.univ_prelude.num_cells {
let index_offset = idx * mem::size_of::<Addr>();
let ptr = (ptr + index_offset) as *mut Addr;
ptr::drop_in_place(ptr);
}
}
}
}
pub struct OrFramePrelude {
pub univ_prelude: FramePrelude,
pub e: usize,
pub cp: LocalCodePtr,
pub b: usize,
pub bp: LocalCodePtr,
pub tr: usize,
pub pstr_tr: usize,
pub h: usize,
pub b0: usize,
pub attr_var_init_queue_b: usize,
pub attr_var_init_bindings_b: usize,
}
pub struct OrFrame {
pub prelude: OrFramePrelude,
_marker: PhantomData<Addr>
}
impl Index<usize> for OrFrame {
type Output = Addr;
fn index(&self, index: usize) -> &Self::Output {
let prelude_offset = prelude_size::<OrFramePrelude>();
let index_offset = index * mem::size_of::<Addr>();
unsafe {
let ptr = mem::transmute::<&OrFrame, *const u8>(self);
let ptr = ptr as usize + prelude_offset + index_offset;
&*(ptr as *const Addr)
}
}
}
impl IndexMut<usize> for OrFrame {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
let prelude_offset = prelude_size::<OrFramePrelude>();
let index_offset = index * mem::size_of::<Addr>();
unsafe {
let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
let ptr = ptr as usize + prelude_offset + index_offset;
&mut *(ptr as *mut Addr)
}
}
}
impl Drop for OrFrame {
fn drop(&mut self) {
let prelude_offset = prelude_size::<OrFramePrelude>();
unsafe {
let ptr = mem::transmute::<&mut OrFrame, *const u8>(self);
let ptr = ptr as usize + prelude_offset;
for idx in 0 .. self.prelude.univ_prelude.num_cells {
let index_offset = idx * mem::size_of::<Addr>();
let ptr = (ptr + index_offset) as *mut Addr;
ptr::drop_in_place(ptr);
}
}
}
}
impl OrFrame {
pub fn size_of(num_cells: usize) -> usize {
prelude_size::<OrFramePrelude>() + num_cells * mem::size_of::<Addr>()
}
}
impl Stack {
pub fn new() -> Self {
let mut stack = Stack { size: 0, base: ptr::null(), top: ptr::null(),
_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 {
let frame_size = AndFrame::size_of(num_cells);
unsafe {
let new_top = self.new_frame_ptr(frame_size);
for idx in 0 .. num_cells {
let offset = prelude_size::<AndFramePrelude>() + idx * mem::size_of::<Addr>();
ptr::write((self.top as usize + offset) as *mut Addr, Addr::HeapCell(0));
}
let and_frame = &mut *(self.top as *mut AndFrame);
and_frame.prelude.univ_prelude.is_or_frame = 0;
and_frame.prelude.univ_prelude.num_cells = num_cells;
let e = self.top as usize - self.base as usize;
self.top = new_top;
e
}
}
pub fn allocate_or_frame(&mut self, num_cells: usize) -> usize {
let frame_size = OrFrame::size_of(num_cells);
unsafe {
let new_top = self.new_frame_ptr(frame_size);
for idx in 0 .. num_cells {
let offset = prelude_size::<OrFramePrelude>() + idx * mem::size_of::<Addr>();
ptr::write((self.top as usize + offset) as *mut Addr, Addr::HeapCell(0));
}
let or_frame = &mut *(self.top as *mut OrFrame);
or_frame.prelude.univ_prelude.is_or_frame = 1;
or_frame.prelude.univ_prelude.num_cells = num_cells;
let b = self.top as usize - self.base as usize;
self.top = new_top;
b
}
}
#[inline]
pub fn index_and_frame(&self, e: usize) -> &AndFrame {
unsafe {
let ptr = self.base as usize + e;
&*(ptr as *const AndFrame)
}
}
#[inline]
pub fn index_and_frame_mut(&mut self, e: usize) -> &mut AndFrame {
unsafe {
let ptr = self.base as usize + e;
&mut *(ptr as *mut AndFrame)
}
}
#[inline]
pub fn index_or_frame(&self, b: usize) -> &OrFrame {
unsafe {
let ptr = self.base as usize + b;
&*(ptr as *const OrFrame)
}
}
#[inline]
pub fn index_or_frame_mut(&mut self, b: usize) -> &mut OrFrame {
unsafe {
let ptr = self.base as usize + b;
&mut *(ptr as *mut OrFrame)
}
}
pub fn deallocate(&mut self) {
unsafe {
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_to_frame(&mut self, b: usize) {
if b == 0 {
self.truncate(mem::align_of::<Addr>());
} else {
let univ_prelude = self.index_or_frame(b).prelude.univ_prelude;
let size = OrFrame::size_of(univ_prelude.num_cells);
self.truncate(b + size);
}
}
fn truncate(&mut self, b: usize) {
let mut b = b + self.base as usize;
let base = b;
unsafe {
while b as *const _ < self.top {
let univ_prelude = ptr::read(b as *const FramePrelude);
let offset = if univ_prelude.is_or_frame == 0 {
let frame_ptr = b as *mut AndFrame;
let frame = &mut *frame_ptr;
let size_of_frame = AndFrame::size_of(frame.prelude.univ_prelude.num_cells);
ptr::drop_in_place(frame_ptr);
ptr::write(frame_ptr, mem::zeroed::<AndFrame>());
b + size_of_frame
} else {
debug_assert!(univ_prelude.is_or_frame == 1);
let frame_ptr = b as *mut OrFrame;
let frame = &mut *frame_ptr;
let size_of_frame = OrFrame::size_of(frame.prelude.univ_prelude.num_cells);
ptr::drop_in_place(frame_ptr);
ptr::write(frame_ptr, mem::zeroed::<OrFrame>());
b + size_of_frame
};
b = offset;
}
if base < self.top as usize {
self.top = base as *const _;
}
}
}
pub fn drop_in_place(&mut self) {
self.truncate(mem::align_of::<Addr>());
debug_assert!(if self.top.is_null() {
self.top == self.base
} else {
self.top as usize == self.base as usize + mem::align_of::<Addr>()
});
}
}