Skip to content

Commit

Permalink
separate the node list into two separate vectors, to avoid the overhe…
Browse files Browse the repository at this point in the history
…ad of a variant discriminator for every item
  • Loading branch information
arvidn authored and richardkiss committed Feb 16, 2021
1 parent 67f3543 commit d231e2f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 30 deletions.
58 changes: 35 additions & 23 deletions src/int_allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,25 @@ pub struct IntAtomBuf {
end: u32,
}

enum NodePtr {
Atom(IntAtomBuf),
Pair(u32, u32),
#[derive(Clone, Copy)]
pub struct IntPair {
first: i32,
rest: i32,
}

pub struct IntAllocator {
// this is effectively a grow-only stack where atoms are allocated. Atoms
// are immutable, so once they are created, they will stay around until the
// program completes
u8_vec: Vec<u8>,
node_vec: Vec<NodePtr>,

// storage for all pairs (positive indices)
pair_vec: Vec<IntPair>,

// storage for all atoms (negative indices).
// node index -1 refers to index 0 in this vector, -2 refers to 1 and so
// on.
atom_vec: Vec<IntAtomBuf>,
}

impl Default for IntAllocator {
Expand All @@ -29,62 +37,66 @@ impl IntAllocator {
pub fn new() -> Self {
let mut r = IntAllocator {
u8_vec: Vec::new(),
node_vec: Vec::new(),
pair_vec: Vec::new(),
atom_vec: Vec::new(),
};
r.u8_vec.reserve(1024 * 1024);
r.atom_vec.reserve(256);
r.pair_vec.reserve(256);
r.u8_vec.push(1_u8);
// Preallocated empty list
r.node_vec
.push(NodePtr::Atom(IntAtomBuf { start: 0, end: 0 }));
r.atom_vec.push(IntAtomBuf { start: 0, end: 0 });
// Preallocated 1
r.node_vec
.push(NodePtr::Atom(IntAtomBuf { start: 0, end: 1 }));
r.atom_vec.push(IntAtomBuf { start: 0, end: 1 });
r
}
}

impl Allocator for IntAllocator {
type Ptr = u32;
type Ptr = i32;
type AtomBuf = IntAtomBuf;

fn new_atom(&mut self, v: &[u8]) -> Self::Ptr {
let start = self.u8_vec.len() as u32;
self.u8_vec.extend_from_slice(v);
let end = self.u8_vec.len() as u32;
let r = self.node_vec.len() as u32;
self.node_vec.push(NodePtr::Atom(IntAtomBuf { start, end }));
r
self.atom_vec.push(IntAtomBuf { start, end });
-(self.atom_vec.len() as i32)
}

fn new_pair(&mut self, first: Self::Ptr, rest: Self::Ptr) -> Self::Ptr {
let r: u32 = self.node_vec.len() as u32;
self.node_vec.push(NodePtr::Pair(first, rest));
let r = self.pair_vec.len() as i32;
self.pair_vec.push(IntPair { first, rest });
r
}

fn atom<'a>(&'a self, node: &'a Self::Ptr) -> &'a [u8] {
match self.node_vec[*node as usize] {
NodePtr::Atom(IntAtomBuf { start, end }) => &self.u8_vec[start as usize..end as usize],
_ => panic!("expected atom, got pair"),
if *node >= 0 {
panic!("expected atom, got pair");
}
let atom = self.atom_vec[(-*node - 1) as usize];
&self.u8_vec[atom.start as usize..atom.end as usize]
}

fn buf<'a>(&'a self, node: &'a Self::AtomBuf) -> &'a [u8] {
&self.u8_vec[node.start as usize..node.end as usize]
}

fn sexp(&self, node: &Self::Ptr) -> SExp<Self::Ptr, Self::AtomBuf> {
match self.node_vec[*node as usize] {
NodePtr::Atom(atombuf) => SExp::Atom(atombuf),
NodePtr::Pair(left, right) => SExp::Pair(left, right),
if *node >= 0 {
let pair = self.pair_vec[*node as usize];
SExp::Pair(pair.first, pair.rest)
} else {
let atom = self.atom_vec[(-*node - 1) as usize];
SExp::Atom(atom)
}
}

fn null(&self) -> Self::Ptr {
0
-1
}

fn one(&self) -> Self::Ptr {
1
-2
}
}
13 changes: 6 additions & 7 deletions src/py/run_program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::int_allocator::IntAllocator;
use crate::more_ops::op_unknown;
use crate::node::Node;
use crate::py::f_table::{make_f_lookup, FLookup};
use crate::reduction::{EvalErr, Reduction};
use crate::reduction::Response;
use crate::run_program::{run_program, OperatorHandler};
use crate::serialize::{node_from_bytes, node_to_bytes};
use lazy_static::lazy_static;
Expand All @@ -26,8 +26,8 @@ impl OperatorHandler<IntAllocator> for OperatorHandlerWithMode {
&self,
allocator: &mut IntAllocator,
o: <IntAllocator as Allocator>::AtomBuf,
argument_list: &u32,
) -> Result<Reduction<u32>, EvalErr<u32>> {
argument_list: &<IntAllocator as Allocator>::Ptr,
) -> Response<<IntAllocator as Allocator>::Ptr> {
let op = &allocator.buf(&o);
if op.len() == 1 {
if let Some(f) = F_TABLE[op[0] as usize] {
Expand Down Expand Up @@ -58,11 +58,10 @@ pub fn serialize_and_run_program(
let f: Box<dyn OperatorHandler<IntAllocator>> = Box::new(OperatorHandlerWithMode {
strict: (flags & STRICT_MODE) != 0,
});
let program: u32 = node_from_bytes(&mut allocator, program).unwrap();
let program = node_from_bytes(&mut allocator, program).unwrap();
let args = node_from_bytes(&mut allocator, args).unwrap();

let args: u32 = node_from_bytes(&mut allocator, args).unwrap();

let r: Result<Reduction<u32>, EvalErr<u32>> = run_program(
let r = run_program(
&mut allocator,
&program,
&args,
Expand Down

0 comments on commit d231e2f

Please sign in to comment.