From 88fa78d4c93ce07e6323d41788c278f0a56fbee7 Mon Sep 17 00:00:00 2001 From: Miguel Liezun Date: Sun, 14 Jan 2024 15:22:13 -0300 Subject: [PATCH] Speedup function calling by using RC --- Cargo.lock | 45 +++++++++++++++++++++++++++++++++++++++++++ src/interpreter.rs | 48 +++++++++++++++++++++++++++++++++------------- src/vm.rs | 27 +++++++++++++------------- 3 files changed, 94 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ea2a6a..b595bd7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + [[package]] name = "bincode" version = "1.3.3" @@ -16,6 +25,7 @@ name = "grotsky-rs" version = "0.0.8" dependencies = [ "bincode", + "regex", "serde", "socket2", ] @@ -26,6 +36,12 @@ version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "memchr" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" + [[package]] name = "proc-macro2" version = "1.0.69" @@ -44,6 +60,35 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "serde" version = "1.0.190" diff --git a/src/interpreter.rs b/src/interpreter.rs index 1beb9bf..88b35f5 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -1,7 +1,8 @@ -use crate::vm::StackEntry; +use crate::vm::{StackEntry, VMFnPrototype}; use crate::{compiler, lexer, native, parser, state, stmt, value, vm}; use std::collections::{HashMap, HashSet}; use std::panic; +use std::rc::Rc; static mut ABSOLUTE_PATH: &'static str = ""; @@ -40,9 +41,9 @@ fn setup_global_interpreter() { globals: HashSet::new(), }; let mut my_vm = vm::VM { - instructions: vec![], - instructions_data: vec![], - prototypes: vec![], + instructions: Rc::new(vec![]), + instructions_data: Rc::new(vec![]), + prototypes: Rc::new(vec![]), constants: vec![], globals: HashMap::new(), builtins: HashMap::new(), @@ -132,9 +133,16 @@ pub fn run_interpreter_from_bytecode(bytecode: &[u8]) -> bool { .map(|c| c.instructions.clone()) .flatten() .collect(); - interpreter.vm.instructions = instructions.iter().map(|i| i.inst.clone()).collect(); - interpreter.vm.instructions_data = instructions.iter().map(|i| i.src.clone()).collect(); - interpreter.vm.prototypes = interpreter.compiler.prototypes.clone(); + interpreter.vm.instructions = Rc::new(instructions.iter().map(|i| i.inst.clone()).collect()); + interpreter.vm.instructions_data = Rc::new(instructions.iter().map(|i| i.src.clone()).collect()); + interpreter.vm.prototypes = Rc::new(interpreter.compiler.prototypes.iter().map(|p| VMFnPrototype{ + instructions: Rc::new(p.instructions.clone()), + register_count: p.register_count, + upvalues: p.upvalues.clone(), + instruction_data: Rc::new(p.instruction_data.clone()), + param_count: p.param_count, + name: p.name.clone(), + }).collect()); interpreter.vm.constants = interpreter .compiler .constants @@ -165,9 +173,16 @@ pub fn run_bytecode_interpreter(source: String) { .map(|c| c.instructions.clone()) .flatten() .collect(); - interpreter.vm.instructions = instructions.iter().map(|i| i.inst.clone()).collect(); - interpreter.vm.instructions_data = instructions.iter().map(|i| i.src.clone()).collect(); - interpreter.vm.prototypes = interpreter.compiler.prototypes.clone(); + interpreter.vm.instructions = Rc::new(instructions.iter().map(|i| i.inst.clone()).collect()); + interpreter.vm.instructions_data = Rc::new(instructions.iter().map(|i| i.src.clone()).collect()); + interpreter.vm.prototypes = Rc::new(interpreter.compiler.prototypes.iter().map(|p| VMFnPrototype{ + instructions: Rc::new(p.instructions.clone()), + register_count: p.register_count, + upvalues: p.upvalues.clone(), + instruction_data: Rc::new(p.instruction_data.clone()), + param_count: p.param_count, + name: p.name.clone(), + }).collect()); interpreter.vm.constants = interpreter .compiler .constants @@ -210,9 +225,16 @@ pub fn import_module(source: String) -> HashMap { .map(|c| c.instructions.clone()) .flatten() .collect(); - interpreter.vm.instructions = instructions.iter().map(|i| i.inst.clone()).collect(); - interpreter.vm.instructions_data = instructions.iter().map(|i| i.src.clone()).collect(); - interpreter.vm.prototypes = interpreter.compiler.prototypes.clone(); + interpreter.vm.instructions = Rc::new(instructions.iter().map(|i| i.inst.clone()).collect()); + interpreter.vm.instructions_data = Rc::new(instructions.iter().map(|i| i.src.clone()).collect()); + interpreter.vm.prototypes = Rc::new(interpreter.compiler.prototypes.iter().map(|p| VMFnPrototype{ + instructions: Rc::new(p.instructions.clone()), + register_count: p.register_count, + upvalues: p.upvalues.clone(), + instruction_data: Rc::new(p.instruction_data.clone()), + param_count: p.param_count, + name: p.name.clone(), + }).collect()); interpreter.vm.constants = interpreter .compiler .constants diff --git a/src/vm.rs b/src/vm.rs index 2b4ab76..d4c1f94 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use crate::compiler::FnPrototype; +use crate::compiler::UpvalueRef; use crate::errors::*; use crate::instruction::*; use crate::interpreter; @@ -67,7 +67,6 @@ macro_rules! make_call { $instructions = prototype.instructions.clone(); $pc = 0; // Point to new instructions metadata - // TODO: use reference instead of cloning $self.instructions_data = prototype.instruction_data.clone(); }}; } @@ -93,11 +92,9 @@ macro_rules! throw_exception { if let Some(func) = &stack.function { let proto = &$self.prototypes[func.0.borrow().prototype as usize]; - // TODO: use reference instead of cloning $self.instructions = proto.instructions.clone(); $self.instructions_data = proto.instruction_data.clone(); } else { - // TODO: use reference instead of cloning $self.instructions = $original_instructions.clone(); $self.instructions_data = $original_instructions_data.clone(); } @@ -152,16 +149,26 @@ pub struct CatchException { exception: Option, } +#[derive(Debug)] +pub struct VMFnPrototype { + pub instructions: Rc>, + pub register_count: u8, + pub upvalues: Vec, + pub instruction_data: Rc>>, + pub param_count: usize, + pub name: String, +} + #[derive(Debug)] pub struct VM { - pub instructions: Vec, - pub prototypes: Vec, + pub instructions: Rc>, + pub prototypes: Rc>, pub constants: Vec, pub globals: HashMap, pub builtins: HashMap, pub stack: Vec, pub activation_records: Vec, - pub instructions_data: Vec>, + pub instructions_data: Rc>>, pub catch_exceptions: Vec, } @@ -351,16 +358,13 @@ impl VM { sp = stack.sp; if let Some(func) = &self.stack.last().unwrap().function { let proto = &self.prototypes[func.0.borrow().prototype as usize]; - // TODO: use reference instead of cloning self.instructions = proto.instructions.clone(); self.instructions_data = proto.instruction_data.clone(); } else { - // TODO: use reference instead of cloning self.instructions = original_instructions.clone(); self.instructions_data = original_instructions_data.clone(); } } - OpCode::Jmp => { pc = pc.wrapping_add(inst.sbx() as usize); } @@ -1013,7 +1017,6 @@ impl VM { sp, ERR_EXPECTED_STRING ); - unreachable!(); }; match val_b.get(prop) { Ok(v) => { @@ -1203,7 +1206,6 @@ impl VM { sp, ERR_EXPECTED_NUMBER ); - 0 }; match val_b.as_val() { Value::Dict(d) => { @@ -1269,7 +1271,6 @@ impl VM { sp, ERR_EXPECTED_NUMBER ); - 0 }; match val_b.as_val() { Value::Dict(d) => {