From c8739df379a6cc8754cdb1740e2ab0745a904892 Mon Sep 17 00:00:00 2001 From: Kangzhi Shi Date: Sun, 13 Nov 2022 10:27:28 +0200 Subject: [PATCH 1/5] introduce PyObjectAtomicRef --- vm/src/object/ext.rs | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index 9a0e9acbd7..cb4ea6a1c0 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -257,6 +257,42 @@ impl PyAtomicRef { } } +pub struct PyObjectAtomicRef(PyAtomic<*mut PyObject>); + +impl From for PyObjectAtomicRef { + fn from(obj: PyObjectRef) -> Self { + let obj = obj.into_raw(); + Self(Radium::new(obj as *mut _)) + } +} + +impl Deref for PyObjectAtomicRef { + type Target = PyObject; + + fn deref(&self) -> &Self::Target { + unsafe { &*self.0.load(Ordering::Relaxed) } + } +} + +impl PyObjectAtomicRef { + /// # Safety + /// The caller is responsible to keep the returned reference alive + /// until no more reference can be used via PyObjectAtomicRef::deref() + #[must_use] + pub unsafe fn swap(&self, obj: PyObjectRef) -> PyObjectRef { + let obj = obj.into_raw(); + let old = Radium::swap(&self.0, obj as *mut _, Ordering::AcqRel); + PyObjectRef::from_raw(old) + } + + pub fn swap_to_temporary_refs(&self, obj: PyObjectRef, vm: &VirtualMachine) { + let old = unsafe { self.swap(obj) }; + if let Some(frame) = vm.current_frame() { + frame.temporary_refs.lock().push(old); + } + } +} + pub trait AsObject where Self: Borrow, From 1d30a1b467a807a94428b26b9e6b69e20730e250 Mon Sep 17 00:00:00 2001 From: Kangzhi Shi Date: Sun, 13 Nov 2022 11:25:56 +0200 Subject: [PATCH 2/5] impl Debug for PyObjectAtomicRef --- vm/src/object/ext.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index cb4ea6a1c0..59a280b65a 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -259,6 +259,12 @@ impl PyAtomicRef { pub struct PyObjectAtomicRef(PyAtomic<*mut PyObject>); +impl std::fmt::Debug for PyObjectAtomicRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.deref().fmt(f) + } +} + impl From for PyObjectAtomicRef { fn from(obj: PyObjectRef) -> Self { let obj = obj.into_raw(); From e408ea5b8d529672251f80ac3ec4c3fd0e73d298 Mon Sep 17 00:00:00 2001 From: Kangzhi Shi Date: Thu, 17 Nov 2022 22:13:23 +0200 Subject: [PATCH 3/5] add supporting for PyAtomicRef> --- vm/src/object/ext.rs | 65 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 7 deletions(-) diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index 59a280b65a..f5f453706c 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -11,7 +11,7 @@ use crate::{ convert::{IntoPyException, ToPyObject, ToPyResult, TryFromObject}, VirtualMachine, }; -use std::{borrow::Borrow, fmt, ops::Deref}; +use std::{borrow::Borrow, fmt, marker::PhantomData, ops::Deref, ptr::null_mut}; /* Python objects and references. @@ -214,7 +214,10 @@ impl ToPyObject for PyRefExact { } } -pub struct PyAtomicRef(PyAtomic<*mut Py>); +pub struct PyAtomicRef { + inner: PyAtomic<*mut i8>, + _phantom: PhantomData, +} cfg_if::cfg_if! { if #[cfg(feature = "threading")] { @@ -226,7 +229,10 @@ cfg_if::cfg_if! { impl From> for PyAtomicRef { fn from(pyref: PyRef) -> Self { let py = PyRef::leak(pyref); - Self(Radium::new(py as *const _ as *mut _)) + Self { + inner: Radium::new(py as *const _ as *mut _), + _phantom: Default::default(), + } } } @@ -234,7 +240,13 @@ impl Deref for PyAtomicRef { type Target = Py; fn deref(&self) -> &Self::Target { - unsafe { &*self.0.load(Ordering::Relaxed) } + unsafe { + self.inner + .load(Ordering::Relaxed) + .cast::>() + .as_ref() + .unwrap_unchecked() + } } } @@ -244,9 +256,9 @@ impl PyAtomicRef { /// until no more reference can be used via PyAtomicRef::deref() #[must_use] pub unsafe fn swap(&self, pyref: PyRef) -> PyRef { - let py = PyRef::leak(pyref); - let old = Radium::swap(&self.0, py as *const _ as *mut _, Ordering::AcqRel); - PyRef::from_raw(old) + let py = PyRef::leak(pyref) as *const Py as *mut i8; + let old = Radium::swap(&self.inner, py, Ordering::AcqRel); + PyRef::from_raw(old.cast()) } pub fn swap_to_temporary_refs(&self, pyref: PyRef, vm: &VirtualMachine) { @@ -257,6 +269,45 @@ impl PyAtomicRef { } } +impl From>> for PyAtomicRef> { + fn from(opt_ref: Option>) -> Self { + let val = opt_ref + .map(|x| PyRef::leak(x) as *const Py as *mut i8) + .unwrap_or(null_mut()); + Self { + inner: Radium::new(val), + _phantom: Default::default(), + } + } +} + +impl PyAtomicRef> { + pub fn deref(&self) -> Option<&Py> { + unsafe { self.inner.load(Ordering::Relaxed).cast::>().as_ref() } + } + + /// # Safety + /// The caller is responsible to keep the returned PyRef alive + /// until no more reference can be used via PyAtomicRef::deref() + #[must_use] + pub unsafe fn swap(&self, opt_ref: Option>) -> Option> { + let val = opt_ref + .map(|x| PyRef::leak(x) as *const Py as *mut i8) + .unwrap_or(null_mut()); + let old = Radium::swap(&self.inner, val, Ordering::AcqRel); + unsafe { old.cast::>().as_ref().map(|x| PyRef::from_raw(x)) } + } + + pub fn swap_to_temporary_refs(&self, opt_ref: Option>, vm: &VirtualMachine) { + let old = unsafe { self.swap(opt_ref) }; + if let Some(old) = old { + if let Some(frame) = vm.current_frame() { + frame.temporary_refs.lock().push(old.into()); + } + } + } +} + pub struct PyObjectAtomicRef(PyAtomic<*mut PyObject>); impl std::fmt::Debug for PyObjectAtomicRef { From e1b691c522145743a047dd093b0b68e57bc56a6b Mon Sep 17 00:00:00 2001 From: Kangzhi Shi Date: Fri, 18 Nov 2022 19:50:16 +0200 Subject: [PATCH 4/5] add supporting for PyAtomic --- vm/src/object/ext.rs | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index f5f453706c..8ded65b624 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -308,38 +308,39 @@ impl PyAtomicRef> { } } -pub struct PyObjectAtomicRef(PyAtomic<*mut PyObject>); - -impl std::fmt::Debug for PyObjectAtomicRef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.deref().fmt(f) - } -} - -impl From for PyObjectAtomicRef { +impl From for PyAtomicRef { fn from(obj: PyObjectRef) -> Self { let obj = obj.into_raw(); - Self(Radium::new(obj as *mut _)) + Self { + inner: Radium::new(obj as *mut _), + _phantom: Default::default(), + } } } -impl Deref for PyObjectAtomicRef { +impl Deref for PyAtomicRef { type Target = PyObject; fn deref(&self) -> &Self::Target { - unsafe { &*self.0.load(Ordering::Relaxed) } + unsafe { + self.inner + .load(Ordering::Relaxed) + .cast::() + .as_ref() + .unwrap_unchecked() + } } } -impl PyObjectAtomicRef { +impl PyAtomicRef { /// # Safety - /// The caller is responsible to keep the returned reference alive - /// until no more reference can be used via PyObjectAtomicRef::deref() + /// The caller is responsible to keep the returned PyRef alive + /// until no more reference can be used via PyAtomicRef::deref() #[must_use] pub unsafe fn swap(&self, obj: PyObjectRef) -> PyObjectRef { - let obj = obj.into_raw(); - let old = Radium::swap(&self.0, obj as *mut _, Ordering::AcqRel); - PyObjectRef::from_raw(old) + let obj = obj.into_raw() as *mut i8; + let old = Radium::swap(&self.inner, obj, Ordering::AcqRel); + PyObjectRef::from_raw(old.cast()) } pub fn swap_to_temporary_refs(&self, obj: PyObjectRef, vm: &VirtualMachine) { From 3026541808357296be16951a2cf350e244eb8c11 Mon Sep 17 00:00:00 2001 From: Kangzhi Shi Date: Wed, 23 Nov 2022 21:34:17 +0200 Subject: [PATCH 5/5] impl Send Sync --- vm/src/object/ext.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/vm/src/object/ext.rs b/vm/src/object/ext.rs index 8ded65b624..d9683b35d9 100644 --- a/vm/src/object/ext.rs +++ b/vm/src/object/ext.rs @@ -215,7 +215,7 @@ impl ToPyObject for PyRefExact { } pub struct PyAtomicRef { - inner: PyAtomic<*mut i8>, + inner: PyAtomic<*mut u8>, _phantom: PhantomData, } @@ -223,6 +223,10 @@ cfg_if::cfg_if! { if #[cfg(feature = "threading")] { unsafe impl Send for PyAtomicRef {} unsafe impl Sync for PyAtomicRef {} + unsafe impl Send for PyAtomicRef> {} + unsafe impl Sync for PyAtomicRef> {} + unsafe impl Send for PyAtomicRef {} + unsafe impl Sync for PyAtomicRef {} } } @@ -256,7 +260,7 @@ impl PyAtomicRef { /// until no more reference can be used via PyAtomicRef::deref() #[must_use] pub unsafe fn swap(&self, pyref: PyRef) -> PyRef { - let py = PyRef::leak(pyref) as *const Py as *mut i8; + let py = PyRef::leak(pyref) as *const Py as *mut _; let old = Radium::swap(&self.inner, py, Ordering::AcqRel); PyRef::from_raw(old.cast()) } @@ -272,7 +276,7 @@ impl PyAtomicRef { impl From>> for PyAtomicRef> { fn from(opt_ref: Option>) -> Self { let val = opt_ref - .map(|x| PyRef::leak(x) as *const Py as *mut i8) + .map(|x| PyRef::leak(x) as *const Py as *mut _) .unwrap_or(null_mut()); Self { inner: Radium::new(val), @@ -292,18 +296,18 @@ impl PyAtomicRef> { #[must_use] pub unsafe fn swap(&self, opt_ref: Option>) -> Option> { let val = opt_ref - .map(|x| PyRef::leak(x) as *const Py as *mut i8) + .map(|x| PyRef::leak(x) as *const Py as *mut _) .unwrap_or(null_mut()); let old = Radium::swap(&self.inner, val, Ordering::AcqRel); unsafe { old.cast::>().as_ref().map(|x| PyRef::from_raw(x)) } } pub fn swap_to_temporary_refs(&self, opt_ref: Option>, vm: &VirtualMachine) { - let old = unsafe { self.swap(opt_ref) }; - if let Some(old) = old { - if let Some(frame) = vm.current_frame() { - frame.temporary_refs.lock().push(old.into()); - } + let Some(old) = (unsafe { self.swap(opt_ref) }) else { + return; + }; + if let Some(frame) = vm.current_frame() { + frame.temporary_refs.lock().push(old.into()); } } } @@ -338,7 +342,7 @@ impl PyAtomicRef { /// until no more reference can be used via PyAtomicRef::deref() #[must_use] pub unsafe fn swap(&self, obj: PyObjectRef) -> PyObjectRef { - let obj = obj.into_raw() as *mut i8; + let obj = obj.into_raw() as *mut _; let old = Radium::swap(&self.inner, obj, Ordering::AcqRel); PyObjectRef::from_raw(old.cast()) }