Skip to content

Commit 67f3543

Browse files
arvidnrichardkiss
authored andcommitted
allocate atoms on a stack rather than individually on the heap
1 parent c8971d7 commit 67f3543

File tree

1 file changed

+31
-19
lines changed

1 file changed

+31
-19
lines changed

src/int_allocator.rs

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,21 @@
1-
use std::vec;
2-
31
use crate::allocator::{Allocator, SExp};
42

3+
#[derive(Clone, Copy)]
4+
pub struct IntAtomBuf {
5+
start: u32,
6+
end: u32,
7+
}
8+
59
enum NodePtr {
6-
Atom(u32),
10+
Atom(IntAtomBuf),
711
Pair(u32, u32),
812
}
913

1014
pub struct IntAllocator {
11-
u8_vec: Vec<Vec<u8>>,
15+
// this is effectively a grow-only stack where atoms are allocated. Atoms
16+
// are immutable, so once they are created, they will stay around until the
17+
// program completes
18+
u8_vec: Vec<u8>,
1219
node_vec: Vec<NodePtr>,
1320
}
1421

@@ -24,23 +31,28 @@ impl IntAllocator {
2431
u8_vec: Vec::new(),
2532
node_vec: Vec::new(),
2633
};
27-
r.u8_vec.push(vec![]);
28-
r.u8_vec.push(vec![1_u8]);
29-
r.node_vec.push(NodePtr::Atom(0));
30-
r.node_vec.push(NodePtr::Atom(1));
34+
r.u8_vec.reserve(1024 * 1024);
35+
r.u8_vec.push(1_u8);
36+
// Preallocated empty list
37+
r.node_vec
38+
.push(NodePtr::Atom(IntAtomBuf { start: 0, end: 0 }));
39+
// Preallocated 1
40+
r.node_vec
41+
.push(NodePtr::Atom(IntAtomBuf { start: 0, end: 1 }));
3142
r
3243
}
3344
}
3445

3546
impl Allocator for IntAllocator {
3647
type Ptr = u32;
37-
type AtomBuf = u32;
48+
type AtomBuf = IntAtomBuf;
3849

39-
fn new_atom(&mut self, v: &[u8]) -> u32 {
40-
let index = self.u8_vec.len() as u32;
41-
self.u8_vec.push(v.into());
42-
let r: u32 = self.node_vec.len() as u32;
43-
self.node_vec.push(NodePtr::Atom(index));
50+
fn new_atom(&mut self, v: &[u8]) -> Self::Ptr {
51+
let start = self.u8_vec.len() as u32;
52+
self.u8_vec.extend_from_slice(v);
53+
let end = self.u8_vec.len() as u32;
54+
let r = self.node_vec.len() as u32;
55+
self.node_vec.push(NodePtr::Atom(IntAtomBuf { start, end }));
4456
r
4557
}
4658

@@ -52,27 +64,27 @@ impl Allocator for IntAllocator {
5264

5365
fn atom<'a>(&'a self, node: &'a Self::Ptr) -> &'a [u8] {
5466
match self.node_vec[*node as usize] {
55-
NodePtr::Atom(index) => &self.u8_vec[index as usize],
67+
NodePtr::Atom(IntAtomBuf { start, end }) => &self.u8_vec[start as usize..end as usize],
5668
_ => panic!("expected atom, got pair"),
5769
}
5870
}
5971

6072
fn buf<'a>(&'a self, node: &'a Self::AtomBuf) -> &'a [u8] {
61-
&self.u8_vec[*node as usize]
73+
&self.u8_vec[node.start as usize..node.end as usize]
6274
}
6375

6476
fn sexp(&self, node: &Self::Ptr) -> SExp<Self::Ptr, Self::AtomBuf> {
6577
match self.node_vec[*node as usize] {
66-
NodePtr::Atom(index) => SExp::Atom(index),
78+
NodePtr::Atom(atombuf) => SExp::Atom(atombuf),
6779
NodePtr::Pair(left, right) => SExp::Pair(left, right),
6880
}
6981
}
7082

71-
fn null(&self) -> u32 {
83+
fn null(&self) -> Self::Ptr {
7284
0
7385
}
7486

75-
fn one(&self) -> u32 {
87+
fn one(&self) -> Self::Ptr {
7688
1
7789
}
7890
}

0 commit comments

Comments
 (0)