Merge pull request #1933 from RustPython/coolreader18/arc-vm-state

Move some vm fields to an Arc-wrapped struct
This commit is contained in:
Noah
2020-05-22 12:32:16 -05:00
committed by GitHub
9 changed files with 94 additions and 75 deletions

View File

@@ -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 {
@@ -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

View File

@@ -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") => {
@@ -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| {

View File

@@ -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 {
@@ -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())
@@ -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();
@@ -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(|| {

View File

@@ -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,
@@ -68,7 +72,7 @@ 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)
@@ -76,7 +80,11 @@ fn signal(signalnum: i32, handler: PyObjectRef, vm: &VirtualMachine) -> PyResult
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)]
@@ -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()])?;
}
@@ -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");

View File

@@ -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()))
@@ -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 {
@@ -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();
@@ -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()))
@@ -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();
@@ -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),

View File

@@ -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>,
}
pub const NSIG: usize = 64;
#[derive(Copy, Clone)]
@@ -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,
};
@@ -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")?;
@@ -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;
}
@@ -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();
@@ -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?;
}
}
@@ -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,
}
}

View File

@@ -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};
@@ -375,11 +376,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",
));

View File

@@ -5,6 +5,7 @@ use rustpython_vm::obj::{objfloat::PyFloatRef, objstr::PyStringRef, objtype::PyC
use rustpython_vm::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject};
use rustpython_vm::types::create_type;
use rustpython_vm::VirtualMachine;
use std::sync::Arc;
use wasm_bindgen::{prelude::*, JsCast};
#[wasm_bindgen(inline_js = "
@@ -257,8 +258,9 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
})
}
pub fn setup_js_module(vm: &VirtualMachine) {
vm.stdlib_inits
.borrow_mut()
pub fn setup_js_module(vm: &mut VirtualMachine) {
let state = Arc::get_mut(&mut vm.state).unwrap();
state
.stdlib_inits
.insert("_js".to_owned(), Box::new(make_module));
}

View File

@@ -1,6 +1,7 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::{Rc, Weak};
use std::sync::Arc;
use js_sys::{Object, TypeError};
use wasm_bindgen::prelude::*;
@@ -36,9 +37,9 @@ impl StoredVirtualMachine {
vm.wasm_id = Some(id);
let scope = vm.new_scope_with_builtins();
js_module::setup_js_module(&vm);
js_module::setup_js_module(&mut vm);
if inject_browser_module {
vm.stdlib_inits.borrow_mut().insert(
Arc::get_mut(&mut vm.state).unwrap().stdlib_inits.insert(
"_window".to_owned(),
Box::new(|vm| {
py_module!(vm, "_window", {
@@ -46,7 +47,7 @@ impl StoredVirtualMachine {
})
}),
);
setup_browser_module(&vm);
setup_browser_module(&mut vm);
}
vm.initialize(InitParameter::InitializeInternal);
@@ -288,26 +289,19 @@ impl WASMVirtualMachine {
#[wasm_bindgen(js_name = injectJSModule)]
pub fn inject_js_module(&self, name: String, module: Object) -> Result<(), JsValue> {
self.with(|StoredVirtualMachine { ref vm, .. }| {
let mut module_items: HashMap<String, PyObjectRef> = HashMap::new();
let py_module = vm.new_module(&name, vm.ctx.new_dict());
for entry in convert::object_entries(&module) {
let (key, value) = entry?;
let key = Object::from(key).to_string();
module_items.insert(key.into(), convert::js_to_py(vm, value));
extend_module!(vm, py_module, {
String::from(key) => convert::js_to_py(vm, value),
});
}
let mod_name = name.clone();
let stdlib_init_fn = move |vm: &VirtualMachine| {
let module = vm.new_module(&name, vm.ctx.new_dict());
for (key, value) in module_items.clone() {
vm.set_attr(&module, key, value).unwrap();
}
module
};
vm.stdlib_inits
.borrow_mut()
.insert(mod_name, Box::new(stdlib_init_fn));
let sys_modules = vm
.get_attribute(vm.sys_module.clone(), "modules")
.to_js(vm)?;
sys_modules.set_item(&name, py_module, vm).to_js(vm)?;
Ok(())
})?