summaryrefslogtreecommitdiffstats
path: root/bytecode
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2024-02-04 18:55:19 -0800
committerRose Hogenson <rosehogenson@posteo.net>2024-02-04 18:55:19 -0800
commit1a25a5cc66c8ae48bfd5569da04e9cfc8f9c3501 (patch)
treeed8e7e4abf54321279b7ecf8d1b976b751e32baf /bytecode
parent17face3633686e374aa0859271ccf462a48e60aa (diff)
downloadsml-1a25a5cc66c8ae48bfd5569da04e9cfc8f9c3501.tar.zst
Fix some bugs in the bytecode interpreter.
Diffstat (limited to 'bytecode')
-rw-r--r--bytecode/.encoding.c.swpbin12288 -> 0 bytes
-rw-r--r--bytecode/src/encoding.rs23
-rw-r--r--bytecode/src/heap.rs48
-rw-r--r--bytecode/src/value.rs2
4 files changed, 42 insertions, 31 deletions
diff --git a/bytecode/.encoding.c.swp b/bytecode/.encoding.c.swp
deleted file mode 100644
index fc8e88a..0000000
--- a/bytecode/.encoding.c.swp
+++ /dev/null
Binary files differ
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 {