diff options
| author | Rose Hogenson <rosehogenson@posteo.net> | 2024-02-04 18:55:19 -0800 |
|---|---|---|
| committer | Rose Hogenson <rosehogenson@posteo.net> | 2024-02-04 18:55:19 -0800 |
| commit | 1a25a5cc66c8ae48bfd5569da04e9cfc8f9c3501 (patch) | |
| tree | ed8e7e4abf54321279b7ecf8d1b976b751e32baf | |
| parent | 17face3633686e374aa0859271ccf462a48e60aa (diff) | |
| download | sml-1a25a5cc66c8ae48bfd5569da04e9cfc8f9c3501.tar.zst | |
Fix some bugs in the bytecode interpreter.
| -rw-r--r-- | bytecode/.encoding.c.swp | bin | 12288 -> 0 bytes | |||
| -rw-r--r-- | bytecode/src/encoding.rs | 23 | ||||
| -rw-r--r-- | bytecode/src/heap.rs | 48 | ||||
| -rw-r--r-- | bytecode/src/value.rs | 2 |
4 files changed, 42 insertions, 31 deletions
diff --git a/bytecode/.encoding.c.swp b/bytecode/.encoding.c.swp Binary files differdeleted file mode 100644 index fc8e88a..0000000 --- a/bytecode/.encoding.c.swp +++ /dev/null diff --git a/bytecode/src/encoding.rs b/bytecode/src/encoding.rs index e37696d..eb6633d 100644 --- a/bytecode/src/encoding.rs +++ b/bytecode/src/encoding.rs @@ -2,37 +2,44 @@ use crate::heap; use crate::value::Value; use std::error::Error; +#[derive(Debug, Clone, Copy)] pub enum Arg { Local(u8), Const(Value), } +#[derive(Debug, Clone, Copy)] pub struct Alloc { pub out: u8, pub size: Arg, } +#[derive(Debug, Clone, Copy)] pub struct Poke { pub offset: usize, pub ptr: u8, pub val: Arg, } +#[derive(Debug, Clone, Copy)] pub struct Peek { pub out: u8, pub offset: usize, pub val: Arg, } +#[derive(Debug, Clone, Copy)] pub struct Shuf { pub out: u8, pub val: Arg, } +#[derive(Debug, Clone, Copy)] pub struct Exit { pub val: Arg, } +#[derive(Debug, Clone, Copy)] pub enum Op { Alloc(Alloc), Call, @@ -74,19 +81,19 @@ impl Reader<'_> { Ok(res) } - fn parse_u64(&mut self) -> Result<u64, Box<dyn Error>> { + fn parse_value(&mut self) -> Result<Value, Box<dyn Error>> { if self.data.len() < 8 { return Err(Box::from("value: no data")); } let mut res = [0; 8]; res.copy_from_slice(&self.data[..8]); self.advance(8); - Ok(u64::from_le_bytes(res)) + Ok(Value(u64::from_le_bytes(res))) } fn parse_arg(&mut self, is_const: bool) -> Result<Arg, Box<dyn Error>> { if is_const { - Ok(Arg::Const(Value(self.parse_u64()?))) + Ok(Arg::Const(self.parse_value()?)) } else { Ok(Arg::Local(self.parse_local()?)) } @@ -109,14 +116,20 @@ impl Op { } 2 => Op::Call, 3 => { - let offset = usize::try_from(r.parse_u64()?)?; + let Some(ioffset) = r.parse_value()?.to_int() else { + return Err(Box::from("invalid offset")); + }; + let offset = usize::try_from(ioffset)?; let ptr = r.parse_local()?; let val = r.parse_arg(arg1_const)?; Op::Poke(Poke { offset, ptr, val }) } 4 => { let out = r.parse_local()?; - let offset = usize::try_from(r.parse_u64()?)?; + let Some(ioffset) = r.parse_value()?.to_int() else { + return Err(Box::from("invalid offset")); + }; + let offset = usize::try_from(ioffset)?; let val = r.parse_arg(arg1_const)?; Op::Peek(Peek { out, offset, val }) } diff --git a/bytecode/src/heap.rs b/bytecode/src/heap.rs index f1b9d81..45ce283 100644 --- a/bytecode/src/heap.rs +++ b/bytecode/src/heap.rs @@ -3,8 +3,10 @@ use std::error::Error; pub const NUM_LOCALS: usize = 8; +#[derive(Debug)] pub struct Heap { pub buf: Vec<u64>, + first_active: bool, free_ptr: usize, last_live: usize, pub locals: [Value; NUM_LOCALS], @@ -14,6 +16,7 @@ impl Heap { pub fn new() -> Heap { Heap { buf: Vec::new(), + first_active: true, free_ptr: 0, last_live: 0, locals: [Value(0); NUM_LOCALS], @@ -24,7 +27,7 @@ impl Heap { let Some(q) = Value(self.buf[p]).to_pointer() else { return false; }; - return (self.free_ptr < self.buf.len() / 2) == (q < self.buf.len() / 2); + return self.first_active == (q < self.buf.len() / 2); } fn alloc_size(&self, p: usize) -> usize { @@ -64,50 +67,45 @@ impl Heap { Value::from_pointer(q) } + fn size(&self) -> usize { + if self.first_active { + self.free_ptr + } else { + self.free_ptr - self.buf.len() / 2 + } + } + fn collect_garbage(&mut self) { - if self.free_ptr < 2 * self.last_live { + if self.size() < 2 * self.last_live { return; } // Swap the heaps. - if self.free_ptr < self.buf.len() / 2 { + if self.first_active { + self.first_active = false; self.free_ptr = self.buf.len() / 2; } else { + self.first_active = true; self.free_ptr = 0; } for i in 0..self.locals.len() { self.locals[i] = self.process_gc_value(self.locals[i]); } - if self.free_ptr < self.buf.len() / 2 { - self.last_live = self.free_ptr; - } else { - self.last_live = self.free_ptr - self.buf.len() / 2; - } + self.last_live = self.size(); } fn more_space(&mut self, size_hint: usize) { - let current_size = self.buf.len() / 2; - let mut new_size = current_size * 2; + let mut new_size = self.buf.len() / 2; if new_size == 0 { new_size = 1; } - while new_size <= current_size + size_hint { + while new_size < self.free_ptr + size_hint { new_size *= 2; } - let active; - if self.free_ptr < current_size { - active = &self.buf[..current_size]; - } else { - active = &self.buf[current_size..]; - self.free_ptr -= current_size; - } - - let mut new_buf = Vec::with_capacity(new_size * 2); - new_buf.extend_from_slice(active); - new_buf.resize(new_size * 2, 0); - self.buf = new_buf; + self.first_active = true; + self.buf.resize(new_size * 2, 0); } pub fn alloc(&mut self, size: i64) -> Result<usize, Box<dyn Error>> { @@ -116,8 +114,8 @@ impl Heap { } let usize = usize::try_from(size).expect("32 bits in 2024 LULW"); self.collect_garbage(); - if self.free_ptr + usize + 1 >= self.buf.len() / 2 { - self.more_space(usize); + if self.size() + usize + 1 > self.buf.len() / 2 { + self.more_space(usize + 1); } let p = self.simple_alloc(usize::try_from(size).expect("using 32 bits in 2024 LULW")); diff --git a/bytecode/src/value.rs b/bytecode/src/value.rs index fbaa128..1b49d0f 100644 --- a/bytecode/src/value.rs +++ b/bytecode/src/value.rs @@ -1,4 +1,4 @@ -#[derive(Clone, Copy)] +#[derive(Debug, Clone, Copy)] pub struct Value(pub u64); impl Value { |
