Skip to content

Commit c244575

Browse files
qingshi163youknowone
authored andcommitted
proto heaptypeext
1 parent 0ebd4e0 commit c244575

File tree

9 files changed

+64
-44
lines changed

9 files changed

+64
-44
lines changed

derive/src/pyclass.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,10 +564,15 @@ where
564564
let slot_name = slot_ident.to_string();
565565
let tokens = {
566566
const NON_ATOMIC_SLOTS: &[&str] = &["as_buffer"];
567+
const POINTER_SLOTS: &[&str] = &["as_number"];
567568
if NON_ATOMIC_SLOTS.contains(&slot_name.as_str()) {
568569
quote_spanned! { span =>
569570
slots.#slot_ident = Some(Self::#ident as _);
570571
}
572+
} else if POINTER_SLOTS.contains(&slot_name.as_str()) {
573+
quote_spanned! { span =>
574+
slots.#slot_ident.store(Some(NonNull::from(Self::#ident())));
575+
}
571576
} else {
572577
quote_spanned! { span =>
573578
slots.#slot_ident.store(Some(Self::#ident as _));

vm/src/builtins/float.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ impl From<f64> for PyFloat {
6060

6161
impl PyObject {
6262
pub fn try_float_opt(&self, vm: &VirtualMachine) -> PyResult<Option<PyRef<PyFloat>>> {
63-
PyNumber::new(self, vm).float_opt(vm)
63+
PyNumber::from(self).float_opt(vm)
6464
}
6565

6666
pub fn try_float(&self, vm: &VirtualMachine) -> PyResult<PyRef<PyFloat>> {
67-
PyNumber::new(self, vm).float(vm)
67+
PyNumber::from(self).float(vm)
6868
}
6969
}
7070

vm/src/builtins/int.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ impl Constructor for PyInt {
266266
val
267267
};
268268

269-
PyNumber::new(val.as_ref(), vm)
269+
PyNumber::from(val.as_ref())
270270
.int(vm)
271271
.map(|x| x.as_bigint().clone())
272272
}

vm/src/builtins/type.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,6 @@ use super::{
22
mappingproxy::PyMappingProxy, object, union_, PyClassMethod, PyDictRef, PyList, PyStaticMethod,
33
PyStr, PyStrInterned, PyStrRef, PyTuple, PyTupleRef, PyWeak,
44
};
5-
use crate::common::{
6-
ascii,
7-
borrow::BorrowedValue,
8-
lock::{PyRwLock, PyRwLockReadGuard},
9-
};
105
use crate::{
116
builtins::PyBaseExceptionRef,
127
class::{PyClassImpl, StaticType},
@@ -15,9 +10,17 @@ use crate::{
1510
types::{Callable, GetAttr, PyTypeFlags, PyTypeSlots, SetAttr},
1611
AsObject, Context, Py, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
1712
};
13+
use crate::{
14+
common::{
15+
ascii,
16+
borrow::BorrowedValue,
17+
lock::{PyRwLock, PyRwLockReadGuard},
18+
},
19+
protocol::PyNumberMethods,
20+
};
1821
use indexmap::{map::Entry, IndexMap};
1922
use itertools::Itertools;
20-
use std::{borrow::Borrow, collections::HashSet, fmt, ops::Deref};
23+
use std::{borrow::Borrow, collections::HashSet, fmt, ops::Deref, pin::Pin};
2124

2225
/// type(object_or_name, bases, dict)
2326
/// type(object) -> the object's type
@@ -30,10 +33,23 @@ pub struct PyType {
3033
pub subclasses: PyRwLock<Vec<PyRef<PyWeak>>>,
3134
pub attributes: PyRwLock<PyAttributes>,
3235
pub slots: PyTypeSlots,
36+
pub heaptype_ext: Option<Pin<Box<HeapTypeExt>>>,
37+
}
38+
39+
#[derive(Default)]
40+
pub struct HeapTypeExt {
41+
pub number_methods: PyNumberMethods,
3342
}
3443

3544
pub type PyTypeRef = PyRef<PyType>;
3645

46+
cfg_if::cfg_if! {
47+
if #[cfg(feature = "threading")] {
48+
unsafe impl Send for PyType {}
49+
unsafe impl Sync for PyType {}
50+
}
51+
}
52+
3753
/// For attributes we do not use a dict, but an IndexMap, which is an Hash Table
3854
/// that maintains order and is compatible with the standard HashMap This is probably
3955
/// faster and only supports strings as keys.
@@ -112,6 +128,7 @@ impl PyType {
112128
subclasses: PyRwLock::default(),
113129
attributes: PyRwLock::new(attrs),
114130
slots,
131+
heaptype_ext: Some(Pin::new(Box::new(HeapTypeExt::default()))),
115132
},
116133
metaclass,
117134
None,

vm/src/function/number.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ impl Deref for ArgIntoFloat {
8282
impl TryFromObject for ArgIntoFloat {
8383
// Equivalent to PyFloat_AsDouble.
8484
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
85-
let value = PyNumber::new(obj.as_ref(), vm).float(vm)?.to_f64();
85+
let value = PyNumber::from(obj.as_ref()).float(vm)?.to_f64();
8686
Ok(ArgIntoFloat { value })
8787
}
8888
}

vm/src/object/core.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,6 +1105,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
11051105
subclasses: PyRwLock::default(),
11061106
attributes: PyRwLock::new(Default::default()),
11071107
slots: PyType::make_slots(),
1108+
heaptype_ext: None,
11081109
};
11091110
let object_payload = PyType {
11101111
base: None,
@@ -1113,6 +1114,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
11131114
subclasses: PyRwLock::default(),
11141115
attributes: PyRwLock::new(Default::default()),
11151116
slots: object::PyBaseObject::make_slots(),
1117+
heaptype_ext: None,
11161118
};
11171119
let type_type_ptr = Box::into_raw(Box::new(partially_init!(
11181120
PyInner::<PyType> {
@@ -1173,6 +1175,7 @@ pub(crate) fn init_type_hierarchy() -> (PyTypeRef, PyTypeRef, PyTypeRef) {
11731175
subclasses: PyRwLock::default(),
11741176
attributes: PyRwLock::default(),
11751177
slots: PyWeak::make_slots(),
1178+
heaptype_ext: None,
11761179
};
11771180
let weakref_type = PyRef::new_ref(weakref_type, type_type.clone(), None);
11781181

vm/src/protocol/number.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
use std::ptr::NonNull;
2+
13
use crossbeam_utils::atomic::AtomicCell;
4+
use once_cell::sync::OnceCell;
25

36
use crate::{
47
builtins::{int, PyByteArray, PyBytes, PyComplex, PyFloat, PyInt, PyIntRef, PyStr},
@@ -12,6 +15,7 @@ type UnaryFunc<R = PyObjectRef> = AtomicCell<Option<fn(&PyNumber, &VirtualMachin
1215
type BinaryFunc<R = PyObjectRef> =
1316
AtomicCell<Option<fn(&PyNumber, &PyObject, &VirtualMachine) -> PyResult<R>>>;
1417

18+
#[derive(Default)]
1519
pub struct PyNumberMethods {
1620
/* Number implementations must check *both*
1721
arguments for proper type and implement the necessary conversions
@@ -124,36 +128,38 @@ impl PyNumberMethods {
124128
pub struct PyNumber<'a> {
125129
pub obj: &'a PyObject,
126130
// some fast path do not need methods, so we do lazy initialize
127-
pub methods: Option<&'static PyNumberMethods>,
131+
methods: OnceCell<NonNull<PyNumberMethods>>,
128132
}
129133

130-
impl<'a> PyNumber<'a> {
131-
pub fn new(obj: &'a PyObject, vm: &VirtualMachine) -> Self {
134+
impl<'a> From<&'a PyObject> for PyNumber<'a> {
135+
fn from(obj: &'a PyObject) -> Self {
132136
Self {
133137
obj,
134-
methods: Self::find_methods(obj, vm),
138+
methods: OnceCell::new(),
135139
}
136140
}
137141
}
138142

139143
impl PyNumber<'_> {
140-
pub fn find_methods(obj: &PyObject, vm: &VirtualMachine) -> Option<&'static PyNumberMethods> {
141-
let as_number = obj.class().mro_find_map(|x| x.slots.as_number.load());
142-
as_number.map(|f| f(obj, vm))
144+
pub fn methods(&self) -> &PyNumberMethods {
145+
let as_number = self.methods.get_or_init(|| {
146+
Self::find_methods(self.obj).unwrap_or(NonNull::from(&PyNumberMethods::NOT_IMPLEMENTED))
147+
});
148+
unsafe { as_number.as_ref() }
143149
}
144150

145-
pub fn methods(&self) -> &'static PyNumberMethods {
146-
self.methods.unwrap_or(&PyNumberMethods::NOT_IMPLEMENTED)
151+
fn find_methods<'a>(obj: &'a PyObject) -> Option<NonNull<PyNumberMethods>> {
152+
obj.class().mro_find_map(|x| x.slots.as_number.load())
147153
}
148154

149155
// PyNumber_Check
150-
pub fn check(obj: &PyObject, vm: &VirtualMachine) -> bool {
151-
Self::find_methods(obj, vm).map_or(false, |methods| {
152-
methods.int.load().is_some()
153-
|| methods.index.load().is_some()
154-
|| methods.float.load().is_some()
155-
|| obj.payload_is::<PyComplex>()
156-
})
156+
pub fn check<'a>(obj: &'a PyObject, vm: &VirtualMachine) -> bool {
157+
let num = PyNumber::from(obj);
158+
let methods = num.methods();
159+
methods.int.load().is_some()
160+
|| methods.index.load().is_some()
161+
|| methods.float.load().is_some()
162+
|| obj.payload_is::<PyComplex>()
157163
}
158164

159165
// PyIndex_Check
@@ -207,7 +213,7 @@ impl PyNumber<'_> {
207213
// vm,
208214
// )?;
209215
let ret = f.invoke((), vm)?;
210-
PyNumber::new(ret.as_ref(), vm).index(vm).map_err(|_| {
216+
PyNumber::from(ret.as_ref()).index(vm).map_err(|_| {
211217
vm.new_type_error(format!(
212218
"__trunc__ returned non-Integral (type {})",
213219
ret.class()

vm/src/types/slot.rs

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use crate::{
1515
};
1616
use crossbeam_utils::atomic::AtomicCell;
1717
use num_traits::{Signed, ToPrimitive};
18+
use std::ptr::NonNull;
1819
use std::{borrow::Borrow, cmp::Ordering};
1920

2021
// The corresponding field in CPython is `tp_` prefixed.
@@ -30,7 +31,7 @@ pub struct PyTypeSlots {
3031
// Methods to implement standard operations
3132

3233
// Method suites for standard classes
33-
pub as_number: AtomicCell<Option<AsNumberFunc>>,
34+
pub as_number: AtomicCell<Option<NonNull<PyNumberMethods>>>,
3435
pub as_sequence: AtomicCell<Option<AsSequenceFunc>>,
3536
pub as_mapping: AtomicCell<Option<AsMappingFunc>>,
3637

@@ -139,7 +140,6 @@ impl Default for PyTypeFlags {
139140

140141
pub(crate) type GenericMethod = fn(&PyObject, FuncArgs, &VirtualMachine) -> PyResult;
141142
pub(crate) type AsMappingFunc = fn(&PyObject, &VirtualMachine) -> &'static PyMappingMethods;
142-
pub(crate) type AsNumberFunc = fn(&PyObject, &VirtualMachine) -> &'static PyNumberMethods;
143143
pub(crate) type HashFunc = fn(&PyObject, &VirtualMachine) -> PyResult<PyHash>;
144144
// CallFunc = GenericMethod
145145
pub(crate) type GetattroFunc = fn(&PyObject, PyStrRef, &VirtualMachine) -> PyResult;
@@ -205,15 +205,6 @@ fn slot_as_sequence(zelf: &PyObject, vm: &VirtualMachine) -> &'static PySequence
205205
PySequenceMethods::generic(has_length, has_ass_item)
206206
}
207207

208-
fn slot_as_number(zelf: &PyObject, vm: &VirtualMachine) -> &'static PyNumberMethods {
209-
let (has_int, has_float, has_index) = (
210-
zelf.class().has_attr(identifier!(vm, __int__)),
211-
zelf.class().has_attr(identifier!(vm, __float__)),
212-
zelf.class().has_attr(identifier!(vm, __index__)),
213-
);
214-
PyNumberMethods::generic(has_int, has_float, has_index)
215-
}
216-
217208
fn hash_wrapper(zelf: &PyObject, vm: &VirtualMachine) -> PyResult<PyHash> {
218209
let hash_obj = vm.call_special_method(zelf.to_owned(), identifier!(vm, __hash__), ())?;
219210
match hash_obj.payload_if_subclass::<PyInt>(vm) {
@@ -374,7 +365,7 @@ impl PyType {
374365
update_slot!(del, del_wrapper);
375366
}
376367
"__int__" | "__index__" | "__float__" => {
377-
update_slot!(as_number, slot_as_number);
368+
// update_slot!(as_number, slot_as_number);
378369
}
379370
_ => {}
380371
}
@@ -884,7 +875,7 @@ pub trait AsNumber: PyPayload {
884875

885876
#[inline]
886877
#[pyslot]
887-
fn as_number(_zelf: &PyObject, _vm: &VirtualMachine) -> &'static PyNumberMethods {
878+
fn as_number() -> &'static PyNumberMethods {
888879
&Self::AS_NUMBER
889880
}
890881

vm/src/vm/vm_ops.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@ use crate::{
1010
/// Collection of operators
1111
impl VirtualMachine {
1212
pub fn to_index_opt(&self, obj: PyObjectRef) -> Option<PyResult<PyIntRef>> {
13-
PyNumber::new(obj.as_ref(), self)
14-
.index_opt(self)
15-
.transpose()
13+
PyNumber::from(obj.as_ref()).index_opt(self).transpose()
1614
}
1715

1816
pub fn to_index(&self, obj: &PyObject) -> PyResult<PyIntRef> {
19-
PyNumber::new(obj, self).index(self)
17+
PyNumber::from(obj).index(self)
2018
}
2119

2220
#[inline]

0 commit comments

Comments
 (0)