diff options
| author | Rose Hogenson <rhogenson@posteo.net> | 2022-07-29 22:41:17 -0700 |
|---|---|---|
| committer | Rose Hogenson <rhogenson@posteo.net> | 2022-07-29 22:41:17 -0700 |
| commit | c7ff0b98146693b60a3f075818f96764f646b2d5 (patch) | |
| tree | b8d2f409a934ae8c3858a30f42d1799b8abee5da /bytecode/src/heap.rs | |
| parent | 762431b0f0a6ead18a93a05c0f3269dca5b8fef1 (diff) | |
| download | chromatopelma-c7ff0b98146693b60a3f075818f96764f646b2d5.tar.zst | |
Fix the bytecode interpreter.
I'm too scared to actually try to run it right now.
Diffstat (limited to 'bytecode/src/heap.rs')
| -rw-r--r-- | bytecode/src/heap.rs | 68 |
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(()) } } |
