Skip to content

Commit bf6060a

Browse files
committed
Move some vm fields to an Arc-wrapped struct
1 parent 4647731 commit bf6060a

File tree

9 files changed

+83
-63
lines changed

9 files changed

+83
-63
lines changed

vm/src/builtins.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ fn builtin_sum(iterable: PyIterable, start: OptionalArg, vm: &VirtualMachine) ->
736736

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

742742
fn builtin_vars(obj: OptionalArg, vm: &VirtualMachine) -> PyResult {

vm/src/import.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@ use crate::vm::{InitParameter, VirtualMachine};
1414
#[cfg(feature = "rustpython-compiler")]
1515
use rustpython_compiler::compile;
1616

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

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

6059
pub fn import_frozen(vm: &VirtualMachine, module_name: &str) -> PyResult {
61-
vm.frozen
62-
.borrow()
60+
vm.state
61+
.frozen
6362
.get(module_name)
6463
.ok_or_else(|| vm.new_import_error(format!("Cannot import frozen module {}", module_name)))
6564
.and_then(|frozen| import_codeobj(vm, module_name, frozen.code.clone(), false))
6665
}
6766

6867
pub fn import_builtin(vm: &VirtualMachine, module_name: &str) -> PyResult {
69-
vm.stdlib_inits
70-
.borrow()
68+
vm.state
69+
.stdlib_inits
7170
.get(module_name)
7271
.ok_or_else(|| vm.new_import_error(format!("Cannot import bultin module {}", module_name)))
7372
.and_then(|make_module_func| {

vm/src/stdlib/imp.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ fn imp_lock_held(_vm: &VirtualMachine) -> PyResult<()> {
2626
}
2727

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

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

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

4141
if let Ok(module) = sys_modules.get_item(name, vm) {
4242
Ok(module)
43-
} else if let Some(make_module_func) = vm.stdlib_inits.borrow().get(name) {
43+
} else if let Some(make_module_func) = vm.state.stdlib_inits.get(name) {
4444
Ok(make_module_func(vm))
4545
} else {
4646
Ok(vm.get_none())
@@ -53,8 +53,8 @@ fn imp_exec_builtin(_mod: PyModuleRef) -> i32 {
5353
}
5454

5555
fn imp_get_frozen_object(name: PyStringRef, vm: &VirtualMachine) -> PyResult<PyCode> {
56-
vm.frozen
57-
.borrow()
56+
vm.state
57+
.frozen
5858
.get(name.as_str())
5959
.map(|frozen| {
6060
let mut frozen = frozen.code.clone();
@@ -71,8 +71,8 @@ fn imp_init_frozen(name: PyStringRef, vm: &VirtualMachine) -> PyResult {
7171
}
7272

7373
fn imp_is_frozen_package(name: PyStringRef, vm: &VirtualMachine) -> PyResult<bool> {
74-
vm.frozen
75-
.borrow()
74+
vm.state
75+
.frozen
7676
.get(name.as_str())
7777
.map(|frozen| frozen.package)
7878
.ok_or_else(|| {

vm/src/stdlib/signal.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ fn assert_in_range(signum: i32, vm: &VirtualMachine) -> PyResult<()> {
3838

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

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

6973
let mut old_handler = handler;
7074
std::mem::swap(
71-
&mut vm.signal_handlers.borrow_mut()[signalnum as usize],
75+
&mut signal_handlers.borrow_mut()[signalnum as usize],
7276
&mut old_handler,
7377
);
7478
Ok(old_handler)
7579
}
7680

7781
fn getsignal(signalnum: i32, vm: &VirtualMachine) -> PyResult {
7882
assert_in_range(signalnum, vm)?;
79-
Ok(vm.signal_handlers.borrow()[signalnum as usize].clone())
83+
let signal_handlers = vm
84+
.signal_handlers
85+
.as_ref()
86+
.ok_or_else(|| vm.new_value_error("getsignal only works in main thread".to_owned()))?;
87+
Ok(signal_handlers.borrow()[signalnum as usize].clone())
8088
}
8189

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

92100
#[cfg_attr(feature = "flame-it", flame)]
93101
pub fn check_signals(vm: &VirtualMachine) -> PyResult<()> {
102+
let signal_handlers = match vm.signal_handlers {
103+
Some(ref h) => h.borrow(),
104+
None => return Ok(()),
105+
};
106+
94107
if !ANY_TRIGGERED.swap(false, Ordering::Relaxed) {
95108
return Ok(());
96109
}
97110
for (signum, trigger) in TRIGGERS.iter().enumerate().skip(1) {
98111
let triggerd = trigger.swap(false, Ordering::Relaxed);
99112
if triggerd {
100-
let handler = &vm.signal_handlers.borrow()[signum];
113+
let handler = &signal_handlers[signum];
101114
if vm.is_callable(handler) {
102115
vm.invoke(handler, vec![vm.new_int(signum), vm.get_none()])?;
103116
}
@@ -145,7 +158,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
145158
} else {
146159
vm.get_none()
147160
};
148-
vm.signal_handlers.borrow_mut()[signum] = py_handler;
161+
vm.signal_handlers.as_ref().unwrap().borrow_mut()[signum] = py_handler;
149162
}
150163

151164
signal(libc::SIGINT, int_handler, vm).expect("Failed to set sigint handler");

vm/src/sysmodule.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,14 +154,14 @@ fn update_use_tracing(vm: &VirtualMachine) {
154154
}
155155

156156
fn sys_getrecursionlimit(vm: &VirtualMachine) -> usize {
157-
vm.recursion_limit.get()
157+
vm.state.recursion_limit.load()
158158
}
159159

160160
fn sys_setrecursionlimit(recursion_limit: usize, vm: &VirtualMachine) -> PyResult {
161161
let recursion_depth = vm.frames.borrow().len();
162162

163163
if recursion_limit > recursion_depth + 1 {
164-
vm.recursion_limit.set(recursion_limit);
164+
vm.state.recursion_limit.store(recursion_limit);
165165
Ok(vm.ctx.none())
166166
} else {
167167
Err(vm.new_recursion_error(format!(
@@ -348,7 +348,7 @@ setprofile() -- set the global profiling function
348348
setrecursionlimit() -- set the max recursion depth for the interpreter
349349
settrace() -- set the global debug tracing function
350350
";
351-
let mut module_names: Vec<String> = vm.stdlib_inits.borrow().keys().cloned().collect();
351+
let mut module_names: Vec<String> = vm.state.stdlib_inits.keys().cloned().collect();
352352
module_names.push("sys".to_owned());
353353
module_names.push("builtins".to_owned());
354354
module_names.sort();

vm/src/vm.rs

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
//! https://github.com/ProgVal/pythonvm-rust/blob/master/src/processor/mod.rs
55
//!
66
7-
use std::cell::{Cell, Ref, RefCell};
7+
use std::cell::{Ref, RefCell};
88
use std::collections::hash_map::HashMap;
99
use std::collections::hash_set::HashSet;
1010
use std::sync::{Arc, Mutex, MutexGuard};
@@ -46,6 +46,7 @@ use crate::pyobject::{
4646
use crate::scope::Scope;
4747
use crate::stdlib;
4848
use crate::sysmodule;
49+
use crossbeam_utils::atomic::AtomicCell;
4950

5051
// use objects::objects;
5152

@@ -56,23 +57,27 @@ use crate::sysmodule;
5657
pub struct VirtualMachine {
5758
pub builtins: PyObjectRef,
5859
pub sys_module: PyObjectRef,
59-
pub stdlib_inits: RefCell<HashMap<String, stdlib::StdlibInitFunc>>,
6060
pub ctx: PyContext,
6161
pub frames: RefCell<Vec<FrameRef>>,
6262
pub wasm_id: Option<String>,
6363
pub exceptions: RefCell<Vec<PyBaseExceptionRef>>,
64-
pub frozen: RefCell<HashMap<String, bytecode::FrozenModule>>,
65-
pub import_func: RefCell<PyObjectRef>,
64+
pub import_func: PyObjectRef,
6665
pub profile_func: RefCell<PyObjectRef>,
6766
pub trace_func: RefCell<PyObjectRef>,
6867
pub use_tracing: RefCell<bool>,
69-
pub signal_handlers: RefCell<[PyObjectRef; NSIG]>,
68+
pub signal_handlers: Option<RefCell<[PyObjectRef; NSIG]>>,
7069
pub settings: PySettings,
71-
pub recursion_limit: Cell<usize>,
7270
pub codec_registry: RefCell<Vec<PyObjectRef>>,
71+
pub state: Arc<PyGlobalState>,
7372
pub initialized: bool,
7473
}
7574

75+
pub struct PyGlobalState {
76+
pub recursion_limit: AtomicCell<usize>,
77+
pub stdlib_inits: HashMap<String, stdlib::StdlibInitFunc>,
78+
pub frozen: HashMap<String, bytecode::FrozenModule>,
79+
}
80+
7681
pub const NSIG: usize = 64;
7782

7883
#[derive(Copy, Clone)]
@@ -175,31 +180,34 @@ impl VirtualMachine {
175180
let sysmod_dict = ctx.new_dict();
176181
let sysmod = new_module(sysmod_dict.clone());
177182

178-
let stdlib_inits = RefCell::new(stdlib::get_module_inits());
179-
let frozen = RefCell::new(frozen::get_module_inits());
180-
let import_func = RefCell::new(ctx.none());
183+
let import_func = ctx.none();
181184
let profile_func = RefCell::new(ctx.none());
182185
let trace_func = RefCell::new(ctx.none());
183186
let signal_handlers = RefCell::new(arr![ctx.none(); 64]);
184187
let initialize_parameter = settings.initialization_parameter;
185188

189+
let stdlib_inits = stdlib::get_module_inits();
190+
let frozen = frozen::get_module_inits();
191+
186192
let mut vm = VirtualMachine {
187193
builtins: builtins.clone(),
188194
sys_module: sysmod.clone(),
189-
stdlib_inits,
190195
ctx,
191196
frames: RefCell::new(vec![]),
192197
wasm_id: None,
193198
exceptions: RefCell::new(vec![]),
194-
frozen,
195199
import_func,
196200
profile_func,
197201
trace_func,
198202
use_tracing: RefCell::new(false),
199-
signal_handlers,
203+
signal_handlers: Some(signal_handlers),
200204
settings,
201-
recursion_limit: Cell::new(if cfg!(debug_assertions) { 256 } else { 512 }),
202205
codec_registry: RefCell::default(),
206+
state: Arc::new(PyGlobalState {
207+
recursion_limit: AtomicCell::new(if cfg!(debug_assertions) { 256 } else { 512 }),
208+
stdlib_inits,
209+
frozen,
210+
}),
203211
initialized: false,
204212
};
205213

@@ -232,7 +240,7 @@ impl VirtualMachine {
232240
builtins::make_module(self, self.builtins.clone());
233241
sysmodule::make_module(self, self.sys_module.clone(), self.builtins.clone());
234242

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

@@ -266,7 +274,9 @@ impl VirtualMachine {
266274
Ok(())
267275
};
268276

269-
self.expect_pyresult(inner_init(), "initializiation failed");
277+
let res = inner_init();
278+
279+
self.expect_pyresult(res, "initializiation failed");
270280

271281
self.initialized = true;
272282
}
@@ -302,7 +312,7 @@ impl VirtualMachine {
302312
}
303313

304314
fn check_recursive_call(&self, _where: &str) -> PyResult<()> {
305-
if self.frames.borrow().len() > self.recursion_limit.get() {
315+
if self.frames.borrow().len() > self.state.recursion_limit.load() {
306316
Err(self.new_recursion_error(format!("maximum recursion depth exceeded {}", _where)))
307317
} else {
308318
Ok(())

wasm/lib/src/browser_module.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use futures::Future;
22
use js_sys::Promise;
3+
use std::sync::Arc;
34
use wasm_bindgen::prelude::*;
45
use wasm_bindgen::JsCast;
56
use wasm_bindgen_futures::{future_to_promise, JsFuture};
@@ -367,11 +368,12 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
367368
})
368369
}
369370

370-
pub fn setup_browser_module(vm: &VirtualMachine) {
371-
vm.stdlib_inits
372-
.borrow_mut()
371+
pub fn setup_browser_module(vm: &mut VirtualMachine) {
372+
let state = Arc::get_mut(&mut vm.state).unwrap();
373+
state
374+
.stdlib_inits
373375
.insert("_browser".to_owned(), Box::new(make_module));
374-
vm.frozen.borrow_mut().extend(py_compile_bytecode!(
376+
state.frozen.extend(py_compile_bytecode!(
375377
file = "src/browser.py",
376378
module_name = "browser",
377379
));

wasm/lib/src/js_module.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustpython_vm::obj::{objfloat::PyFloatRef, objstr::PyStringRef, objtype::PyC
55
use rustpython_vm::pyobject::{PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject};
66
use rustpython_vm::types::create_type;
77
use rustpython_vm::VirtualMachine;
8+
use std::sync::Arc;
89
use wasm_bindgen::{prelude::*, JsCast};
910

1011
#[wasm_bindgen(inline_js = "
@@ -253,8 +254,9 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
253254
})
254255
}
255256

256-
pub fn setup_js_module(vm: &VirtualMachine) {
257-
vm.stdlib_inits
258-
.borrow_mut()
257+
pub fn setup_js_module(vm: &mut VirtualMachine) {
258+
let state = Arc::get_mut(&mut vm.state).unwrap();
259+
state
260+
.stdlib_inits
259261
.insert("_js".to_owned(), Box::new(make_module));
260262
}

0 commit comments

Comments
 (0)