FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Prepare interpreter-local runtime state and thread lifecycle for GC isolation by 1ndahous3 · Pull Request #8944 · RustPython/RustPython · GitHub

Repository navigation

Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension .py  (2) .rs  (184) All 2 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
1 change: 0 additions & 1 deletion Lib/test/test_descr.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1865,7 +1865,6 @@ class D(C):
self.assertEqual(b.foo, 3)
self.assertEqual(b.__class__, D)

@unittest.expectedSuccess # TODO: RUSTPYTHON; The `expectedFailure` here is from CPython, so this test must fail
@unittest.expectedFailure
def test_bad_new(self):
self.assertRaises(TypeError, object.__new__)
Expand Down
22 changes: 12 additions & 10 deletions benches/execution.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,19 @@ fn bench_rustpython_code(b: &mut Bencher<'_>, name: &str, source: &str) {
settings.write_bytecode = false;
settings.user_site_directory = false;
let builder = Interpreter::builder(settings);
let defs = rustpython_stdlib::stdlib_module_defs(&builder.ctx);
builder.add_native_modules(&defs).build().enter(|vm| {
// Note: bench_cpython is both compiling and executing the code.
// As such we compile the code in the benchmark loop as well.
b.iter(|| {
let code = vm.compile(source, Mode::Exec, name).unwrap();
let scope = vm.new_scope_with_builtins();
let res: PyResult = vm.run_code_obj(code, scope);
vm.unwrap_pyresult(res);
let defs = rustpython_stdlib::stdlib_module_defs(unsafe { builder.context() });
unsafe { builder.add_native_modules(&defs) }
.build()
.enter(|vm| {
// Note: bench_cpython is both compiling and executing the code.
// As such we compile the code in the benchmark loop as well.
b.iter(|| {
let code = vm.compile(source, Mode::Exec, name).unwrap();
let scope = vm.new_scope_with_builtins();
let res: PyResult = vm.run_code_obj(code, scope);
vm.unwrap_pyresult(res);
})
})
})
}

pub fn benchmark_file_execution(
Expand Down
4 changes: 2 additions & 2 deletions benches/microbenchmarks.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ fn bench_rustpython_code(group: &mut BenchmarkGroup<'_, WallTime>, bench: &Micro
settings.user_site_directory = false;

let builder = Interpreter::builder(settings);
let defs = rustpython_stdlib::stdlib_module_defs(&builder.ctx);
let interp = builder.add_native_modules(&defs).build();
let defs = rustpython_stdlib::stdlib_module_defs(unsafe { builder.context() });
let interp = unsafe { builder.add_native_modules(&defs) }.build();
interp.enter(|vm| {
let setup_code = vm
.compile(&bench.setup, Mode::Exec, &bench.name)
Expand Down
4 changes: 3 additions & 1 deletion crates/capi/src/bytearrayobject.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ pub unsafe extern "C" fn PyByteArray_Size(bytearray: *mut PyObject) -> isize {
pub unsafe extern "C" fn PyByteArray_AsString(bytearray: *mut PyObject) -> *mut c_char {
with_vm(|vm| {
let bytearray = unsafe { bytearray.assume_borrowed_and_cast::<PyByteArray>(vm) }?;
Ok(bytearray.borrow_buf_mut().as_mut_ptr())
// SAFETY: the C caller owns the PyByteArray_AsString lifetime and
// synchronization contract; no resizable Rust Vec escapes this API.
Ok(unsafe { bytearray.as_mut_ptr_unchecked() })
})
}

Expand Down
2 changes: 1 addition & 1 deletion crates/capi/src/ceval.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ mod tests {
#[pyfunction]
fn legacy_locals_is_frame_mapping() -> bool {
let locals = super::PyEval_GetLocals();
rustpython_vm::vm::thread::with_current_vm(|vm| {
crate::pystate::with_current_vm(|vm| {
let frame = vm.current_frame().unwrap();
core::ptr::eq(
locals.cast_const(),
Expand Down
10 changes: 3 additions & 7 deletions crates/capi/src/descrobject.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::pystate::with_vm;
use crate::util::{CStrExt, FfiPtrExt};
use core::ffi::{c_char, c_int, c_void};
use rustpython_vm::builtins::{
DescriptorMemberDef, MemberAccess, MemberKind, PyDescriptorOwned, PyGetSet, PyMappingProxy,
DescriptorMemberDef, MemberAccess, MemberKind, PyDescriptor, PyGetSet, PyMappingProxy,
PyMemberDescriptor, PyMemberFlags, PyType,
};
use rustpython_vm::common::lock::PyRwLock;
Expand Down Expand Up @@ -40,11 +40,7 @@ impl PyGetSetDef {
}
})
}
pub(crate) fn build(
&self,
ty: &'static Py<PyType>,
vm: &VirtualMachine,
) -> PyResult<PyRef<PyGetSet>> {
pub(crate) fn build(&self, ty: &Py<PyType>, vm: &VirtualMachine) -> PyResult<PyRef<PyGetSet>> {
let name = unsafe { self.name.try_as_str(vm) }?;
let closure = self.closure as usize;

Expand Down Expand Up @@ -167,7 +163,7 @@ impl PyMemberDef {
});

let descriptor = PyMemberDescriptor {
common: PyDescriptorOwned {
common: PyDescriptor {
typ: ty.to_owned(),
name: vm.ctx.intern_str(name),
qualname: PyRwLock::new(None),
Expand Down
2 changes: 1 addition & 1 deletion crates/capi/src/lib.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn init_main_interpreter(interpreter: Interpreter) {
let mut interp = get_main_interpreter();
assert!(interp.is_none(), "Main interpreter is already set");
// Safety: Interpreter was not initialized before, so we can safely assume the statics are not used
unsafe { init_exception_statics(&Context::genesis().exceptions) };
unsafe { init_exception_statics(&Context::genesis_unchecked().exceptions) };
*interp = Some(interpreter);
MAIN_INTERP_PTR.store(
interp.as_ref().unwrap() as *const _ as *mut _,
Expand Down
17 changes: 5 additions & 12 deletions crates/capi/src/object/pytype.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ pub unsafe extern "C" fn Py_IS_TYPE(op: *mut PyObject, ty: *mut PyTypeObject) ->
#[unsafe(no_mangle)]
pub unsafe extern "C" fn PyType_GetFlags(ptr: *mut PyTypeObject) -> c_ulong {
let ty = unsafe { ptr.assume_borrowed() };
ty.slots.flags.load().bits() as u32 as c_ulong
ty.effective_flags().bits() as u32 as c_ulong
}

#[unsafe(no_mangle)]
Expand Down Expand Up @@ -227,27 +227,20 @@ pub extern "C" fn PyType_FromSlots(slots: *const PySlot) -> *mut PyObject {
|msg| vm.new_system_error(format!("Failed to create type from slots: {msg}")),
)?;

let attrs = &class.attributes;
let class_static = unsafe { &*((&*class) as *const _) };
let attrs = class.attributes();
for (name, method) in methods {
attrs.insert(
vm.ctx.intern_str(name),
method.build_method(class_static, vm).into(),
method.build_method(&class, vm).into(),
);
}
for getset in getsets {
let name = unsafe { getset.name.try_as_str(vm)? };
attrs.insert(
vm.ctx.intern_str(name),
getset.build(class_static, vm)?.into(),
);
attrs.insert(vm.ctx.intern_str(name), getset.build(&class, vm)?.into());
}
for member in members {
let name = unsafe { member.name.try_as_str(vm)? };
attrs.insert(
vm.ctx.intern_str(name),
member.build(class_static, vm)?.into(),
);
attrs.insert(vm.ctx.intern_str(name), member.build(&class, vm)?.into());
}

Ok(class)
Expand Down
6 changes: 3 additions & 3 deletions crates/capi/src/pyframe.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ mod tests {
use rustpython_vm::AsObject;

fn current_frame_ptr() -> *mut super::PyFrameObject {
rustpython_vm::vm::thread::with_current_vm(|vm| {
crate::pystate::with_current_vm(|vm| {
vm.current_frame()
.unwrap()
.as_object()
Expand Down Expand Up @@ -83,7 +83,7 @@ mod tests {

#[pyfunction]
fn frame_globals_is_globals() -> bool {
rustpython_vm::vm::thread::with_current_vm(|vm| {
crate::pystate::with_current_vm(|vm| {
let frame = vm.current_frame().unwrap();
let got = unsafe { super::PyFrame_GetGlobals(current_frame_ptr()) };
let expected = frame.iframe().globals().as_object().as_raw();
Expand All @@ -95,7 +95,7 @@ mod tests {

#[pyfunction]
fn frame_builtins_is_builtins() -> bool {
rustpython_vm::vm::thread::with_current_vm(|vm| {
crate::pystate::with_current_vm(|vm| {
let frame = vm.current_frame().unwrap();
let got = unsafe { super::PyFrame_GetBuiltins(current_frame_ptr()) };
let expected = frame.iframe().builtins().as_object().as_raw();
Expand Down
30 changes: 15 additions & 15 deletions crates/capi/src/pylifecycle.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use crate::pystate::ensure_thread_has_vm_attached;
use alloc::ffi::CString;
use core::ffi::{c_char, c_int, c_ulong};
use core::sync::atomic::{AtomicPtr, Ordering};
use rustpython_vm::common::rc::PyRc;
use rustpython_vm::stdlib::sys;
use rustpython_vm::version::{MAJOR, MICRO, MINOR, RUSTPYTHON_BUILD_INFO, VERSION_HEX};
use rustpython_vm::vm::thread::ThreadedVirtualMachine;
Expand All @@ -19,7 +18,7 @@ pub(crate) fn request_vm_from_interpreter() -> ThreadedVirtualMachine {
get_main_interpreter()
.as_ref()
.expect("Interpreter not initialized")
.enter(|vm| vm.new_thread())
.new_thread()
}

#[unsafe(no_mangle)]
Expand All @@ -40,20 +39,21 @@ pub extern "C" fn Py_InitializeEx(_initsigs: c_int) {
let mut interp = get_main_interpreter();
if interp.is_none() {
// Safety: Interpreter was not initialized before, so we can safely assume the statics are not used
unsafe { init_exception_statics(&Context::genesis().exceptions) };
unsafe { init_exception_statics(&Context::genesis_unchecked().exceptions) };
let builder = Interpreter::builder(Default::default());
let defs = rustpython_stdlib::stdlib_module_defs(&builder.ctx);
*interp = builder
.add_native_modules(&defs)
.init_hook(|vm| {
let state = PyRc::get_mut(&mut vm.state).unwrap();
let path = rustpython_pylib::LIB_PATH.to_owned();

state.config.paths.stdlib_dir = Some(path.clone());
state.config.paths.module_search_paths.insert(0, path);
})
.build()
.into();
let defs = rustpython_stdlib::stdlib_module_defs(unsafe { builder.context() });
*interp = unsafe {
builder
.add_native_modules(&defs)
.configure(|config| {
let path = rustpython_pylib::LIB_PATH.to_owned();

config.paths.stdlib_dir = Some(path.clone());
config.paths.module_search_paths.insert(0, path);
})
.build()
.into()
};
MAIN_INTERP_PTR.store(
interp.as_ref().unwrap() as *const _ as *mut _,
Ordering::Release,
Expand Down
20 changes: 14 additions & 6 deletions crates/capi/src/pystate.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ use core::ffi::c_int;
use core::sync::atomic::Ordering;
use rustpython_vm::vm::thread::{
CurrentVmAttachState, SavedThreadState, attach_current_thread, release_current_thread,
restore_current_thread, save_current_thread, with_current_vm,
restore_current_thread_unchecked, save_current_thread_unchecked,
};
use rustpython_vm::{Interpreter, VirtualMachine};

// Native C API callbacks already require an attached interpreter and follow
// CPython's ownership rules. Keep that boundary inside this crate.
pub(crate) fn with_current_vm<R>(f: impl FnOnce(&VirtualMachine) -> R) -> R {
unsafe { rustpython_vm::vm::thread::with_current_vm_unchecked(f) }
}

pub(crate) fn with_vm<R: FfiResult<O>, O>(f: impl FnOnce(&VirtualMachine) -> R) -> O {
with_current_vm(|vm| f(vm).into_output(vm))
}
Expand All @@ -28,7 +34,8 @@ pub struct PyThreadState {
/// Make sure this thread has a running vm attached. This only creates a new vm if we don't already
/// have one. So this will only create a new vm when we are in a new thread created outside RustPython.
pub(crate) fn ensure_thread_has_vm_attached() -> CurrentVmAttachState {
attach_current_thread(request_vm_from_interpreter)
// SAFETY: the C API pairs Ensure/Release on the calling native thread.
unsafe { attach_current_thread(request_vm_from_interpreter) }
}

#[unsafe(no_mangle)]
Expand All @@ -42,7 +49,7 @@ pub extern "C" fn PyGILState_Ensure() -> PyGILState_STATE {
#[unsafe(no_mangle)]
pub extern "C" fn PyGILState_Release(state: PyGILState_STATE) {
if state == PYGILSTATE_UNLOCKED {
release_current_thread(CurrentVmAttachState::Attached);
unsafe { release_current_thread(CurrentVmAttachState::Attached) };
}
}

Expand All @@ -51,7 +58,7 @@ pub extern "C" fn PyEval_SaveThread() -> *mut PyThreadState {
let interp = PyInterpreterState_Get();
let state = Box::new(PyThreadState {
interp,
vm: save_current_thread(),
vm: unsafe { save_current_thread_unchecked() },
});
Box::into_raw(state)
}
Expand All @@ -62,7 +69,7 @@ pub unsafe extern "C" fn PyEval_RestoreThread(state: *mut PyThreadState) {
// SAFETY: PyEval_SaveThread returns this allocation and CPython's API
// requires callers to restore exactly that thread state once.
let state = unsafe { Box::from_raw(state) };
restore_current_thread(state.vm);
unsafe { restore_current_thread_unchecked(state.vm) };
}

#[unsafe(no_mangle)]
Expand All @@ -87,10 +94,11 @@ pub extern "C" fn PyInterpreterState_GetID(interp: *mut PyInterpreterState) -> i

#[cfg(test)]
mod tests {
use super::with_current_vm;
use crate::get_main_interpreter;
use crate::pystate::{PyGILState_Ensure, PyGILState_Release};
use pyo3::prelude::*;
use rustpython_vm::vm::thread::{current_vm_is_set, with_current_vm};
use rustpython_vm::vm::thread::current_vm_is_set;

#[test]
fn new_thread() {
Expand Down
Loading
Loading

Back | FazBrowse Home | New Git URL