Skip to content

Commit

Permalink
Store a vm in the runtime. This improves performance on multiple vm r…
Browse files Browse the repository at this point in the history
…uns considerably.
  • Loading branch information
Ivorforce committed Jul 18, 2024
1 parent ce2ac8e commit e64c0b1
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 26 deletions.
10 changes: 3 additions & 7 deletions src/interpreter/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(())
Expand Down Expand Up @@ -49,13 +47,11 @@ pub fn transpile(module: &Module, runtime: &mut Runtime) -> RResult<Box<Transpil
// Set the transpiler object.
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![Value { u8: 0 }])?;
runtime.vm.run(compiled, &runtime.compile_server, vec![Value { u8: 0 }], &mut std::io::stdout())?;
}

let exported_artifacts = gather_functions_logic(runtime, &vm.transpile_functions);
let exported_artifacts = gather_functions_logic(runtime, &runtime.vm.transpile_functions);

Ok(Box::new(Transpiler {
// TODO This should be one of the exported artifacts
Expand Down
7 changes: 3 additions & 4 deletions src/interpreter/runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub struct Runtime {
pub traits: Option<builtins::traits::Traits>,

pub compile_server: CompileServer,
pub vm: VM,

// These remain unchanged after resolution.
pub source: Source,
Expand All @@ -42,6 +43,7 @@ impl Runtime {
primitives: None,
traits: None,
compile_server: CompileServer::new(),
vm: VM::new(),
source: Source::new(),
repository: Repository::new(),
});
Expand Down Expand Up @@ -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<u8> = 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())?)
Expand Down
11 changes: 4 additions & 7 deletions src/interpreter/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ mod tests {
chunk.push(OpCode::RETURN);

let mut out: Vec<u8> = 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); }

Expand All @@ -57,9 +56,8 @@ mod tests {
let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?;

let mut out: Vec<u8> = 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())
Expand Down Expand Up @@ -161,9 +159,8 @@ mod tests {
let compiled = runtime.compile_server.compile_deep(&runtime.source, entry_function)?;

let mut out: Vec<u8> = 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 {
Expand All @@ -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(())
Expand Down
15 changes: 7 additions & 8 deletions src/interpreter/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ 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;
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<Value>,
pub transpile_functions: Vec<Uuid>,
pub call_frames: Vec<CallFrame>,
Expand All @@ -28,18 +28,17 @@ pub unsafe fn to_str_ptr<A: ToString>(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![],
call_frames: Default::default(),
}
}

pub fn run(&mut self, initial_chunk: Rc<Chunk>, runtime: &mut Runtime, parameters: Vec<Value>) -> RResult<Option<Value>> {
pub fn run(&mut self, initial_chunk: Rc<Chunk>, compile_server: &CompileServer, parameters: Vec<Value>, pipe_out: &mut dyn std::io::Write) -> RResult<Option<Value>> {
unsafe {
let mut sp: *mut Value = &mut self.stack[0] as *mut Value;
for parameter in parameters {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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 => {
Expand Down

0 comments on commit e64c0b1

Please sign in to comment.