From 6030fae68584e30a6a92f9f99dc4abf0fe1bf27c Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Wed, 4 May 2022 21:54:46 -0600 Subject: [PATCH] track f64 offsets in Literal (#1190) --- build/instructions_template.rs | 5 +- src/arena.rs | 100 +++++++++++++++++++++++++++++++-- src/arithmetic.rs | 2 +- src/forms.rs | 2 +- src/indexing.rs | 76 +++++++++++-------------- src/machine/dispatch.rs | 2 +- src/machine/heap.rs | 4 +- src/machine/system_calls.rs | 2 +- src/parser/ast.rs | 9 ++- src/parser/lexer.rs | 6 +- src/parser/parser.rs | 4 +- src/raw_block.rs | 7 --- src/types.rs | 15 ++++- 13 files changed, 163 insertions(+), 71 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index 988067f8..75a7d60d 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -806,6 +806,7 @@ fn generate_instruction_preface() -> TokenStream { use crate::parser::ast::*; use crate::types::*; + use fxhash::FxBuildHasher; use indexmap::IndexMap; use std::collections::VecDeque; @@ -918,8 +919,8 @@ fn generate_instruction_preface() -> TokenStream { IndexingCodePtr, IndexingCodePtr, ), - SwitchOnConstant(IndexMap), - SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr>), + SwitchOnConstant(IndexMap), + SwitchOnStructure(IndexMap<(Atom, usize), IndexingCodePtr, FxBuildHasher>), } #[derive(Debug, Clone, Copy)] diff --git a/src/arena.rs b/src/arena.rs index e4ec79ff..1c2999fc 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -104,7 +104,9 @@ pub fn lookup_float(offset: usize) -> *mut OrderedFloat { impl F64Table { #[inline] pub fn new() -> Self { - F64Table { block: RawBlock::new() } + let table = Self { block: RawBlock::new() }; + set_f64_tbl_buf_base(table.block.base); + table } pub unsafe fn build_with(&mut self, value: f64) -> F64Ptr { @@ -121,7 +123,7 @@ impl F64Table { } } - ptr::write(ptr as *mut f64, value); + ptr::write(ptr as *mut OrderedFloat, OrderedFloat(value)); F64Ptr(ptr::NonNull::new_unchecked(ptr as *mut _)) } } @@ -297,9 +299,36 @@ pub trait ArenaAllocated { Self: Sized; } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug)] pub struct F64Ptr(pub ptr::NonNull>); +impl PartialEq for F64Ptr { + fn eq(&self, other: &F64Ptr) -> bool { + self.0 == other.0 || &**self == &**other + } +} + +impl Eq for F64Ptr {} + +impl PartialOrd for F64Ptr { + fn partial_cmp(&self, other: &Self) -> Option { + (**self).partial_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) @@ -331,8 +360,69 @@ impl F64Ptr { } #[inline(always)] - pub fn as_offset(&self) -> usize { - self.0.as_ptr() as usize - get_f64_tbl_buf_base() as usize + pub fn as_offset(&self) -> F64Offset { + F64Offset(self.0.as_ptr() as usize - get_f64_tbl_buf_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.0) + } + + #[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 { + self.as_ptr().partial_cmp(&other.as_ptr()) + } +} + +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/arithmetic.rs b/src/arithmetic.rs index 77274fbd..1bac6bf8 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -167,7 +167,7 @@ fn push_literal(interm: &mut Vec, c: &Literal) -> Result<(), Ari match c { Literal::Fixnum(n) => interm.push(ArithmeticTerm::Number(Number::Fixnum(*n))), Literal::Integer(n) => interm.push(ArithmeticTerm::Number(Number::Integer(*n))), - Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(**n))), + Literal::Float(n) => interm.push(ArithmeticTerm::Number(Number::Float(*n.as_ptr()))), Literal::Rational(n) => interm.push(ArithmeticTerm::Number(Number::Rational(*n))), Literal::Atom(name) if name == &atom!("e") => interm.push(ArithmeticTerm::Number( Number::Float(OrderedFloat(std::f64::consts::E)) diff --git a/src/forms.rs b/src/forms.rs index b1427193..ee632b6d 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -619,7 +619,7 @@ impl ArenaFrom for Literal { match value { Number::Fixnum(n) => Literal::Fixnum(n), Number::Integer(n) => Literal::Integer(n), - Number::Float(OrderedFloat(f)) => Literal::Float(float_alloc!(f, arena)), + Number::Float(OrderedFloat(f)) => Literal::from(float_alloc!(f, arena)), Number::Rational(r) => Literal::Rational(r), } } diff --git a/src/indexing.rs b/src/indexing.rs index 9d7af807..ceace331 100644 --- a/src/indexing.rs +++ b/src/indexing.rs @@ -4,6 +4,7 @@ use crate::parser::ast::*; use crate::forms::*; use crate::instructions::*; +use fxhash::FxBuildHasher; use indexmap::IndexMap; use std::collections::VecDeque; @@ -107,7 +108,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { self.append_or_prepend, ); - let mut constants = IndexMap::new(); + let mut constants = IndexMap::with_hasher(FxBuildHasher::default()); match constant_key { Some(OptArgIndexKey::Literal(_, _, constant, _)) => { @@ -249,7 +250,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { break; } IndexingCodePtr::DynamicExternal(_) | IndexingCodePtr::External(_) => { - let mut constants = IndexMap::new(); + let mut constants = IndexMap::with_hasher(FxBuildHasher::default()); constants.insert(orig_constant, *c); *c = IndexingCodePtr::Internal(indexing_code_len); @@ -389,7 +390,7 @@ impl<'a> IndexingCodeMergingPtr<'a> { self.append_or_prepend, ); - let mut structures = IndexMap::new(); + let mut structures = IndexMap::with_hasher(FxBuildHasher::default()); match structure_key { Some(OptArgIndexKey::Structure(_, _, name, arity)) => { @@ -1121,15 +1122,6 @@ pub(crate) fn constant_key_alternatives( }).unwrap(); } } - /* - Literal::Usize(n) => { - constants.push(Literal::Integer(Rc::new(Integer::from(*n)))); - - if let Ok(n) = isize::try_from(*n) { - constants.push(Literal::Fixnum(n)); - } - } - */ _ => {} } @@ -1138,16 +1130,16 @@ pub(crate) fn constant_key_alternatives( #[derive(Debug)] pub(crate) struct StaticCodeIndices { - constants: IndexMap>, + constants: IndexMap, FxBuildHasher>, lists: VecDeque, - structures: IndexMap<(Atom, usize), VecDeque>, + structures: IndexMap<(Atom, usize), VecDeque, FxBuildHasher>, } #[derive(Debug)] pub(crate) struct DynamicCodeIndices { - constants: IndexMap>, + constants: IndexMap, FxBuildHasher>, lists: VecDeque, - structures: IndexMap<(Atom, usize), VecDeque>, + structures: IndexMap<(Atom, usize), VecDeque, FxBuildHasher>, } pub(crate) trait Indexer { @@ -1155,20 +1147,20 @@ pub(crate) trait Indexer { fn new() -> Self; - fn constants(&mut self) -> &mut IndexMap>; + fn constants(&mut self) -> &mut IndexMap, FxBuildHasher>; fn lists(&mut self) -> &mut VecDeque; - fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque>; + fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque, FxBuildHasher>; fn compute_index(is_initial_index: bool, index: usize) -> Self::ThirdLevelIndex; fn second_level_index( - indices: IndexMap>, + indices: IndexMap, FxBuildHasher>, prelude: &mut VecDeque, - ) -> IndexMap; + ) -> IndexMap; fn switch_on( - instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, - index: &mut IndexMap>, + instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, + index: &mut IndexMap, FxBuildHasher>, prelude: &mut VecDeque, ) -> IndexingCodePtr; @@ -1188,14 +1180,14 @@ impl Indexer for StaticCodeIndices { #[inline] fn new() -> Self { Self { - constants: IndexMap::new(), + constants: IndexMap::with_hasher(FxBuildHasher::default()), lists: VecDeque::new(), - structures: IndexMap::new(), + structures: IndexMap::with_hasher(FxBuildHasher::default()), } } #[inline] - fn constants(&mut self) -> &mut IndexMap> { + fn constants(&mut self) -> &mut IndexMap, FxBuildHasher> { &mut self.constants } @@ -1205,7 +1197,7 @@ impl Indexer for StaticCodeIndices { } #[inline] - fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque> { + fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque, FxBuildHasher> { &mut self.structures } @@ -1218,10 +1210,10 @@ impl Indexer for StaticCodeIndices { } fn second_level_index( - indices: IndexMap>, + indices: IndexMap, FxBuildHasher>, prelude: &mut VecDeque, - ) -> IndexMap { - let mut index_locs = IndexMap::new(); + ) -> IndexMap { + let mut index_locs = IndexMap::with_hasher(FxBuildHasher::default()); for (key, mut code) in indices.into_iter() { if code.len() > 1 { @@ -1239,11 +1231,11 @@ impl Indexer for StaticCodeIndices { } fn switch_on( - mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, - index: &mut IndexMap>, + mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, + index: &mut IndexMap, FxBuildHasher>, prelude: &mut VecDeque, ) -> IndexingCodePtr { - let index = mem::replace(index, IndexMap::new()); + let index = mem::replace(index, IndexMap::with_hasher(FxBuildHasher::default())); let index = Self::second_level_index(index, prelude); if index.len() > 1 { @@ -1304,14 +1296,14 @@ impl Indexer for DynamicCodeIndices { #[inline] fn new() -> Self { Self { - constants: IndexMap::new(), + constants: IndexMap::with_hasher(FxBuildHasher::default()), lists: VecDeque::new(), - structures: IndexMap::new(), + structures: IndexMap::with_hasher(FxBuildHasher::default()), } } #[inline] - fn constants(&mut self) -> &mut IndexMap> { + fn constants(&mut self) -> &mut IndexMap, FxBuildHasher> { &mut self.constants } @@ -1321,7 +1313,7 @@ impl Indexer for DynamicCodeIndices { } #[inline] - fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque> { + fn structures(&mut self) -> &mut IndexMap<(Atom, usize), VecDeque, FxBuildHasher> { &mut self.structures } @@ -1331,10 +1323,10 @@ impl Indexer for DynamicCodeIndices { } fn second_level_index( - indices: IndexMap>, + indices: IndexMap, FxBuildHasher>, prelude: &mut VecDeque, - ) -> IndexMap { - let mut index_locs = IndexMap::new(); + ) -> IndexMap { + let mut index_locs = IndexMap::with_hasher(FxBuildHasher::default()); for (key, code) in indices.into_iter() { if code.len() > 1 { @@ -1351,11 +1343,11 @@ impl Indexer for DynamicCodeIndices { } fn switch_on( - mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, - index: &mut IndexMap>, + mut instr_fn: impl FnMut(IndexMap) -> IndexingInstruction, + index: &mut IndexMap, FxBuildHasher>, prelude: &mut VecDeque, ) -> IndexingCodePtr { - let index = mem::replace(index, IndexMap::new()); + let index = mem::replace(index, IndexMap::with_hasher(FxBuildHasher::default())); let index = Self::second_level_index(index, prelude); if index.len() > 1 { diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 514f80ac..9d031c71 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -415,7 +415,7 @@ impl Machine { Literal::Fixnum(n) } (HeapCellValueTag::F64, f) => { - Literal::Float(f) + Literal::Float(f.as_offset()) } (HeapCellValueTag::Atom, (atom, arity)) => { debug_assert_eq!(arity, 0); diff --git a/src/machine/heap.rs b/src/machine/heap.rs index 5f9d4909..9ef796b5 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -24,7 +24,7 @@ impl From for HeapCellValue { Literal::Rational(bigint_ptr) => { typed_arena_ptr_as_cell!(bigint_ptr) } - Literal::Float(f) => HeapCellValue::from(f), + Literal::Float(f) => HeapCellValue::from(f.as_ptr()), Literal::String(s) => { if s == atom!("") { empty_list_as_cell!() @@ -55,7 +55,7 @@ impl TryFrom for Literal { Ok(Literal::Fixnum(n)) } (HeapCellValueTag::F64, f) => { - Ok(Literal::Float(f)) + Ok(Literal::Float(f.as_offset())) } (HeapCellValueTag::Cons, cons_ptr) => { match_untyped_arena_ptr!(cons_ptr, diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index fcbeb553..01c6fae2 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -742,7 +742,7 @@ impl MachineState { self.unify_rational(n, nx); } Ok(Term::Literal(_, Literal::Float(n))) => { - self.unify_f64(n, nx); + self.unify_f64(n.as_ptr(), nx); } Ok(Term::Literal(_, Literal::Integer(n))) => { self.unify_big_int(n, nx); diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 3cc1ccbb..ece4c90e 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -533,10 +533,17 @@ pub enum Literal { Fixnum(Fixnum), Integer(TypedArenaPtr), Rational(TypedArenaPtr), - Float(F64Ptr), + Float(F64Offset), String(Atom), } +impl From for Literal { + #[inline(always)] + fn from(ptr: F64Ptr) -> Literal { + Literal::Float(ptr.as_offset()) + } +} + impl fmt::Display for Literal { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 02bbd1d1..887a3562 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -633,7 +633,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { fn vacate_with_float(&mut self, mut token: String) -> Result { self.return_char(token.pop().unwrap()); let n = parse_lossy::(token.as_bytes())?; - Ok(Token::Literal(Literal::Float(float_alloc!(n, self.machine_st.arena)))) + Ok(Token::Literal(Literal::from(float_alloc!(n, self.machine_st.arena)))) } fn skip_underscore_in_number(&mut self) -> Result { @@ -744,7 +744,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { } let n = parse_lossy::(token.as_bytes())?; - Ok(Token::Literal(Literal::Float( + Ok(Token::Literal(Literal::from( float_alloc!(n, self.machine_st.arena) ))) } else { @@ -752,7 +752,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { } } else { let n = parse_lossy::(token.as_bytes())?; - Ok(Token::Literal(Literal::Float( + Ok(Token::Literal(Literal::from( float_alloc!(n, self.machine_st.arena) ))) } diff --git a/src/parser/parser.rs b/src/parser/parser.rs index ecdc2ab0..ee08cec1 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -949,9 +949,9 @@ impl<'a, R: CharRead> Parser<'a, R> { self.negate_number(n, negate_rc, |r, _| Literal::Rational(r)) } Token::Literal(Literal::Float(n)) => self.negate_number( - **n, + **n.as_ptr(), |n| -n, - |n, arena| Literal::Float(float_alloc!(n, arena)) + |n, arena| Literal::from(float_alloc!(n, arena)), ), Token::Literal(c) => { if let Some(name) = atomize_constant(&mut self.lexer.machine_st.atom_tbl, c) { diff --git a/src/raw_block.rs b/src/raw_block.rs index d39c65ca..a96ae1af 100644 --- a/src/raw_block.rs +++ b/src/raw_block.rs @@ -58,13 +58,6 @@ impl RawBlock { } } - /* - #[inline] - pub fn take(&mut self) -> Self { - mem::replace(self, Self::empty_block()) - } - */ - #[inline] pub fn size(&self) -> usize { self.top as usize - self.base as usize diff --git a/src/types.rs b/src/types.rs index 578014b7..be940a54 100644 --- a/src/types.rs +++ b/src/types.rs @@ -248,13 +248,22 @@ pub struct HeapCellValue { impl fmt::Debug for HeapCellValue { fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { match self.get_tag() { - tag @ (HeapCellValueTag::Cons | HeapCellValueTag::F64) => { + HeapCellValueTag::F64 => { + f.debug_struct("HeapCellValue") + .field("tag", &HeapCellValueTag::F64) + .field("offset", &self.get_value()) + .field("m", &self.m()) + .field("f", &self.f()) + .finish() + } + HeapCellValueTag::Cons => { let cons_ptr = ConsPtr::from_bytes(self.into_bytes()); f.debug_struct("HeapCellValue") - .field("tag", &tag) + .field("tag", &HeapCellValueTag::Cons) .field("ptr", &cons_ptr.ptr()) .field("m", &cons_ptr.m()) + .field("f", &cons_ptr.f()) .finish() } HeapCellValueTag::Atom => { @@ -304,7 +313,7 @@ impl From for HeapCellValue { fn from(f64_ptr: F64Ptr) -> HeapCellValue { HeapCellValue::build_with( HeapCellValueTag::F64, - f64_ptr.as_offset() as u64, + f64_ptr.as_offset().to_u64(), ) } } -- 2.54.0