From 1332611f8338a924f09390e819f9e50abfdd1ebe Mon Sep 17 00:00:00 2001 From: Mark Thom Date: Thu, 22 May 2025 23:49:57 -0700 Subject: [PATCH] use OffsetTableImpl without synchronization by default --- build/instructions_template.rs | 2 +- src/arena.rs | 26 +- src/arithmetic.rs | 30 +- src/codegen.rs | 25 +- src/forms.rs | 3 +- src/heap_print.rs | 105 +++++-- src/machine/arithmetic_ops.rs | 5 +- src/machine/compile.rs | 96 +++--- src/machine/disjuncts.rs | 2 +- src/machine/dispatch.rs | 80 +++-- src/machine/heap.rs | 30 +- src/machine/lib_machine/mod.rs | 44 +-- src/machine/load_state.rs | 163 ++++++---- src/machine/loader.rs | 50 +++- src/machine/machine_indices.rs | 60 ++-- src/machine/machine_state.rs | 3 +- src/machine/machine_state_impl.rs | 199 ++---------- src/machine/mock_wam.rs | 1 + src/machine/mod.rs | 89 +++--- src/machine/preprocessor.rs | 16 +- src/machine/system_calls.rs | 182 ++++++----- src/machine/unify.rs | 28 +- src/macros.rs | 41 +-- src/offset_table.rs | 483 ++++++++++++++++-------------- src/parser/ast.rs | 17 +- src/parser/lexer.rs | 12 +- src/parser/parser.rs | 19 +- src/types.rs | 118 ++++---- 28 files changed, 972 insertions(+), 957 deletions(-) diff --git a/build/instructions_template.rs b/build/instructions_template.rs index baa59626..dc2ed9f7 100644 --- a/build/instructions_template.rs +++ b/build/instructions_template.rs @@ -2698,7 +2698,7 @@ pub fn generate_instructions_rs() -> TokenStream { if ident == "Named" { clause_type_from_name_and_arity_arms.push(quote! { - (name, arity) => ClauseType::Named(arity, name, CodeIndex::default(arena)) + (name, arity) => ClauseType::Named(arity, name, CodeIndex::default(&mut arena.code_index_tbl)) }); clause_type_to_instr_arms.push(quote! { diff --git a/src/arena.rs b/src/arena.rs index a6ccb921..2be3a9f9 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -21,7 +21,6 @@ use std::ops::{Deref, DerefMut}; use std::ptr; use std::ptr::addr_of_mut; use std::ptr::NonNull; -use std::sync::Arc; macro_rules! arena_alloc { ($e:expr, $arena:expr) => {{ @@ -32,8 +31,7 @@ macro_rules! arena_alloc { macro_rules! float_alloc { ($e:expr, $arena:expr) => {{ - let result = $e; - unsafe { $arena.f64_tbl.build_with(OrderedFloat(result)).as_ptr() } + $arena.f64_tbl.build_with(OrderedFloat($e)) }}; } @@ -458,8 +456,8 @@ impl Drop for UntypedArenaSlab { #[derive(Debug)] pub struct Arena { base: Option, - pub f64_tbl: Arc, - pub code_index_tbl: Arc, + pub f64_tbl: F64Table, + pub code_index_tbl: CodeIndexTable, } unsafe impl Send for Arena {} @@ -584,23 +582,27 @@ mod tests { #[test] fn float_ptr_cast() { - let wam = MockWAM::new(); + let mut wam = MockWAM::new(); let f = 0f64; let fp = float_alloc!(f, wam.machine_st.arena); - let mut cell = HeapCellValue::from(fp.clone()); + let mut cell = HeapCellValue::from(fp); - assert_eq!(cell.get_tag(), HeapCellValueTag::F64); + assert_eq!(cell.get_tag(), HeapCellValueTag::F64Offset); assert!(!cell.get_mark_bit()); - assert_eq!(fp.deref(), &OrderedFloat(f)); + assert_eq!( + wam.machine_st.arena.f64_tbl.lookup(fp).deref(), + &OrderedFloat(f) + ); cell.set_mark_bit(true); assert!(cell.get_mark_bit()); read_heap_cell!(cell, - (HeapCellValueTag::F64, ptr) => { - assert_eq!(OrderedFloat(*ptr), OrderedFloat(f)) + (HeapCellValueTag::F64Offset, offset) => { + let fp = wam.machine_st.arena.f64_tbl.lookup(offset.into()); + assert_eq!(*fp, OrderedFloat(0f64)) } _ => { unreachable!() } ); @@ -825,7 +827,7 @@ mod tests { let float_ptr = float_alloc!(float, wam.machine_st.arena); let cell = HeapCellValue::from(float_ptr); - assert_eq!(cell.get_tag(), HeapCellValueTag::F64); + assert_eq!(cell.get_tag(), HeapCellValueTag::F64Offset); // char diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 2f0df28d..a4aad3f8 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -138,6 +138,7 @@ impl<'a> Iterator for ArithInstructionIterator<'a> { #[derive(Debug)] pub(crate) struct ArithmeticEvaluator<'a> { marker: &'a mut DebrayAllocator, + f64_tbl: &'a F64Table, interm: Vec, interm_c: usize, } @@ -156,11 +157,18 @@ impl<'a> ArithmeticTermIter<'a> for &'a Term { } } -fn push_literal(interm: &mut Vec, c: &Literal) -> Result<(), ArithmeticError> { +fn push_literal( + f64_tbl: &F64Table, + interm: &mut Vec, + c: &Literal, +) -> Result<(), ArithmeticError> { 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.as_ptr()))), + &Literal::F64Offset(offset) => { + let n = *f64_tbl.lookup(offset); + interm.push(ArithmeticTerm::Number(Number::Float(n))); + } 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)), @@ -178,9 +186,14 @@ fn push_literal(interm: &mut Vec, c: &Literal) -> Result<(), Ari } impl<'a> ArithmeticEvaluator<'a> { - pub(crate) fn new(marker: &'a mut DebrayAllocator, target_int: usize) -> Self { + pub(crate) fn new( + marker: &'a mut DebrayAllocator, + f64_tbl: &'a F64Table, + target_int: usize, + ) -> Self { ArithmeticEvaluator { marker, + f64_tbl, interm: Vec::new(), interm_c: target_int, } @@ -318,7 +331,7 @@ impl<'a> ArithmeticEvaluator<'a> { for term_ref in src.iter()? { match term_ref? { - ArithTermRef::Literal(c) => push_literal(&mut self.interm, &c)?, + ArithTermRef::Literal(c) => push_literal(self.f64_tbl, &mut self.interm, &c)?, ArithTermRef::Var(lvl, cell, name) => { let var_num = name.to_var_num().unwrap(); @@ -652,11 +665,11 @@ impl Ord for Number { } } -impl TryFrom for Number { +impl TryFrom<(HeapCellValue, &'_ F64Table)> for Number { type Error = (); #[inline] - fn try_from(value: HeapCellValue) -> Result { + fn try_from((value, f64_tbl): (HeapCellValue, &F64Table)) -> Result { read_heap_cell!(value, (HeapCellValueTag::Cons, c) => { match_untyped_arena_ptr!(c, @@ -671,8 +684,9 @@ impl TryFrom for Number { } ) } - (HeapCellValueTag::F64, n) => { - Ok(Number::Float(*n)) + (HeapCellValueTag::F64Offset, offset) => { + let n = *f64_tbl.lookup(offset.into()); + Ok(Number::Float(n)) } (HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint, n) => { Ok(Number::Fixnum(n)) diff --git a/src/codegen.rs b/src/codegen.rs index 41458653..afde0ab7 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -6,6 +6,7 @@ use crate::forms::*; use crate::indexing::*; use crate::instructions::*; use crate::iterators::*; +use crate::offset_table::F64Table; use crate::parser::ast::*; use crate::targets::*; use crate::types::*; @@ -269,9 +270,10 @@ impl CodeGenSettings { } #[derive(Debug)] -pub(crate) struct CodeGenerator { +pub(crate) struct CodeGenerator<'f64_tbl> { marker: DebrayAllocator, settings: CodeGenSettings, + f64_tbl: &'f64_tbl F64Table, pub(crate) skeleton: PredicateSkeleton, } @@ -323,7 +325,7 @@ trait AddToFreeList<'a, Target: CompilationTarget<'a>> { fn add_subterm_to_free_list(&mut self, term: &Term); } -impl<'a> AddToFreeList<'a, FactInstruction> for CodeGenerator { +impl<'a> AddToFreeList<'a, FactInstruction> for CodeGenerator<'_> { fn add_term_to_free_list(&mut self, r: RegType) { self.marker.add_reg_to_free_list(r); } @@ -331,7 +333,7 @@ impl<'a> AddToFreeList<'a, FactInstruction> for CodeGenerator { fn add_subterm_to_free_list(&mut self, _term: &Term) {} } -impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator { +impl<'a> AddToFreeList<'a, QueryInstruction> for CodeGenerator<'_> { #[inline(always)] fn add_term_to_free_list(&mut self, _r: RegType) {} @@ -353,11 +355,12 @@ fn structure_cell(term: &Term) -> Option<&Cell> { } } -impl CodeGenerator { - pub(crate) fn new(settings: CodeGenSettings) -> Self { +impl<'f64_tbl> CodeGenerator<'f64_tbl> { + pub(crate) fn new(f64_tbl: &'f64_tbl F64Table, settings: CodeGenSettings) -> Self { CodeGenerator { marker: DebrayAllocator::new(), settings, + f64_tbl, skeleton: PredicateSkeleton::new(), } } @@ -427,7 +430,7 @@ impl CodeGenerator { where Target: crate::targets::CompilationTarget<'a>, Iter: Iterator>, - CodeGenerator: AddToFreeList<'a, Target>, + CodeGenerator<'f64_tbl>: AddToFreeList<'a, Target>, { let mut target = CodeDeque::new(); @@ -443,7 +446,7 @@ impl CodeGenerator { } TermRef::Clause(lvl, cell, name, terms) => { let terms_range = - if let Some(subterm @ Term::Literal(_, Literal::CodeIndex(_))) = + if let Some(subterm @ Term::Literal(_, Literal::CodeIndexOffset(_))) = terms.last() { self.subterm_to_instr::(subterm, context, &mut target); @@ -666,7 +669,7 @@ impl CodeGenerator { } }, InlinedClauseType::IsFloat(..) => match terms[0] { - Term::Literal(_, Literal::Float(_)) => { + Term::Literal(_, Literal::F64Offset(_)) => { instr!("$succeed") } Term::Var(ref vr, ref name) => { @@ -687,7 +690,7 @@ impl CodeGenerator { } }, InlinedClauseType::IsNumber(..) => match terms[0] { - Term::Literal(_, Literal::Float(_)) + Term::Literal(_, Literal::F64Offset(_)) | Term::Literal(_, Literal::Rational(_)) | Term::Literal(_, Literal::Integer(_)) | Term::Literal(_, Literal::Fixnum(_)) => { @@ -791,7 +794,7 @@ impl CodeGenerator { term_loc: GenContext, arg: usize, ) -> Result { - let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, target_int); + let mut evaluator = ArithmeticEvaluator::new(&mut self.marker, self.f64_tbl, target_int); evaluator.compile_is(term, term_loc, arg) } @@ -861,7 +864,7 @@ impl CodeGenerator { Term::Literal( _, c @ Literal::Integer(_) - | c @ Literal::Float(_) + | c @ Literal::F64Offset(_) | c @ Literal::Rational(_) | c @ Literal::Fixnum(_), ) => { diff --git a/src/forms.rs b/src/forms.rs index 0779d5b8..1418b570 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -6,6 +6,7 @@ use crate::machine::disjuncts::VarData; use crate::machine::loader::PredicateQueue; use crate::machine::machine_errors::*; use crate::machine::machine_indices::*; +use crate::offset_table::OffsetTable; use crate::parser::ast::*; use crate::parser::dashu::{Integer, Rational}; use crate::parser::parser::CompositeOpDesc; @@ -742,7 +743,7 @@ impl ArenaFrom for HeapCellValue { match value { Number::Fixnum(n) => fixnum_as_cell!(n), Number::Integer(n) => typed_arena_ptr_as_cell!(n), - Number::Float(OrderedFloat(n)) => HeapCellValue::from(float_alloc!(n, arena)), + Number::Float(n) => HeapCellValue::from(arena.f64_tbl.build_with(n)), Number::Rational(n) => typed_arena_ptr_as_cell!(n), } } diff --git a/src/heap_print.rs b/src/heap_print.rs index c23344bf..d45e45a9 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -8,7 +8,6 @@ use crate::parser::dashu::{ibig, Integer, Rational}; use crate::forms::*; use crate::heap_iter::*; use crate::machine::heap::*; -use crate::machine::machine_indices::*; use crate::machine::partial_string::*; use crate::machine::stack::*; use crate::machine::streams::*; @@ -389,17 +388,20 @@ fn is_numbered_var(name: Atom, arity: usize) -> bool { #[inline] fn negated_op_needs_bracketing( iter: &StackfulPreOrderHeapIter, + f64_tbl: &F64Table, op_dir: &OpDir, op: &Option, ) -> bool { if let Some(ref op) = op { op.is_negative_sign() - && iter.leftmost_leaf_has_property(op_dir, |addr| match Number::try_from(addr) { - Ok(Number::Fixnum(n)) => n.get_num() > 0, - Ok(Number::Float(OrderedFloat(f))) => f > 0f64, - Ok(Number::Integer(n)) => n.is_positive(), - Ok(Number::Rational(n)) => n.is_positive(), - _ => false, + && iter.leftmost_leaf_has_property(op_dir, |addr| { + match Number::try_from((addr, f64_tbl)) { + Ok(Number::Fixnum(n)) => n.get_num() > 0, + Ok(Number::Float(OrderedFloat(f))) => f > 0f64, + Ok(Number::Integer(n)) => n.is_positive(), + Ok(Number::Rational(n)) => n.is_positive(), + _ => false, + } }) } else { false @@ -473,6 +475,7 @@ pub fn fmt_float(mut fl: f64) -> String { pub struct HCPrinter<'a, Outputter> { outputter: Outputter, iter: StackfulPreOrderHeapIter<'a, ListElider>, + arena: &'a Arena, op_dir: &'a OpDir, state_stack: Vec, toplevel_spec: Option, @@ -530,19 +533,39 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option } } - match Number::try_from(addr) { - Ok(Number::Fixnum(n)) if n.get_num() >= 0 => { - Some(numbervar(offset + Integer::from(n.get_num()))) + read_heap_cell!(addr, + (HeapCellValueTag::Cons, c) => { + match_untyped_arena_ptr!(c, + (ArenaHeaderTag::Integer, n) => { + if !n.is_negative() { + Some(numbervar(Integer::from(offset + &*n))) + } else { + None + } + } + _ => { + None + } + ) } - Ok(Number::Integer(n)) if !n.is_negative() => Some(numbervar(Integer::from(offset + &*n))), - _ => None, - } + (HeapCellValueTag::Fixnum, n) => { + if n.get_num() >= 0 { + Some(numbervar(offset + Integer::from(n.get_num()))) + } else { + None + } + } + _ => { + None + } + ) } impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn new( heap: &'a mut Heap, stack: &'a mut Stack, + arena: &'a Arena, op_dir: &'a OpDir, output: Outputter, term_loc: usize, @@ -550,6 +573,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { HCPrinter { outputter: output, iter: stackful_preorder_iter(heap, stack, term_loc), + arena, op_dir, state_stack: vec![], toplevel_spec: None, @@ -1280,11 +1304,13 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { let at_cdr = self.outputter.ends_with("|"); - if self.double_quotes && !self.ignore_ops && !is_cyclic { - if end_cell.is_string_terminator(self.iter.heap) { - self.remove_list_children(focus.value() as usize); - return self.print_proper_string(focus.value() as usize, max_depth); - } + if self.double_quotes + && !self.ignore_ops + && !is_cyclic + && end_cell.is_string_terminator(self.iter.heap) + { + self.remove_list_children(focus.value() as usize); + return self.print_proper_string(focus.value() as usize, max_depth); } if self.ignore_ops { @@ -1426,7 +1452,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { || if let Some(ref op) = op { if self.numbervars && arity == 1 && name == atom!("$VAR") { !self.iter.immediate_leaf_has_property(|addr| { - match Number::try_from(addr) { + match Number::try_from((addr, &self.arena.f64_tbl)) { Ok(Number::Integer(n)) => (*n).sign() == Sign::Positive, Ok(Number::Fixnum(n)) => n.get_num() >= 0, Ok(Number::Float(f)) => f >= OrderedFloat(0f64), @@ -1511,28 +1537,29 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } } - fn print_index_ptr(&mut self, idx: CodeIndex, max_depth: usize) { + fn print_index_ptr(&mut self, idx: CodeIndexOffset, 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 idx_ptr = idx.as_ptr(); + let idx_ptr = self.arena.code_index_tbl.lookup(idx); let offset = if idx_ptr.is_undefined() || idx_ptr.is_dynamic_undefined() { TokenOrRedirect::Atom(atom!("undefined")) } else { let idx_ptr_p = idx_ptr.p() as i64; - TokenOrRedirect::NumberFocus( - max_depth, - NumberFocus::Unfocused(Number::Fixnum( - /* FIXME this is not safe */ - unsafe { Fixnum::build_with_unchecked(idx_ptr_p) }, - )), - None, - ) + if let Ok(n) = Fixnum::build_with_checked(idx_ptr_p) { + TokenOrRedirect::NumberFocus( + max_depth, + NumberFocus::Unfocused(Number::Fixnum(n)), + None, + ) + } else { + TokenOrRedirect::Atom(atom!("out_of_bounds_idx_ptr")) + } }; self.state_stack.push(offset); @@ -1612,7 +1639,8 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { is_functor_redirect: bool, mut max_depth: usize, ) { - let negated_operand = negated_op_needs_bracketing(&self.iter, self.op_dir, &op); + let negated_operand = + negated_op_needs_bracketing(&self.iter, &self.arena.f64_tbl, self.op_dir, &op); let addr = match self.check_for_seen(&mut max_depth) { Some(addr) => addr, @@ -1714,14 +1742,15 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { }); } } - (HeapCellValueTag::CodeIndex, idx) => { + (HeapCellValueTag::CodeIndexOffset, 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); } - (HeapCellValueTag::F64, f) => { - self.print_number(max_depth, NumberFocus::Unfocused(Number::Float(*f)), &op); + (HeapCellValueTag::F64Offset, offset) => { + let f = *self.arena.f64_tbl.lookup(offset.into()); + self.print_number(max_depth, NumberFocus::Unfocused(Number::Float(f)), &op); } (HeapCellValueTag::PStrLoc) => { self.print_list_like(max_depth); @@ -1885,6 +1914,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 3, @@ -1917,6 +1947,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 5, @@ -1944,6 +1975,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 0, @@ -1956,6 +1988,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 0, @@ -1999,6 +2032,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 0, @@ -2017,6 +2051,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 0, @@ -2033,6 +2068,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 0, @@ -2069,6 +2105,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 0, @@ -2094,6 +2131,7 @@ mod tests { let printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 2, @@ -2123,6 +2161,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, &mut wam.machine_st.stack, + &wam.machine_st.arena, &wam.op_dir, PrinterOutputter::new(), 2, diff --git a/src/machine/arithmetic_ops.rs b/src/machine/arithmetic_ops.rs index d1667795..8e4c0552 100644 --- a/src/machine/arithmetic_ops.rs +++ b/src/machine/arithmetic_ops.rs @@ -1124,7 +1124,7 @@ impl MachineState { &ArithmeticTerm::Reg(r) => { let value = self.store(self.deref(self[r])); - match Number::try_from(value) { + match Number::try_from((value, &self.arena.f64_tbl)) { Ok(n) => Ok(n), Err(_) => { self.heap[0] = value; @@ -1388,7 +1388,8 @@ impl MachineState { (HeapCellValueTag::Fixnum, n) => { self.interms.push(Number::Fixnum(n)); } - (HeapCellValueTag::F64, fl) => { + (HeapCellValueTag::F64Offset, offset) => { + let fl = self.arena.f64_tbl.lookup(offset); self.interms.push(Number::Float(*fl)); } (HeapCellValueTag::Cons, ptr) => { diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 1b2f6bff..0ce7b5b8 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -700,31 +700,25 @@ fn remove_non_leading_clause( } } -fn finalize_retract( +fn finalize_retract<'a, LS: LoadState<'a>>( + payload: &mut >::LoaderFieldType, key: PredicateKey, compilation_target: CompilationTarget, skeleton: &mut PredicateSkeleton, code_index: CodeIndex, target_pos: usize, index_ptr_opt: Option, - retraction_info: &mut RetractionInfo, ) -> usize { let clause_clause_loc = delete_from_skeleton( compilation_target, key, skeleton, target_pos, - retraction_info, + &mut payload.retraction_info, ); if let Some(index_ptr) = index_ptr_opt { - set_code_index( - retraction_info, - &compilation_target, - key, - code_index, - index_ptr, - ); + set_code_index::(payload, &compilation_target, key, code_index, index_ptr); } clause_clause_loc @@ -1239,7 +1233,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let mut preprocessor = Preprocessor::new(settings); let clause = preprocessor.try_term_to_tl(self, term)?; - let mut cg = CodeGenerator::new(settings); + let f64_tbl = &LS::machine_st(&mut self.payload).arena.f64_tbl; + + let mut cg = CodeGenerator::new(f64_tbl, settings); let clause_code = cg.compile_predicate(vec![clause])?; Ok(StandaloneCompileResult { @@ -1254,7 +1250,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { mut predicates: PredicateQueue, settings: CodeGenSettings, ) -> Result { - let code_index = self.get_or_insert_code_index(key, predicates.compilation_target); + let code_idx = self.get_or_insert_code_index(key, predicates.compilation_target); LS::err_on_builtin_overwrite(self, key)?; @@ -1268,7 +1264,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { clauses.push(preprocessor.try_term_to_tl(self, term)?); } - let mut cg = CodeGenerator::new(settings); + let f64_tbl = &LS::machine_st(&mut self.payload).arena.f64_tbl; + + let mut cg = CodeGenerator::new(f64_tbl, settings); let mut code = cg.compile_predicate(clauses)?; if settings.is_extensible { @@ -1327,9 +1325,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { ); } + let index_ptr = LS::machine_st(&mut self.payload) + .arena + .code_index_tbl + .lookup(code_idx.into()); + print_overwrite_warning( &predicates.compilation_target, - code_index.get(), + *index_ptr, key, settings.is_dynamic(), ); @@ -1340,16 +1343,16 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { IndexPtr::index(code_ptr) }; - set_code_index( - &mut self.payload.retraction_info, + set_code_index::( + &mut self.payload, &predicates.compilation_target, key, - code_index, + code_idx, index_ptr, ); self.wam_prelude.code.extend(code); - Ok(code_index) + Ok(code_idx) } fn extend_local_predicate_skeleton( @@ -1551,19 +1554,19 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { self.push_back_to_local_predicate_skeleton(&compilation_target, &key, code_len); - let code_index = self.get_or_insert_code_index(key, compilation_target); + let code_idx = self.get_or_insert_code_index(key, compilation_target); if let Some(new_code_ptr) = result { - set_code_index( - &mut self.payload.retraction_info, + set_code_index::( + &mut self.payload, &compilation_target, key, - code_index, + code_idx, new_code_ptr, ); } - Ok(code_index) + Ok(code_idx) } AppendOrPrepend::Prepend => { let clause_index_info = standalone_skeleton.clauses.pop_back().unwrap(); @@ -1593,17 +1596,17 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { self.push_front_to_local_predicate_skeleton(&compilation_target, &key, code_len); - let code_index = self.get_or_insert_code_index(key, compilation_target); + let code_idx = self.get_or_insert_code_index(key, compilation_target); - set_code_index( - &mut self.payload.retraction_info, + set_code_index::( + &mut self.payload, &compilation_target, key, - code_index, + code_idx, new_code_ptr, ); - Ok(code_index) + Ok(code_idx) } } } @@ -1651,7 +1654,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { pub(super) fn retract_clause(&mut self, key: PredicateKey, target_pos: usize) -> usize { let payload_compilation_target = self.payload.compilation_target; - let code_index = self.get_or_insert_code_index(key, payload_compilation_target); + let code_idx_offset = self.get_or_insert_code_index(key, payload_compilation_target); let skeleton = self .wam_prelude @@ -1729,14 +1732,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { None }; - return finalize_retract( + return finalize_retract::( + &mut self.payload, key, payload_compilation_target, skeleton, - code_index, + code_idx_offset, target_pos, index_ptr_opt, - &mut self.payload.retraction_info, ); } None => { @@ -1758,14 +1761,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { ) }; - return finalize_retract( + return finalize_retract::( + &mut self.payload, key, payload_compilation_target, skeleton, - code_index, + code_idx_offset, target_pos, index_ptr_opt, - &mut self.payload.retraction_info, ); } } @@ -1988,14 +1991,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { } }; - finalize_retract( + finalize_retract::( + &mut self.payload, key, payload_compilation_target, skeleton, - code_index, + code_idx_offset, target_pos, index_ptr_opt, - &mut self.payload.retraction_info, ) } } @@ -2222,18 +2225,23 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { }; let predicates = self.payload.predicates.take(); - let code_index = self.compile(key, predicates, settings)?; + let offset = self.compile(key, predicates, settings)?; if let Some(filename) = self.listing_src_file_name() { if let Some(ref mut module) = self.wam_prelude.indices.modules.get_mut(&filename) { - let index_ptr = code_index.get(); - let code_index = *module.code_dir.entry(key).or_insert(code_index); + let code_idx = LS::machine_st(&mut self.payload) + .arena + .code_index_tbl + .lookup_mut(offset.into()); - set_code_index( - &mut self.payload.retraction_info, + let index_ptr = *code_idx; + let offset = *module.code_dir.entry(key).or_insert(offset); + + set_code_index::( + &mut self.payload, &CompilationTarget::Module(filename), key, - code_index, + offset, index_ptr, ); } diff --git a/src/machine/disjuncts.rs b/src/machine/disjuncts.rs index 2187e7b8..4ecac7bc 100644 --- a/src/machine/disjuncts.rs +++ b/src/machine/disjuncts.rs @@ -579,7 +579,7 @@ impl VariableClassifier { mut terms, ) if terms.len() == 3 => { if let Some(last_arg) = terms.last() { - if let Term::Literal(_, Literal::CodeIndex(_)) = last_arg { + if let Term::Literal(_, Literal::CodeIndexOffset(_)) = last_arg { terms.pop(); state_stack.push(TraversalState::Term(Term::Clause( Cell::default(), diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 20dfd8ee..20d60c94 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -232,13 +232,11 @@ impl MachineState { } (HeapCellValueTag::PStrLoc | HeapCellValueTag::Lis) => { - // HeapCellValueTag::CStr) => { l } (HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint | - // HeapCellValueTag::Char | - HeapCellValueTag::F64) => { + HeapCellValueTag::F64Offset) => { c } (HeapCellValueTag::Atom, (_name, arity)) => { @@ -548,19 +546,33 @@ impl Machine { let p = self.machine_st.p; // Find the boundaries of the current predicate - self.indices.code_dir.sort_by(|_, a, _, b| a.cmp(b)); + self.indices.code_dir.sort_by(|_, a, _, b| { + let a = *self.machine_st.arena.code_index_tbl.lookup((*a).into()); + let b = *self.machine_st.arena.code_index_tbl.lookup((*b).into()); + + a.cmp(&b) + }); let predicate_idx = self .indices .code_dir - .binary_search_by_key(&p, |_, x| x.get().p() as usize) + .binary_search_by_key(&p, |_, x| -> usize { + self.machine_st.arena.code_index_tbl.lookup((*x).into()).p() + as usize + }) .unwrap_or_else(|x| x - 1); let current_pred_start = self .indices .code_dir .get_index(predicate_idx) - .map(|x| x.1.as_ptr().p() as usize) + .map(|idx| { + self.machine_st + .arena + .code_index_tbl + .lookup((*idx.1).into()) + .p() as usize + }) .unwrap(); debug_assert!(current_pred_start <= p); @@ -569,7 +581,13 @@ impl Machine { .indices .code_dir .get_index(predicate_idx + 1) - .map(|x| x.1.as_ptr().p() as usize) + .map(|idx| { + self.machine_st + .arena + .code_index_tbl + .lookup((*idx.1).into()) + .p() as usize + }) .unwrap_or(self.code.len()); debug_assert!(current_pred_end >= p); @@ -2343,7 +2361,7 @@ impl Machine { .store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, - (HeapCellValueTag::Fixnum | HeapCellValueTag::F64 | + (HeapCellValueTag::Fixnum | HeapCellValueTag::F64Offset | HeapCellValueTag::Cons) => { self.machine_st.p += 1; } @@ -2375,7 +2393,7 @@ impl Machine { .store(self.machine_st.deref(self.machine_st[r])); read_heap_cell!(d, - (HeapCellValueTag::Fixnum | HeapCellValueTag::F64 | + (HeapCellValueTag::Fixnum | HeapCellValueTag::F64Offset | HeapCellValueTag::Cons) => { self.machine_st.p = self.machine_st.cp; } @@ -2472,7 +2490,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[r])); - match Number::try_from(d) { + match Number::try_from((d, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(_) | Number::Integer(_)) => { self.machine_st.p += 1; } @@ -2493,7 +2511,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[r])); - match Number::try_from(d) { + match Number::try_from((d, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(_) | Number::Integer(_)) => { self.machine_st.p = self.machine_st.cp; } @@ -2514,7 +2532,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[r])); - match Number::try_from(d) { + match Number::try_from((d, &self.machine_st.arena.f64_tbl)) { Ok(_) => { self.machine_st.p += 1; } @@ -2528,7 +2546,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[r])); - match Number::try_from(d) { + match Number::try_from((d, &self.machine_st.arena.f64_tbl)) { Ok(_) => { self.machine_st.p = self.machine_st.cp; } @@ -2590,7 +2608,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[r])); - match Number::try_from(d) { + match Number::try_from((d, &self.machine_st.arena.f64_tbl)) { Ok(Number::Float(_)) => { self.machine_st.p += 1; } @@ -2604,7 +2622,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[r])); - match Number::try_from(d) { + match Number::try_from((d, &self.machine_st.arena.f64_tbl)) { Ok(Number::Float(_)) => { self.machine_st.p = self.machine_st.cp; } @@ -2677,10 +2695,10 @@ impl Machine { } } } - &Instruction::CallNamed(arity, name, ref idx) => { - let idx = idx.get(); + &Instruction::CallNamed(arity, name, idx) => { + let idx = self.machine_st.arena.code_index_tbl.lookup(idx.into()); - try_or_throw!(self.machine_st, self.try_call(name, arity, idx)); + try_or_throw!(self.machine_st, self.try_call(name, arity, *idx)); if self.machine_st.fail { self.machine_st.backtrack(); @@ -2688,10 +2706,10 @@ impl Machine { increment_call_count!(self.machine_st); } } - &Instruction::ExecuteNamed(arity, name, ref idx) => { - let idx = idx.get(); + &Instruction::ExecuteNamed(arity, name, idx) => { + let idx = self.machine_st.arena.code_index_tbl.lookup(idx.into()); - try_or_throw!(self.machine_st, self.try_execute(name, arity, idx)); + try_or_throw!(self.machine_st, self.try_execute(name, arity, *idx)); if self.machine_st.fail { self.machine_st.backtrack(); @@ -2699,19 +2717,19 @@ impl Machine { increment_call_count!(self.machine_st); } } - &Instruction::DefaultCallNamed(arity, name, ref idx) => { - let idx = idx.get(); + &Instruction::DefaultCallNamed(arity, name, idx) => { + let idx = self.machine_st.arena.code_index_tbl.lookup(idx.into()); - try_or_throw!(self.machine_st, self.try_call(name, arity, idx)); + try_or_throw!(self.machine_st, self.try_call(name, arity, *idx)); if self.machine_st.fail { self.machine_st.backtrack(); } } - &Instruction::DefaultExecuteNamed(arity, name, ref idx) => { - let idx = idx.get(); + &Instruction::DefaultExecuteNamed(arity, name, idx) => { + let idx = self.machine_st.arena.code_index_tbl.lookup(idx.into()); - try_or_throw!(self.machine_st, self.try_execute(name, arity, idx)); + try_or_throw!(self.machine_st, self.try_execute(name, arity, *idx)); if self.machine_st.fail { self.machine_st.backtrack(); @@ -5251,7 +5269,7 @@ impl Machine { let l = self.machine_st.registers[3]; let l = self.machine_st.store(self.machine_st.deref(l)); - let l = match Number::try_from(l) { + let l = match Number::try_from((l, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(l)) => l.get_num() as usize, _ => unreachable!(), }; @@ -5259,7 +5277,7 @@ impl Machine { let p = self.machine_st.registers[4]; let p = self.machine_st.store(self.machine_st.deref(p)); - let p = match Number::try_from(p) { + let p = match Number::try_from((p, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(p)) => p.get_num() as usize, _ => unreachable!(), }; @@ -5297,7 +5315,7 @@ impl Machine { let l = self.machine_st.registers[3]; let l = self.machine_st.store(self.machine_st.deref(l)); - let l = match Number::try_from(l) { + let l = match Number::try_from((l, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(l)) => l.get_num() as usize, _ => unreachable!(), }; @@ -5305,7 +5323,7 @@ impl Machine { let p = self.machine_st.registers[4]; let p = self.machine_st.store(self.machine_st.deref(p)); - let p = match Number::try_from(p) { + let p = match Number::try_from((p, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(p)) => p.get_num() as usize, _ => unreachable!(), }; diff --git a/src/machine/heap.rs b/src/machine/heap.rs index dc4d2ce0..fdf24047 100644 --- a/src/machine/heap.rs +++ b/src/machine/heap.rs @@ -1,6 +1,6 @@ use crate::atom_table::*; -use crate::forms::*; use crate::functor_macro::*; +use crate::machine::{ArenaHeaderTag, Fixnum, Integer}; use crate::types::*; use std::alloc; @@ -717,7 +717,7 @@ impl Heap { pub(crate) fn slice_to_str(&self, slice_loc: usize, slice_len: usize) -> &str { unsafe { let slice = std::slice::from_raw_parts(self.inner.ptr.add(slice_loc), slice_len); - std::str::from_utf8_unchecked(&slice) + std::str::from_utf8_unchecked(slice) } } @@ -824,7 +824,7 @@ impl Heap { let s = unsafe { let char_ptr = self.inner.ptr.add(byte_idx); let slice = std::slice::from_raw_parts(char_ptr, size_of::()); - std::str::from_utf8_unchecked(&slice) + std::str::from_utf8_unchecked(slice) }; s.chars().next().unwrap() @@ -1158,14 +1158,24 @@ pub fn sized_iter_to_heap_list>( pub(crate) fn to_local_code_ptr(heap: &Heap, addr: HeapCellValue) -> Option { let extract_integer = |s: usize| -> Option { - match Number::try_from(heap[s]) { - Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(), - Ok(Number::Integer(n)) => { - let value: usize = (&*n).try_into().unwrap(); - Some(value) + read_heap_cell!(heap[s], + (HeapCellValueTag::Cons, c) => { + match_untyped_arena_ptr!(c, + (ArenaHeaderTag::Integer, n) => { + (&*n).try_into().ok() + } + _ => { + None + } + ) } - _ => None, - } + (HeapCellValueTag::Fixnum, n) => { + usize::try_from(n.get_num()).ok() + } + _ => { + None + } + ) }; read_heap_cell!(addr, diff --git a/src/machine/lib_machine/mod.rs b/src/machine/lib_machine/mod.rs index 7e87dc00..dbaac207 100644 --- a/src/machine/lib_machine/mod.rs +++ b/src/machine/lib_machine/mod.rs @@ -277,14 +277,15 @@ impl Term { }, } } - (HeapCellValueTag::F64, f) => { - term_stack.push(Term::Float((*f).into())); + (HeapCellValueTag::F64Offset, offset) => { + let f = *machine.machine_st.arena.f64_tbl.lookup(offset); + term_stack.push(Term::Float(f.into())); } (HeapCellValueTag::Fixnum, n) => { term_stack.push(Term::Integer(n.into())); } (HeapCellValueTag::Cons, ptr) => { - if let Ok(n) = Number::try_from(addr) { + if let Ok(n) = Number::try_from((addr, &machine.machine_st.arena.f64_tbl)) { match n { Number::Integer(i) => term_stack.push(Term::Integer((*i).clone())), Number::Rational(r) => term_stack.push(Term::Rational((*r).clone())), @@ -312,31 +313,6 @@ impl Term { } } (HeapCellValueTag::Atom, (name, arity)) => { - //let h = iter.focus().value() as usize; - //let mut arity = arity; - - // Not sure why/if this is needed. - // Might find out with better testing later. - /* - if iter.heap.len() > h + arity + 1 { - let value = iter.heap[h + arity + 1]; - - if let Some(idx) = get_structure_index(value) { - // in the second condition, arity == 0, - // meaning idx cannot pertain to this atom - // if it is the direct subterm of a larger - // structure. - if arity > 0 || !iter.direct_subterm_of_str(h) { - term_stack.push( - Term::Literal(Cell::default(), Literal::CodeIndex(idx)) - ); - - arity += 1; - } - } - } - */ - if arity == 0 { let atom_name = name.as_str().to_string(); if atom_name == "[]" { @@ -621,9 +597,15 @@ impl Machine { .indices .code_dir .get(&(atom!("call"), 1)) - .expect("couldn't get code index") - .local() - .unwrap(); + .cloned() + .map(|offset| { + self.machine_st + .arena + .code_index_tbl + .lookup(offset.into()) + .p() as usize + }) + .expect("couldn't get code index"); self.machine_st.execute_at_index(1, call_index_p); diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 0a712c1a..123c7be5 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -15,35 +15,40 @@ use std::mem; pub(super) type ModuleOpExports = Vec<(OpDecl, Option)>; -pub(super) fn set_code_index( - retraction_info: &mut RetractionInfo, +pub(super) fn set_code_index<'a, LS: LoadState<'a>>( + payload: &mut >::LoaderFieldType, compilation_target: &CompilationTarget, key: PredicateKey, - mut code_index: CodeIndex, + code_idx: CodeIndex, code_ptr: IndexPtr, ) { + let mut code_idx_ptr = LS::machine_st(payload) + .arena + .code_index_tbl + .lookup_mut(code_idx.into()); + let record = match compilation_target { CompilationTarget::User => { - if IndexPtrTag::Undefined == code_index.get().tag() { - code_index.set(code_ptr); + if IndexPtrTag::Undefined == code_idx_ptr.tag() { + code_idx_ptr.set(code_ptr); RetractionRecord::AddedUserPredicate(key) } else { - let replaced = code_index.replace(code_ptr); + let replaced = code_idx_ptr.replace(code_ptr); RetractionRecord::ReplacedUserPredicate(key, replaced) } } CompilationTarget::Module(ref module_name) => { - if IndexPtrTag::Undefined == code_index.get().tag() { - code_index.set(code_ptr); + if IndexPtrTag::Undefined == code_idx_ptr.tag() { + code_idx_ptr.set(code_ptr); RetractionRecord::AddedModulePredicate(*module_name, key) } else { - let replaced = code_index.replace(code_ptr); + let replaced = code_idx_ptr.replace(code_ptr); RetractionRecord::ReplacedModulePredicate(*module_name, key, replaced) } } }; - retraction_info.push_record(record); + payload.retraction_info.push_record(record); } fn add_op_decl_as_module_export<'a, LS: LoadState<'a>>( @@ -133,21 +138,28 @@ pub(super) fn import_module_exports<'a, LS: LoadState<'a>>( } if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() { - let arena = &mut LS::machine_st(payload).arena; + let code_idx_tbl = &mut LS::machine_st(payload).arena.code_index_tbl; let target_code_index = *code_dir .entry(key) - .or_insert_with(|| CodeIndex::default(arena)); + .or_insert_with(|| CodeIndex::default(code_idx_tbl)); + + let src_code_index_ptr = *code_idx_tbl.lookup(src_code_index.into()); - set_code_index( - &mut payload.retraction_info, + set_code_index::( + payload, compilation_target, key, target_code_index, - src_code_index.get(), + src_code_index_ptr, ); - if src_code_index.as_ptr().is_dynamic_undefined() { + if LS::machine_st(payload) + .arena + .code_index_tbl + .lookup(src_code_index.into()) + .is_dynamic_undefined() + { code_dir.insert(key, src_code_index); } } else { @@ -189,19 +201,20 @@ fn import_module_exports_into_module<'a, LS: LoadState<'a>>( meta_predicates.insert(key, meta_specs.clone()); } - if let Some(src_code_index) = imported_module.code_dir.get(&key) { - let arena = &mut LS::machine_st(payload).arena; + if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() { + let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl; + let src_code_ptr = *code_index_tbl.lookup(src_code_index.into()); let target_code_index = *code_dir .entry(key) - .or_insert_with(|| CodeIndex::default(arena)); + .or_insert_with(|| CodeIndex::default(code_index_tbl)); - set_code_index( - &mut payload.retraction_info, + set_code_index::( + payload, compilation_target, key, target_code_index, - src_code_index.get(), + src_code_ptr, ); } else { return Err(SessionError::ModuleDoesNotContainExport( @@ -242,21 +255,21 @@ fn import_qualified_module_exports<'a, LS: LoadState<'a>>( .insert(key, meta_specs.clone()); } - if let Some(src_code_index) = imported_module.code_dir.get(&key) { - let arena = &mut LS::machine_st(payload).arena; + if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() { + let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl; - let target_code_index = *wam_prelude - .indices - .code_dir - .entry(key) - .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena)); + let src_code_ptr = *code_index_tbl.lookup(src_code_index.into()); + let target_code_index = + *wam_prelude.indices.code_dir.entry(key).or_insert_with(|| { + CodeIndex::new(IndexPtr::undefined(), code_index_tbl) + }); - set_code_index( - &mut payload.retraction_info, + set_code_index::( + payload, compilation_target, key, target_code_index, - src_code_index.get(), + src_code_ptr, ); } else { return Err(SessionError::ModuleDoesNotContainExport( @@ -303,19 +316,20 @@ fn import_qualified_module_exports_into_module<'a, LS: LoadState<'a>>( meta_predicates.insert(key, meta_specs.clone()); } - if let Some(src_code_index) = imported_module.code_dir.get(&key) { - let arena = &mut LS::machine_st(payload).arena; + if let Some(src_code_index) = imported_module.code_dir.get(&key).cloned() { + let code_index_tbl = &mut LS::machine_st(payload).arena.code_index_tbl; + let src_code_ptr = *code_index_tbl.lookup(src_code_index.into()); let target_code_index = *code_dir .entry(key) - .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena)); + .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), code_index_tbl)); - set_code_index( - &mut payload.retraction_info, + set_code_index::( + payload, &payload_compilation_target, key, target_code_index, - src_code_index.get(), + src_code_ptr, ); } else { return Err(SessionError::ModuleDoesNotContainExport( @@ -468,11 +482,14 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { .indices .get_predicate_skeleton(local_compilation_target, key) { - let old_index_ptr = code_index.replace(if global_skeleton.core.is_dynamic { - IndexPtr::dynamic_undefined() - } else { - IndexPtr::undefined() - }); + let old_index_ptr = code_index.replace( + &mut LS::machine_st(&mut self.payload).arena.code_index_tbl, + if global_skeleton.core.is_dynamic { + IndexPtr::dynamic_undefined() + } else { + IndexPtr::undefined() + }, + ); self.payload.retraction_info.push_record( RetractionRecord::ReplacedModulePredicate(module_name, *key, old_index_ptr), @@ -486,8 +503,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { continue; } - if !code_index.as_ptr().is_undefined() && !code_index.as_ptr().is_dynamic_undefined() { - let old_index_ptr = code_index.replace(IndexPtr::undefined()); + let code_index_tbl = &mut LS::machine_st(&mut self.payload).arena.code_index_tbl; + let code_ptr = code_index_tbl.lookup((*code_index).into()); + + if !code_ptr.is_undefined() && !code_ptr.is_dynamic_undefined() { + let old_index_ptr = code_index.replace(code_index_tbl, IndexPtr::undefined()); self.payload.retraction_info.push_record( RetractionRecord::ReplacedModulePredicate(module_name, *key, old_index_ptr), @@ -517,25 +537,34 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { None => return, }; - fn remove_module_exports( + fn remove_module_exports<'b, LS: LoadState<'b>>( + payload: &mut >::LoaderFieldType, removed_module: &Module, code_dir: &mut CodeDir, op_dir: &mut OpDir, - retraction_info: &mut RetractionInfo, predicate_retractor: impl Fn(PredicateKey, IndexPtr) -> RetractionRecord, op_retractor: impl Fn(OpDecl, OpDesc) -> RetractionRecord, ) { for export in removed_module.module_decl.exports.iter() { match export { ModuleExport::PredicateKey(ref key) => { - match (removed_module.code_dir.get(key), code_dir.get_mut(key)) { - (Some(module_code_index), Some(target_code_index)) - if module_code_index.get() == target_code_index.get() => - { - let old_index_ptr = - target_code_index.replace(IndexPtr::undefined()); - retraction_info - .push_record(predicate_retractor(*key, old_index_ptr)); + match ( + removed_module.code_dir.get(key).cloned(), + code_dir.get_mut(key).cloned(), + ) { + (Some(module_code_idx), Some(target_code_idx)) => { + let code_index_tbl = + &mut LS::machine_st(payload).arena.code_index_tbl; + let module_code_ptr = code_index_tbl.lookup(module_code_idx.into()); + let target_code_ptr = code_index_tbl.lookup(target_code_idx.into()); + + if module_code_ptr == target_code_ptr { + let old_index_ptr = target_code_idx + .replace(code_index_tbl, IndexPtr::undefined()); + payload + .retraction_info + .push_record(predicate_retractor(*key, old_index_ptr)); + } } _ => {} } @@ -545,7 +574,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { .swap_remove(&(op_decl.name, op_decl.op_desc.get_spec().fixity())); if let Some(op_desc) = op_dir_value_opt { - retraction_info.push_record(op_retractor(*op_decl, op_desc)); + payload + .retraction_info + .push_record(op_retractor(*op_decl, op_desc)); } } } @@ -554,11 +585,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { match self.payload.compilation_target { CompilationTarget::User => { - remove_module_exports( + remove_module_exports::( + &mut self.payload, &removed_module, &mut self.wam_prelude.indices.code_dir, &mut self.wam_prelude.indices.op_dir, - &mut self.payload.retraction_info, RetractionRecord::ReplacedUserPredicate, RetractionRecord::ReplacedUserOp, ); @@ -578,11 +609,11 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { .modules .get_mut(&target_module_name) { - remove_module_exports( + remove_module_exports::( + &mut self.payload, &removed_module, &mut module.code_dir, &mut module.op_dir, - &mut self.payload.retraction_info, predicate_retractor, op_retractor, ); @@ -608,7 +639,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { Some(ref mut module) => *module.code_dir.entry(key).or_insert_with(|| { CodeIndex::new( IndexPtr::undefined(), - &mut LS::machine_st(&mut self.payload).arena, + &mut LS::machine_st(&mut self.payload).arena.code_index_tbl, ) }), None => { @@ -618,7 +649,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { Some(ref mut module) => *module.code_dir.entry(key).or_insert_with(|| { CodeIndex::new( IndexPtr::undefined(), - &mut LS::machine_st(&mut self.payload).arena, + &mut LS::machine_st(&mut self.payload).arena.code_index_tbl, ) }), None => { @@ -634,7 +665,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { key: PredicateKey, compilation_target: CompilationTarget, ) -> CodeIndex { - let arena = &mut LS::machine_st(&mut self.payload).arena; + let code_index_tbl = &mut LS::machine_st(&mut self.payload).arena.code_index_tbl; match compilation_target { CompilationTarget::User => *self @@ -642,7 +673,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { .indices .code_dir .entry(key) - .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena)), + .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), code_index_tbl)), CompilationTarget::Module(module_name) => { self.get_or_insert_local_code_index(module_name, key) } @@ -654,7 +685,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { module_name: Atom, key: PredicateKey, ) -> CodeIndex { - let arena = &mut LS::machine_st(&mut self.payload).arena; + let code_index_tbl = &mut LS::machine_st(&mut self.payload).arena.code_index_tbl; if module_name == atom!("user") { return *self @@ -662,7 +693,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { .indices .code_dir .entry(key) - .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena)); + .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), code_index_tbl)); } else { self.get_or_insert_local_code_index(module_name, key) } diff --git a/src/machine/loader.rs b/src/machine/loader.rs index c18eceda..cfec0bf6 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -720,7 +720,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { self.wam_prelude.indices.modules.get_mut(&module_name) { if let Some(code_idx) = module.code_dir.get_mut(&key) { - code_idx.set(old_code_idx) + let code_index_tbl = + &mut LS::machine_st(&mut self.payload).arena.code_index_tbl; + code_idx.set(code_index_tbl, old_code_idx); } } } @@ -741,7 +743,9 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { } RetractionRecord::ReplacedUserPredicate(key, old_code_idx) => { if let Some(code_idx) = self.wam_prelude.indices.code_dir.get_mut(&key) { - code_idx.set(old_code_idx) + let code_index_tbl = + &mut LS::machine_st(&mut self.payload).arena.code_index_tbl; + code_idx.set(code_index_tbl, old_code_idx) } } RetractionRecord::AddedIndex(index_key, clause_loc) => { @@ -1217,14 +1221,18 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { * but to multifile and discontiguous predicates as well. */ - let code_index = self.get_or_insert_code_index(key, compilation_target); + let offset = self.get_or_insert_code_index(key, compilation_target); + let code_idx_ptr = LS::machine_st(&mut self.payload) + .arena + .code_index_tbl + .lookup_mut(offset.into()); - if code_index.as_ptr().is_undefined() { - set_code_index( - &mut self.payload.retraction_info, + if code_idx_ptr.is_undefined() { + set_code_index::( + &mut self.payload, &compilation_target, key, - code_index, + offset, IndexPtr::dynamic_undefined(), ); } @@ -1395,7 +1403,7 @@ impl MachineState { Err(cons_term) => term_stack.push(cons_term), } } - (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | HeapCellValueTag::F64) => { + (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | HeapCellValueTag::F64Offset) => { term_stack.push(Term::Literal(Cell::default(), Literal::try_from(addr).unwrap())); } (HeapCellValueTag::StackVar, h) => { @@ -1410,7 +1418,7 @@ impl MachineState { 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))); + term_stack.push(Term::Literal(Cell::default(), Literal::CodeIndexOffset(idx.into()))); arity += 1; } @@ -1588,7 +1596,7 @@ impl Machine { let predicate_name = cell_as_atom!(self.deref_register(2)); let arity = self.deref_register(3); - let arity = match Number::try_from(arity) { + let arity = match Number::try_from((arity, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) if *n >= Integer::ZERO && *n <= Integer::from(MAX_ARITY) => { let value: usize = (&*n).try_into().unwrap(); Ok(value) @@ -1999,7 +2007,15 @@ impl Machine { .wam_prelude .indices .get_predicate_code_index(name, arity, module_name) - .map(|code_idx| code_idx.get_tag()) + .map(|offset| { + loader + .payload + .machine_st + .arena + .code_index_tbl + .lookup(offset.into()) + .tag() + }) .unwrap_or(IndexPtrTag::DynamicUndefined); if idx_tag == IndexPtrTag::Index { @@ -2142,9 +2158,15 @@ impl Machine { .indices .remove_predicate_skeleton(&compilation_target, &key); - let mut code_index = loader.get_or_insert_code_index(key, compilation_target); + let offset = loader.get_or_insert_code_index(key, compilation_target); + let mut code_idx = loader + .payload + .machine_st + .arena + .code_index_tbl + .lookup_mut(offset.into()); - code_index.set(IndexPtr::undefined()); + code_idx.set(IndexPtr::undefined()); loader.payload.compilation_target = clause_clause_compilation_target; @@ -2174,7 +2196,7 @@ impl Machine { .machine_st .store(self.machine_st.deref(self.machine_st[temp_v!(3)])); - let target_pos = match Number::try_from(target_pos) { + let target_pos = match Number::try_from((target_pos, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let value: usize = (&*n).try_into().unwrap(); value diff --git a/src/machine/machine_indices.rs b/src/machine/machine_indices.rs index 8dc5291f..66caba46 100644 --- a/src/machine/machine_indices.rs +++ b/src/machine/machine_indices.rs @@ -2,7 +2,6 @@ use crate::parser::ast::*; -use crate::arena::*; use crate::atom_table::*; use crate::forms::*; use crate::machine::loader::*; @@ -19,7 +18,6 @@ use scryer_modular_bitfield::{bitfield, BitfieldSpecifier}; use std::cmp::Ordering; use std::collections::BTreeSet; -use std::ops::Deref; use crate::types::*; @@ -127,9 +125,18 @@ impl IndexPtr { pub(crate) fn is_dynamic_undefined(&self) -> bool { matches!(self.tag(), IndexPtrTag::DynamicUndefined) } + + #[inline] + pub(crate) fn local(&self) -> Option { + match self.tag() { + IndexPtrTag::Index => Some(self.p() as usize), + IndexPtrTag::DynamicIndex => Some(self.p() as usize), + _ => None, + } + } } -#[derive(Debug, Clone, Copy, Ord, Hash, PartialOrd, Eq, PartialEq)] +#[derive(Debug, Clone, Copy)] // , Ord, Hash, PartialOrd, Eq, PartialEq)] pub struct CodeIndex(CodeIndexOffset); #[cfg(target_pointer_width = "32")] @@ -141,7 +148,7 @@ const_assert!(std::mem::align_of::() == 8); impl From for HeapCellValue { #[inline(always)] fn from(idx: CodeIndex) -> HeapCellValue { - HeapCellValue::from(idx.as_ptr()) + HeapCellValue::from(idx.0) } } @@ -152,48 +159,39 @@ impl From for CodeIndex { } } -impl CodeIndex { - #[inline] - pub(crate) fn new(ptr: IndexPtr, arena: &mut Arena) -> Self { - unsafe { CodeIndex(arena.code_index_tbl.build_with(ptr)) } - } - +impl Into for CodeIndex { #[inline(always)] - pub(crate) fn default(arena: &mut Arena) -> Self { - CodeIndex::new(IndexPtr::undefined(), arena) - } - - pub(crate) fn local(&self) -> Option { - match self.0.as_ptr().tag() { - IndexPtrTag::Index => Some(self.get().p() as usize), - IndexPtrTag::DynamicIndex => Some(self.get().p() as usize), - _ => None, - } + fn into(self) -> CodeIndexOffset { + self.0 } +} +impl Into for &'_ CodeIndex { #[inline(always)] - pub(crate) fn get(&self) -> IndexPtr { - *self.as_ptr().deref() + fn into(self) -> CodeIndexOffset { + self.0 } +} - #[inline(always)] - pub(crate) fn set(&mut self, value: IndexPtr) { - self.as_ptr().set(value); +impl CodeIndex { + #[inline] + pub(crate) fn new(ptr: IndexPtr, code_index_tbl: &mut CodeIndexTable) -> Self { + CodeIndex(code_index_tbl.build_with(ptr)) } #[inline(always)] - pub(crate) fn get_tag(self) -> IndexPtrTag { - self.get().tag() + pub(crate) fn default(code_index_tbl: &mut CodeIndexTable) -> Self { + CodeIndex::new(IndexPtr::undefined(), code_index_tbl) } #[inline(always)] - pub(crate) fn replace(&mut self, value: IndexPtr) -> IndexPtr { - self.as_ptr().replace(value) + pub(crate) fn set(&self, code_index_tbl: &mut CodeIndexTable, value: IndexPtr) { + code_index_tbl.lookup_mut(self.0).set(value); } #[inline(always)] - pub(crate) fn as_ptr(&self) -> CodeIndexPtr { - self.0.as_ptr() + pub(crate) fn replace(&self, code_index_tbl: &mut CodeIndexTable, value: IndexPtr) -> IndexPtr { + code_index_tbl.lookup_mut(self.0).replace(value) } } diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index e3236483..fac5d7b6 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -952,6 +952,7 @@ impl MachineState { let mut printer = HCPrinter::new( &mut self.heap, &mut self.stack, + &self.arena, op_dir, PrinterOutputter::new(), 0, @@ -962,7 +963,7 @@ impl MachineState { printer.quoted = quoted; printer.double_quotes = double_quotes; - match Number::try_from(max_depth) { + match Number::try_from((max_depth, &self.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => { if let Ok(n) = usize::try_from(n.get_num()) { printer.max_depth = n; diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index b72b18d2..385d9a4e 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -288,7 +288,7 @@ impl MachineState { unifier.unify_big_rational(n1, value); } - pub fn unify_f64(&mut self, f1: F64Ptr, value: HeapCellValue) { + pub fn unify_f64(&mut self, f1: F64Offset, value: HeapCellValue) { let mut unifier = DefaultUnifier::from(self); unifier.unify_f64(f1, value); } @@ -409,8 +409,11 @@ impl MachineState { } } Some(TermOrderCategory::FloatingPoint) => { - let v1 = cell_as_f64_ptr!(v1); - let v2 = cell_as_f64_ptr!(v2); + let v1 = cell_as_f64_offset!(v1); + let v2 = cell_as_f64_offset!(v2); + + let v1 = self.arena.f64_tbl.lookup(v1); + let v2 = self.arena.f64_tbl.lookup(v2); if v1 != v2 { self.pdl.clear(); @@ -418,8 +421,8 @@ impl MachineState { } } Some(TermOrderCategory::Integer) => { - let v1 = Number::try_from(v1).unwrap(); - let v2 = Number::try_from(v2).unwrap(); + let v1 = Number::try_from((v1, &self.arena.f64_tbl)).unwrap(); + let v2 = Number::try_from((v2, &self.arena.f64_tbl)).unwrap(); if v1 != v2 { self.pdl.clear(); @@ -436,22 +439,6 @@ impl MachineState { return Some(n1.cmp(&n2)); } } - /* - (HeapCellValueTag::Char, c2) => { - if let Some(c1) = n1.as_char() { - if c1 != c2 { - self.pdl.clear(); - return Some(c1.cmp(&c2)); - } - } else { - self.pdl.clear(); - return Some( - n1.as_str().chars().next().cmp(&Some(c2)) - .then(Ordering::Greater) - ); - } - } - */ (HeapCellValueTag::Str, s) => { let n2 = cell_as_atom_cell!(self.heap[s]) .get_name(); @@ -466,52 +453,6 @@ impl MachineState { } ) } - /* - (HeapCellValueTag::Char, c1) => { - read_heap_cell!(v2, - (HeapCellValueTag::Atom, (n2, _a2)) => { - if let Some(c2) = n2.as_char() { - if c1 != c2 { - self.pdl.clear(); - return Some(c1.cmp(&c2)); - } - } else { - self.pdl.clear(); - return Some( - Some(c1).cmp(&n2.as_str().chars().next()) - .then(Ordering::Less) - ); - } - } - (HeapCellValueTag::Char, c2) => { - if c1 != c2 { - self.pdl.clear(); - return Some(c1.cmp(&c2)); - } - } - (HeapCellValueTag::Str, s) => { - let n2 = cell_as_atom_cell!(self.heap[s]) - .get_name(); - - if let Some(c2) = n2.as_char() { - if c1 != c2 { - self.pdl.clear(); - return Some(c1.cmp(&c2)); - } - } else { - self.pdl.clear(); - return Some( - Some(c1).cmp(&n2.as_str().chars().next()) - .then(Ordering::Less) - ); - } - } - _ => { - unreachable!() - } - ) - } - */ (HeapCellValueTag::Str, s) => { let n1 = cell_as_atom_cell!(self.heap[s]) .get_name(); @@ -523,22 +464,6 @@ impl MachineState { return Some(n1.cmp(&n2)); } } - /* - (HeapCellValueTag::Char, c2) => { - if let Some(c1) = n1.as_char() { - if c1 != c2 { - self.pdl.clear(); - return Some(c1.cmp(&c2)); - } - } else { - self.pdl.clear(); - return Some( - n1.as_str().chars().next().cmp(&Some(c2)) - .then(Ordering::Greater) - ); - } - } - */ (HeapCellValueTag::Str, s) => { let n2 = cell_as_atom_cell!(self.heap[s]) .get_name(); @@ -865,7 +790,7 @@ impl MachineState { return Err(self.error_form(err, stub_gen())); } _ => { - let n = match Number::try_from(n) { + let n = match Number::try_from((n, &self.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => Number::Fixnum(n), Ok(Number::Integer(n)) => Number::Integer(n), _ => { @@ -917,46 +842,18 @@ impl MachineState { (HeapCellValueTag::PStrLoc, pstr_loc) => { if n == 1 || n == 2 { let a3 = self.registers[3]; - // let (h, offset) = pstr_loc_and_offset(&self.heap, pstr_loc); let mut char_iter = self.heap.char_iter(pstr_loc); - // let pstr = cell_as_string!(self.heap[h]); - // let offset = offset.get_num() as usize; - - if let Some(c) = char_iter.next() { // pstr.as_str_from(offset).chars().next() { + if let Some(c) = char_iter.next() { if n == 1 { self.unify_char(c, a3); } else { - // let offset = (offset + c.len_utf8()) as i64; - // let h_len = self.heap.len(); - // let pstr_atom: Atom = pstr.into(); if char_iter.next().is_some() { unify_fn!(*self, pstr_loc_as_cell!(pstr_loc + c.len_utf8()), a3); } else { let tail_idx = Heap::pstr_tail_idx(pstr_loc + c.len_utf8()); unify_fn!(*self, self.heap[tail_idx], a3); } - - /* - if pstr_atom.len() > offset as usize { - self.heap.push(pstr_offset_as_cell!(h)); - self.heap.push(fixnum_as_cell!(Fixnum::build_with_unchecked(offset as i64))); - - unify_fn!(*self, pstr_loc_as_cell!(h_len), a3); - } else { - match self.heap[h].get_tag() { - HeapCellValueTag::CStr => { - self.unify_atom(atom!("[]"), self.store(self.deref(a3))); - } - HeapCellValueTag::PStr => { - unify_fn!(*self, self.heap[h+1], a3); - } - _ => { - unreachable!(); - } - } - } - */ } } else { unreachable!() @@ -965,34 +862,6 @@ impl MachineState { self.fail = true; } } - /* - (HeapCellValueTag::CStr, cstr_atom) => { - let cstr = PartialString::from(cstr_atom); - - if let Some(c) = cstr.as_str_from(0).chars().next() { - if n == 1 { - self.unify_char(c, self.store(self.deref(self.registers[3]))); - } else if n == 2 { - let offset = c.len_utf8(); - let h_len = self.heap.len(); - - if cstr_atom.len() > offset{ - self.heap.push(atom_as_cstr_cell!(cstr_atom)); - self.heap.push(pstr_offset_as_cell!(h_len)); - self.heap.push(fixnum_as_cell!(Fixnum::build_with_unchecked(offset as i64))); - - unify_fn!(*self, pstr_loc_as_cell!(h_len+1), self.registers[3]); - } else { - self.unify_atom(atom!("[]"), self.store(self.deref(self.registers[3]))); - } - } else { - self.fail = true; - } - } else { - unreachable!() - } - } - */ _ => { // 8.5.2.3 d) let err = self.type_error(ValidType::Compound, term); @@ -1077,7 +946,7 @@ impl MachineState { read_heap_cell!(a1, (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // | HeapCellValueTag::Char - HeapCellValueTag::F64) => { + HeapCellValueTag::F64Offset) => { self.try_functor_unify_components(a1, 0); } (HeapCellValueTag::Atom, (_name, arity)) => { @@ -1103,17 +972,17 @@ impl MachineState { return Err(self.error_form(err, stub_gen())); } - let mut type_error = |arity| { - let err = self.type_error(ValidType::Integer, arity); - Err(self.error_form(err, stub_gen())) + let type_error = |machine_st: &mut Self, arity| { + let err = machine_st.type_error(ValidType::Integer, arity); + Err(machine_st.error_form(err, stub_gen())) }; - let arity = match Number::try_from(arity) { + let arity = match Number::try_from((arity, &self.arena.f64_tbl)) { Ok(Number::Float(_)) => { - return type_error(arity); + return type_error(self, arity); } Ok(Number::Rational(n)) if !n.denominator().is_one() => { - return type_error(arity); + return type_error(self, arity); } Ok(n) if n > MAX_ARITY => { // 8.5.1.3 f) @@ -1135,15 +1004,15 @@ impl MachineState { value }, Err(_) => { - return type_error(arity); + return type_error(self, arity); } }; read_heap_cell!(store_name, - (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | // HeapCellValueTag::Char | - HeapCellValueTag::F64) if arity == 0 => { - self.bind(a1.as_var().unwrap(), deref_name); - } + (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | HeapCellValueTag::F64Offset) + if arity == 0 => { + self.bind(a1.as_var().unwrap(), deref_name); + } (HeapCellValueTag::Atom, (name, atom_arity)) => { debug_assert_eq!(atom_arity, 0); resource_error_call_result!( @@ -1173,22 +1042,8 @@ impl MachineState { return Err(self.error_form(err, stub_gen())); } } - /* - (HeapCellValueTag::Char, c) => { - let c = AtomTable::build_with(&self.atom_tbl, &c.to_string()); - - resource_error_call_result!( - self, - self.try_functor_fabricate_struct( - c, - arity as usize, - a1.as_var().unwrap(), - ) - ); - } - */ (HeapCellValueTag::Cons | HeapCellValueTag::Fixnum | - HeapCellValueTag::F64) if arity != 0 => { + HeapCellValueTag::F64Offset) if arity != 0 => { let err = self.type_error(ValidType::Atom, store_name); return Err(self.error_form(err, stub_gen())); // 8.5.1.3 e) } @@ -1243,12 +1098,6 @@ impl MachineState { Err(self.error_form(err, stub_gen())) } } - /* - (HeapCellValueTag::CStr, cstr_atom) => { - let cstr = cstr_atom.as_str(); - Ok(cstr.chars().map(|c| char_as_cell!(c)).collect()) - } - */ _ => { let err = self.type_error(ValidType::List, value); Err(self.error_form(err, stub_gen())) @@ -1372,7 +1221,7 @@ impl MachineState { for addr in addrs { let addr = self.store(self.deref(addr)); - match Number::try_from(addr) { + match Number::try_from((addr, &self.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => { if let Ok(b) = u8::try_from(n.get_num()) { bytes.push(b) diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index a372e0af..b7201b71 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -56,6 +56,7 @@ impl MockWAM { let mut printer = HCPrinter::new( &mut self.machine_st.heap, &mut self.machine_st.stack, + &mut self.machine_st.arena, &self.op_dir, PrinterOutputter::new(), term_write_result.heap_loc, diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 4c987373..fb336248 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -208,8 +208,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::CodeIndex, ip) => { - return Some(ip); + (HeapCellValueTag::CodeIndexOffset, offset) => { + return Some(CodeIndex::from(offset)); } _ => { } @@ -242,7 +242,7 @@ impl Machine { } /// Runs the predicate `key` in `module_name` until completion. - /// Siltently ignores failure, thrown errors and choice points. + /// Silently ignores failure, thrown errors and choice points. /// /// Consider using [`Machine::run_query`] if you wish to handle /// predicates that may fail, leave a choice point or throw. @@ -252,8 +252,10 @@ impl Machine { key: PredicateKey, ) -> std::process::ExitCode { if let Some(module) = self.indices.modules.get(&module_name) { - if let Some(code_index) = module.code_dir.get(&key) { - let p = code_index.local().unwrap(); + if let Some(code_idx) = module.code_dir.get(&key) { + let index_ptr = self.machine_st.arena.code_index_tbl.lookup(code_idx.into()); + let p = index_ptr.local().unwrap(); + // Leave a halting choice point to backtrack to in case the predicate fails or throws. self.allocate_stub_choice_point(); @@ -324,8 +326,9 @@ impl Machine { self.load_file(path_buf.to_str().unwrap(), stream); if let Some(module) = self.indices.modules.get(&atom!("$atts")) { - if let Some(code_index) = module.code_dir.get(&(atom!("driver"), 2)) { - self.machine_st.attr_var_init.verify_attrs_loc = code_index.local().unwrap(); + if let Some(code_idx) = module.code_dir.get(&(atom!("driver"), 2)) { + let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(code_idx.into()); + self.machine_st.attr_var_init.verify_attrs_loc = index_ptr.local().unwrap(); } } } @@ -339,13 +342,16 @@ impl Machine { for arity in 1..66 { let key = (atom!("call"), arity); - match loader.code_dir.get(&key) { + match loader.code_dir.get(&key).cloned() { Some(src_code_index) => { - let target_code_index = target_code_dir - .entry(key) - .or_insert_with(|| CodeIndex::new(IndexPtr::undefined(), arena)); + let code_index_tbl = &mut arena.code_index_tbl; + + let target_code_index = target_code_dir.entry(key).or_insert_with(|| { + CodeIndex::new(IndexPtr::undefined(), code_index_tbl) + }); - target_code_index.set(src_code_index.get()); + let src_code_ptr = *code_index_tbl.lookup(src_code_index.into()); + target_code_index.set(code_index_tbl, src_code_ptr); } None => { unreachable!(); @@ -454,7 +460,7 @@ impl Machine { key, CodeIndex::new( IndexPtr::index(p + impls_offset), - &mut self.machine_st.arena, + &mut self.machine_st.arena.code_index_tbl, ), ); } @@ -535,37 +541,8 @@ impl Machine { if cell.is_var() { offset += 1; - /* - } else if lit.get_tag() == HeapCellValueTag::CStr { - read_heap_cell!(cell, - (HeapCellValueTag::CStr) => { - if cell == lit { - offset += 1; - } else { - return false; - } - } - (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => { - offset += 1; - } - (HeapCellValueTag::Str, s) => { - let (name, arity) = cell_as_atom_cell!(self.machine_st.heap[s]) - .get_name_and_arity(); - - if name == atom!(".") && arity == 2 { - offset += 1; - } else { - return false; - } - } - _ => { - return false; - } - ); - */ } else { unify!(self.machine_st, cell, lit); - // self.machine_st.write_literal_to_var(cell, lit); if self.machine_st.fail { self.machine_st.fail = false; @@ -1068,13 +1045,15 @@ impl Machine { if module_name == atom!("user") { if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() { - self.try_call(name, arity, idx.get()) + let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into()); + self.try_call(name, arity, index_ptr) } else { Err(self.machine_st.throw_undefined_error(name, arity)) } } else if let Some(module) = self.indices.modules.get(&module_name) { if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() { - self.try_call(name, arity, idx.get()) + let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into()); + self.try_call(name, arity, index_ptr) } else { self.undefined_procedure(name, arity) } @@ -1098,13 +1077,15 @@ impl Machine { if module_name == atom!("user") { if let Some(idx) = self.indices.code_dir.get(&(name, arity)).cloned() { - self.try_execute(name, arity, idx.get()) + let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into()); + self.try_execute(name, arity, index_ptr) } else { self.undefined_procedure(name, arity) } } else if let Some(module) = self.indices.modules.get(&module_name) { if let Some(idx) = module.code_dir.get(&(name, arity)).cloned() { - self.try_execute(name, arity, idx.get()) + let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(idx.into()); + self.try_execute(name, arity, index_ptr) } else { self.undefined_procedure(name, arity) } @@ -1146,12 +1127,24 @@ impl Machine { let r_c_w_h = self .indices .get_predicate_code_index(r_c_w_h_atom, 0, iso_ext) - .and_then(|item| item.local()) + .and_then(|code_idx| { + self.machine_st + .arena + .code_index_tbl + .lookup(code_idx.into()) + .local() + }) .unwrap(); let r_c_wo_h = self .indices .get_predicate_code_index(r_c_wo_h_atom, 1, iso_ext) - .and_then(|item| item.local()) + .and_then(|code_idx| { + self.machine_st + .arena + .code_index_tbl + .lookup(code_idx.into()) + .local() + }) .unwrap(); (r_c_w_h, r_c_wo_h) }); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 9ee332ed..3a043402 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -424,7 +424,7 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>( let term = match term { Term::Clause(cell, name, mut terms) => { - if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() { + if let Some(Term::Literal(_, Literal::CodeIndexOffset(_))) = terms.last() { arg_terms .push(process_term(module_name, Term::Clause(cell, name, terms))); @@ -433,7 +433,10 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>( let idx = loader.get_or_insert_qualified_code_index(module_name, key); - terms.push(Term::Literal(Cell::default(), Literal::CodeIndex(idx))); + terms.push(Term::Literal( + Cell::default(), + Literal::CodeIndexOffset(idx.into()), + )); process_term(module_name, Term::Clause(cell, name, terms)) } Term::Literal(cell, Literal::Atom(name)) => { @@ -444,7 +447,10 @@ fn build_meta_predicate_clause<'a, LS: LoadState<'a>>( Term::Clause( cell, name, - vec![Term::Literal(Cell::default(), Literal::CodeIndex(idx))], + vec![Term::Literal( + Cell::default(), + Literal::CodeIndexOffset(idx.into()), + )], ), ) } @@ -469,7 +475,7 @@ pub(super) fn clause_to_query_term<'a, LS: LoadState<'a>>( mut terms: Vec, call_policy: CallPolicy, ) -> QueryTerm { - if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() { + if let Some(Term::Literal(_, Literal::CodeIndexOffset(_))) = terms.last() { // supplementary code vector indices are unnecessary for // root-level clauses. terms.pop(); @@ -504,7 +510,7 @@ pub(super) fn qualified_clause_to_query_term<'a, LS: LoadState<'a>>( mut terms: Vec, call_policy: CallPolicy, ) -> QueryTerm { - if let Some(Term::Literal(_, Literal::CodeIndex(_))) = terms.last() { + if let Some(Term::Literal(_, Literal::CodeIndexOffset(_))) = terms.last() { // supplementary code vector indices are unnecessary for // root-level clauses. terms.pop(); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index dc07cb78..94728dce 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -25,6 +25,7 @@ use crate::machine::partial_string::*; use crate::machine::stack::*; use crate::machine::streams::*; use crate::machine::{get_structure_index, Machine, VERIFY_ATTR_INTERRUPT_LOC}; +use crate::offset_table::*; use crate::parser::ast::*; use crate::parser::char_reader::*; use crate::parser::dashu::Integer; @@ -821,7 +822,7 @@ impl MachineState { let mut max_old = -1i64; if !max_steps.is_var() { - let max_steps = Number::try_from(max_steps); + let max_steps = Number::try_from((max_steps, &self.arena.f64_tbl)); let max_steps_n = match max_steps { Ok(Number::Fixnum(n)) => Some(n.get_num()), @@ -1132,7 +1133,7 @@ impl MachineState { for addr in addrs { let addr = self.store(self.deref(addr)); - match Number::try_from(addr) { + match Number::try_from((addr, &self.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => { if let Ok(n) = u32::try_from(n.get_num()) { if let Some(c) = std::char::from_u32(n) { @@ -1241,7 +1242,13 @@ impl Machine { let mut bp = self .indices .get_predicate_code_index(atom!("$clause"), 2, module_name) - .and_then(|idx| idx.local()) + .and_then(|idx| { + self.machine_st + .arena + .code_index_tbl + .lookup(idx.into()) + .local() + }) .unwrap(); macro_rules! extract_ptr { @@ -1431,7 +1438,7 @@ impl Machine { self.machine_st.error_form(err, stub) })?; - let index_cell = if index_cell_opt.is_some() { + let index_cell_opt = if index_cell_opt.is_some() { index_cell_opt } else { let is_internal_call = name == atom!("$call") && goal_arity > 0; @@ -1469,11 +1476,13 @@ impl Machine { } }; - if let Some(code_index) = index_cell { - if !code_index.as_ptr().is_undefined() { + if let Some(code_idx) = index_cell_opt { + let index_ptr = *self.machine_st.arena.code_index_tbl.lookup(code_idx.into()); + + if !index_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()); + return call_at_index(self, name, arity, index_ptr); } } @@ -1653,7 +1662,7 @@ impl Machine { let idx = CodeIndex::new( IndexPtr::index(helper_clause_loc), - &mut self.machine_st.arena, + &mut self.machine_st.arena.code_index_tbl, ); writer.write_with(|section| { @@ -1694,7 +1703,7 @@ impl Machine { let idx_cell = self.machine_st.heap[s.saturating_sub(1)]; - if HeapCellValueTag::CodeIndex == idx_cell.get_tag() { + if HeapCellValueTag::CodeIndexOffset == idx_cell.get_tag() { return true; } } @@ -1846,7 +1855,7 @@ impl Machine { #[inline(always)] pub(crate) fn bind_from_register(&mut self) { let reg = self.deref_register(2); - let n = match Number::try_from(reg) { + let n = match Number::try_from((reg, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).ok(), Ok(Number::Integer(n)) => { let value: usize = (&*n).try_into().unwrap(); @@ -2608,7 +2617,7 @@ impl Machine { let addr = match addr { addr if addr.is_var() => addr, - addr => match Number::try_from(addr) { + addr => match Number::try_from((addr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let result: Result = (&*n).try_into(); if let Ok(value) = result { @@ -2797,7 +2806,7 @@ impl Machine { a2 } _ => { - match Number::try_from(a2) { + match Number::try_from((a2, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let n: u32 = (&*n).try_into().unwrap(); @@ -2864,7 +2873,7 @@ impl Machine { let n = self.deref_register(1); let chs = self.deref_register(2); - let string = match Number::try_from(n) { + let string = match Number::try_from((n, &self.machine_st.arena.f64_tbl)) { Ok(Number::Float(OrderedFloat(n))) => fmt_float(n), Ok(Number::Fixnum(n)) => n.get_num().to_string(), Ok(Number::Integer(n)) => n.to_string(), @@ -2892,7 +2901,7 @@ impl Machine { let n = self.deref_register(1); let chs = self.machine_st.registers[2]; - let string = match Number::try_from(n) { + let string = match Number::try_from((n, &self.machine_st.arena.f64_tbl)) { Ok(Number::Float(OrderedFloat(n))) => { format!("{0:<20?}", n) } @@ -2979,13 +2988,8 @@ impl Machine { debug_assert_eq!(arity, 0); name.as_char().unwrap() } - /* - (HeapCellValueTag::Char, c) => { - c - } - */ _ => { - match Number::try_from(a2) { + match Number::try_from((a2, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let n: u32 = (&*n).try_into().unwrap(); let n = std::char::from_u32(n); @@ -3223,7 +3227,7 @@ impl Machine { let err = self.machine_st.instantiation_error(); Err(self.machine_st.error_form(err, stub_gen())) } else { - match Number::try_from(addr) { + match Number::try_from((addr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let n: u32 = (&*n).try_into().unwrap(); let n = char::try_from(n); @@ -3370,7 +3374,7 @@ impl Machine { let err = self.machine_st.instantiation_error(); return Err(self.machine_st.error_form(err, stub_gen())); } else { - match Number::try_from(addr) { + match Number::try_from((addr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let n: u8 = (&*n).try_into().unwrap(); @@ -3449,7 +3453,7 @@ impl Machine { let addr = if addr.is_var() { addr } else { - match Number::try_from(addr) { + match Number::try_from((addr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(ref n)) if (**n).num_eq(&1_i64) => { fixnum_as_cell!(Fixnum::build_with(-1)) } @@ -3603,7 +3607,7 @@ impl Machine { 3, )?; - let num = match Number::try_from(self.deref_register(2)) { + let num = match Number::try_from((self.deref_register(2), &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(), Ok(Number::Integer(n)) => match (&*n).try_into() as Result { Ok(u) => u, @@ -3704,7 +3708,7 @@ impl Machine { let addr = if addr.is_var() { addr } else { - match Number::try_from(addr) { + match Number::try_from((addr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let n: u32 = (&*n).try_into().unwrap(); let n = std::char::from_u32(n); @@ -4040,7 +4044,7 @@ impl Machine { } else { arity_match = |arity_1, arity_2| arity_1 == arity_2; - let arity = match Number::try_from(arity) { + let arity = match Number::try_from((arity, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => Some(n.get_num() as usize), Ok(Number::Integer(n)) => { let value: usize = (&*n).try_into().unwrap(); @@ -4299,7 +4303,10 @@ impl Machine { pub(crate) fn random_integer(&mut self) { let a1 = self.deref_register(1); let a2 = self.deref_register(2); - let value = match (Number::try_from(a1), Number::try_from(a2)) { + let value = match ( + Number::try_from((a1, &self.machine_st.arena.f64_tbl)), + Number::try_from((a2, &self.machine_st.arena.f64_tbl)), + ) { (Ok(Number::Fixnum(lower)), Ok(Number::Fixnum(upper))) => { let (lower, upper) = (lower.get_num(), upper.get_num()); if lower >= upper { @@ -4390,7 +4397,7 @@ impl Machine { let stub_gen = || functor_stub(atom!("length"), 2); let len = self.deref_register(2); - let n = match Number::try_from(len) { + let n = match Number::try_from((len, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num() as usize, Ok(Number::Integer(n)) => match (&*n).try_into() as Result { Ok(n) => n, @@ -4581,23 +4588,24 @@ impl Machine { let tls_cert = self.deref_register(4); let content_length_limit = self.deref_register(5); const CONTENT_LENGTH_LIMIT_DEFAULT: u64 = 32768; - let content_length_limit = match Number::try_from(content_length_limit) { - Ok(Number::Fixnum(n)) => { - if n.get_num() >= 0 { - n.get_num() as u64 - } else { - CONTENT_LENGTH_LIMIT_DEFAULT + let content_length_limit = + match Number::try_from((content_length_limit, &self.machine_st.arena.f64_tbl)) { + Ok(Number::Fixnum(n)) => { + if n.get_num() >= 0 { + n.get_num() as u64 + } else { + CONTENT_LENGTH_LIMIT_DEFAULT + } } - } - Ok(Number::Integer(n)) => { - let n: Result = (&*n).try_into(); - match n { - Ok(u) => u, - Err(_) => CONTENT_LENGTH_LIMIT_DEFAULT, + Ok(Number::Integer(n)) => { + let n: Result = (&*n).try_into(); + match n { + Ok(u) => u, + Err(_) => CONTENT_LENGTH_LIMIT_DEFAULT, + } } - } - _ => CONTENT_LENGTH_LIMIT_DEFAULT, - }; + _ => CONTENT_LENGTH_LIMIT_DEFAULT, + }; let ssl_server: Option<(String, String)> = { match self.machine_st.value_to_str_like(tls_key) { @@ -4864,7 +4872,8 @@ impl Machine { pub(crate) fn http_answer(&mut self) -> CallResult { let culprit = self.deref_register(1); let status_code = self.deref_register(2); - let status_code: u16 = match Number::try_from(status_code) { + let status_code: u16 = match Number::try_from((status_code, &self.machine_st.arena.f64_tbl)) + { Ok(Number::Fixnum(n)) => n.get_num() as u16, Ok(Number::Integer(n)) => { let n: Result = (&*n).try_into(); @@ -4994,7 +5003,7 @@ impl Machine { if let Some(function_name) = self.machine_st.value_to_str_like(function_name) { let stub_gen = || functor_stub(atom!("foreign_call"), 3); fn map_arg(machine_st: &mut MachineState, source: HeapCellValue) -> crate::ffi::Value { - match Number::try_from(source) { + match Number::try_from((source, &machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => Value::Int(n.get_num()), Ok(Number::Float(n)) => Value::Float(n.into_inner()), _ => { @@ -5297,7 +5306,7 @@ impl Machine { let priority = self.deref_register(1); let specifier = cell_as_atom_cell!(self.deref_register(2)).get_name(); - let priority = match Number::try_from(priority) { + let priority = match Number::try_from((priority, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let n: u16 = (&*n).try_into().unwrap(); n @@ -5465,7 +5474,7 @@ impl Machine { pub(crate) fn get_attr_var_queue_beyond(&mut self) { let addr = self.deref_register(1); - let b = match Number::try_from(addr) { + let b = match Number::try_from((addr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Integer(n)) => { let value: usize = (&*n).try_into().unwrap(); Some(value) @@ -5892,7 +5901,7 @@ impl Machine { pub(crate) fn halt(&mut self) -> std::process::ExitCode { let code = self.deref_register(1); - let code = match Number::try_from(code) { + let code = match Number::try_from((code, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => u8::try_from(n.get_num()).unwrap(), Ok(Number::Integer(n)) => { let n: u8 = (&*n).try_into().unwrap(); @@ -5929,7 +5938,7 @@ impl Machine { let a1 = self.deref_register(1); let a2 = self.deref_register(2); - let n = match Number::try_from(a2) { + let n = match Number::try_from((a2, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(bp)) => Integer::from(bp.get_num() as usize), Ok(Number::Integer(n)) => (*n).clone(), _ => { @@ -5974,7 +5983,7 @@ impl Machine { let name = cell_as_atom!(self.deref_register(2)); let a3 = self.deref_register(3); - let arity = match Number::try_from(a3) { + let arity = match Number::try_from((a3, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num() as usize, Ok(Number::Integer(n)) => { let result = (&*n).try_into(); @@ -5992,7 +6001,14 @@ impl Machine { self.indices .get_predicate_code_index(name, arity, module_name) - .map(|index| index.local().is_some()) + .map(|idx| { + self.machine_st + .arena + .code_index_tbl + .lookup(idx.into()) + .local() + .is_some() + }) .unwrap_or(false) } @@ -6014,7 +6030,10 @@ impl Machine { arity, module_name, ) - .map(|index| index.get()) + .map(|idx| *self.machine_st + .arena + .code_index_tbl + .lookup(idx.into())) .unwrap_or(IndexPtr::dynamic_undefined()); !matches!(index.tag(), IndexPtrTag::DynamicUndefined | IndexPtrTag::Undefined) @@ -6031,7 +6050,10 @@ impl Machine { 0, module_name, ) - .map(|index| index.get()) + .map(|idx| *self.machine_st + .arena + .code_index_tbl + .lookup(idx.into())) .unwrap_or(IndexPtr::dynamic_undefined()); !matches!(index.tag(), IndexPtrTag::DynamicUndefined) @@ -6667,7 +6689,7 @@ impl Machine { pub(crate) fn set_seed(&mut self) { let seed = self.deref_register(1); - match Number::try_from(seed) { + match Number::try_from((seed, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => { let n: u64 = Integer::from(n).try_into().unwrap(); let rng: StdRng = SeedableRng::seed_from_u64(n); @@ -6695,7 +6717,7 @@ impl Machine { pub(crate) fn sleep(&mut self) { let time = self.deref_register(1); - let time = match Number::try_from(time) { + let time = match Number::try_from((time, &self.machine_st.arena.f64_tbl)) { Ok(Number::Float(n)) => n.into_inner(), Ok(Number::Fixnum(n)) => n.get_num() as f64, Ok(Number::Integer(n)) => n.to_f64().value(), @@ -6730,7 +6752,7 @@ impl Machine { name } _ => { - AtomTable::build_with(&self.machine_st.atom_tbl, &match Number::try_from(port) { + AtomTable::build_with(&self.machine_st.atom_tbl, &match Number::try_from((port, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num().to_string(), Ok(Number::Integer(n)) => n.to_string(), _ => { @@ -6829,7 +6851,7 @@ impl Machine { let port = if port.is_var() { String::from("0") } else { - match Number::try_from(port) { + match Number::try_from((port, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num().to_string(), Ok(Number::Integer(n)) => n.to_string(), _ => { @@ -7107,7 +7129,7 @@ impl Machine { let position = self.deref_register(2); - let position = match Number::try_from(position) { + let position = match Number::try_from((position, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num() as u64, Ok(Number::Integer(n)) => { let n: Result = (&*n).try_into(); @@ -7426,7 +7448,7 @@ impl Machine { let name = cell_as_atom!(self.deref_register(2)); let arity = self.deref_register(3); - let arity = match Number::try_from(arity) { + let arity = match Number::try_from((arity, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num() as usize, Ok(Number::Integer(n)) => { let value: usize = (&*n).try_into().unwrap(); @@ -7454,22 +7476,23 @@ impl Machine { }, }; - let first_idx = match first_idx { - Some(idx) if idx.local().is_some() => { - if let Some(idx) = idx.local() { - idx - } else { - unreachable!() - } - } - _ => { - let stub = functor_stub(name, arity); - let err = self - .machine_st - .existence_error(ExistenceError::Procedure(name, arity)); + let first_idx = first_idx.and_then(|first_idx| { + self.machine_st + .arena + .code_index_tbl + .lookup(first_idx.into()) + .local() + }); - return Err(self.machine_st.error_form(err, stub)); - } + let first_idx = if let Some(idx) = first_idx { + idx + } else { + let stub = functor_stub(name, arity); + let err = self + .machine_st + .existence_error(ExistenceError::Procedure(name, arity)); + + return Err(self.machine_st.error_form(err, stub)); }; let listing = @@ -7484,7 +7507,7 @@ impl Machine { #[inline(always)] pub(crate) fn inlined_instructions(&mut self) { let index_ptr = self.deref_register(1); - let index_ptr = match Number::try_from(index_ptr) { + let index_ptr = match Number::try_from((index_ptr, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => n.get_num() as usize, Ok(Number::Integer(n)) => { let value: usize = (&*n).try_into().unwrap(); @@ -7843,7 +7866,7 @@ impl Machine { let length = self.deref_register(6); - let length = match Number::try_from(length) { + let length = match Number::try_from((length, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => usize::try_from(n.get_num()).unwrap(), Ok(Number::Integer(n)) => match (&*n).try_into() as Result { Ok(u) => u, @@ -7909,7 +7932,7 @@ impl Machine { let iterations = self.deref_register(3); - let iterations = match Number::try_from(iterations) { + let iterations = match Number::try_from((iterations, &self.machine_st.arena.f64_tbl)) { Ok(Number::Fixnum(n)) => u64::try_from(n.get_num()).unwrap(), Ok(Number::Integer(n)) => { let n: Result = (&*n).try_into(); @@ -8555,7 +8578,10 @@ impl Machine { #[inline(always)] pub(crate) fn pop_count(&mut self) { let number = self.deref_register(1); - let pop_count = integer_as_cell!(match Number::try_from(number) { + let pop_count = integer_as_cell!(match Number::try_from(( + number, + &self.machine_st.arena.f64_tbl + )) { Ok(Number::Fixnum(n)) => { Number::Fixnum(Fixnum::build_with(n.get_num().count_ones())) } diff --git a/src/machine/unify.rs b/src/machine/unify.rs index fdc996a0..6d3bc3ad 100644 --- a/src/machine/unify.rs +++ b/src/machine/unify.rs @@ -216,7 +216,9 @@ pub(crate) trait Unifier: DerefMut { return; } - match Number::try_from(value) { + let machine_st = self.deref(); + + match Number::try_from((value, &machine_st.arena.f64_tbl)) { Ok(n2) => match n2 { Number::Fixnum(n2) if n1.get_num() == n2.get_num() => {} Number::Integer(n2) if (*n2).num_eq(&n1.get_num()) => {} @@ -237,7 +239,9 @@ pub(crate) trait Unifier: DerefMut { return; } - match Number::try_from(value) { + let machine_st = self.deref(); + + match Number::try_from((value, &machine_st.arena.f64_tbl)) { Ok(n2) => match n2 { Number::Fixnum(n2) if (*n1).num_eq(&n2.get_num()) => {} Number::Integer(n2) if (*n1).num_eq(&*n2) => {} @@ -258,7 +262,9 @@ pub(crate) trait Unifier: DerefMut { return; } - match Number::try_from(value) { + let machine_st = self.deref_mut(); + + match Number::try_from((value, &machine_st.arena.f64_tbl)) { Ok(n2) => match n2 { Number::Fixnum(n2) if (*n1).num_eq(&Integer::from(n2.get_num())) => {} Number::Integer(n2) if (*n1).num_eq(&*n2) => {} @@ -273,14 +279,19 @@ pub(crate) trait Unifier: DerefMut { } } - fn unify_f64(&mut self, f1: F64Ptr, value: HeapCellValue) { + fn unify_f64(&mut self, f1: F64Offset, value: HeapCellValue) { if let Some(r) = value.as_var() { Self::bind(self, r, HeapCellValue::from(f1)); return; } read_heap_cell!(value, - (HeapCellValueTag::F64, f2) => { + (HeapCellValueTag::F64Offset, f2) => { + let machine_st = self.deref_mut(); + + let f1 = machine_st.arena.f64_tbl.lookup(f1); + let f2 = machine_st.arena.f64_tbl.lookup(f2.into()); + self.fail = **f1 != **f2; } _ => { @@ -414,17 +425,12 @@ pub(crate) trait Unifier: DerefMut { tabu_list.insert((d1, d2)); } } - (HeapCellValueTag::F64, f1) => { + (HeapCellValueTag::F64Offset, f1) => { Self::unify_f64(self, f1, d2); } (HeapCellValueTag::Fixnum, n1) => { Self::unify_fixnum(self, n1, d2); } - /* - (HeapCellValueTag::Char, c1) => { - Self::unify_char(self, c1, d2); - } - */ (HeapCellValueTag::Cons, ptr_1) => { Self::unify_constant(self, ptr_1, d2); } diff --git a/src/macros.rs b/src/macros.rs index 29e3369f..e301832b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -53,17 +53,17 @@ macro_rules! cell_as_atom_cell { }; } -macro_rules! cell_as_f64_ptr { +macro_rules! cell_as_f64_offset { ($cell:expr) => {{ let offset = $cell.get_value() as usize; - F64Ptr::from_offset(F64Offset::from(offset)) + F64Offset::from(offset) }}; } -macro_rules! cell_as_code_index { +macro_rules! cell_as_code_index_offset { ($cell:expr) => {{ let offset = $cell.get_value() as usize; - CodeIndex::from(CodeIndexOffset::from(offset)) + CodeIndexOffset::from(offset) }}; } @@ -266,13 +266,13 @@ macro_rules! read_heap_cell_pat_body { #[allow(unused_braces)] $code }}; - ($cell:ident, F64, $n:ident, $code:expr) => {{ - let $n = cell_as_f64_ptr!($cell); + ($cell:ident, F64Offset, $n:ident, $code:expr) => {{ + let $n = cell_as_f64_offset!($cell); #[allow(unused_braces)] $code }}; - ($cell:ident, CodeIndex, $n:ident, $code:expr) => {{ - let $n = cell_as_code_index!($cell); + ($cell:ident, CodeIndexOffset, $n:ident, $code:expr) => {{ + let $n = cell_as_code_index_offset!($cell); #[allow(unused_braces)] $code }}; @@ -281,26 +281,6 @@ macro_rules! read_heap_cell_pat_body { #[allow(unused_braces)] $code }}; - ($cell:ident, PStr, $atom:ident, $code:expr) => {{ - let $atom = cell_as_atom!($cell); - #[allow(unused_braces)] - $code - }}; - ($cell:ident, CStr, $atom:ident, $code:expr) => {{ - let $atom = cell_as_atom!($cell); - #[allow(unused_braces)] - $code - }}; - ($cell:ident, CStr | PStr, $atom:ident, $code:expr) => {{ - let $atom = cell_as_atom!($cell); - #[allow(unused_braces)] - $code - }}; - ($cell:ident, PStr | CStr, $atom:ident, $code:expr) => {{ - let $atom = cell_as_atom!($cell); - #[allow(unused_braces)] - $code - }}; ($cell:ident, Fixnum, $value:ident, $code:expr) => {{ let $value = Fixnum::from_bytes($cell.into_bytes()); #[allow(unused_braces)] @@ -321,11 +301,6 @@ macro_rules! read_heap_cell_pat_body { #[allow(unused_braces)] $code }}; - ($cell:ident, Char, $value:ident, $code:expr) => {{ - let $value = unsafe { char::from_u32_unchecked($cell.get_value() as u32) }; - #[allow(unused_braces)] - $code - }}; ($cell:ident, $($tags:tt)|+, $value:ident, $code:expr) => {{ let $value = $cell.get_value() as usize; #[allow(unused_braces)] diff --git a/src/offset_table.rs b/src/offset_table.rs index 7b47b96f..a384cb84 100644 --- a/src/offset_table.rs +++ b/src/offset_table.rs @@ -1,8 +1,6 @@ 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}; @@ -23,19 +21,7 @@ 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 { +impl RawBlockTraits for OrderedFloat { #[inline] fn init_size() -> usize { F64_TABLE_INIT_SIZE @@ -47,7 +33,7 @@ impl RawBlockTraits for F64Table { } } -impl RawBlockTraits for CodeIndexTable { +impl RawBlockTraits for IndexPtr { #[inline] fn init_size() -> usize { CODE_INDEX_TABLE_INIT_SIZE @@ -59,72 +45,159 @@ impl RawBlockTraits for CodeIndexTable { } } -pub trait OffsetTable: RawBlockTraits { - type Offset: Copy + From + Into; - type Stored; +#[derive(Debug)] +pub struct OffsetTableImpl(InnerOffsetTableImpl); - fn global_table() -> &'static RwLock>; +impl OffsetTableImpl { + #[inline(always)] + pub fn new() -> Self { + Self(InnerOffsetTableImpl::Serial(SerialOffsetTable::new())) + } } -impl OffsetTable for F64Table { - type Offset = F64Offset; - type Stored = OrderedFloat; +impl Default for OffsetTableImpl { + fn default() -> Self { + Self::new() + } +} + +#[derive(Debug)] +enum InnerOffsetTableImpl { + Serial(SerialOffsetTable), + #[allow(dead_code)] + Concurrent(Arc>), +} + +impl InnerOffsetTableImpl { + #[inline(always)] + fn build_with(&mut self, value: T) -> usize { + match self { + Self::Concurrent(concurrent_tbl) => unsafe { concurrent_tbl.build_with(value) }, + Self::Serial(serial_tbl) => unsafe { serial_tbl.build_with(value) }, + } + } #[inline(always)] - fn global_table() -> &'static RwLock> { - static GLOBAL_ATOM_TABLE: RwLock> = RwLock::new(Weak::new()); - &GLOBAL_ATOM_TABLE + fn lookup<'a>(&'a self, offset: usize) -> TablePtr<'a, T> { + match self { + Self::Concurrent(concurrent_tbl) => { + TablePtr(InnerTablePtr::Concurrent(concurrent_tbl.lookup(offset))) + } + Self::Serial(serial_tbl) => unsafe { + TablePtr(InnerTablePtr::Serial(serial_tbl.lookup(offset))) + }, + } + } + + #[inline(always)] + fn lookup_mut<'a>(&'a mut self, offset: usize) -> TablePtrMut<'a, T> { + match self { + Self::Concurrent(concurrent_tbl) => TablePtrMut(InnerTablePtrMut::Concurrent( + concurrent_tbl.lookup_mut(offset), + )), + Self::Serial(serial_tbl) => unsafe { + TablePtrMut(InnerTablePtrMut::Serial(serial_tbl.lookup_mut(offset))) + }, + } } } -impl OffsetTable for CodeIndexTable { +pub trait OffsetTable { + type Offset: Copy + Into; + + fn build_with(&mut self, value: T) -> Self::Offset; + fn lookup<'a>(&'a self, offset: Self::Offset) -> TablePtr<'a, T>; + fn lookup_mut<'a>(&'a mut self, offset: Self::Offset) -> TablePtrMut<'a, T>; +} + +impl OffsetTable> for OffsetTableImpl> { + type Offset = F64Offset; + + fn build_with(&mut self, value: OrderedFloat) -> F64Offset { + F64Offset(self.0.build_with(value)) + } + + fn lookup<'a>(&'a self, offset: F64Offset) -> TablePtr<'a, OrderedFloat> { + self.0.lookup(offset.into()) + } + + fn lookup_mut<'a>(&'a mut self, offset: F64Offset) -> TablePtrMut<'a, OrderedFloat> { + self.0.lookup_mut(offset.into()) + } +} + +impl OffsetTable for OffsetTableImpl { 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 + fn build_with(&mut self, value: IndexPtr) -> CodeIndexOffset { + CodeIndexOffset(self.0.build_with(value)) } + + fn lookup<'a>(&'a self, offset: CodeIndexOffset) -> TablePtr<'a, IndexPtr> { + self.0.lookup(offset.into()) + } + + fn lookup_mut<'a>(&'a mut self, offset: CodeIndexOffset) -> TablePtrMut<'a, IndexPtr> { + self.0.lookup_mut(offset.into()) + } +} + +#[derive(Debug)] +struct SerialOffsetTable { + block: RawBlock, } -impl OffsetTableImpl -where - OffsetTableImpl: OffsetTable, -{ +impl SerialOffsetTable { #[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 + fn new() -> Self { + Self { + block: RawBlock::new(), + } + } + + unsafe fn build_with(&mut self, value: T) -> usize { + let mut ptr; + + loop { + ptr = self.block.alloc(size_of::()); + + if ptr.is_null() { + let new_block = self.block.grow_new().unwrap(); + self.block = new_block; } else { - let table = Arc::new(Self { - block: Arcu::new(RawBlock::new(), GlobalEpochCounterPool), - update: Mutex::new(()), - }); - *guard = Arc::downgrade(&table); - table + break; } } + + ptr::write(ptr as *mut T, value); + ptr.addr() - self.block.base.addr() } + #[inline] + unsafe fn lookup(&self, offset: usize) -> &T { + &*self.block.base.add(offset).cast::() + } + + #[inline] + unsafe fn lookup_mut(&mut self, offset: usize) -> &mut T { + &mut *self.block.base.add(offset).cast::().cast_mut() + } +} + +#[derive(Debug)] +pub struct ConcurrentOffsetTable { + block: Arcu, GlobalEpochCounterPool>, + update: Mutex<()>, +} + +impl ConcurrentOffsetTable { #[allow(clippy::missing_safety_doc)] - pub unsafe fn build_with( - &self, - value: as OffsetTable>::Stored, - ) -> as OffsetTable>::Offset { + unsafe fn build_with(&self, value: T) -> usize { 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 { @@ -141,8 +214,7 @@ where ptr::write(ptr as *mut T, value); - let value = - as OffsetTable>::Offset::from(ptr.addr() - block_epoch.base.addr()); + let value = ptr.addr() - block_epoch.base.addr(); // AtomTable would have to update the index table at this point // explicit drop to ensure we don't accidentally drop it early @@ -151,17 +223,20 @@ where 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"); + #[inline] + fn lookup(&self, offset: usize) -> RcuRef, T> { + RcuRef::try_map(self.block.read(), |raw_block| unsafe { + raw_block.base.add(offset).cast::().as_ref() + }) + .expect("The offset should result in a non-null pointer") + } - RcuRef::try_map(table.block.read(), |raw_block| unsafe { + #[inline] + fn lookup_mut(&self, offset: usize) -> RcuRef, UnsafeCell> { + RcuRef::try_map(self.block.read(), |raw_block| unsafe { raw_block .base - .add(offset.into()) + .add(offset) .cast_mut() .cast::>() .as_ref() @@ -170,109 +245,8 @@ where } } -#[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().addr() - RcuRef::get_root(&self.0).base.addr(), - ) - } -} +pub type F64Table = OffsetTableImpl>; +pub type CodeIndexTable = OffsetTableImpl; #[derive(Clone, Copy, Debug)] pub struct F64Offset(usize); @@ -284,10 +258,9 @@ impl From for F64Offset { } } -impl Into for F64Offset { - #[inline(always)] - fn into(self: Self) -> usize { - self.0 +impl From for usize { + fn from(val: F64Offset) -> Self { + val.0 } } @@ -301,127 +274,177 @@ impl From for CodeIndexOffset { } } -impl Into for CodeIndexOffset { +impl From for usize { #[inline(always)] - fn into(self: Self) -> usize { - self.0 + fn from(val: CodeIndexOffset) -> Self { + val.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() +#[derive(Debug)] +pub struct TablePtr<'a, T: RawBlockTraits>(InnerTablePtr<'a, T>); + +#[derive(Debug)] +enum InnerTablePtr<'a, T: RawBlockTraits> { + Concurrent(RcuRef, T>), + Serial(&'a T), +} + +impl PartialEq for TablePtr<'_, T> { + fn eq(&self, other: &TablePtr<'_, T>) -> bool { + self.deref() == other.deref() } } -impl Eq for CodeIndexOffset {} +impl Eq for TablePtr<'_, T> {} -impl PartialOrd for CodeIndexOffset { - #[inline(always)] +impl PartialOrd for TablePtr<'_, T> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for CodeIndexOffset { - #[inline(always)] +impl Ord for TablePtr<'_, T> { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ptr().cmp(&other.as_ptr()) + (**self).cmp(&**other) } } -impl Hash for CodeIndexOffset { +impl Hash for TablePtr<'_, T> { #[inline(always)] fn hash(&self, hasher: &mut H) { - self.as_ptr().hash(hasher) + (self as &T).hash(hasher) } } -impl fmt::Display for CodeIndexOffset { +impl fmt::Display for TablePtr<'_, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "CodeIndexOffset({})", self.0) + write!(f, "{}", self as &T) } } -impl CodeIndexPtr { +impl Deref for TablePtr<'_, T> { + type Target = T; + #[inline] - pub fn set(&self, val: IndexPtr) { - unsafe { *self.0.get() = val }; + fn deref(&self) -> &Self::Target { + match &self.0 { + InnerTablePtr::Concurrent(rcu_ref) => rcu_ref, + InnerTablePtr::Serial(ref_mut) => ref_mut, + } } +} - #[inline] - pub fn replace(&self, val: IndexPtr) -> IndexPtr { - unsafe { self.0.get().replace(val) } +impl fmt::Display for CodeIndexOffset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "CodeIndexOffset({})", self.0) } } impl F64Offset { #[inline(always)] - pub fn from_ptr(ptr: F64Ptr) -> Self { - ptr.as_offset() + pub fn to_u64(self) -> u64 { + self.0 as u64 } +} - #[inline(always)] - pub fn as_ptr(self) -> F64Ptr { - F64Ptr::from_offset(self) +impl fmt::Display for F64Offset { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "F64Offset({})", self.0) } +} - #[inline(always)] - pub fn to_u64(self) -> u64 { - self.0 as u64 - } +#[derive(Debug)] +pub struct TablePtrMut<'a, T: RawBlockTraits>(InnerTablePtrMut<'a, T>); + +#[derive(Debug)] +enum InnerTablePtrMut<'a, T: RawBlockTraits> { + Concurrent(RcuRef, UnsafeCell>), + Serial(&'a mut T), } -impl PartialEq for F64Offset { - #[inline(always)] - fn eq(&self, other: &F64Offset) -> bool { - self.as_ptr() == other.as_ptr() +impl PartialEq for TablePtrMut<'_, T> { + fn eq(&self, other: &TablePtrMut<'_, T>) -> bool { + self.deref() == other.deref() } } -impl Eq for F64Offset {} +impl Eq for TablePtrMut<'_, T> {} -impl PartialOrd for F64Offset { - #[inline(always)] +impl PartialOrd for TablePtrMut<'_, T> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl Ord for F64Offset { - #[inline(always)] +impl Ord for TablePtrMut<'_, T> { fn cmp(&self, other: &Self) -> std::cmp::Ordering { - self.as_ptr().cmp(&other.as_ptr()) + (**self).cmp(&**other) } } -impl Hash for F64Offset { +impl Hash for TablePtrMut<'_, T> { #[inline(always)] fn hash(&self, hasher: &mut H) { - self.as_ptr().hash(hasher) + (self as &T).hash(hasher) } } -impl fmt::Display for F64Offset { +impl fmt::Display for TablePtrMut<'_, T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "F64Offset({})", self.0) + write!(f, "{}", self as &T) + } +} + +impl Deref for TablePtrMut<'_, T> { + type Target = T; + + #[inline] + fn deref(&self) -> &Self::Target { + match &self.0 { + InnerTablePtrMut::Concurrent(rcu_ref) => unsafe { rcu_ref.get().as_ref().unwrap() }, + InnerTablePtrMut::Serial(ref_mut) => ref_mut, + } + } +} + +impl DerefMut for TablePtrMut<'_, T> { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + match &mut self.0 { + InnerTablePtrMut::Concurrent(rcu_ref) => unsafe { + &mut *rcu_ref.get().as_mut().unwrap() + }, + InnerTablePtrMut::Serial(ref_mut) => ref_mut, + } + } +} + +impl TablePtrMut<'_, IndexPtr> { + #[inline] + pub fn set(&mut self, val: IndexPtr) { + match &mut self.0 { + InnerTablePtrMut::Concurrent(rcu_ref) => unsafe { + *rcu_ref.get() = val; + }, + InnerTablePtrMut::Serial(ref_mut) => { + **ref_mut = val; + } + } + } + + #[inline] + pub fn replace(&mut self, val: IndexPtr) -> IndexPtr { + match &mut self.0 { + InnerTablePtrMut::Concurrent(rcu_ref) => unsafe { rcu_ref.get().replace(val) }, + InnerTablePtrMut::Serial(ref_mut) => mem::replace(*ref_mut, val), + } } } diff --git a/src/parser/ast.rs b/src/parser/ast.rs index d67d97ce..4fc10e05 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -2,7 +2,6 @@ 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; @@ -698,17 +697,18 @@ impl Not for Fixnum { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone)] pub enum Literal { Atom(Atom), - CodeIndex(CodeIndex), + CodeIndexOffset(CodeIndexOffset), Fixnum(Fixnum), Integer(TypedArenaPtr), Rational(TypedArenaPtr), - Float(F64Offset), + F64Offset(F64Offset), } -impl From for Literal { +/* +impl From> for Literal { #[inline(always)] fn from(ptr: F64Ptr) -> Literal { Literal::Float(ptr.as_offset()) @@ -721,14 +721,15 @@ impl fmt::Display for Literal { Literal::Atom(ref atom) => { write!(f, "{}", atom.flat_index()) } - Literal::CodeIndex(i) => write!(f, "{:?}", *i.as_ptr()), + Literal::CodeIndexOffset(i) => write!(f, "{}", *i), Literal::Fixnum(n) => write!(f, "{}", n.get_num()), Literal::Integer(ref n) => write!(f, "{}", n), Literal::Rational(ref n) => write!(f, "{}", n), - Literal::Float(ref n) => write!(f, "{}", *n), + Literal::FloatOffset(ref n) => write!(f, "{}", *n), } } } +*/ impl Literal { pub fn as_atom(&self, atom_tbl: &Arc) -> Option { @@ -874,7 +875,7 @@ impl Term { pub(crate) fn unfold_by_str_once(term: &mut Term, s: Atom) -> Option<(Term, Term)> { if let Term::Clause(_, ref name, ref mut subterms) = term { - if let Some(Term::Literal(_, Literal::CodeIndex(_))) = subterms.last() { + if let Some(Term::Literal(_, Literal::CodeIndexOffset(_))) = subterms.last() { subterms.pop(); } diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index a1b8cb4a..6584dd32 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -1,7 +1,7 @@ use crate::arena::*; use crate::atom_table::*; pub use crate::machine::machine_state::*; -use crate::offset_table::F64Ptr; +use crate::offset_table::*; use crate::parser::ast::*; use crate::parser::char_reader::*; use crate::parser::dashu::Integer; @@ -30,7 +30,7 @@ struct LayoutInfo { more: bool, } -#[derive(Debug, PartialEq)] +#[derive(Debug)] pub enum Token { Literal(Literal), Var(String), @@ -58,7 +58,7 @@ impl Token { enum Number { BigInt(TypedArenaPtr), Fixnum(Fixnum), - Float(F64Ptr), + Float(F64Offset), } impl Number { @@ -67,7 +67,7 @@ impl Number { match self { Number::BigInt(ibig) => Literal::Integer(ibig), Number::Fixnum(fixnum) => Literal::Fixnum(fixnum), - Number::Float(f) => Literal::Float(f.as_offset()), + Number::Float(f) => Literal::F64Offset(f), } } } @@ -944,8 +944,8 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(n) => Ok(Token::Literal(n.to_literal())), Err(_) => { let n = parse_float_lossy(&token_string)?; - Ok(Token::Literal(Literal::Float( - float_alloc!(n, self.machine_st.arena).as_offset(), + Ok(Token::Literal(Literal::F64Offset( + float_alloc!(n, self.machine_st.arena), ))) } }, diff --git a/src/parser/parser.rs b/src/parser/parser.rs index 10702109..b989738d 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -3,12 +3,11 @@ use dashu::Rational; use crate::arena::*; use crate::atom_table::*; +use crate::offset_table::OffsetTable; 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; @@ -963,17 +962,21 @@ impl<'a, R: CharRead> Parser<'a, R> { Token::Literal(Literal::Rational(n)) => { self.negate_number(n, negate_rat_rc, |r, _| Literal::Rational(r)) } - Token::Literal(Literal::Float(n)) if n.as_ptr().is_infinite() => { + Token::Literal(Literal::F64Offset(n)) if self.lexer.machine_st.arena.f64_tbl.lookup(n).is_infinite() => { return Err(ParserError::InfiniteFloat( self.lexer.line_num, self.lexer.col_num, )); } - Token::Literal(Literal::Float(n)) => self.negate_number( - **n.as_ptr(), - |n, _| -n, - |n, arena| Literal::from(float_alloc!(n, arena)), - ), + Token::Literal(Literal::F64Offset(n)) => { + let n = *self.lexer.machine_st.arena.f64_tbl.lookup(n); + + self.negate_number( + n, + |n, _| -n, + |n, arena| Literal::F64Offset(arena.f64_tbl.build_with(n)), + ) + } Token::Literal(Literal::Fixnum(n)) => { self.negate_number(n, |n, _| -n, |n, _| Literal::Fixnum(n)) } diff --git a/src/types.rs b/src/types.rs index b4765930..60b3b132 100644 --- a/src/types.rs +++ b/src/types.rs @@ -30,9 +30,9 @@ pub enum HeapCellValueTag { PStrLoc = 0b010011, // constants. Cons = 0b0, - F64 = 0b010101, + F64Offset = 0b010101, Fixnum = 0b011001, - CodeIndex = 0b011011, + CodeIndexOffset = 0b011011, Atom = 0b011111, CutPoint = 0b011101, // trail elements. @@ -57,9 +57,9 @@ pub enum HeapCellValueView { PStrLoc = 0b010011, // constants. Cons = 0b0, - F64 = 0b010101, + F64Offset = 0b010101, Fixnum = 0b011001, - CodeIndex = 0b011011, + CodeIndexOffset = 0b011011, Atom = 0b011111, CutPoint = 0b011101, // trail elements. @@ -261,9 +261,9 @@ pub struct HeapCellValue { impl fmt::Debug for HeapCellValue { fn fmt(&self, f: &mut std::fmt::Formatter) -> fmt::Result { match self.get_tag() { - HeapCellValueTag::F64 => f + HeapCellValueTag::F64Offset => f .debug_struct("HeapCellValue") - .field("tag", &HeapCellValueTag::F64) + .field("tag", &HeapCellValueTag::F64Offset) .field("offset", &self.get_value()) .field("m", &self.m()) .field("f", &self.f()) @@ -289,18 +289,6 @@ impl fmt::Debug for HeapCellValue { .field("f", &self.f()) .finish() } - /* - HeapCellValueTag::PStr => { - let (name, _) = cell_as_atom_cell!(self).get_name_and_arity(); - - f.debug_struct("HeapCellValue") - .field("tag", &HeapCellValueTag::PStr) - .field("contents", &name.as_str()) - .field("m", &self.m()) - .field("f", &self.f()) - .finish() - } - */ tag => f .debug_struct("HeapCellValue") .field("tag", &tag) @@ -317,7 +305,7 @@ impl From for HeapCellValue { fn from(literal: Literal) -> Self { match literal { Literal::Atom(name) => atom_as_cell!(name), - Literal::CodeIndex(idx) => HeapCellValue::from(idx), + Literal::CodeIndexOffset(idx) => HeapCellValue::from(idx), Literal::Fixnum(n) => fixnum_as_cell!(n), Literal::Integer(bigint_ptr) => { typed_arena_ptr_as_cell!(bigint_ptr) @@ -325,7 +313,7 @@ impl From for HeapCellValue { Literal::Rational(bigint_ptr) => { typed_arena_ptr_as_cell!(bigint_ptr) } - Literal::Float(f) => HeapCellValue::from(f.as_ptr()), + Literal::F64Offset(f) => HeapCellValue::from(f), } } } @@ -345,11 +333,11 @@ impl TryFrom for Literal { (HeapCellValueTag::Fixnum, n) => { Ok(Literal::Fixnum(n)) } - (HeapCellValueTag::F64, f) => { - Ok(Literal::Float(f.as_offset())) + (HeapCellValueTag::F64Offset, f) => { + Ok(Literal::F64Offset(f)) } - (HeapCellValueTag::CodeIndex, idx) => { - Ok(Literal::CodeIndex(idx)) + (HeapCellValueTag::CodeIndexOffset, idx) => { + Ok(Literal::CodeIndexOffset(idx)) } (HeapCellValueTag::Cons, cons_ptr) => { match_untyped_arena_ptr!(cons_ptr, @@ -381,19 +369,19 @@ where } } -impl From for HeapCellValue { +impl From for HeapCellValue { #[inline] - fn from(f64_ptr: F64Ptr) -> HeapCellValue { - HeapCellValue::build_with(HeapCellValueTag::F64, f64_ptr.as_offset().to_u64()) + fn from(f64_offset: F64Offset) -> HeapCellValue { + HeapCellValue::build_with(HeapCellValueTag::F64Offset, f64_offset.to_u64()) } } -impl From for HeapCellValue { +impl From for HeapCellValue { #[inline] - fn from(code_index_ptr: CodeIndexPtr) -> HeapCellValue { + fn from(code_index_offset: CodeIndexOffset) -> HeapCellValue { HeapCellValue::build_with( - HeapCellValueTag::CodeIndex, - code_index_ptr.as_offset().to_u64(), + HeapCellValueTag::CodeIndexOffset, + code_index_offset.to_u64(), ) } } @@ -472,7 +460,7 @@ impl HeapCellValue { | HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar - | HeapCellValueTag::PStrLoc // | HeapCellValueTag::PStrOffset + | HeapCellValueTag::PStrLoc ) } @@ -496,7 +484,7 @@ impl HeapCellValue { pub fn is_constant(self) -> bool { match self.get_tag() { HeapCellValueTag::Cons - | HeapCellValueTag::F64 + | HeapCellValueTag::F64Offset | HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint => true, HeapCellValueTag::Atom => cell_as_atom_cell!(self).get_arity() == 0, @@ -661,38 +649,52 @@ impl HeapCellValue { } pub fn order_category(self, heap: &Heap) -> Option { - match Number::try_from(self).ok() { - Some(Number::Integer(_)) | Some(Number::Fixnum(_)) | Some(Number::Rational(_)) => { + read_heap_cell!(self, + (HeapCellValueTag::Cons, c) => { + match_untyped_arena_ptr!(c, + (ArenaHeaderTag::Integer, _n) => { + Some(TermOrderCategory::Integer) + } + (ArenaHeaderTag::Rational, _n) => { + Some(TermOrderCategory::Integer) + } + _ => { + None + } + ) + } + (HeapCellValueTag::F64Offset) => { + Some(TermOrderCategory::FloatingPoint) + } + (HeapCellValueTag::Fixnum | HeapCellValueTag::CutPoint) => { Some(TermOrderCategory::Integer) } - Some(Number::Float(_)) => Some(TermOrderCategory::FloatingPoint), - None => match self.get_tag() { - HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar => { - Some(TermOrderCategory::Variable) - } - // HeapCellValueTag::Char => Some(TermOrderCategory::Atom), - HeapCellValueTag::Atom => Some(if cell_as_atom_cell!(self).get_arity() > 0 { + (HeapCellValueTag::Var | HeapCellValueTag::StackVar | HeapCellValueTag::AttrVar) => { + Some(TermOrderCategory::Variable) + } + (HeapCellValueTag::Atom, (_name, arity)) => { + Some(if arity > 0 { TermOrderCategory::Compound } else { TermOrderCategory::Atom - }), - HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc => { - // | HeapCellValueTag::CStr => { + }) + } + (HeapCellValueTag::Lis | HeapCellValueTag::PStrLoc) => { + Some(TermOrderCategory::Compound) + } + (HeapCellValueTag::Str, s) => { + let arity = cell_as_atom_cell!(heap[s]).get_arity(); + + if arity == 0 { + Some(TermOrderCategory::Atom) + } else { Some(TermOrderCategory::Compound) } - HeapCellValueTag::Str => { - let value = heap[self.get_value() as usize]; - let arity = cell_as_atom_cell!(value).get_arity(); - - if arity == 0 { - Some(TermOrderCategory::Atom) - } else { - Some(TermOrderCategory::Compound) - } - } - _ => None, - }, - } + } + _ => { + None + } + ) } #[inline(always)] -- 2.54.0