Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions vm/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ fn builtin_sum(iterable: PyIterable, start: OptionalArg, vm: &VirtualMachine) ->

// Should be renamed to builtin___import__?
fn builtin_import(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
vm.invoke(&vm.import_func.borrow(), args)
vm.invoke(&vm.import_func, args)
}

fn builtin_vars(obj: OptionalArg, vm: &VirtualMachine) -> PyResult {
Expand All @@ -761,7 +761,7 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef) {
});
}

let debug_mode: bool = vm.settings.optimize == 0;
let debug_mode: bool = vm.state.settings.optimize == 0;
extend_module!(vm, module, {
"__debug__" => ctx.new_bool(debug_mode),
//set __name__ fixes: https://github.com/RustPython/RustPython/issues/146
Expand Down
13 changes: 6 additions & 7 deletions vm/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ use crate::vm::{InitParameter, VirtualMachine};
#[cfg(feature = "rustpython-compiler")]
use rustpython_compiler::compile;

pub fn init_importlib(vm: &VirtualMachine, initialize_parameter: InitParameter) -> PyResult {
pub fn init_importlib(vm: &mut VirtualMachine, initialize_parameter: InitParameter) -> PyResult {
flame_guard!("init importlib");
let importlib = import_frozen(vm, "_frozen_importlib")?;
let impmod = import_builtin(vm, "_imp")?;
let install = vm.get_attribute(importlib.clone(), "_install")?;
vm.invoke(&install, vec![vm.sys_module.clone(), impmod])?;
vm.import_func
.replace(vm.get_attribute(importlib.clone(), "__import__")?);
vm.import_func = vm.get_attribute(importlib.clone(), "__import__")?;

match initialize_parameter {
InitParameter::InitializeExternal if cfg!(feature = "rustpython-compiler") => {
Expand Down Expand Up @@ -58,16 +57,16 @@ pub fn init_importlib(vm: &VirtualMachine, initialize_parameter: InitParameter)
}

pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult {
vm.frozen
.borrow()
vm.state
.frozen
.get(module_name)
.ok_or_else(|| vm.new_import_error(format!("Cannot import frozen module {}", module_name)))
.and_then(|frozen| import_codeobj(vm, module_name, frozen.code.clone(), false))
}

pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult {
vm.stdlib_inits
.borrow()
vm.state
.stdlib_inits
.get(module_name)
.ok_or_else(|| vm.new_import_error(format!("Cannot import bultin module {}", module_name)))
.and_then(|make_module_func| {
Expand Down
14 changes: 7 additions & 7 deletions vm/src/stdlib/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ fn imp_lock_held(_vm: &VirtualMachine) -> PyResult<()> {
}

fn imp_is_builtin(name: PyStringRef, vm: &VirtualMachine) -> bool {
vm.stdlib_inits.borrow().contains_key(name.as_str())
vm.state.stdlib_inits.contains_key(name.as_str())
}

fn imp_is_frozen(name: PyStringRef, vm: &VirtualMachine) -> bool {
vm.frozen.borrow().contains_key(name.as_str())
vm.state.frozen.contains_key(name.as_str())
}

fn imp_create_builtin(spec: PyObjectRef, vm: &VirtualMachine) -> PyResult {
Expand All @@ -40,7 +40,7 @@ fn imp_create_builtin(spec: PyObjectRef, vm: &VirtualMachine) -> PyResult {

if let Ok(module) = sys_modules.get_item(name, vm) {
Ok(module)
} else if let Some(make_module_func) = vm.stdlib_inits.borrow().get(name) {
} else if let Some(make_module_func) = vm.state.stdlib_inits.get(name) {
Ok(make_module_func(vm))
} else {
Ok(vm.get_none())
Expand All @@ -53,8 +53,8 @@ fn imp_exec_builtin(_mod: PyModuleRef) -> i32 {
}

fn imp_get_frozen_object(name: PyStringRef, vm: &VirtualMachine) -> PyResult<PyCode> {
vm.frozen
.borrow()
vm.state
.frozen
.get(name.as_str())
.map(|frozen| {
let mut frozen = frozen.code.clone();
Expand All @@ -71,8 +71,8 @@ fn imp_init_frozen(name: PyStringRef, vm: &VirtualMachine) -> PyResult {
}

fn imp_is_frozen_package(name: PyStringRef, vm: &VirtualMachine) -> PyResult<bool> {
vm.frozen
.borrow()
vm.state
.frozen
.get(name.as_str())
.map(|frozen| frozen.package)
.ok_or_else(|| {
Expand Down
21 changes: 17 additions & 4 deletions vm/src/stdlib/signal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ fn assert_in_range(signum: i32, vm: &VirtualMachine) -> PyResult<()> {

fn signal(signalnum: i32, handler: PyObjectRef, vm: &VirtualMachine) -> PyResult {
assert_in_range(signalnum, vm)?;
let signal_handlers = vm
.signal_handlers
.as_ref()
.ok_or_else(|| vm.new_value_error("signal only works in main thread".to_owned()))?;

let sig_handler = match usize::try_from_object(vm, handler.clone()).ok() {
Some(SIG_DFL) => SIG_DFL,
Expand Down Expand Up @@ -68,15 +72,19 @@ fn signal(signalnum: i32, handler: PyObjectRef, vm: &VirtualMachine) -> PyResult

let mut old_handler = handler;
std::mem::swap(
&mut vm.signal_handlers.borrow_mut()[signalnum as usize],
&mut signal_handlers.borrow_mut()[signalnum as usize],
&mut old_handler,
);
Ok(old_handler)
}

fn getsignal(signalnum: i32, vm: &VirtualMachine) -> PyResult {
assert_in_range(signalnum, vm)?;
Ok(vm.signal_handlers.borrow()[signalnum as usize].clone())
let signal_handlers = vm
.signal_handlers
.as_ref()
.ok_or_else(|| vm.new_value_error("getsignal only works in main thread".to_owned()))?;
Ok(signal_handlers.borrow()[signalnum as usize].clone())
}

#[cfg(unix)]
Expand All @@ -91,13 +99,18 @@ fn alarm(time: u32) -> u32 {

#[cfg_attr(feature = "flame-it", flame)]
pub fn check_signals(vm: &VirtualMachine) -> PyResult<()> {
let signal_handlers = match vm.signal_handlers {
Some(ref h) => h.borrow(),
None => return Ok(()),
};

if !ANY_TRIGGERED.swap(false, Ordering::Relaxed) {
return Ok(());
}
for (signum, trigger) in TRIGGERS.iter().enumerate().skip(1) {
let triggerd = trigger.swap(false, Ordering::Relaxed);
if triggerd {
let handler = &vm.signal_handlers.borrow()[signum];
let handler = &signal_handlers[signum];
if vm.is_callable(handler) {
vm.invoke(handler, vec![vm.new_int(signum), vm.get_none()])?;
}
Expand Down Expand Up @@ -145,7 +158,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
} else {
vm.get_none()
};
vm.signal_handlers.borrow_mut()[signum] = py_handler;
vm.signal_handlers.as_ref().unwrap().borrow_mut()[signum] = py_handler;
}

signal(libc::SIGINT, int_handler, vm).expect("Failed to set sigint handler");
Expand Down
14 changes: 8 additions & 6 deletions vm/src/sysmodule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use crate::vm::{PySettings, VirtualMachine};

fn argv(vm: &VirtualMachine) -> PyObjectRef {
vm.ctx.new_list(
vm.settings
vm.state
.settings
.argv
.iter()
.map(|arg| vm.new_str(arg.to_owned()))
Expand Down Expand Up @@ -150,7 +151,7 @@ fn update_use_tracing(vm: &VirtualMachine) {
let trace_is_none = vm.is_none(&vm.trace_func.borrow());
let profile_is_none = vm.is_none(&vm.profile_func.borrow());
let tracing = !(trace_is_none && profile_is_none);
vm.use_tracing.replace(tracing);
vm.use_tracing.set(tracing);
}

fn sys_getrecursionlimit(vm: &VirtualMachine) -> usize {
Expand Down Expand Up @@ -225,7 +226,7 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef, builtins: PyObjectR
let ctx = &vm.ctx;

let flags_type = SysFlags::make_class(ctx);
let flags = SysFlags::from_settings(&vm.settings)
let flags = SysFlags::from_settings(&vm.state.settings)
.into_struct_sequence(vm, flags_type)
.unwrap();

Expand All @@ -246,7 +247,8 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef, builtins: PyObjectR
});

let path = ctx.new_list(
vm.settings
vm.state
.settings
.path_list
.iter()
.map(|path| ctx.new_str(path.clone()))
Expand Down Expand Up @@ -348,7 +350,7 @@ setprofile() -- set the global profiling function
setrecursionlimit() -- set the max recursion depth for the interpreter
settrace() -- set the global debug tracing function
";
let mut module_names: Vec<String> = vm.stdlib_inits.borrow().keys().cloned().collect();
let mut module_names: Vec<String> = vm.state.stdlib_inits.keys().cloned().collect();
module_names.push("sys".to_owned());
module_names.push("builtins".to_owned());
module_names.sort();
Expand Down Expand Up @@ -399,7 +401,7 @@ settrace() -- set the global debug tracing function
"path_hooks" => ctx.new_list(vec![]),
"path_importer_cache" => ctx.new_dict(),
"pycache_prefix" => vm.get_none(),
"dont_write_bytecode" => vm.new_bool(vm.settings.dont_write_bytecode),
"dont_write_bytecode" => vm.new_bool(vm.state.settings.dont_write_bytecode),
"setprofile" => ctx.new_function(sys_setprofile),
"setrecursionlimit" => ctx.new_function(sys_setrecursionlimit),
"settrace" => ctx.new_function(sys_settrace),
Expand Down
55 changes: 31 additions & 24 deletions vm/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,23 +56,26 @@ use crate::sysmodule;
pub struct VirtualMachine {
pub builtins: PyObjectRef,
pub sys_module: PyObjectRef,
pub stdlib_inits: RefCell<HashMap<String, stdlib::StdlibInitFunc>>,
pub ctx: PyContext,
pub frames: RefCell<Vec<FrameRef>>,
pub wasm_id: Option<String>,
pub exceptions: RefCell<Vec<PyBaseExceptionRef>>,
pub frozen: RefCell<HashMap<String, bytecode::FrozenModule>>,
pub import_func: RefCell<PyObjectRef>,
pub import_func: PyObjectRef,
pub profile_func: RefCell<PyObjectRef>,
pub trace_func: RefCell<PyObjectRef>,
pub use_tracing: RefCell<bool>,
pub signal_handlers: RefCell<[PyObjectRef; NSIG]>,
pub settings: PySettings,
pub use_tracing: Cell<bool>,
pub recursion_limit: Cell<usize>,
pub codec_registry: RefCell<Vec<PyObjectRef>>,
pub signal_handlers: Option<RefCell<[PyObjectRef; NSIG]>>,
pub state: Arc<PyGlobalState>,
pub initialized: bool,
}

pub struct PyGlobalState {
pub settings: PySettings,
pub stdlib_inits: HashMap<String, stdlib::StdlibInitFunc>,
pub frozen: HashMap<String, bytecode::FrozenModule>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the frozen modules should be a global static? This should not change between VMs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, but it's possible that someone would want to inject a frozen module into one VM to wrap their API or something, but want to use another vm for something different. I've done that myself in another project that uses RustPython.

}

pub const NSIG: usize = 64;

#[derive(Copy, Clone)]
Expand Down Expand Up @@ -175,31 +178,33 @@ impl VirtualMachine {
let sysmod_dict = ctx.new_dict();
let sysmod = new_module(sysmod_dict.clone());

let stdlib_inits = RefCell::new(stdlib::get_module_inits());
let frozen = RefCell::new(frozen::get_module_inits());
let import_func = RefCell::new(ctx.none());
let import_func = ctx.none();
let profile_func = RefCell::new(ctx.none());
let trace_func = RefCell::new(ctx.none());
let signal_handlers = RefCell::new(arr![ctx.none(); 64]);
let initialize_parameter = settings.initialization_parameter;

let stdlib_inits = stdlib::get_module_inits();
let frozen = frozen::get_module_inits();

let mut vm = VirtualMachine {
builtins: builtins.clone(),
sys_module: sysmod.clone(),
stdlib_inits,
ctx,
frames: RefCell::new(vec![]),
wasm_id: None,
exceptions: RefCell::new(vec![]),
frozen,
import_func,
profile_func,
trace_func,
use_tracing: RefCell::new(false),
signal_handlers,
settings,
use_tracing: Cell::new(false),
recursion_limit: Cell::new(if cfg!(debug_assertions) { 256 } else { 512 }),
codec_registry: RefCell::default(),
signal_handlers: Some(signal_handlers),
state: Arc::new(PyGlobalState {
settings,
stdlib_inits,
frozen,
}),
initialized: false,
};

Expand Down Expand Up @@ -232,7 +237,7 @@ impl VirtualMachine {
builtins::make_module(self, self.builtins.clone());
sysmodule::make_module(self, self.sys_module.clone(), self.builtins.clone());

let inner_init = || -> PyResult<()> {
let mut inner_init = || -> PyResult<()> {
#[cfg(not(target_arch = "wasm32"))]
import::import_builtin(self, "signal")?;

Expand Down Expand Up @@ -266,7 +271,9 @@ impl VirtualMachine {
Ok(())
};

self.expect_pyresult(inner_init(), "initializiation failed");
let res = inner_init();

self.expect_pyresult(res, "initializiation failed");

self.initialized = true;
}
Expand Down Expand Up @@ -814,7 +821,7 @@ impl VirtualMachine {

/// Call registered trace function.
fn trace_event(&self, event: TraceEvent) -> PyResult<()> {
if *self.use_tracing.borrow() {
if self.use_tracing.get() {
let frame = self.get_none();
let event = self.new_str(event.to_string());
let arg = self.get_none();
Expand All @@ -824,17 +831,17 @@ impl VirtualMachine {
// tracing function itself.
let trace_func = self.trace_func.borrow().clone();
if !self.is_none(&trace_func) {
self.use_tracing.replace(false);
self.use_tracing.set(false);
let res = self.invoke(&trace_func, args.clone());
self.use_tracing.replace(true);
self.use_tracing.set(true);
res?;
}

let profile_func = self.profile_func.borrow().clone();
if !self.is_none(&profile_func) {
self.use_tracing.replace(false);
self.use_tracing.set(false);
let res = self.invoke(&profile_func, args);
self.use_tracing.replace(true);
self.use_tracing.set(true);
res?;
}
}
Expand Down Expand Up @@ -1033,7 +1040,7 @@ impl VirtualMachine {
#[cfg(feature = "rustpython-compiler")]
pub fn compile_opts(&self) -> CompileOpts {
CompileOpts {
optimize: self.settings.optimize,
optimize: self.state.settings.optimize,
}
}

Expand Down
10 changes: 6 additions & 4 deletions wasm/lib/src/browser_module.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use futures::Future;
use js_sys::Promise;
use std::sync::Arc;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::{future_to_promise, JsFuture};
Expand Down Expand Up @@ -367,11 +368,12 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
})
}

pub fn setup_browser_module(vm: &VirtualMachine) {
vm.stdlib_inits
.borrow_mut()
pub fn setup_browser_module(vm: &mut VirtualMachine) {
let state = Arc::get_mut(&mut vm.state).unwrap();
state
.stdlib_inits
.insert("_browser".to_owned(), Box::new(make_module));
vm.frozen.borrow_mut().extend(py_compile_bytecode!(
state.frozen.extend(py_compile_bytecode!(
file = "src/browser.py",
module_name = "browser",
));
Expand Down
Loading