Skip to content

Commit 30aeb8b

Browse files
authored
Introduce PyAtomicRef and impl for PyObject.typ (RustPython#3828)
* introduce PyAtomicRef * refactor PyObject.typ use PyAtomicRef * add documents * add swap_to_temporary_refs * replace AtomicCell with PyAtomic * fix name conflict
1 parent 4be533a commit 30aeb8b

34 files changed

+158
-138
lines changed

stdlib/src/array.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ mod array {
11281128
return Self::reduce(zelf, vm);
11291129
}
11301130
let array = zelf.read();
1131-
let cls = zelf.class().clone();
1131+
let cls = zelf.class().to_owned();
11321132
let typecode = vm.ctx.new_str(array.typecode_str());
11331133
let bytes = vm.ctx.new_bytes(array.get_bytes().to_vec());
11341134
let code = MachineFormatCode::from_typecode(array.typecode()).unwrap();
@@ -1148,7 +1148,7 @@ mod array {
11481148
vm: &VirtualMachine,
11491149
) -> PyResult<(PyObjectRef, PyTupleRef, Option<PyDictRef>)> {
11501150
let array = zelf.read();
1151-
let cls = zelf.class().clone();
1151+
let cls = zelf.class().to_owned();
11521152
let typecode = vm.ctx.new_str(array.typecode_str());
11531153
let values = if array.typecode() == 'u' {
11541154
let s = Self::_wchar_bytes_to_string(array.get_bytes(), array.itemsize(), vm)?;

stdlib/src/math.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ mod math {
55
use crate::vm::{
66
builtins::{try_bigint_to_f64, try_f64_to_bigint, PyFloat, PyInt, PyIntRef, PyStrInterned},
77
function::{ArgIntoFloat, ArgIterable, Either, OptionalArg, PosArgs},
8-
identifier, AsObject, PyObject, PyObjectRef, PyRef, PyResult, VirtualMachine,
8+
identifier, PyObject, PyObjectRef, PyRef, PyResult, VirtualMachine,
99
};
1010
use num_bigint::BigInt;
1111
use num_traits::{One, Signed, Zero};

vm/src/anystr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::{
22
builtins::{PyIntRef, PyTupleRef},
33
cformat::CFormatString,
44
function::OptionalOption,
5-
AsObject, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
5+
PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
66
};
77
use num_traits::{cast::ToPrimitive, sign::Signed};
88
use std::str::FromStr;

vm/src/builtins/builtinfunc.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ impl GetDescriptor for PyBuiltinMethod {
194194
Ok(obj) => obj,
195195
Err(result) => return result,
196196
};
197-
let r = if vm.is_none(&obj) && !Self::_cls_is(&cls, &obj.class()) {
197+
let r = if vm.is_none(&obj) && !Self::_cls_is(&cls, obj.class()) {
198198
zelf.into()
199199
} else {
200200
PyBoundMethod::new_ref(obj, zelf.into(), &vm.ctx).into()

vm/src/builtins/bytearray.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ impl PyByteArray {
684684
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
685685
let bytes = PyBytes::from(zelf.borrow_buf().to_vec()).to_pyobject(vm);
686686
(
687-
zelf.class().clone(),
687+
zelf.class().to_owned(),
688688
PyTuple::new_ref(vec![bytes], &vm.ctx),
689689
zelf.as_object().dict(),
690690
)

vm/src/builtins/bytes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ impl PyBytes {
545545
) -> (PyTypeRef, PyTupleRef, Option<PyDictRef>) {
546546
let bytes = PyBytes::from(zelf.inner.elements.clone()).to_pyobject(vm);
547547
(
548-
zelf.class().clone(),
548+
zelf.class().to_owned(),
549549
PyTuple::new_ref(vec![bytes], &vm.ctx),
550550
zelf.as_object().dict(),
551551
)

vm/src/builtins/classmethod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl GetDescriptor for PyClassMethod {
5454
vm: &VirtualMachine,
5555
) -> PyResult {
5656
let (zelf, _obj) = Self::_unwrap(zelf, obj, vm)?;
57-
let cls = cls.unwrap_or_else(|| _obj.class().clone().into());
57+
let cls = cls.unwrap_or_else(|| _obj.class().to_owned().into());
5858
let call_descr_get: PyResult<PyObjectRef> = zelf.callable.lock().get_attr("__get__", vm);
5959
match call_descr_get {
6060
Err(_) => Ok(PyBoundMethod::new_ref(cls, zelf.callable.lock().clone(), &vm.ctx).into()),

vm/src/builtins/enumerate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl PyEnumerate {
6060
#[pymethod(magic)]
6161
fn reduce(zelf: PyRef<Self>) -> (PyTypeRef, (PyIter, BigInt)) {
6262
(
63-
zelf.class().clone(),
63+
zelf.class().to_owned(),
6464
(zelf.iterator.clone(), zelf.counter.read().clone()),
6565
)
6666
}

vm/src/builtins/function.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,7 @@ impl GetDescriptor for PyFunction {
435435
vm: &VirtualMachine,
436436
) -> PyResult {
437437
let (zelf, obj) = Self::_unwrap(zelf, obj, vm)?;
438-
let obj = if vm.is_none(&obj) && !Self::_cls_is(&cls, &obj.class()) {
438+
let obj = if vm.is_none(&obj) && !Self::_cls_is(&cls, obj.class()) {
439439
zelf.into()
440440
} else {
441441
PyBoundMethod::new_ref(obj, zelf.into(), &vm.ctx).into()

vm/src/builtins/object.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ impl PyBaseObject {
261261

262262
#[pygetset(name = "__class__")]
263263
fn get_class(obj: PyObjectRef) -> PyTypeRef {
264-
obj.class().clone()
264+
obj.class().to_owned()
265265
}
266266

267267
#[pygetset(name = "__class__", setter)]
@@ -270,7 +270,7 @@ impl PyBaseObject {
270270
match value.downcast::<PyType>() {
271271
Ok(cls) => {
272272
// FIXME(#1979) cls instances might have a payload
273-
*instance.class_lock().write() = cls;
273+
instance.set_class(cls, vm);
274274
Ok(())
275275
}
276276
Err(value) => {
@@ -311,7 +311,7 @@ impl PyBaseObject {
311311
let __reduce__ = identifier!(vm, __reduce__);
312312
if let Some(reduce) = vm.get_attribute_opt(obj.clone(), __reduce__)? {
313313
let object_reduce = vm.ctx.types.object_type.get_attr(__reduce__).unwrap();
314-
let typ_obj: PyObjectRef = obj.class().clone().into();
314+
let typ_obj: PyObjectRef = obj.class().to_owned().into();
315315
let class_reduce = typ_obj.get_attr(__reduce__, vm)?;
316316
if !class_reduce.is(&object_reduce) {
317317
return vm.invoke(&reduce, ());

vm/src/builtins/property.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl PyProperty {
168168
deleter: PyRwLock::new(zelf.fdel()),
169169
doc: PyRwLock::new(None),
170170
}
171-
.into_ref_with_type(vm, zelf.class().clone())
171+
.into_ref_with_type(vm, zelf.class().to_owned())
172172
}
173173

174174
#[pymethod]
@@ -183,7 +183,7 @@ impl PyProperty {
183183
deleter: PyRwLock::new(zelf.fdel()),
184184
doc: PyRwLock::new(None),
185185
}
186-
.into_ref_with_type(vm, zelf.class().clone())
186+
.into_ref_with_type(vm, zelf.class().to_owned())
187187
}
188188

189189
#[pymethod]
@@ -198,7 +198,7 @@ impl PyProperty {
198198
deleter: PyRwLock::new(deleter.or_else(|| zelf.fdel())),
199199
doc: PyRwLock::new(None),
200200
}
201-
.into_ref_with_type(vm, zelf.class().clone())
201+
.into_ref_with_type(vm, zelf.class().to_owned())
202202
}
203203

204204
#[pygetset(magic)]

vm/src/builtins/set.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ fn reduce_set(
485485
vm: &VirtualMachine,
486486
) -> PyResult<(PyTypeRef, PyTupleRef, Option<PyDictRef>)> {
487487
Ok((
488-
zelf.class().clone(),
488+
zelf.class().to_owned(),
489489
vm.new_tuple((extract_set(zelf)
490490
.unwrap_or(&PySetInner::default())
491491
.elements(),)),
@@ -1056,8 +1056,6 @@ impl TryFromObject for AnySet {
10561056
if class.fast_issubclass(vm.ctx.types.set_type)
10571057
|| class.fast_issubclass(vm.ctx.types.frozenset_type)
10581058
{
1059-
// the class lease needs to be drop to be able to return the object
1060-
drop(class);
10611059
Ok(AnySet { object: obj })
10621060
} else {
10631061
Err(vm.new_type_error(format!("{} is not a subtype of set or frozenset", class)))

vm/src/builtins/slice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ impl PySlice {
204204
(Option<PyObjectRef>, PyObjectRef, Option<PyObjectRef>),
205205
)> {
206206
Ok((
207-
zelf.class().clone(),
207+
zelf.class().to_owned(),
208208
(zelf.start.clone(), zelf.stop.clone(), zelf.step.clone()),
209209
))
210210
}

vm/src/builtins/super.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ impl GetDescriptor for PySuper {
188188
Ok(PySuper::new(zelf.typ.clone(), obj, vm)?.into_pyobject(vm))
189189
} else {
190190
let obj = vm.unwrap_or_none(zelf.obj.clone().map(|(o, _)| o));
191-
vm.invoke(&zelf.class(), (zelf.typ.clone(), obj))
191+
vm.invoke(zelf.class(), (zelf.typ.clone(), obj))
192192
}
193193
}
194194
}
@@ -200,7 +200,7 @@ fn supercheck(ty: PyTypeRef, obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<
200200
}
201201
}
202202
if obj.fast_isinstance(&ty) {
203-
return Ok(obj.class().clone());
203+
return Ok(obj.class().to_owned());
204204
}
205205
let class_attr = obj.get_attr("__class__", vm)?;
206206
if let Ok(cls) = class_attr.downcast::<PyType>() {

vm/src/builtins/type.rs

+18-21
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl PyType {
173173

174174
let mros = bases
175175
.iter()
176-
.map(|x| x.iter_mro().cloned().collect())
176+
.map(|x| x.iter_mro().map(|x| x.to_owned()).collect())
177177
.collect();
178178
let mro = linearise_mro(mros)?;
179179

@@ -247,7 +247,7 @@ impl PyType {
247247
*slots.name.get_mut() = Some(String::from(name));
248248

249249
let bases = vec![base.clone()];
250-
let mro = base.iter_mro().cloned().collect();
250+
let mro = base.iter_mro().map(|x| x.to_owned()).collect();
251251

252252
let new_type = PyRef::new_ref(
253253
PyType {
@@ -353,20 +353,20 @@ impl PyType {
353353
}
354354
}
355355

356-
impl PyTypeRef {
356+
impl Py<PyType> {
357357
/// Determines if `subclass` is actually a subclass of `cls`, this doesn't call __subclasscheck__,
358358
/// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic
359359
/// method.
360360
pub fn fast_issubclass(&self, cls: &impl Borrow<crate::PyObject>) -> bool {
361361
self.as_object().is(cls.borrow()) || self.mro.iter().any(|c| c.is(cls.borrow()))
362362
}
363363

364-
pub fn iter_mro(&self) -> impl Iterator<Item = &PyTypeRef> + DoubleEndedIterator {
365-
std::iter::once(self).chain(self.mro.iter())
364+
pub fn iter_mro(&self) -> impl Iterator<Item = &Py<PyType>> + DoubleEndedIterator {
365+
std::iter::once(self).chain(self.mro.iter().map(|x| x.deref()))
366366
}
367367

368-
pub fn iter_base_chain(&self) -> impl Iterator<Item = &PyTypeRef> {
369-
std::iter::successors(Some(self), |cls| cls.base.as_ref())
368+
pub fn iter_base_chain(&self) -> impl Iterator<Item = &Py<PyType>> {
369+
std::iter::successors(Some(self), |cls| cls.base.as_deref())
370370
}
371371
}
372372

@@ -569,7 +569,7 @@ impl PyType {
569569

570570
#[pymethod]
571571
fn mro(zelf: PyRef<Self>) -> Vec<PyObjectRef> {
572-
zelf.iter_mro().map(|cls| cls.clone().into()).collect()
572+
zelf.iter_mro().map(|cls| cls.to_owned().into()).collect()
573573
}
574574

575575
#[pymethod(magic)]
@@ -588,7 +588,7 @@ impl PyType {
588588

589589
let is_type_type = metatype.is(vm.ctx.types.type_type);
590590
if is_type_type && args.args.len() == 1 && args.kwargs.is_empty() {
591-
return Ok(args.args[0].class().clone().into());
591+
return Ok(args.args[0].class().to_owned().into());
592592
}
593593

594594
if args.args.len() != 3 {
@@ -921,7 +921,7 @@ impl GetAttr for PyType {
921921
if has_descr_set {
922922
let descr_get = attr_class.mro_find_map(|cls| cls.slots.descr_get.load());
923923
if let Some(descr_get) = descr_get {
924-
let mcl = mcl.into_owned().into();
924+
let mcl = mcl.to_owned().into();
925925
return descr_get(attr.clone(), Some(zelf.to_owned().into()), Some(mcl), vm);
926926
}
927927
}
@@ -932,15 +932,13 @@ impl GetAttr for PyType {
932932
if let Some(ref attr) = zelf_attr {
933933
let descr_get = attr.class().mro_find_map(|cls| cls.slots.descr_get.load());
934934
if let Some(descr_get) = descr_get {
935-
drop(mcl);
936935
return descr_get(attr.clone(), None, Some(zelf.to_owned().into()), vm);
937936
}
938937
}
939938

940939
if let Some(cls_attr) = zelf_attr {
941940
Ok(cls_attr)
942941
} else if let Some(attr) = mcl_attr {
943-
drop(mcl);
944942
vm.call_if_get_descriptor(attr, zelf.to_owned().into())
945943
} else {
946944
return Err(attribute_error(zelf, name_str.as_str(), vm));
@@ -1007,7 +1005,7 @@ impl Callable for PyType {
10071005
}
10081006
}
10091007

1010-
fn find_base_dict_descr(cls: &PyTypeRef, vm: &VirtualMachine) -> Option<PyObjectRef> {
1008+
fn find_base_dict_descr(cls: &Py<PyType>, vm: &VirtualMachine) -> Option<PyObjectRef> {
10111009
cls.iter_base_chain().skip(1).find_map(|cls| {
10121010
// TODO: should actually be some translation of:
10131011
// cls.slot_dictoffset != 0 && !cls.flags.contains(HEAPTYPE)
@@ -1021,12 +1019,11 @@ fn find_base_dict_descr(cls: &PyTypeRef, vm: &VirtualMachine) -> Option<PyObject
10211019

10221020
fn subtype_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
10231021
// TODO: obj.class().as_pyref() need to be supported
1024-
let cls = obj.class().clone();
1025-
let ret = match find_base_dict_descr(&cls, vm) {
1026-
Some(descr) => vm.call_get_descriptor(descr, obj).unwrap_or_else(|_| {
1022+
let ret = match find_base_dict_descr(obj.class(), vm) {
1023+
Some(descr) => vm.call_get_descriptor(descr, obj).unwrap_or_else(|obj| {
10271024
Err(vm.new_type_error(format!(
10281025
"this __dict__ descriptor does not support '{}' objects",
1029-
cls.name()
1026+
obj.class()
10301027
)))
10311028
})?,
10321029
None => object::object_get_dict(obj, vm)?.into(),
@@ -1035,8 +1032,8 @@ fn subtype_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
10351032
}
10361033

10371034
fn subtype_set_dict(obj: PyObjectRef, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
1038-
let cls = obj.class().clone();
1039-
match find_base_dict_descr(&cls, vm) {
1035+
let cls = obj.class();
1036+
match find_base_dict_descr(cls, vm) {
10401037
Some(descr) => {
10411038
let descr_set = descr
10421039
.class()
@@ -1152,10 +1149,10 @@ fn calculate_meta_class(
11521149
let mut winner = metatype;
11531150
for base in bases {
11541151
let base_type = base.class();
1155-
if winner.fast_issubclass(&base_type) {
1152+
if winner.fast_issubclass(base_type) {
11561153
continue;
11571154
} else if base_type.fast_issubclass(&winner) {
1158-
winner = base_type.into_owned();
1155+
winner = base_type.to_owned();
11591156
continue;
11601157
}
11611158

vm/src/builtins/zip.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ impl Constructor for PyZip {
4444
impl PyZip {
4545
#[pymethod(magic)]
4646
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
47-
let cls = zelf.class().clone();
47+
let cls = zelf.class().to_owned();
4848
let iterators = zelf
4949
.iterators
5050
.iter()

vm/src/exceptions.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ impl VirtualMachine {
183183
exc: PyBaseExceptionRef,
184184
) -> (PyObjectRef, PyObjectRef, PyObjectRef) {
185185
let tb = exc.traceback().to_pyobject(self);
186-
let class = exc.class().clone();
186+
let class = exc.class().to_owned();
187187
(class.into(), exc.into(), tb)
188188
}
189189

@@ -524,9 +524,9 @@ impl PyBaseException {
524524
#[pymethod(magic)]
525525
fn reduce(zelf: PyRef<Self>, vm: &VirtualMachine) -> PyTupleRef {
526526
if let Some(dict) = zelf.as_object().dict().filter(|x| !x.is_empty()) {
527-
return vm.new_tuple((zelf.class().clone(), zelf.args(), dict));
527+
return vm.new_tuple((zelf.class().to_owned(), zelf.args(), dict));
528528
} else {
529-
return vm.new_tuple((zelf.class().clone(), zelf.args()));
529+
return vm.new_tuple((zelf.class().to_owned(), zelf.args()));
530530
}
531531
}
532532
}
@@ -912,7 +912,7 @@ fn os_error_str(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyResult<PyStrR
912912
fn os_error_reduce(exc: PyBaseExceptionRef, vm: &VirtualMachine) -> PyTupleRef {
913913
let args = exc.args();
914914
let obj = exc.as_object().to_owned();
915-
let mut result: Vec<PyObjectRef> = vec![obj.class().clone().into()];
915+
let mut result: Vec<PyObjectRef> = vec![obj.class().to_owned().into()];
916916

917917
if args.len() >= 2 && args.len() <= 5 {
918918
// SAFETY: len() == 2 is checked so get_arg 1 or 2 won't panic

vm/src/frame.rs

+2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ pub struct Frame {
114114

115115
// member
116116
pub trace_lines: PyMutex<bool>,
117+
pub temporary_refs: PyMutex<Vec<PyObjectRef>>,
117118
}
118119

119120
impl PyPayload for Frame {
@@ -162,6 +163,7 @@ impl Frame {
162163
state: PyMutex::new(state),
163164
trace: PyMutex::new(vm.ctx.none()),
164165
trace_lines: PyMutex::new(true),
166+
temporary_refs: PyMutex::new(vec![]),
165167
}
166168
}
167169
}

0 commit comments

Comments
 (0)