From a5b6f28167f0b432a50b11f3c89216584b531dae Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Mon, 10 Sep 2018 23:40:06 -0400 Subject: [PATCH 1/6] Cache imported modules in sys.modules --- vm/src/import.rs | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/vm/src/import.rs b/vm/src/import.rs index 67824f0e3..3bf0d8e2b 100644 --- a/vm/src/import.rs +++ b/vm/src/import.rs @@ -13,13 +13,7 @@ use super::compile; use super::pyobject::{DictProtocol, PyObjectKind, PyResult}; use super::vm::VirtualMachine; -fn import_module(vm: &mut VirtualMachine, module: &String) -> PyResult { - // First, see if we already loaded the module: - let sys_modules = vm.sys_module.get_item("modules").unwrap(); - if let Some(module) = sys_modules.get_item(module) { - return Ok(module); - } - +fn import_uncached_module(vm: &mut VirtualMachine, module: &String) -> PyResult { // Check for Rust-native modules if let Some(module) = vm.stdlib_inits.get(module) { return Ok(module(&vm.ctx).clone()); @@ -56,8 +50,18 @@ fn import_module(vm: &mut VirtualMachine, module: &String) -> PyResult { Ok(_) => {} Err(value) => return Err(value), } - let py_module = vm.ctx.new_module(module, scope); - Ok(py_module) + Ok(vm.ctx.new_module(module, scope)) +} + +fn import_module(vm: &mut VirtualMachine, module_name: &String) -> PyResult { + // First, see if we already loaded the module: + let sys_modules = vm.sys_module.get_item("modules").unwrap(); + if let Some(module) = sys_modules.get_item(module_name) { + return Ok(module); + } + let module = import_uncached_module(vm, module_name)?; + sys_modules.set_item(module_name, module.clone()); + Ok(module) } pub fn import(vm: &mut VirtualMachine, module_name: &String, symbol: &Option) -> PyResult { From c5e36e8530250465cd61edd40378f7396b926d2d Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Tue, 28 Aug 2018 16:57:36 -0400 Subject: [PATCH 2/6] Ignore clippy warnings in lalrpop generated code --- parser/src/python.lalrpop | 2 ++ 1 file changed, 2 insertions(+) diff --git a/parser/src/python.lalrpop b/parser/src/python.lalrpop index 98170ca04..9596f3d13 100644 --- a/parser/src/python.lalrpop +++ b/parser/src/python.lalrpop @@ -1,4 +1,6 @@ // See also: file:///usr/share/doc/python/html/reference/grammar.html?highlight=grammar +#![allow(unknown_lints,clippy)] + use super::ast; use super::lexer; use std::iter::FromIterator; From ea7f6b4d37bd75f3e1df4792bc0820690db5231e Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Tue, 28 Aug 2018 16:59:32 -0400 Subject: [PATCH 3/6] Pass a string slice around in main.rs We only need to convert it to a String once we're passing it in to compile::compile. --- src/main.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 36c11400e..194cef3bd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,9 +50,14 @@ fn main() { } } -fn _run_string(source: &String, source_path: Option) { +fn _run_string(source: &str, source_path: Option) { let mut vm = VirtualMachine::new(); - let code_obj = compile::compile(&mut vm, &source, compile::Mode::Exec, source_path).unwrap(); + let code_obj = compile::compile( + &mut vm, + &source.to_string(), + compile::Mode::Exec, + source_path, + ).unwrap(); debug!("Code object: {:?}", code_obj.borrow()); let builtins = vm.get_builtin_scope(); let vars = vm.context().new_scope(Some(builtins)); // Keep track of local variables @@ -74,7 +79,7 @@ fn run_command(source: &mut String) { _run_string(source, None) } -fn run_script(script_file: &String) { +fn run_script(script_file: &str) { debug!("Running file {}", script_file); // Parse an ast from it: let filepath = Path::new(script_file); @@ -87,8 +92,8 @@ fn run_script(script_file: &String) { } } -fn shell_exec(vm: &mut VirtualMachine, source: &String, scope: PyObjectRef) -> bool { - match compile::compile(vm, source, compile::Mode::Single, None) { +fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> bool { + match compile::compile(vm, &source.to_string(), compile::Mode::Single, None) { Ok(code) => { match vm.run_code_obj(code, scope.clone()) { Ok(_value) => { From d88917f5a2f7e0cff11781738807eb042feb1436 Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Tue, 28 Aug 2018 17:00:17 -0400 Subject: [PATCH 4/6] Remove needless clone of scope in main.rs --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 194cef3bd..9722735bf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,7 +95,7 @@ fn run_script(script_file: &str) { fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> bool { match compile::compile(vm, &source.to_string(), compile::Mode::Single, None) { Ok(code) => { - match vm.run_code_obj(code, scope.clone()) { + match vm.run_code_obj(code, scope) { Ok(_value) => { // Printed already. } From 5a680053886f07538eb06ca41ea74caafaad1693 Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Tue, 28 Aug 2018 17:04:57 -0400 Subject: [PATCH 5/6] Remove needless .ok() calls in main.rs --- src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9722735bf..fc6c285d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,7 +119,7 @@ fn shell_exec(vm: &mut VirtualMachine, source: &str, scope: PyObjectRef) -> bool fn read_until_empty_line(input: &mut String) -> Result { loop { print!("..... "); - io::stdout().flush().ok().expect("Could not flush stdout"); + io::stdout().flush().expect("Could not flush stdout"); let mut line = String::new(); match io::stdin().read_line(&mut line) { Ok(0) => { @@ -151,7 +151,7 @@ fn run_shell() { let mut input = String::new(); loop { print!(">>>>> "); // Use 5 items. pypy has 4, cpython has 3. - io::stdout().flush().ok().expect("Could not flush stdout"); + io::stdout().flush().expect("Could not flush stdout"); match io::stdin().read_line(&mut input) { Ok(0) => { break; From 5a27e34e4c38486050cf5ea5d2ed85e7e53efa2f Mon Sep 17 00:00:00 2001 From: Daniel Watkins Date: Mon, 10 Sep 2018 23:47:55 -0400 Subject: [PATCH 6/6] Pass label by value to VirtualMachine.jump() Per [0], this is more efficient for usize. [0] https://rust-lang-nursery.github.io/rust-clippy/v0.0.212/index.html#trivially_copy_pass_by_ref --- vm/src/vm.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/vm/src/vm.rs b/vm/src/vm.rs index d01309a18..1286f2d03 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -193,7 +193,7 @@ impl VirtualMachine { match block { Some(Block::TryExcept { handler }) => { self.push_value(exc); - self.jump(&handler); + self.jump(handler); return None; } Some(_) => {} @@ -866,7 +866,7 @@ impl VirtualMachine { } else { panic!("Wrong block type") }; - self.jump(&end_label); + self.jump(end_label); None } else { Some(Err(next_error)) @@ -939,7 +939,7 @@ impl VirtualMachine { } } bytecode::Instruction::Jump { target } => { - self.jump(target); + self.jump(*target); None } bytecode::Instruction::JumpIf { target } => { @@ -947,7 +947,7 @@ impl VirtualMachine { match objbool::boolval(self, obj) { Ok(value) => { if value { - self.jump(target); + self.jump(*target); } None } @@ -960,7 +960,7 @@ impl VirtualMachine { match objbool::boolval(self, obj) { Ok(value) => { if !value { - self.jump(target); + self.jump(*target); } None } @@ -994,7 +994,7 @@ impl VirtualMachine { bytecode::Instruction::Break => { let block = self.unwind_loop(); if let Block::Loop { start: _, end } = block { - self.jump(&end); + self.jump(end); } None } @@ -1005,7 +1005,7 @@ impl VirtualMachine { bytecode::Instruction::Continue => { let block = self.unwind_loop(); if let Block::Loop { start, end: _ } = block { - self.jump(&start); + self.jump(start); } else { assert!(false); } @@ -1065,9 +1065,9 @@ impl VirtualMachine { } } - fn jump(&mut self, label: &bytecode::Label) { + fn jump(&mut self, label: bytecode::Label) { let current_frame = self.current_frame_mut(); - let target_pc = current_frame.code.label_map[label]; + let target_pc = current_frame.code.label_map[&label]; trace!( "program counter from {:?} to {:?}", current_frame.lasti,