From e64c0b11c3f1c4b740071955245edf1da100dbe9 Mon Sep 17 00:00:00 2001 From: Lukas Tenbrink Date: Thu, 18 Jul 2024 20:28:07 +0200 Subject: [PATCH] Store a vm in the runtime. This improves performance on multiple vm runs considerably. --- src/interpreter/run.rs | 10 +++------- src/interpreter/runtime.rs | 7 +++---- src/interpreter/tests.rs | 11 ++++------- src/interpreter/vm.rs | 15 +++++++-------- 4 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/interpreter/run.rs b/src/interpreter/run.rs index 8b396b2..e14ceeb 100644 --- a/src/interpreter/run.rs +++ b/src/interpreter/run.rs @@ -17,10 +17,8 @@ pub fn main(module: &Module, runtime: &mut Runtime) -> RResult<()> { // TODO Should gather all used functions and compile them let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?; - let mut out = std::io::stdout(); - let mut vm = VM::new(&mut out); unsafe { - vm.run(compiled, runtime, vec![])?; + runtime.vm.run(compiled, &runtime.compile_server, vec![], &mut std::io::stdout())?; } Ok(()) @@ -49,13 +47,11 @@ pub fn transpile(module: &Module, runtime: &mut Runtime) -> RResult, pub compile_server: CompileServer, + pub vm: VM, // These remain unchanged after resolution. pub source: Source, @@ -42,6 +43,7 @@ impl Runtime { primitives: None, traits: None, compile_server: CompileServer::new(), + vm: VM::new(), source: Source::new(), repository: Repository::new(), }); @@ -138,10 +140,7 @@ impl Runtime { self.source.fn_logic.insert(Rc::clone(&dummy_head), FunctionLogic::Implementation(implementation)); let compiled = self.compile_server.compile_deep(&self.source, &dummy_head)?; - - let mut out: Vec = vec![]; - let mut vm = VM::new(&mut out); - let result = vm.run(compiled, self, vec![])?; + let result = self.vm.run(compiled, &self.compile_server, vec![], &mut std::io::stdout())?; // We know by now that the expression is supposed to evaluate to something. return Ok(result.ok_or(RuntimeError::error("").to_array())?) diff --git a/src/interpreter/tests.rs b/src/interpreter/tests.rs index bce548f..f0b9f49 100644 --- a/src/interpreter/tests.rs +++ b/src/interpreter/tests.rs @@ -37,8 +37,7 @@ mod tests { chunk.push(OpCode::RETURN); let mut out: Vec = vec![]; - let mut vm = VM::new(&mut out); - let result = vm.run(Rc::new(chunk), &mut runtime, vec![])?; + let result = runtime.vm.run(Rc::new(chunk), &runtime.compile_server, vec![], &mut out)?; unsafe { assert_eq!(result.unwrap().bool, true); } @@ -57,9 +56,8 @@ mod tests { let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?; let mut out: Vec = vec![]; - let mut vm = VM::new(&mut out); unsafe { - vm.run(compiled, &mut runtime, vec![])?; + runtime.vm.run(compiled, &runtime.compile_server, vec![], &mut out)?; } Ok(std::str::from_utf8(&out).unwrap().to_string()) @@ -161,9 +159,8 @@ mod tests { let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?; let mut out: Vec = vec![]; - let mut vm = VM::new(&mut out); unsafe { - let result = vm.run(compiled, &mut runtime, vec![]); + let result = runtime.vm.run(compiled, &runtime.compile_server, vec![], &mut out); assert_eq!(std::str::from_utf8(&out).unwrap().to_string(), "Assertion failure.\n"); if let Ok(_) = result { @@ -190,7 +187,7 @@ mod tests { unsafe { let uuid = *(result.ptr as *mut Uuid); - assert_eq!(uuid, runtime.traits.unwrap().String.id); + assert_eq!(uuid, runtime.traits.as_ref().unwrap().String.id); } Ok(()) diff --git a/src/interpreter/vm.rs b/src/interpreter/vm.rs index 062a85d..82aca7a 100644 --- a/src/interpreter/vm.rs +++ b/src/interpreter/vm.rs @@ -9,6 +9,7 @@ use uuid::Uuid; use crate::error::{RResult, RuntimeError}; use crate::interpreter::chunks::Chunk; +use crate::interpreter::compile::compile_server::CompileServer; use crate::interpreter::data::{string_to_ptr, Value}; use crate::interpreter::opcode::{OpCode, Primitive}; use crate::interpreter::runtime::Runtime; @@ -16,8 +17,7 @@ use crate::interpreter::vm::call_frame::CallFrame; pub mod call_frame; -pub struct VM<'b> { - pub pipe_out: &'b mut dyn std::io::Write, +pub struct VM { pub stack: Vec, pub transpile_functions: Vec, pub call_frames: Vec, @@ -28,10 +28,9 @@ pub unsafe fn to_str_ptr(a: A) -> *mut () { string_to_ptr(&string) } -impl<'b> VM<'b> { - pub fn new(pipe_out: &'b mut dyn std::io::Write) -> VM<'b> { +impl VM { + pub fn new() -> VM { VM { - pipe_out, // TODO This should dynamically resize probably. stack: vec![Value::alloc(); 1024 * 1024], transpile_functions: vec![], @@ -39,7 +38,7 @@ impl<'b> VM<'b> { } } - pub fn run(&mut self, initial_chunk: Rc, runtime: &mut Runtime, parameters: Vec) -> RResult> { + pub fn run(&mut self, initial_chunk: Rc, compile_server: &CompileServer, parameters: Vec, pipe_out: &mut dyn std::io::Write) -> RResult> { unsafe { let mut sp: *mut Value = &mut self.stack[0] as *mut Value; for parameter in parameters { @@ -85,7 +84,7 @@ impl<'b> VM<'b> { }, OpCode::CALL => { let uuid = Uuid::from_u128(pop_ip!(u128)); - let chunk = Rc::clone(&runtime.compile_server.function_evaluators[&uuid]); + let chunk = Rc::clone(&compile_server.function_evaluators[&uuid]); self.call_frames.push(CallFrame { chunk: current_chunk, fp, @@ -333,7 +332,7 @@ impl<'b> VM<'b> { OpCode::PRINT => { // TODO Shouldn't need to copy it let string: String = read_unaligned(pop_sp!().ptr as *mut String); - writeln!(self.pipe_out, "{}", string) + writeln!(pipe_out, "{}", string) .map_err(|e| RuntimeError::error(&e.to_string()).to_array())?; } OpCode::NEG => {