From a2e4c4a213e3c49e6dcf3c8c1951b675f02226d0 Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Sun, 6 Apr 2025 12:11:57 -0700 Subject: [PATCH] move CodeIndex to F64Table-like table --- Cargo.toml | 1 + src/arena.rs | 338 +---------------------- src/arithmetic.rs | 1 + src/heap_print.rs | 17 +- src/lib.rs | 1 + src/machine/arithmetic_ops.rs | 1 + src/machine/dispatch.rs | 4 +- src/machine/lib_machine/mod.rs | 4 +- src/machine/load_state.rs | 4 +- src/machine/loader.rs | 119 ++++----- src/machine/machine_indices.rs | 60 ++--- src/machine/machine_state_impl.rs | 1 + src/machine/mod.rs | 10 +- src/machine/system_calls.rs | 17 +- src/machine/unify.rs | 1 + src/macros.rs | 28 +- src/offset_table.rs | 428 ++++++++++++++++++++++++++++++ src/parser/ast.rs | 4 +- src/parser/lexer.rs | 2 + src/parser/parser.rs | 2 + src/types.rs | 34 ++- 21 files changed, 582 insertions(+), 495 deletions(-) create mode 100644 src/offset_table.rs diff --git a/Cargo.toml b/Cargo.toml index 536e5793..aeb66eb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -137,6 +137,7 @@ opt-level = 3 [profile.release] lto = true opt-level = 3 +debug = 2 [profile.wasm-dev] inherits = "dev" diff --git a/src/arena.rs b/src/arena.rs index f9c2f274..47de6fa3 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -3,20 +3,14 @@ #[cfg(feature = "http")] use crate::http::{HttpListener, HttpResponse}; use crate::machine::loader::LiveLoadState; -use crate::machine::machine_indices::*; use crate::machine::streams::*; -use crate::raw_block::*; +use crate::offset_table::*; use crate::read::*; use crate::types::UntypedArenaPtr; use crate::parser::dashu::{Integer, Rational}; -use arcu::atomic::Arcu; -use arcu::epoch_counters::GlobalEpochCounterPool; -use arcu::rcu_ref::RcuRef; -use arcu::Rcu; use ordered_float::OrderedFloat; -use std::cell::UnsafeCell; use std::fmt; use std::fmt::Debug; use std::hash::{Hash, Hasher}; @@ -27,7 +21,7 @@ use std::ops::{Deref, DerefMut}; use std::ptr; use std::ptr::addr_of_mut; use std::ptr::NonNull; -use std::sync::RwLock; +use std::sync::Arc; macro_rules! arena_alloc { ($e:expr, $arena:expr) => {{ @@ -39,7 +33,7 @@ macro_rules! arena_alloc { macro_rules! float_alloc { ($e:expr, $arena:expr) => {{ let result = $e; - unsafe { $arena.f64_tbl.build_with(result).as_ptr() } + unsafe { $arena.f64_tbl.build_with(OrderedFloat(result)).as_ptr() } }}; } @@ -55,116 +49,6 @@ where payload_offset - header_offset } -use std::sync::Arc; -use std::sync::Mutex; -use std::sync::Weak; - -const F64_TABLE_INIT_SIZE: usize = 1 << 16; -const F64_TABLE_ALIGN: usize = 8; - -#[inline(always)] -fn global_f64table() -> &'static RwLock> { - static GLOBAL_ATOM_TABLE: RwLock> = RwLock::new(Weak::new()); - &GLOBAL_ATOM_TABLE -} - -impl RawBlockTraits for F64Table { - #[inline] - fn init_size() -> usize { - F64_TABLE_INIT_SIZE - } - - #[inline] - fn align() -> usize { - F64_TABLE_ALIGN - } -} - -#[derive(Debug)] -pub struct F64Table { - block: Arcu, GlobalEpochCounterPool>, - update: Mutex<()>, -} - -#[inline(always)] -pub fn lookup_float( - offset: F64Offset, -) -> RcuRef, UnsafeCell>> { - let f64table = global_f64table() - .read() - .unwrap() - .upgrade() - .expect("We should only be looking up floats while there is a float table"); - - RcuRef::try_map(f64table.block.read(), |raw_block| unsafe { - raw_block - .base - .add(offset.0) - .cast_mut() - .cast::>>() - .as_ref() - }) - .expect("The offset should result in a non-null pointer") -} - -impl F64Table { - #[inline] - pub fn new() -> Arc { - let upgraded = global_f64table().read().unwrap().upgrade(); - // don't inline upgraded, otherwise temporary will be dropped too late in case of None - if let Some(atom_table) = upgraded { - atom_table - } else { - let mut guard = global_f64table().write().unwrap(); - // try to upgrade again in case we lost the race on the write lock - if let Some(atom_table) = guard.upgrade() { - atom_table - } else { - let atom_table = Arc::new(Self { - block: Arcu::new(RawBlock::new(), GlobalEpochCounterPool), - update: Mutex::new(()), - }); - *guard = Arc::downgrade(&atom_table); - atom_table - } - } - } - - #[allow(clippy::missing_safety_doc)] - pub unsafe fn build_with(&self, value: f64) -> F64Offset { - let update_guard = self.update.lock(); - - // we don't have an index table for lookups as AtomTable does so - // just get the epoch after we take the upgrade lock - let mut block_epoch = self.block.read(); - - let mut ptr; - - loop { - ptr = block_epoch.alloc(mem::size_of::()); - - if ptr.is_null() { - let new_block = block_epoch.grow_new().unwrap(); - self.block.replace(new_block); - block_epoch = self.block.read(); - } else { - break; - } - } - - ptr::write(ptr as *mut OrderedFloat, OrderedFloat(value)); - - let float = F64Offset(ptr as usize - block_epoch.base as usize); - - // atometable would have to update the index table at this point - - // expicit drop to ensure we don't accidentally drop it early - drop(update_guard); - - float - } -} - #[derive(BitfieldSpecifier, Copy, Clone, Debug, PartialEq)] #[bits = 7] pub enum ArenaHeaderTag { @@ -190,10 +74,6 @@ pub enum ArenaHeaderTag { HttpListener = 0b1000001, HttpResponse = 0b1000010, Dropped = 0b1000100, - IndexPtrDynamicUndefined = 0b1000101, - IndexPtrDynamicIndex = 0b1000110, - IndexPtrIndex = 0b1000111, - IndexPtrUndefined = 0b1001000, } #[bitfield] @@ -432,137 +312,6 @@ pub trait ArenaAllocated { } } -#[derive(Debug)] -pub struct F64Ptr(RcuRef, UnsafeCell>>); - -impl Clone for F64Ptr { - fn clone(&self) -> Self { - Self(RcuRef::clone(&self.0)) - } -} - -impl PartialEq for F64Ptr { - fn eq(&self, other: &F64Ptr) -> bool { - RcuRef::ptr_eq(&self.0, &other.0) || self.deref() == other.deref() - } -} - -impl Eq for F64Ptr {} - -impl PartialOrd for F64Ptr { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for F64Ptr { - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - (**self).cmp(&**other) - } -} - -impl Hash for F64Ptr { - #[inline(always)] - fn hash(&self, hasher: &mut H) { - (self as &OrderedFloat).hash(hasher) - } -} - -impl fmt::Display for F64Ptr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self as &OrderedFloat) - } -} - -impl Deref for F64Ptr { - type Target = OrderedFloat; - - #[inline] - fn deref(&self) -> &Self::Target { - unsafe { self.0.get().as_ref().unwrap() } - } -} - -impl DerefMut for F64Ptr { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut *self.0.get().as_mut().unwrap() } - } -} - -impl F64Ptr { - #[inline(always)] - pub fn from_offset(offset: F64Offset) -> Self { - Self(lookup_float(offset)) - } - - #[inline(always)] - pub fn as_offset(&self) -> F64Offset { - F64Offset(self.0.get() as usize - RcuRef::get_root(&self.0).base as usize) - } -} - -#[derive(Clone, Copy, Debug)] -pub struct F64Offset(usize); - -impl F64Offset { - #[inline(always)] - pub fn new(offset: usize) -> Self { - Self(offset) - } - - #[inline(always)] - pub fn from_ptr(ptr: F64Ptr) -> Self { - ptr.as_offset() - } - - #[inline(always)] - pub fn as_ptr(self) -> F64Ptr { - F64Ptr::from_offset(self) - } - - #[inline(always)] - pub fn to_u64(self) -> u64 { - self.0 as u64 - } -} - -impl PartialEq for F64Offset { - #[inline(always)] - fn eq(&self, other: &F64Offset) -> bool { - self.as_ptr() == other.as_ptr() - } -} - -impl Eq for F64Offset {} - -impl PartialOrd for F64Offset { - #[inline(always)] - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for F64Offset { - #[inline(always)] - fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ptr().cmp(&other.as_ptr()) - } -} - -impl Hash for F64Offset { - #[inline(always)] - fn hash(&self, hasher: &mut H) { - self.as_ptr().hash(hasher) - } -} - -impl fmt::Display for F64Offset { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "F64Offset({})", self.0) - } -} - impl ArenaAllocated for Integer { type Payload = Self; #[inline] @@ -640,46 +389,6 @@ impl ArenaAllocated for HttpResponse { } } -impl ArenaAllocated for IndexPtr { - type Payload = Self; - #[inline] - fn tag() -> ArenaHeaderTag { - ArenaHeaderTag::IndexPtrUndefined - } - - #[inline] - fn header_offset_from_payload() -> usize { - 0 - } - - /// # Safety - /// - the caller must guarantee that the pointee type of UntypedArenaPtr is T - /// - the pointer must be non-null - unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr { - TypedArenaPtr(NonNull::new_unchecked( - ptr.get_ptr().cast_mut().cast::(), - )) - } - - #[inline] - fn alloc(arena: &mut Arena, value: Self) -> TypedArenaPtr { - let slab = Box::new(IndexPtrSlab { - next: arena.base.take(), - index_ptr: value, - }); - - let (allocated_ptr, untyped_slab) = slab.to_untyped(); - arena.base = Some(untyped_slab); - allocated_ptr - } - - /// # Safety - /// - ptr points to an allocated slab of the correct kind - unsafe fn dealloc(ptr: NonNull>) { - drop(unsafe { Box::from_raw(ptr.as_ptr().cast::()) }); - } -} - #[repr(C)] #[derive(Debug)] pub struct AllocSlab { @@ -687,13 +396,6 @@ pub struct AllocSlab { header: ArenaHeader, } -#[repr(C)] -#[derive(Debug)] -pub struct IndexPtrSlab { - next: Option, - index_ptr: IndexPtr, -} - const _: () = { if std::mem::align_of::() < std::mem::align_of::<*const ()>() { panic!("alignment of AllocSlab is too low"); @@ -702,34 +404,8 @@ const _: () = { if std::mem::offset_of!(AllocSlab, header) % std::mem::align_of::<*const ()>() != 0 { panic!("alignment of header not a multiple of pointers alignment"); } - - if std::mem::offset_of!(AllocSlab, header) != std::mem::offset_of!(IndexPtrSlab, index_ptr) { - panic!("IndexPtrSlab.index_ptr and AllocSlab.header are at different offsets"); - } }; -impl IndexPtrSlab { - #[inline] - pub fn to_untyped(self: Box) -> (TypedArenaPtr, UntypedArenaSlab) { - let raw_box = Box::into_raw(self); - - // safety: the pointer from Box::into_raw fullfills addr_of_mut's saftey requirements - let index_ptr_ptr = unsafe { ptr::addr_of_mut!((*raw_box).index_ptr) }; - let allocated_ptr = TypedArenaPtr( - // safety: the pointer points into a valid allocation so it is non null - unsafe { NonNull::new_unchecked(index_ptr_ptr) }, - ); - - let untyped_arena = UntypedArenaSlab { - // safety: pointer from Box::into_raw is never null - slab: unsafe { NonNull::new_unchecked(raw_box.cast::()) }, - tag: ::tag(), - }; - - (allocated_ptr, untyped_arena) - } -} - #[repr(C)] #[derive(Debug)] pub struct TypedAllocSlab { @@ -783,6 +459,7 @@ impl Drop for UntypedArenaSlab { pub struct Arena { base: Option, pub f64_tbl: Arc, + pub code_index_tbl: Arc, } unsafe impl Send for Arena {} @@ -795,6 +472,7 @@ impl Arena { Arena { base: None, f64_tbl: F64Table::new(), + code_index_tbl: CodeIndexTable::new(), } } } @@ -870,12 +548,6 @@ unsafe fn drop_slab_in_place(value: NonNull, tag: ArenaHeaderTag) { ArenaHeaderTag::StandardErrorStream => { drop_typed_slab_in_place!(StandardErrorStream, value); } - ArenaHeaderTag::IndexPtrUndefined - | ArenaHeaderTag::IndexPtrDynamicUndefined - | ArenaHeaderTag::IndexPtrDynamicIndex - | ArenaHeaderTag::IndexPtrIndex => { - drop_typed_slab_in_place!(IndexPtr, value); - } ArenaHeaderTag::NullStream => { unreachable!("NullStream is never arena allocated!"); } diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 4863932a..2bdcc315 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -7,6 +7,7 @@ use crate::debray_allocator::*; use crate::forms::*; use crate::instructions::*; use crate::iterators::*; +use crate::offset_table::*; use crate::targets::QueryInstruction; use crate::types::*; diff --git a/src/heap_print.rs b/src/heap_print.rs index 8c39b41e..f11fb4d5 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -12,6 +12,7 @@ use crate::machine::machine_indices::*; use crate::machine::partial_string::*; use crate::machine::stack::*; use crate::machine::streams::*; +use crate::offset_table::*; use crate::types::*; use dashu::base::Signed; @@ -1506,21 +1507,23 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - fn print_index_ptr(&mut self, index_ptr: IndexPtr, max_depth: usize) { + fn print_index_ptr(&mut self, idx: CodeIndex, max_depth: usize) { if self.format_struct(max_depth, 1, atom!("$index_ptr")) { let atom = self.state_stack.pop().unwrap(); self.state_stack.pop(); self.state_stack.pop(); - let offset = if index_ptr.is_undefined() || index_ptr.is_dynamic_undefined() { + let idx_ptr = idx.as_ptr(); + + let offset = if idx_ptr.is_undefined() || idx_ptr.is_dynamic_undefined() { TokenOrRedirect::Atom(atom!("undefined")) } else { - let idx = index_ptr.p() as i64; + let idx_ptr_p = idx_ptr.p() as i64; TokenOrRedirect::NumberFocus( max_depth, - NumberFocus::Unfocused(Number::Fixnum(Fixnum::build_with(idx))), + NumberFocus::Unfocused(Number::Fixnum(Fixnum::build_with(idx_ptr_p))), None, ) }; @@ -1707,6 +1710,9 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }); } } + (HeapCellValueTag::CodeIndex, idx) => { + self.print_index_ptr(idx, self.max_depth); + } (HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint, n) => { self.print_number(max_depth, NumberFocus::Unfocused(Number::Fixnum(n)), &op); } @@ -1750,9 +1756,6 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { (ArenaHeaderTag::Dropped, _value) => { self.print_impromptu_atom(atom!("$dropped_value")); } - (ArenaHeaderTag::IndexPtr, index_ptr) => { - self.print_index_ptr(*index_ptr, max_depth); - } _ => { } ); diff --git a/src/lib.rs b/src/lib.rs index 1926c7df..598110ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ pub(crate) mod macros; pub(crate) mod atom_table; #[macro_use] pub(crate) mod arena; +pub(crate) mod offset_table; #[macro_use] pub(crate) mod parser; #[macro_use] diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index f7bd69ef..43bb3723 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -11,6 +11,7 @@ use crate::forms::*; use crate::heap_iter::*; use crate::machine::machine_errors::*; use crate::machine::machine_state::*; +use crate::offset_table::*; use crate::parser::ast::*; use crate::parser::dashu::{Integer, Rational}; use crate::types::*; diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index f1519986..4c9db0e8 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -610,7 +610,7 @@ impl Machine { .indices .code_dir .get_index(predicate_idx) - .map(|x| x.1.p() as usize) + .map(|x| x.1.as_ptr().p() as usize) .unwrap(); debug_assert!(current_pred_start <= p); @@ -619,7 +619,7 @@ impl Machine { .indices .code_dir .get_index(predicate_idx + 1) - .map(|x| x.1.p() as usize) + .map(|x| x.1.as_ptr().p() as usize) .unwrap_or(self.code.len()); debug_assert!(current_pred_end >= p); diff --git a/src/machine/lib_machine/mod.rs b/src/machine/lib_machine/mod.rs index 66c1783a..d11419e0 100644 --- a/src/machine/lib_machine/mod.rs +++ b/src/machine/lib_machine/mod.rs @@ -7,9 +7,9 @@ use crate::heap_iter::{stackful_post_order_iter, NonListElider}; use crate::machine::machine_indices::VarKey; use crate::machine::mock_wam::CompositeOpDir; use crate::machine::{ - ArenaHeaderTag, F64Offset, F64Ptr, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC, - LIB_QUERY_SUCCESS, + ArenaHeaderTag, Fixnum, Number, BREAK_FROM_DISPATCH_LOOP_LOC, LIB_QUERY_SUCCESS, }; +use crate::offset_table::*; use crate::parser::ast::{Var, VarPtr}; use crate::parser::parser::{Parser, Tokens}; use crate::read::{write_term_to_heap, TermWriteResult}; diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 64d0bb82..0a712c1a 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -147,7 +147,7 @@ pub(super) fn import_module_exports<'a, LS: LoadState<'a>>( src_code_index.get(), ); - if src_code_index.is_dynamic_undefined() { + if src_code_index.as_ptr().is_dynamic_undefined() { code_dir.insert(key, src_code_index); } } else { @@ -486,7 +486,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { continue; } - if !code_index.is_undefined() && !code_index.is_dynamic_undefined() { + if !code_index.as_ptr().is_undefined() && !code_index.as_ptr().is_dynamic_undefined() { let old_index_ptr = code_index.replace(IndexPtr::undefined()); self.payload.retraction_info.push_record( diff --git a/src/machine/loader.rs b/src/machine/loader.rs index c117887b..89b83ed3 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1219,7 +1219,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let code_index = self.get_or_insert_code_index(key, compilation_target); - if code_index.is_undefined() { + if code_index.as_ptr().is_undefined() { set_code_index( &mut self.payload.retraction_info, &compilation_target, @@ -1378,73 +1378,72 @@ impl MachineState { while let Some(addr) = iter.next() { let addr = unmark_cell_bits!(addr); - if let Ok(literal) = Literal::try_from(addr) { - term_stack.push(Term::Literal(Cell::default(), literal)); - } else { - read_heap_cell!(addr, - (HeapCellValueTag::Lis) => { - use crate::parser::parser::as_partial_string; + read_heap_cell!(addr, + (HeapCellValueTag::Lis) => { + use crate::parser::parser::as_partial_string; - let tail = term_stack.pop().unwrap(); - let head = term_stack.pop().unwrap(); + let tail = term_stack.pop().unwrap(); + let head = term_stack.pop().unwrap(); - match as_partial_string(head, tail) { - Ok((string, Some(tail))) => { - term_stack.push(Term::PartialString(Cell::default(), Rc::new(string), tail)); - } - Ok((string, None)) => { - term_stack.push(Term::CompleteString(Cell::default(), Rc::new(string))); - } - Err(cons_term) => term_stack.push(cons_term), + match as_partial_string(head, tail) { + Ok((string, Some(tail))) => { + term_stack.push(Term::PartialString(Cell::default(), Rc::new(string), tail)); } + Ok((string, None)) => { + term_stack.push(Term::CompleteString(Cell::default(), Rc::new(string))); + } + Err(cons_term) => term_stack.push(cons_term), } - (HeapCellValueTag::StackVar, h) => { - term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("s_{}", h)))); - } - (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => { - term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h)))); + } + (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | HeapCellValueTag::F64) => { + term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap())); + } + (HeapCellValueTag::StackVar, h) => { + term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("s_{}", h)))); + } + (HeapCellValueTag::Var | HeapCellValueTag::AttrVar, h) => { + term_stack.push(Term::Var(Cell::default(), VarPtr::from(format!("_{}", h)))); + } + (HeapCellValueTag::Atom, (name, arity)) => { + let h = iter.focus().value() as usize; + let mut arity = arity; + let value = iter.heap[h.saturating_sub(1)]; + + if let Some(idx) = get_structure_index(value) { + term_stack.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx))); + arity += 1; } - (HeapCellValueTag::Atom, (name, arity)) => { - let h = iter.focus().value() as usize; - let mut arity = arity; - let value = iter.heap[h.saturating_sub(1)]; - - if let Some(idx) = get_structure_index(value) { - term_stack.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx))); - arity += 1; - } - if arity == 0 { - term_stack.push(Term::Literal(Cell::default(), Literal::Atom(name))); - } else { - let subterms = term_stack - .drain(term_stack.len() - arity ..) - .collect(); + if arity == 0 { + term_stack.push(Term::Literal(Cell::default(), Literal::Atom(name))); + } else { + let subterms = term_stack + .drain(term_stack.len() - arity ..) + .collect(); - term_stack.push(Term::Clause(Cell::default(), name, subterms)); - } - } - (HeapCellValueTag::PStrLoc, h) => { - let HeapStringScan { string, .. } = iter.heap.scan_slice_to_str(h); - let tail = term_stack.pop().unwrap(); - - term_stack.push(if matches!(tail, Term::Literal(_, Literal::Atom(atom!("[]")))) { - Term::CompleteString( - Cell::default(), - Rc::new(string.to_owned()), - ) - } else { - Term::PartialString( - Cell::default(), - Rc::new(string.to_owned()), - Box::new(tail), - ) - }); - } - _ => { + term_stack.push(Term::Clause(Cell::default(), name, subterms)); } - ); - } + } + (HeapCellValueTag::PStrLoc, h) => { + let HeapStringScan { string, .. } = iter.heap.scan_slice_to_str(h); + let tail = term_stack.pop().unwrap(); + + term_stack.push(if matches!(tail, Term::Literal(_, Literal::Atom(atom!("[]")))) { + Term::CompleteString( + Cell::default(), + Rc::new(string.to_owned()), + ) + } else { + Term::PartialString( + Cell::default(), + Rc::new(string.to_owned()), + Box::new(tail), + ) + }); + } + _ => { + } + ); } debug_assert!(term_stack.len() == 1); diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index d4a10a8c..8dc5291f 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -10,6 +10,7 @@ use crate::machine::machine_state::*; use crate::machine::streams::{Stream, StreamOptions}; use crate::machine::ClauseType; use crate::machine::MachineStubGen; +use crate::offset_table::*; use fxhash::FxBuildHasher; use indexmap::{IndexMap, IndexSet}; @@ -18,7 +19,7 @@ use scryer_modular_bitfield::{bitfield, BitfieldSpecifier}; use std::cmp::Ordering; use std::collections::BTreeSet; -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; use crate::types::*; @@ -129,7 +130,7 @@ impl IndexPtr { } #[derive(Debug, Clone, Copy, Ord, Hash, PartialOrd, Eq, PartialEq)] -pub struct CodeIndex(TypedArenaPtr); +pub struct CodeIndex(CodeIndexOffset); #[cfg(target_pointer_width = "32")] const_assert!(std::mem::align_of::() == 4); @@ -137,47 +138,24 @@ const_assert!(std::mem::align_of::() == 4); #[cfg(target_pointer_width = "64")] const_assert!(std::mem::align_of::() == 8); -impl Deref for CodeIndex { - type Target = TypedArenaPtr; - - #[inline(always)] - fn deref(&self) -> &TypedArenaPtr { - &self.0 - } -} - -impl DerefMut for CodeIndex { - #[inline(always)] - fn deref_mut(&mut self) -> &mut TypedArenaPtr { - &mut self.0 - } -} - -impl From for UntypedArenaPtr { - #[inline(always)] - fn from(ptr: CodeIndex) -> UntypedArenaPtr { - UntypedArenaPtr::build_with(ptr.0.as_ptr() as usize) - } -} - -impl From> for CodeIndex { +impl From for HeapCellValue { #[inline(always)] - fn from(ptr: TypedArenaPtr) -> CodeIndex { - CodeIndex(ptr) + fn from(idx: CodeIndex) -> HeapCellValue { + HeapCellValue::from(idx.as_ptr()) } } -impl From for HeapCellValue { +impl From for CodeIndex { #[inline(always)] - fn from(idx: CodeIndex) -> HeapCellValue { - untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)) + fn from(offset: CodeIndexOffset) -> CodeIndex { + CodeIndex(offset) } } impl CodeIndex { #[inline] pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self { - CodeIndex(arena_alloc!(ptr, arena)) + unsafe { CodeIndex(arena.code_index_tbl.build_with(ptr)) } } #[inline(always)] @@ -186,39 +164,37 @@ impl CodeIndex { } pub(crate) fn local(&self) -> Option { - match self.0.tag() { - IndexPtrTag::Index => Some(self.0.p() as usize), - IndexPtrTag::DynamicIndex => Some(self.0.p() as usize), + match self.0.as_ptr().tag() { + IndexPtrTag::Index => Some(self.get().p() as usize), + IndexPtrTag::DynamicIndex => Some(self.get().p() as usize), _ => None, } } #[inline(always)] pub(crate) fn get(&self) -> IndexPtr { - *self.0.deref() + *self.as_ptr().deref() } #[inline(always)] pub(crate) fn set(&mut self, value: IndexPtr) { - *self.0.deref_mut() = value; + self.as_ptr().set(value); } #[inline(always)] pub(crate) fn get_tag(self) -> IndexPtrTag { - self.0.tag() + self.get().tag() } #[inline(always)] pub(crate) fn replace(&mut self, value: IndexPtr) -> IndexPtr { - std::mem::replace(self.0.deref_mut(), value) + self.as_ptr().replace(value) } - /* #[inline(always)] - pub(crate) fn as_ptr(&self) -> *const IndexPtr { + pub(crate) fn as_ptr(&self) -> CodeIndexPtr { self.0.as_ptr() } - */ } #[derive(Debug, Clone, PartialEq, Eq, Hash)] diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index bd041f36..66d3237b 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -11,6 +11,7 @@ use crate::machine::machine_state::*; use crate::machine::partial_string::*; use crate::machine::stack::*; use crate::machine::unify::*; +use crate::offset_table::*; use crate::parser::ast::*; use crate::parser::dashu::{Integer, Rational}; use crate::types::*; diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 5c4056a7..989ff489 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -45,6 +45,7 @@ use crate::machine::machine_indices::*; use crate::machine::machine_state::*; use crate::machine::stack::*; use crate::machine::streams::*; +use crate::offset_table::*; use crate::parser::ast::*; use crate::parser::dashu::{Integer, Rational}; use crate::types::*; @@ -233,13 +234,8 @@ pub(crate) fn import_builtin_impls(code_dir: &CodeDir, builtins: &mut Module) { #[inline] pub(crate) fn get_structure_index(value: HeapCellValue) -> Option { read_heap_cell!(value, - (HeapCellValueTag::Cons, cons_ptr) => { - match_untyped_arena_ptr!(cons_ptr, - (ArenaHeaderTag::IndexPtr, ip) => { - return Some(CodeIndex::from(ip)); - } - _ => {} - ); + (HeapCellValueTag::CodeIndex, ip) => { + return Some(ip); } _ => { } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 0b1b835f..fb284978 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1468,7 +1468,7 @@ impl Machine { }; if let Some(code_index) = index_cell { - if !code_index.is_undefined() { + if !code_index.as_ptr().is_undefined() { load_registers(&mut self.machine_st, goal, goal_arity); self.machine_st.neck_cut(); return call_at_index(self, name, arity, code_index.get()); @@ -1617,8 +1617,7 @@ impl Machine { let expanded_term = if result.is_simple_goal { let idx = self.get_or_insert_qualified_code_index(module_name, result.key); - self.machine_st.heap[result.index_ptr_loc] = - untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx)); + self.machine_st.heap[result.index_ptr_loc] = HeapCellValue::from(idx); result.goal } else { let mut unexpanded_vars = IndexSet::with_hasher(FxBuildHasher::default()); @@ -1656,7 +1655,7 @@ impl Machine { ); writer.write_with(|section| { - section.push_cell(untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(idx))); + section.push_cell(HeapCellValue::from(idx)); section.push_cell(atom_as_cell!(atom!("$aux"), 0)); for value in unexpanded_vars.difference(&result.supp_vars).cloned() { @@ -1693,14 +1692,8 @@ impl Machine { let idx_cell = self.machine_st.heap[s.saturating_sub(1)]; - if HeapCellValueTag::Cons == idx_cell.get_tag() { - match_untyped_arena_ptr!(cell_as_untyped_arena_ptr!(idx_cell), - (ArenaHeaderTag::IndexPtr, _ip) => { - return true; - } - _ => { - } - ); + if HeapCellValueTag::CodeIndex == idx_cell.get_tag() { + return true; } } diff --git a/src/machine/unify.rs b/src/machine/unify.rs index b9aae0e6..7d451fc8 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -3,6 +3,7 @@ use crate::forms::*; use crate::heap_iter::{stackful_preorder_iter, NonListElider}; use crate::machine::machine_state::*; use crate::machine::*; +use crate::offset_table::*; use crate::types::*; use std::ops::{Deref, DerefMut}; diff --git a/src/macros.rs b/src/macros.rs index e23980f3..73c36b0d 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -62,7 +62,14 @@ macro_rules! cell_as_atom_cell { macro_rules! cell_as_f64_ptr { ($cell:expr) => {{ let offset = $cell.get_value() as usize; - F64Ptr::from_offset(F64Offset::new(offset)) + F64Ptr::from_offset(F64Offset::from(offset)) + }}; +} + +macro_rules! cell_as_code_index { + ($cell:expr) => {{ + let offset = $cell.get_value() as usize; + CodeIndex::from(CodeIndexOffset::from(offset)) }}; } @@ -140,7 +147,7 @@ macro_rules! raw_ptr_as_cell { ($ptr:expr) => {{ // Cell is 64-bit, but raw ptr is 32-bit in 32-bit systems // TODO use <*{const,mut} _>::addr instead of as when the strict_provenance feature is stable rust-lang/rust#95228 - // we might need <*{const,mut} _>::expose_provenance for strict provenance, dependening on how we recreate a pointer later + // we might need <*{const,mut} _>::expose_provenance for strict provenance, depending on how we recreate a pointer later let ptr : *const _ = $ptr; HeapCellValue::from_ptr_addr(ptr as usize) }}; @@ -216,12 +223,6 @@ macro_rules! match_untyped_arena_ptr_pat_body { #[allow(unused_braces)] $code }}; - ($ptr:ident, IndexPtr, $ip:ident, $code:expr) => {{ - #[allow(unused_mut)] - let mut $ip = unsafe { $ptr.as_typed_ptr::() }; - #[allow(unused_braces)] - $code - }}; ($ptr:ident, $($tags:tt)|+, $s:ident, $code:expr) => {{ let $s = Stream::from_tag($ptr.get_tag(), $ptr); #[allow(unused_braces)] @@ -245,12 +246,6 @@ macro_rules! match_untyped_arena_ptr_pat { | ArenaHeaderTag::StandardOutputStream | ArenaHeaderTag::StandardErrorStream }; - (IndexPtr) => { - ArenaHeaderTag::IndexPtrUndefined - | ArenaHeaderTag::IndexPtrDynamicUndefined - | ArenaHeaderTag::IndexPtrDynamicIndex - | ArenaHeaderTag::IndexPtrIndex - }; ($tag:ident) => { ArenaHeaderTag::$tag }; @@ -281,6 +276,11 @@ macro_rules! read_heap_cell_pat_body { #[allow(unused_braces)] $code }}; + ($cell:ident, CodeIndex, $n:ident, $code:expr) => {{ + let $n = cell_as_code_index!($cell); + #[allow(unused_braces)] + $code + }}; ($cell:ident, Atom, ($name:ident, $arity:ident), $code:expr) => {{ let ($name, $arity) = cell_as_atom_cell!($cell).get_name_and_arity(); #[allow(unused_braces)] diff --git a/src/offset_table.rs b/src/offset_table.rs new file mode 100644 index 00000000..5afcf89b --- /dev/null +++ b/src/offset_table.rs @@ -0,0 +1,428 @@ +use std::cell::UnsafeCell; +use std::hash::{Hash, Hasher}; +use std::ops::{Deref, DerefMut}; +use std::sync::RwLock; +use std::sync::Weak; +use std::sync::{Arc, Mutex}; +use std::{fmt, mem, ptr}; + +use arcu::atomic::Arcu; +use arcu::epoch_counters::GlobalEpochCounterPool; +use arcu::rcu_ref::RcuRef; +use arcu::Rcu; + +use crate::machine::machine_indices::IndexPtr; +use crate::raw_block::RawBlock; +use crate::raw_block::RawBlockTraits; + +use ordered_float::OrderedFloat; + +const F64_TABLE_INIT_SIZE: usize = 1 << 16; +const F64_TABLE_ALIGN: usize = 8; + +const CODE_INDEX_TABLE_INIT_SIZE: usize = 1 << 16; +const CODE_INDEX_TABLE_ALIGN: usize = 8; + +#[derive(Debug)] +pub struct OffsetTableImpl +where + OffsetTableImpl: RawBlockTraits, +{ + block: Arcu>, GlobalEpochCounterPool>, + update: Mutex<()>, +} + +pub type F64Table = OffsetTableImpl>; +pub type CodeIndexTable = OffsetTableImpl; + +impl RawBlockTraits for F64Table { + #[inline] + fn init_size() -> usize { + F64_TABLE_INIT_SIZE + } + + #[inline] + fn align() -> usize { + F64_TABLE_ALIGN + } +} + +impl RawBlockTraits for CodeIndexTable { + #[inline] + fn init_size() -> usize { + CODE_INDEX_TABLE_INIT_SIZE + } + + #[inline] + fn align() -> usize { + CODE_INDEX_TABLE_ALIGN + } +} + +pub trait OffsetTable: RawBlockTraits { + type Offset: Copy + From + Into; + type Stored; + + fn global_table() -> &'static RwLock>; +} + +impl OffsetTable for F64Table { + type Offset = F64Offset; + type Stored = OrderedFloat; + + #[inline(always)] + fn global_table() -> &'static RwLock> { + static GLOBAL_ATOM_TABLE: RwLock> = RwLock::new(Weak::new()); + &GLOBAL_ATOM_TABLE + } +} + +impl OffsetTable for CodeIndexTable { + type Offset = CodeIndexOffset; + type Stored = IndexPtr; + + #[inline(always)] + fn global_table() -> &'static RwLock> { + static GLOBAL_CODE_INDEX_TABLE: RwLock> = RwLock::new(Weak::new()); + &GLOBAL_CODE_INDEX_TABLE + } +} + +impl OffsetTableImpl +where + OffsetTableImpl: OffsetTable, +{ + #[inline] + pub fn new() -> Arc { + let upgraded = Self::global_table().read().unwrap().upgrade(); + // don't inline upgraded, otherwise temporary will be dropped too late in case of None + if let Some(atom_table) = upgraded { + atom_table + } else { + let mut guard = Self::global_table().write().unwrap(); + // try to upgrade again in case we lost the race on the write lock + if let Some(atom_table) = guard.upgrade() { + atom_table + } else { + let table = Arc::new(Self { + block: Arcu::new(RawBlock::new(), GlobalEpochCounterPool), + update: Mutex::new(()), + }); + *guard = Arc::downgrade(&table); + table + } + } + } + + #[allow(clippy::missing_safety_doc)] + pub unsafe fn build_with( + &self, + value: as OffsetTable>::Stored, + ) -> as OffsetTable>::Offset { + let update_guard = self.update.lock(); + + // we don't have an index table for lookups as AtomTable does so + // just get the epoch after we take the upgrade lock + let mut block_epoch = self.block.read(); + + let mut ptr; + + loop { + ptr = block_epoch.alloc(mem::size_of::()); + + if ptr.is_null() { + let new_block = block_epoch.grow_new().unwrap(); + self.block.replace(new_block); + block_epoch = self.block.read(); + } else { + break; + } + } + + ptr::write(ptr as *mut T, value); + + let value = as OffsetTable>::Offset::from( + ptr as usize - block_epoch.base as usize, + ); + + // AtomTable would have to update the index table at this point + // explicit drop to ensure we don't accidentally drop it early + drop(update_guard); + + value + } + + pub fn lookup(offset: ::Offset) -> RcuRef, UnsafeCell> { + let table = Self::global_table() + .read() + .unwrap() + .upgrade() + .expect("We should only be looking up entries when there is a table"); + + RcuRef::try_map(table.block.read(), |raw_block| unsafe { + raw_block + .base + .add(offset.into()) + .cast_mut() + .cast::>() + .as_ref() + }) + .expect("The offset should result in a non-null pointer") + } +} + +#[derive(Debug)] +pub struct TablePtr(RcuRef>, UnsafeCell>) +where + OffsetTableImpl: RawBlockTraits; + +pub type CodeIndexPtr = TablePtr; +pub type F64Ptr = TablePtr>; + +impl Clone for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + fn clone(&self) -> Self { + Self(RcuRef::clone(&self.0)) + } +} + +impl PartialEq for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + fn eq(&self, other: &TablePtr) -> bool { + RcuRef::ptr_eq(&self.0, &other.0) || self.deref() == other.deref() + } +} + +impl Eq for TablePtr where OffsetTableImpl: RawBlockTraits {} + +impl PartialOrd for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + (**self).cmp(&**other) + } +} + +impl Hash for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + #[inline(always)] + fn hash(&self, hasher: &mut H) { + (self as &T).hash(hasher) + } +} + +impl fmt::Display for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self as &T) + } +} + +impl Deref for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { self.0.get().as_ref().unwrap() } + } +} + +impl DerefMut for TablePtr +where + OffsetTableImpl: RawBlockTraits, +{ + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.0.get().as_mut().unwrap() } + } +} + +impl TablePtr +where + OffsetTableImpl: OffsetTable, +{ + #[inline(always)] + pub fn from_offset(offset: as OffsetTable>::Offset) -> Self { + Self(OffsetTableImpl::::lookup(offset)) + } + + #[inline(always)] + pub fn as_offset(&self) -> as OffsetTable>::Offset { + as OffsetTable>::Offset::from( + self.0.get() as usize - RcuRef::get_root(&self.0).base as usize, + ) + } +} + +#[derive(Clone, Copy, Debug)] +pub struct F64Offset(usize); + +impl From for F64Offset { + #[inline(always)] + fn from(offset: usize) -> Self { + Self(offset) + } +} + +impl Into for F64Offset { + #[inline(always)] + fn into(self: Self) -> usize { + self.0 + } +} + +#[derive(Debug, Clone, Copy)] +pub struct CodeIndexOffset(usize); + +impl From for CodeIndexOffset { + #[inline(always)] + fn from(offset: usize) -> Self { + Self(offset) + } +} + +impl Into for CodeIndexOffset { + #[inline(always)] + fn into(self: Self) -> usize { + self.0 + } +} + +impl CodeIndexOffset { + #[inline(always)] + pub fn from_ptr(ptr: CodeIndexPtr) -> Self { + ptr.as_offset() + } + + #[inline(always)] + pub fn as_ptr(self) -> CodeIndexPtr { + CodeIndexPtr::from_offset(self) + } + + #[inline(always)] + pub fn to_u64(self) -> u64 { + self.0 as u64 + } +} + +impl PartialEq for CodeIndexOffset { + #[inline(always)] + fn eq(&self, other: &CodeIndexOffset) -> bool { + self.as_ptr() == other.as_ptr() + } +} + +impl Eq for CodeIndexOffset {} + +impl PartialOrd for CodeIndexOffset { + #[inline(always)] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for CodeIndexOffset { + #[inline(always)] + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_ptr().cmp(&other.as_ptr()) + } +} + +impl Hash for CodeIndexOffset { + #[inline(always)] + fn hash(&self, hasher: &mut H) { + self.as_ptr().hash(hasher) + } +} + +impl fmt::Display for CodeIndexOffset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "CodeIndexOffset({})", self.0) + } +} + +impl CodeIndexPtr { + #[inline] + pub fn set(&self, val: IndexPtr) { + unsafe { *self.0.get() = val }; + } + + #[inline] + pub fn replace(&self, val: IndexPtr) -> IndexPtr { + unsafe { self.0.get().replace(val) } + } +} + +impl F64Offset { + #[inline(always)] + pub fn from_ptr(ptr: F64Ptr) -> Self { + ptr.as_offset() + } + + #[inline(always)] + pub fn as_ptr(self) -> F64Ptr { + F64Ptr::from_offset(self) + } + + #[inline(always)] + pub fn to_u64(self) -> u64 { + self.0 as u64 + } +} + +impl PartialEq for F64Offset { + #[inline(always)] + fn eq(&self, other: &F64Offset) -> bool { + self.as_ptr() == other.as_ptr() + } +} + +impl Eq for F64Offset {} + +impl PartialOrd for F64Offset { + #[inline(always)] + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for F64Offset { + #[inline(always)] + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.as_ptr().cmp(&other.as_ptr()) + } +} + +impl Hash for F64Offset { + #[inline(always)] + fn hash(&self, hasher: &mut H) { + self.as_ptr().hash(hasher) + } +} + +impl fmt::Display for F64Offset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "F64Offset({})", self.0) + } +} diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 346b73f4..7cce7ed3 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -3,6 +3,7 @@ use crate::arena::*; use crate::atom_table::*; use crate::machine::machine_indices::CodeIndex; +use crate::offset_table::*; use crate::parser::char_reader::*; use crate::types::HeapCellValueTag; @@ -626,8 +627,7 @@ impl fmt::Display for Literal { Literal::Atom(ref atom) => { write!(f, "{}", atom.flat_index()) } - // Literal::Char(c) => write!(f, "'{}'", *c as u32), - Literal::CodeIndex(i) => write!(f, "{:x}", i.as_ptr() as u64), + Literal::CodeIndex(i) => write!(f, "{:?}", *i.as_ptr()), Literal::Fixnum(n) => write!(f, "{}", n.get_num()), Literal::Integer(ref n) => write!(f, "{}", n), Literal::Rational(ref n) => write!(f, "{}", n), diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 1a6b40e6..5cf41671 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -5,6 +5,8 @@ use crate::parser::ast::*; use crate::parser::char_reader::*; use crate::parser::dashu::Integer; +use ordered_float::OrderedFloat; + use std::convert::TryFrom; use std::fmt; diff --git a/src/parser/parser.rs b/src/parser/parser.rs index dc831c3d..f1d022e2 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -7,6 +7,8 @@ use crate::parser::ast::*; use crate::parser::char_reader::*; use crate::parser::lexer::*; +use ordered_float::OrderedFloat; + use std::cell::Cell; use std::mem; use std::ops::Neg; diff --git a/src/types.rs b/src/types.rs index d04075fa..08d3c642 100644 --- a/src/types.rs +++ b/src/types.rs @@ -6,6 +6,7 @@ use crate::forms::*; use crate::machine::heap::*; use crate::machine::machine_indices::*; use crate::machine::streams::*; +use crate::offset_table::*; use crate::parser::ast::Fixnum; use crate::parser::ast::Literal; @@ -31,7 +32,7 @@ pub enum HeapCellValueTag { Cons = 0b0, F64 = 0b010101, Fixnum = 0b011001, - // Char = 0b011011, + CodeIndex = 0b011011, Atom = 0b011111, CutPoint = 0b011101, // trail elements. @@ -58,7 +59,7 @@ pub enum HeapCellValueView { Cons = 0b0, F64 = 0b010101, Fixnum = 0b011001, - Char = 0b011011, + CodeIndex = 0b011011, Atom = 0b011111, CutPoint = 0b011101, // trail elements. @@ -315,9 +316,7 @@ impl From for HeapCellValue { fn from(literal: Literal) -> Self { match literal { Literal::Atom(name) => atom_as_cell!(name), - Literal::CodeIndex(ptr) => { - untyped_arena_ptr_as_cell!(UntypedArenaPtr::from(ptr)) - } + Literal::CodeIndex(idx) => HeapCellValue::from(idx), Literal::Fixnum(n) => fixnum_as_cell!(n), Literal::Integer(bigint_ptr) => { typed_arena_ptr_as_cell!(bigint_ptr) @@ -348,6 +347,9 @@ impl TryFrom for Literal { (HeapCellValueTag::F64, f) => { Ok(Literal::Float(f.as_offset())) } + (HeapCellValueTag::CodeIndex, idx) => { + Ok(Literal::CodeIndex(idx)) + } (HeapCellValueTag::Cons, cons_ptr) => { match_untyped_arena_ptr!(cons_ptr, (ArenaHeaderTag::Integer, n) => { @@ -356,9 +358,6 @@ impl TryFrom for Literal { (ArenaHeaderTag::Rational, n) => { Ok(Literal::Rational(n)) } - (ArenaHeaderTag::IndexPtr, ip) => { - Ok(Literal::CodeIndex(CodeIndex::from(ip))) - } _ => { Err(()) } @@ -388,6 +387,16 @@ impl From for HeapCellValue { } } +impl From for HeapCellValue { + #[inline] + fn from(code_index_ptr: CodeIndexPtr) -> HeapCellValue { + HeapCellValue::build_with( + HeapCellValueTag::CodeIndex, + code_index_ptr.as_offset().to_u64(), + ) + } +} + impl From for HeapCellValue { #[inline(always)] fn from(cons_ptr: ConsPtr) -> HeapCellValue { @@ -738,21 +747,22 @@ impl UntypedArenaPtr { } #[inline] - pub fn get_ptr(self) -> *const ArenaHeader { - unsafe { mem::transmute::<_, *const ArenaHeader>(self.ptr()) } + pub fn get_ptr(self) -> *const u8 { + let addr: u64 = self.ptr(); + addr as usize as *const u8 } #[inline] pub fn get_tag(self) -> ArenaHeaderTag { unsafe { - let header = *self.get_ptr(); + let header = *(self.get_ptr() as *const ArenaHeader); header.get_tag() } } #[inline] pub fn payload_offset(self) -> *const u8 { - unsafe { self.get_ptr().byte_add(mem::size_of::()) as *const _ } + unsafe { self.get_ptr().add(mem::size_of::()) } } /// # Safety -- 2.54.0