Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rebis-dev: Fix Heap::compute_pstr_size being off by one cell #2759

Open
wants to merge 13 commits into
base: rebis-dev
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
introduce bespoke Heap type for in-heap partial strings
mthom committed Oct 26, 2024
commit 62bea56634e9f1f533873671ab553c5657912e5b
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -49,7 +49,6 @@ jobs:
# Cargo.toml rust-version
- { os: ubuntu-22.04, rust-version: "1.77", target: 'x86_64-unknown-linux-gnu'}
# rust versions
- { os: ubuntu-22.04, rust-version: "1.77", target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-22.04, rust-version: beta, target: 'x86_64-unknown-linux-gnu'}
- { os: ubuntu-22.04, rust-version: nightly, target: 'x86_64-unknown-linux-gnu', miri: true, components: "miri"}
defaults:
2 changes: 1 addition & 1 deletion benches/run_iai.rs
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ mod setup;
mod iai {
use iai_callgrind::{library_benchmark, library_benchmark_group, main};

use scryer_prolog::QueryResolution;
use scryer_prolog::machine::parsed_results::QueryResolution;

use super::setup;

7 changes: 5 additions & 2 deletions benches/setup.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
use std::{collections::BTreeMap, fs, path::Path};

use maplit::btreemap;
use scryer_prolog::{Machine, QueryResolution, Value};
use scryer_prolog::machine::{
parsed_results::{QueryResolution, Value},
Machine,
};

pub fn prolog_benches() -> BTreeMap<&'static str, PrologBenchmark> {
[
@@ -85,7 +88,7 @@ mod test {
#[test]
fn validate_benchmarks() {
use super::prolog_benches;
use scryer_prolog::{QueryMatch, QueryResolution};
use scryer_prolog::machine::parsed_results::{QueryMatch, QueryResolution};
use std::{fmt::Write, fs};

struct BenchResult {
392 changes: 156 additions & 236 deletions build/instructions_template.rs

Large diffs are not rendered by default.

39 changes: 33 additions & 6 deletions build/static_string_indexing.rs
Original file line number Diff line number Diff line change
@@ -84,6 +84,18 @@ impl<'ast> Visit<'ast> for StaticStrVisitor {
}
}

const INLINED_ATOM_MAX_LEN: usize = 6;

fn static_string_index(string: &str, index: usize) -> u64 {
if 0 < string.len() && string.len() <= INLINED_ATOM_MAX_LEN {
let mut string_buf: [u8; 8] = [0u8; 8];
string_buf[.. string.len()].copy_from_slice(string.as_bytes());
(u64::from_le_bytes(string_buf) << 1) | 1
} else {
(index << 1) as u64
}
}

pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStream {
use quote::*;

@@ -149,11 +161,26 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
visitor.visit_file(&syntax)
}

let indices = (0..visitor.static_strs.len()).map(|i| (i << 3) as u64);
let indices_iter = indices.clone();
let mut static_str_keys = vec![];
let mut static_strs = vec![];
let mut static_str_indices = vec![];

let indices: Vec<u64> = visitor.static_strs.iter().map(|string| {
let index = static_string_index(string, static_strs.len());

static_str_keys.push(string);

if index & 1 == 1 {
index
} else {
static_str_indices.push(index);
static_strs.push(string);
index
}
}).collect();

let static_strs_len = visitor.static_strs.len();
let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();
let static_strs_len = static_strs.len(); // visitor.static_strs.len();
//let static_strs: &Vec<_> = &visitor.static_strs.into_iter().collect();

quote! {
static STRINGS: [&str; #static_strs_len] = [
@@ -163,11 +190,11 @@ pub fn index_static_strings(instruction_rs_path: &std::path::Path) -> TokenStrea
];

macro_rules! atom {
#((#static_strs) => { Atom { index: #indices_iter } };)*
#((#static_str_keys) => { Atom { index: #indices } };)*
}

pub static STATIC_ATOMS_MAP: phf::Map<&'static str, Atom> = phf::phf_map! {
#(#static_strs => { Atom { index: #indices } },)*
#(#static_strs => { Atom { index: #static_str_indices } },)*
};
}
}
3 changes: 2 additions & 1 deletion src/allocator.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ use crate::parser::ast::*;

use crate::forms::*;
use crate::instructions::*;
use crate::machine::heap::Heap;
use crate::targets::*;

pub(crate) trait Allocator {
@@ -45,7 +46,7 @@ pub(crate) trait Allocator {

fn reset(&mut self);
fn reset_arg(&mut self, arg_num: usize);
fn reset_at_head(&mut self, term: &mut FocusedHeap, head_loc: usize);
fn reset_at_head(&mut self, heap: &mut Heap, head_loc: usize);
fn reset_contents(&mut self);

fn advance_arg(&mut self);
37 changes: 6 additions & 31 deletions src/arena.rs
Original file line number Diff line number Diff line change
@@ -897,7 +897,7 @@ mod tests {
use crate::arena::*;
use crate::atom_table::*;
use crate::machine::mock_wam::*;
use crate::machine::partial_string::*;
use crate::types::*;

use crate::parser::dashu::{Integer, Rational};
use ordered_float::OrderedFloat;
@@ -980,7 +980,7 @@ mod tests {

assert!(!big_int_ptr.as_ptr().is_null());

let cell = HeapCellValue::from(Literal::Integer(big_int_ptr));
let cell = HeapCellValue::from(big_int_ptr);
assert_eq!(cell.get_tag(), HeapCellValueTag::Cons);

let untyped_arena_ptr = match cell.to_untyped_arena_ptr() {
@@ -1086,31 +1086,6 @@ mod tests {
_ => { unreachable!() }
);

// complete string

let pstr_var_cell =
put_partial_string(&mut wam.machine_st.heap, "ronan", &wam.machine_st.atom_tbl);
let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize];

assert_eq!(pstr_cell.get_tag(), HeapCellValueTag::PStr);

match pstr_cell.to_pstr() {
Some(pstr) => {
assert_eq!(&*pstr.as_str_from(0), "ronan");
}
None => {
unreachable!();
}
}

read_heap_cell!(pstr_cell,
(HeapCellValueTag::PStr, pstr_atom) => {
let pstr = PartialString::from(pstr_atom);
assert_eq!(&*pstr.as_str_from(0), "ronan");
}
_ => { unreachable!() }
);

// fixnum

let fixnum_cell = fixnum_as_cell!(Fixnum::build_with(3));
@@ -1188,8 +1163,8 @@ mod tests {
let char_cell = char_as_cell!(c);

read_heap_cell!(char_cell,
(HeapCellValueTag::Char, c) => {
assert_eq!(c, 'c');
(HeapCellValueTag::Atom, (c, _arity)) => {
assert_eq!(&*c.as_str(), "c");
}
_ => { unreachable!() }
);
@@ -1198,8 +1173,8 @@ mod tests {
let cyrillic_char_cell = char_as_cell!(c);

read_heap_cell!(cyrillic_char_cell,
(HeapCellValueTag::Char, c) => {
assert_eq!(c, 'Ћ');
(HeapCellValueTag::Atom, (c, _arity)) => {
assert_eq!(&*c.as_str(), "Ћ");
}
_ => { unreachable!() }
);
163 changes: 42 additions & 121 deletions src/arithmetic.rs
Original file line number Diff line number Diff line change
@@ -9,7 +9,6 @@ use crate::instructions::*;
use crate::iterators::*;
use crate::machine::disjuncts::*;
use crate::machine::stack::Stack;
use crate::parser::ast::FocusedHeap;
use crate::targets::QueryInstruction;
use crate::types::*;

@@ -55,127 +54,52 @@ impl Default for ArithmeticTerm {

pub(crate) type ArithCont = (CodeDeque, Option<ArithmeticTerm>);

/*
#[derive(Debug)]
pub(crate) struct ArithInstructionIterator<'a> {
state_stack: Vec<TermIterState<'a>>,
}

impl<'a> ArithInstructionIterator<'a> {
fn push_subterm(&mut self, lvl: Level, term: &'a Term) {
self.state_stack
.push(TermIterState::subterm_to_state(lvl, term));
}

fn from(term: &'a Term) -> Result<Self, ArithmeticError> {
let state = match term {
Term::AnonVar => return Err(ArithmeticError::UninstantiatedVar),
Term::Clause(cell, name, terms) => {
TermIterState::Clause(Level::Shallow, 0, cell, *name, terms)
}
Term::Literal(cell, cons) => TermIterState::Literal(Level::Shallow, cell, cons),
Term::Cons(..) | Term::PartialString(..) | Term::CompleteString(..) => {
return Err(ArithmeticError::NonEvaluableFunctor(
Literal::Atom(atom!(".")),
2,
))
}
Term::Var(cell, var_ptr) => TermIterState::Var(Level::Shallow, cell, var_ptr.clone()),
};

Ok(ArithInstructionIterator {
state_stack: vec![state],
})
}
}

#[derive(Debug)]
pub(crate) enum ArithTermRef<'a> {
Literal(&'a Literal),
Op(Atom, usize), // name, arity.
Var(Level, &'a Cell<VarReg>, VarPtr),
}

impl<'a> Iterator for ArithInstructionIterator<'a> {
type Item = Result<ArithTermRef<'a>, ArithmeticError>;

fn next(&mut self) -> Option<Self::Item> {
while let Some(iter_state) = self.state_stack.pop() {
match iter_state {
TermIterState::AnonVar(_) => return Some(Err(ArithmeticError::UninstantiatedVar)),
TermIterState::Clause(lvl, child_num, cell, name, subterms) => {
let arity = subterms.len();

if child_num == arity {
return Some(Ok(ArithTermRef::Op(name, arity)));
} else {
self.state_stack.push(TermIterState::Clause(
lvl,
child_num + 1,
cell,
name,
subterms,
));

self.push_subterm(lvl.child_level(), &subterms[child_num]);
}
}
TermIterState::Literal(_, _, c) => return Some(Ok(ArithTermRef::Literal(c))),
TermIterState::Var(lvl, cell, var_ptr) => {
return Some(Ok(ArithTermRef::Var(lvl, cell, var_ptr)));
}
_ => {
return Some(Err(ArithmeticError::NonEvaluableFunctor(
Literal::Atom(atom!(".")),
2,
)));
}
};
}

None
}
}

pub(crate) trait ArithmeticTermIter<'a> {
type Iter: Iterator<Item = Result<ArithTermRef<'a>, ArithmeticError>>;

fn iter(self) -> Result<Self::Iter, ArithmeticError>;
}

impl<'a> ArithmeticTermIter<'a> for &'a Term {
type Iter = ArithInstructionIterator<'a>;

fn iter(self) -> Result<Self::Iter, ArithmeticError> {
ArithInstructionIterator::from(self)
}
}
*/

#[derive(Debug)]
pub(crate) struct ArithmeticEvaluator<'a> {
marker: &'a mut DebrayAllocator,
interm: Vec<ArithmeticTerm>,
interm_c: usize,
}

fn push_literal(interm: &mut Vec<ArithmeticTerm>, 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::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)),
)),
Literal::Atom(name) if name == atom!("pi") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::PI)),
)),
Literal::Atom(name) if name == atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(f64::EPSILON)),
)),
_ => return Err(ArithmeticError::NonEvaluableFunctor(HeapCellValue::from(c), 0)),
}
fn push_literal(interm: &mut Vec<ArithmeticTerm>, c: HeapCellValue) -> Result<(), ArithmeticError> {
read_heap_cell!(c,
(HeapCellValueTag::Fixnum, n) => {
interm.push(ArithmeticTerm::Number(Number::Fixnum(n)))
}
(HeapCellValueTag::Cons, cons_ptr) => {
match_untyped_arena_ptr!(cons_ptr,
(ArenaHeaderTag::Integer, n) => {
interm.push(ArithmeticTerm::Number(Number::Integer(n)));
}
(ArenaHeaderTag::Rational, n) => {
interm.push(ArithmeticTerm::Number(Number::Rational(n)));
}
_ => return Err(ArithmeticError::NonEvaluableFunctor(c, 0)),
);
}
(HeapCellValueTag::Atom, (name, arity)) => {
debug_assert_eq!(arity, 0);

match name {
atom!("pi") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::PI)),
)),
atom!("epsilon") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::EPSILON)),
)),
atom!("e") => interm.push(ArithmeticTerm::Number(
Number::Float(OrderedFloat(std::f64::consts::E)),
)),
_ => unreachable!(),
}
}
(HeapCellValueTag::F64, n) => {
interm.push(ArithmeticTerm::Number(Number::Float(*n)));
}
_ => {
return Err(ArithmeticError::NonEvaluableFunctor(c, 0));
}
);

Ok(())
}
@@ -313,7 +237,7 @@ impl<'a> ArithmeticEvaluator<'a> {

pub(crate) fn compile_is(
&mut self,
src: &mut FocusedHeap,
src: &mut FocusedHeapRefMut,
term_loc: usize,
context: GenContext,
arg: usize,
@@ -360,16 +284,13 @@ impl<'a> ArithmeticEvaluator<'a> {
}
(HeapCellValueTag::Atom, (name, arity)) => {
if arity == 0 {
push_literal(&mut self.interm, Literal::Atom(name))?;
push_literal(&mut self.interm, atom_as_cell!(name))?;
} else {
code.push_back(self.instr_from_clause(name, arity)?);
}
}
_ => {
match Literal::try_from(term) {
Ok(lit) => push_literal(&mut self.interm, lit)?,
_ => return Err(ArithmeticError::NonEvaluableFunctor(term, 0)),
}
push_literal(&mut self.interm, term)?;
}
);
}
Loading