From 0c7d4d3bcf29e877c99ba21a80128a192a4d26ac Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Thu, 22 Aug 2024 16:22:27 -0500 Subject: [PATCH] one stack, but its somehow 2x slower --- kabel/Cargo.toml | 3 ++ kabel/src/codegen.rs | 8 ++-- kabel/src/macros.rs | 26 +++++------ kabel/src/vm.rs | 106 +++++++++++++++++++++++-------------------- 4 files changed, 76 insertions(+), 67 deletions(-) diff --git a/kabel/Cargo.toml b/kabel/Cargo.toml index 2d7329e786a8b8b44ac16b362c173f0347d63b1f..b665f5d2809d6e7ca8f430dcb22dfb23c87f92d3 100644 --- a/kabel/Cargo.toml +++ b/kabel/Cargo.toml @@ -12,3 +12,6 @@ timer = [] debug = ["debug_lexer", "debug_parser"] debug_lexer = [] debug_parser = [] + +[profile.release] +debug = true diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 93b1474e29e2fe93e4ddfb1e43f7841f200c1222..e6e068f73137e82d830afec145826763b917240b 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -143,22 +143,22 @@ impl Codegen { self.vm.ip = old_ip; } pub fn visit_return(&mut self, ast: &AST, expr: Option) { - let mut scopes = self.scopes.clone(); + /*let mut scopes = self.scopes.clone(); let mut pop_count = 0; - /*loop { + loop { let (scope_type, scope) = scopes.pop().expect("scopes empty in return"); pop_count += scope; if scope_type == ScopeType::Function { break; } - }*/ + } self.vm.units[self.vm.unit_ptr].code.push(OpCode::POP.into()); self.vm.units[self.vm.unit_ptr].code.push(pop_count as u8); if self.vm.units[self.vm.unit_ptr].lines.last().unwrap().0 != ast.end_line { self.vm.units[self.vm.unit_ptr].lines.push((ast.end_line, 2)); } else { self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 2; - } + }*/ if let Some(expr) = expr { self.visit(expr); diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 7d663edf2b01475c77ad03965bc42f834170d85d..8f74e8197ff61c717d49a8c7b4804695fa409b51 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -301,13 +301,13 @@ macro_rules! push_codegen { #[macro_export] macro_rules! vm_boolean_equality { ($self:expr, $oper:tt) => { - match ($self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))), - $self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) { - (Num(v1), Num(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)), - (Str(v1), Str(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)), - (Bool(v1), Bool(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)), - (Null, Null) => $self.stacks[$self.stack_ptr].push(Bool(true)), - (_v1, _v2) => $self.stacks[$self.stack_ptr].push(Bool(false)), + match ($self.stack.pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))), + $self.stack.pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) { + (Num(v1), Num(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Str(v1), Str(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Bool(v1), Bool(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Null, Null) => $self.stack.push(Bool(true)), + (_v1, _v2) => $self.stack.push(Bool(false)), } }; } @@ -315,14 +315,14 @@ macro_rules! vm_boolean_equality { #[macro_export] macro_rules! vm_boolean_comparison { ($self:expr, $oper:tt) => { - match ($self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))), - $self.stacks[$self.stack_ptr].pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) { - (Num(v1), Num(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)), - (Str(v1), Str(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)), - (Bool(v1), Bool(v2)) => $self.stacks[$self.stack_ptr].push(Bool(v1 $oper v2)), + match ($self.stack.pop().expect(&("Couldn't pop left side of ".to_owned() + stringify!($oper))), + $self.stack.pop().expect(&("Couldn't pop right side of ".to_owned() + stringify!($oper)))) { + (Num(v1), Num(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Str(v1), Str(v2)) => $self.stack.push(Bool(v1 $oper v2)), + (Bool(v1), Bool(v2)) => $self.stack.push(Bool(v1 $oper v2)), (Null, _) => return Err(vm_error!($self, RuntimeErrorKind::WrongType, "Tried to perform comparison \"{}\" on value null", stringify!($tt))), (_, Null) => return Err(vm_error!($self, RuntimeErrorKind::WrongType, "Tried to perform comparison \"{}\" on value null", stringify!($tt))), - (_v1, _v2) => $self.stacks[$self.stack_ptr].push(Bool(false)), + (_v1, _v2) => $self.stack.push(Bool(false)), } }; } diff --git a/kabel/src/vm.rs b/kabel/src/vm.rs index 789896998d3a77006828813997b4c10ecf897187..424ed87f5834e9770a4708c9917fb794661bcc4b 100644 --- a/kabel/src/vm.rs +++ b/kabel/src/vm.rs @@ -30,9 +30,10 @@ pub struct VM { pub ip: usize, pub unit_ptr: usize, pub stack_ptr: usize, - pub call_stack: Vec<(usize, usize)>, // (unit_ptr, ip) + pub call_stack: Vec<(usize, usize, usize)>, // (unit_ptr, ip, stack_offset) pub units: Vec, - pub stacks: Vec>, + pub stack: Vec, + pub stack_offset: usize, text: Vec } @@ -43,9 +44,10 @@ impl VM { ip: 0, unit_ptr: 0, stack_ptr: 0, - call_stack: Vec::new(), + call_stack: vec![(0, 0, 0)], units: vec![Unit::new(bytecode, pool, lines)], - stacks: vec![Vec::new()], + stack: Vec::new(), + stack_offset: 0, text: text.lines().map(|s| s.to_string()).collect::>(), } } @@ -56,25 +58,28 @@ impl VM { 0x00 => { // LOAD let byte = self.read() as usize; let value = self.units[self.unit_ptr].pool[byte].clone(); - self.stacks[self.stack_ptr].push(value); + self.stack.push(value); } 0x01 => { // VAR let ptr = self.read() as usize; - let value = self.stacks[self.stack_ptr][ptr].clone(); - self.stacks[self.stack_ptr].push(value); + let value = self.stack[ptr+self.stack_offset].clone(); + //println!("offset {} ptr {}", offset, ptr); + //println!("stack {:?}", self.stack); + self.stack.push(value); } // ASSIGN 0x02 => { - let value = self.stacks[self.stack_ptr].pop().unwrap(); + let value = self.stack.pop().unwrap(); let ptr = self.read(); - self.stacks[self.stack_ptr][ptr as usize] = value.clone(); - self.stacks[self.stack_ptr].push(value); + let offset = self.call_stack.last().expect("var call stack last").2; + self.stack[ptr as usize + offset] = value.clone(); + self.stack.push(value); } 0x03 => { // ADD - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { - (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 + v2)), + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.stack.push(Num(v1 + v2)), (Str(v1), Str(v2)) => { - self.stacks[self.stack_ptr].push(Str(v1 + &v2)); + self.stack.push(Str(v1 + &v2)); }, (Bool(_v1), Bool(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot add booleans")) @@ -85,8 +90,8 @@ impl VM { } } 0x04 => { // SUB - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { - (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 - v2)), + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.stack.push(Num(v1 - v2)), (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot subtract strings")) }, @@ -99,11 +104,11 @@ impl VM { } } 0x05 => { // MUL - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { - (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 * v2)), + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.stack.push(Num(v1 * v2)), (Str(v1), Num(v2)) => { if v2.fract() == 0.0 { - self.stacks[self.stack_ptr].push(Str(v1.repeat(v2 as usize))); + self.stack.push(Str(v1.repeat(v2 as usize))); } else { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Number must be an integer")) } @@ -120,8 +125,8 @@ impl VM { } } 0x06 => { // DIV - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { - (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 / v2)), + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.stack.push(Num(v1 / v2)), (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot divide strings")) }, @@ -134,8 +139,8 @@ impl VM { } } 0x07 => { // MOD - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { - (Num(v1), Num(v2)) => self.stacks[self.stack_ptr].push(Num(v1 % v2)), + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { + (Num(v1), Num(v2)) => self.stack.push(Num(v1 % v2)), (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform modulus on strings")) }, @@ -148,7 +153,7 @@ impl VM { } } 0x08 => { // BITAND - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v1)) @@ -156,7 +161,7 @@ impl VM { if v2.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on {}", v2)) } - self.stacks[self.stack_ptr].push(Num((v1 as u32 & v2 as u32) as f32)) + self.stack.push(Num((v1 as u32 & v2 as u32) as f32)) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise AND on strings")) @@ -170,7 +175,7 @@ impl VM { } } 0x09 => { // BITXOR - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v1)) @@ -178,7 +183,7 @@ impl VM { if v2.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on {}", v2)) } - self.stacks[self.stack_ptr].push(Num((v1 as u32 ^ v2 as u32) as f32)) + self.stack.push(Num((v1 as u32 ^ v2 as u32) as f32)) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise XOR on strings")) @@ -192,7 +197,7 @@ impl VM { } } 0x0A => { // BITOR - match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { + match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(v1), Num(v2)) => { if v1.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v1)) @@ -200,7 +205,7 @@ impl VM { if v2.fract() != 0.0 { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on {}", v2)) } - self.stacks[self.stack_ptr].push(Num((v1 as u32 | v2 as u32) as f32)) + self.stack.push(Num((v1 as u32 | v2 as u32) as f32)) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Cannot perform bitwise OR on strings")) @@ -226,14 +231,14 @@ impl VM { // LE 0x10 => vm_boolean_comparison!(self, <=), // OR - 0x11 => match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { + 0x11 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean numbers")) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean strings")) }, - (Bool(v1), Bool(v2)) => self.stacks[self.stack_ptr].push(Bool(v1 || v2)), + (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 || v2)), (Null, _) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean value null")), (_, Null) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"||\" on non-boolean value null")), (v1, v2) => { @@ -241,14 +246,14 @@ impl VM { } } // AND - 0x12 => match (self.stacks[self.stack_ptr].pop().unwrap(), self.stacks[self.stack_ptr].pop().unwrap()) { + 0x12 => match (self.stack.pop().unwrap(), self.stack.pop().unwrap()) { (Num(_v1), Num(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean numbers")) } (Str(_v1), Str(_v2)) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean strings")) }, - (Bool(v1), Bool(v2)) => self.stacks[self.stack_ptr].push(Bool(v1 && v2)), + (Bool(v1), Bool(v2)) => self.stack.push(Bool(v1 && v2)), (Null, _) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean value null")), (_, Null) => return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"&&\" on non-boolean value null")), (v1, v2) => { @@ -256,7 +261,7 @@ impl VM { } } // NOT - 0x13 => match self.stacks[self.stack_ptr].pop().unwrap() { + 0x13 => match self.stack.pop().unwrap() { Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean value null")) } Num(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean number")) @@ -264,15 +269,15 @@ impl VM { Str(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean string")) } - Bool(v1) => self.stacks[self.stack_ptr].push(Bool(!v1)), + Bool(v1) => self.stack.push(Bool(!v1)), Fun(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"!\" on non-boolean function")) } } // NEG - 0x14 => match self.stacks[self.stack_ptr].pop().unwrap() { + 0x14 => match self.stack.pop().unwrap() { Null => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number value null")) } - Num(v1) => self.stacks[self.stack_ptr].push(Num(-v1)), + Num(v1) => self.stack.push(Num(-v1)), Str(_v1) => { return Err(vm_error!(self, RuntimeErrorKind::WrongType, "Tried to perform \"-\" on non-number string")) } @@ -295,7 +300,7 @@ impl VM { } // JNE 0x17 => { - let condition = self.stacks[self.stack_ptr].pop().unwrap(); + let condition = self.stack.pop().unwrap(); if let Value::Bool(condition) = condition { if !condition { let loc = self.read_u16(); @@ -311,18 +316,19 @@ impl VM { // CALL 0x18 => { let num_args = self.read(); - let function = self.stacks[self.stack_ptr].pop().expect("Stack was empty in call"); + let function = self.stack.pop().expect("Stack was empty in call"); if let Value::Fun(function) = function { - self.stacks.push(Vec::new()); if num_args as usize != function.arity { return Err(vm_error!(self, RuntimeErrorKind::IncorrectArity, "Function has {} arguments, {} provided", function.arity, num_args)) } - self.call_stack.push((self.unit_ptr, self.ip)); - self.stacks[self.stack_ptr+1].push(Value::Fun(function)); + self.stack_offset = self.stack.len()-1; + self.call_stack.push((self.unit_ptr, self.ip, self.stack_offset)); for _ in 0..num_args { - let arg = self.stacks[self.stack_ptr].pop().expect("Missing arguments in call"); - self.stacks[self.stack_ptr+1].push(arg); + let arg = self.stack.pop().expect("Missing arguments in call"); + self.stack.push(arg); } + self.stack.insert(self.stack.len()-num_args as usize, Value::Fun(function)); + //println!("stack call {:?}", self.stack); self.stack_ptr += 1; self.ip = 0; self.unit_ptr = function.unit_ptr as usize; @@ -332,25 +338,25 @@ impl VM { } // RET 0x19 => { - let (unit_ptr, ip) = self.call_stack.pop().expect("Call stack empty on RET"); - let ret = self.stacks[self.stack_ptr].pop().expect("Missing return value"); - //self.stacks[self.stack_ptr].clear(); + let (unit_ptr, ip, stack_offset) = self.call_stack.pop().expect("Call stack empty on RET"); + let ret = self.stack.pop().expect("Missing return value"); + self.stack = self.stack[..stack_offset].to_vec(); + self.stack_offset = self.call_stack.last().expect("call stack empty").2; self.unit_ptr = unit_ptr; self.ip = ip; // returned to code self.stack_ptr -= 1; - self.stacks.pop().expect("RET pop stacks failed"); - self.stacks[self.stack_ptr].push(ret); + self.stack.push(ret); } 0xFD => { // POP let times = self.read(); for _ in 0..times { - self.stacks[self.stack_ptr].pop().expect(&format!("{}: Unable to pop stack", self.ip)); + self.stack.pop().expect(&format!("{}: Unable to pop stack", self.ip)); } } 0xFE => { // PRINT - let value = self.stacks[self.stack_ptr].pop().unwrap(); + let value = self.stack.pop().unwrap(); match value { Null => *output += "null", Num(v) => *output += &v.to_string(),