From 11fd5b6cbc19189cef115b03ecec632b7067f68a Mon Sep 17 00:00:00 2001 From: _ <_@_> Date: Mon, 2 Oct 2023 18:20:03 -0500 Subject: [PATCH] :construction: wip: always keep at least one stack frame handy This removes a bunch of unwraps but doesn't make it any faster --- lunar_wave_vm/src/state.rs | 166 +++++++++++++++---------------------- 1 file changed, 66 insertions(+), 100 deletions(-) diff --git a/lunar_wave_vm/src/state.rs b/lunar_wave_vm/src/state.rs index 5a5d9d0..23bf773 100644 --- a/lunar_wave_vm/src/state.rs +++ b/lunar_wave_vm/src/state.rs @@ -26,7 +26,7 @@ pub struct Chunk { pub blocks: Vec , } -#[derive (Clone, Debug, Default)] +#[derive (Clone, Copy, Debug, Default)] pub struct StackFrame { // Starts at 0 right after OP_CALL @@ -50,15 +50,12 @@ pub struct State { // Currently only used for native function calls top: usize, pub stack: Vec , + stack_top: StackFrame, pub debug_print: bool, - step_count: u32, chunk: Chunk, pub upvalues: Vec , pub si: Interner, - register_offset: usize, - block_idx: usize, - next_pc: usize, } fn lw_io_write (l: &mut State, num_args: usize) -> usize { @@ -188,17 +185,12 @@ impl State { // idk 10,000. I thought it was fixed at 256. registers: vec! [Value::Nil; 256], top: 0, - stack: vec! [ - StackFrame::default (), - ], + stack: vec! [], + stack_top: Default::default (), debug_print: false, - step_count: 0, chunk, upvalues, si: Default::default (), - register_offset: 0, - block_idx: 0, - next_pc: 0, } } @@ -210,22 +202,17 @@ impl State { // idk 10,000. I thought it was fixed at 256. registers: vec! [Value::Nil; 256], top: 0, - stack: vec! [ - StackFrame::default (), - ], + stack: vec! [], + stack_top: Default::default (), debug_print: false, - step_count: 0, chunk, upvalues, si, - register_offset: 0, - block_idx: 0, - next_pc: 0, } } pub fn at_breakpoint (&self, bp: &Breakpoint) -> bool { - let frame = self.stack.last ().unwrap (); + let frame = &self.stack_top; frame.block_idx == bp.block_idx && frame.program_counter == bp.program_counter } @@ -267,29 +254,29 @@ impl State { } fn register_window (&self) -> &[Value] { - let frame = self.stack.last ().unwrap (); + let frame = &self.stack_top; &self.registers [frame.register_offset..] } /// Short form to get access to a register within our window pub fn reg (&self, i: u8) -> &Value { - &self.registers [self.register_offset + i as usize] + &self.registers [self.stack_top.register_offset + i as usize] } pub fn reg_mut (&mut self, i: u8) -> &mut Value { - &mut self.registers [self.register_offset + i as usize] + &mut self.registers [self.stack_top.register_offset + i as usize] } // For native functions to check how many args they got pub fn get_top (&self) -> usize { - self.top - self.stack.last ().unwrap ().register_offset + self.top - self.stack_top.register_offset } fn make_step_error (&self, msg: &'static str, inst: &Instruction) -> StepError { StepError::Generic { - frame: self.stack.last ().unwrap ().clone (), + frame: self.stack_top.clone (), inst: inst.clone (), msg, } @@ -332,35 +319,31 @@ impl State { let target_block = idx; - let new_frame = StackFrame { + self.stack.push (self.stack_top); + self.stack_top = StackFrame { program_counter: 0, block_idx: target_block, - register_offset: self.register_offset + a as usize + 1, + register_offset: self.stack_top.register_offset + a as usize + 1, }; - self.next_pc = 0; - self.block_idx = target_block; - self.register_offset = new_frame.register_offset; - - self.stack.push (new_frame); - // Skip the PC increment at the bottom of the loop return true; }, Value::RsFunc (x) => { - let old_offset = self.register_offset; - self.register_offset = old_offset + usize::from (a) + 1; + let old_offset = self.stack_top.register_offset; + self.stack_top.register_offset = old_offset + usize::from (a) + 1; // Trash the stack frame so it doesn't point to a // valid Lua function - self.stack.push (StackFrame { + self.stack.push (self.stack_top); + self.stack_top = StackFrame { program_counter: 65535, // Bogus for native functions block_idx: 65535, // Bogus - register_offset: self.register_offset, - }); + register_offset: self.stack_top.register_offset, + }; let num_args = if b == 0 { - self.top - self.register_offset + self.top - self.stack_top.register_offset } else { b - 1 @@ -369,8 +352,9 @@ impl State { // Call let num_results = x (self, num_args); - let popped_frame = self.stack.pop ().unwrap (); - self.register_offset = old_offset; + let popped_frame = self.stack_top; + self.stack_top = self.stack.pop ().unwrap (); + self.stack_top.register_offset = old_offset; let offset = old_offset + usize::from (a); for i in (offset)..(offset + usize::try_from (num_results).unwrap ()) { @@ -406,7 +390,7 @@ impl State { } fn op_get_field (&mut self, a: u8, b: u8, c: u8) { - let block = self.chunk.blocks.get (self.block_idx).unwrap (); + let block = self.chunk.blocks.get (self.stack_top.block_idx).unwrap (); let constants = &block.constants; let key = match &constants [usize::from (c)] { @@ -414,7 +398,7 @@ impl State { _ => panic! ("K[C] must be a string"), }; - let val = match &self.registers [self.register_offset + usize::from (b)] { + let val = match &self.registers [self.stack_top.register_offset + usize::from (b)] { Value::Nil => panic! ("R[B] must not be nil"), Value::Table (t) => t.borrow ().get_str (*key).clone (), _ => panic! ("R[B] must be a table"), @@ -464,7 +448,7 @@ impl State { } fn op_set_field (&mut self, a: u8, b: u8, c: u8, k: bool) { - let frame = self.stack.last ().unwrap (); + let frame = &self.stack_top; let block = self.chunk.blocks.get (frame.block_idx).unwrap (); let constants = &block.constants; @@ -505,11 +489,11 @@ impl State { pub fn step (&mut self) -> Result