aboutsummaryrefslogtreecommitdiffstats
path: root/bytecode/src/heap.rs
diff options
context:
space:
mode:
Diffstat (limited to 'bytecode/src/heap.rs')
-rw-r--r--bytecode/src/heap.rs68
1 files changed, 24 insertions, 44 deletions
diff --git a/bytecode/src/heap.rs b/bytecode/src/heap.rs
index 1706d10..d32283e 100644
--- a/bytecode/src/heap.rs
+++ b/bytecode/src/heap.rs
@@ -32,6 +32,7 @@ pub struct Heap {
heap: Vec<u64>,
free_pointer: usize,
spare_heap: Vec<u64>,
+ last_reachable_cells: usize,
}
impl Heap {
@@ -40,13 +41,14 @@ impl Heap {
heap: vec![0; 512], // 4 kB
free_pointer: 0,
spare_heap: vec![0; 512],
+ last_reachable_cells: 0,
}
}
fn alloc_size(&mut self, p: Pointer) -> Result<usize, String> {
let (u, _) = open_ptr(p);
if u == 0 {
- return Err("cannot get the size of a nil pointer");
+ return Err(String::from("cannot get the size of a nil pointer"));
}
// Alloc size is stored just below the pointer.
let size = self.heap[u - 1];
@@ -105,29 +107,12 @@ impl Heap {
return Ok(());
}
- fn collect_garbage(
- &mut self,
- size_hint: usize,
- stack: &mut [Value],
- locals: &mut [Value],
- ) -> Result<(), String> {
- const MAX_HEAP_SIZE: usize = 4 * 1024 * 1024; // 4 GB
- // Always at least double the heap size (keeping in mind the max heap size).
- let mut size_hint = size_hint;
- if size_hint < self.heap.len() {
- size_hint = self.heap.len();
- }
- let mut new_heap_size = self.heap.len() + size_hint;
- if new_heap_size > MAX_HEAP_SIZE / 2 {
- new_heap_size = MAX_HEAP_SIZE / 2;
- }
- self.spare_heap.resize(new_heap_size, 0);
+ fn collect_garbage(&mut self, locals: &mut [Value]) -> Result<(), String> {
+ self.spare_heap.resize(self.heap.len(), 0);
let mut spare_heap_ptr = 0;
let mut rewrites = HashMap::new();
- self.walk_gc_roots(stack, &mut spare_heap_ptr, &mut rewrites)?;
self.walk_gc_roots(locals, &mut spare_heap_ptr, &mut rewrites)?;
- // Walk the stacks and rewrite.
- rewrite_pointers(stack, &rewrites)?;
+ // Rewrite values.
rewrite_pointers(locals, &rewrites)?;
// Activate the new heap!
std::mem::swap(&mut self.heap, &mut self.spare_heap);
@@ -160,6 +145,7 @@ impl Heap {
)?;
}
}
+ self.last_reachable_cells = spare_heap_ptr;
// Done??
return Ok(());
}
@@ -167,42 +153,34 @@ impl Heap {
fn alloc_b(
&mut self,
n: usize,
- stack: &mut [Value],
locals: &mut [Value],
bytevector_p: bool,
) -> Result<Pointer, String> {
+ if self.free_pointer > 2 * self.last_reachable_cells {
+ self.collect_garbage(locals)?;
+ }
let n_cells = (n + 7) / 8;
- if self.heap.len() - self.free_pointer < n_cells {
- self.collect_garbage(n, stack, locals)?;
+ if self.free_pointer + n_cells + 1 > self.heap.len() {
+ self.heap.resize(self.free_pointer + n_cells + 1, 0);
}
- let len_p = &mut self.heap[self.free_pointer]?;
+ let len_p = &mut self.heap[self.free_pointer];
*len_p = u64::try_from(n).unwrap() << 1;
if bytevector_p {
*len_p |= 1;
}
self.free_pointer += 1;
let p = Pointer(self.free_pointer * 8);
- let n_cells = n / 8;
- self.heap[self.free_pointer..self.free_pointer + n].fill(0);
+ self.heap[self.free_pointer..self.free_pointer + n_cells].fill(0);
+ self.free_pointer += n_cells;
return Ok(p);
}
- pub fn alloc(
- &mut self,
- n: usize,
- stack: &mut [Value],
- locals: &mut [Value],
- ) -> Result<Pointer, String> {
- return self.alloc_b(n, stack, locals, false);
+ pub fn alloc(&mut self, n: usize, locals: &mut [Value]) -> Result<Pointer, String> {
+ return self.alloc_b(n * 8, locals, false);
}
- pub fn alloc_bytevector(
- &mut self,
- n: usize,
- stack: &mut [Value],
- locals: &mut [Value],
- ) -> Result<Pointer, String> {
- return self.alloc_b(n, stack, locals, true);
+ pub fn alloc_bytevector(&mut self, n: usize, locals: &mut [Value]) -> Result<Pointer, String> {
+ return self.alloc_b(n, locals, true);
}
pub fn peek(&self, p: Pointer) -> Result<Value, String> {
@@ -218,16 +196,17 @@ impl Heap {
let Value(x) = v;
if u >= self.heap.len() {
return Err(format!("invalid pointer {:x}", p));
+ }
self.heap[u] = x;
return Ok(());
}
- fn peek_byte(&self, p: Pointer) -> Result<u8, String> {
+ pub fn peek_byte(&self, p: Pointer) -> Result<u8, String> {
let (word_cnt, word_offset) = open_ptr(p);
if word_cnt >= self.heap.len() {
return Err(format!("invalid pointer {:x}", p));
}
- return (self.heap[word_cnt] >> word_offset * 8) as u8;
+ Ok((self.heap[word_cnt] >> word_offset * 8) as u8)
}
pub fn poke_byte(&mut self, u: u8, p: Pointer) -> Result<(), String> {
@@ -237,6 +216,7 @@ impl Heap {
}
let surrounding_word = self.heap[word_cnt];
let mask = !(0xff << word_offset * 8);
- self.heap[word_cnt] = surrounding_word & mask | u << word_offset * 8;
+ self.heap[word_cnt] = surrounding_word & mask | u64::from(u) << word_offset * 8;
+ Ok(())
}
}