Skip to content

Commit 01e974e

Browse files
authored
Merge pull request RustPython#2231 from youknowone/slot2
slot optimization 2
2 parents 9e71cb3 + bebfa4b commit 01e974e

File tree

12 files changed

+151
-111
lines changed

12 files changed

+151
-111
lines changed

derive/src/pyclass.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -341,29 +341,9 @@ where
341341
quote! {
342342
slots.#slot_ident = Some(#into_func);
343343
}
344-
} else if slot_name == "cmp" {
345-
let into_func = quote_spanned! {ident.span() =>
346-
::std::boxed::Box::new(Self::#ident)
347-
};
348-
quote! {
349-
slots.#slot_ident = Some(#into_func);
350-
}
351344
} else {
352-
let into_func = if slot_name == "call" {
353-
quote_spanned! {ident.span() =>
354-
|zelf: ::rustpython_vm::pyobject::PyObjectRef, args: ::rustpython_vm::function::PyFuncArgs, vm: &::rustpython_vm::VirtualMachine| -> ::rustpython_vm::pyobject::PyResult {
355-
use ::rustpython_vm::pyobject::TryFromObject;
356-
let zelf = PyRef::<Self>::try_from_object(vm, zelf)?;
357-
Self::#ident(zelf, args, vm)
358-
}
359-
}
360-
} else {
361-
quote_spanned! {ident.span() =>
362-
Self::#ident
363-
}
364-
};
365345
quote! {
366-
slots.#slot_ident.store(Some(#into_func as _))
346+
slots.#slot_ident.store(Some(Self::#ident as _))
367347
}
368348
}
369349
};

vm/src/macros.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,14 @@ macro_rules! py_class {
4747
py_class
4848
}
4949
};
50-
(@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {
51-
$slots.$slot_name = Some(
50+
(@extract_slots($ctx:expr, $slots:expr, (slot new), $value:expr)) => {
51+
$slots.new = Some(
5252
$crate::function::IntoPyNativeFunc::into_func($value)
5353
);
5454
};
55+
(@extract_slots($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {
56+
$slots.$slot_name.store(Some($value));
57+
};
5558
(@extract_slots($ctx:expr, $class:expr, $name:expr, $value:expr)) => {};
5659
(@extract_attrs($ctx:expr, $slots:expr, (slot $slot_name:ident), $value:expr)) => {};
5760
(@extract_attrs($ctx:expr, $class:expr, $name:expr, $value:expr)) => {

vm/src/obj/objbuiltinfunc.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::obj::objtype::PyClassRef;
77
use crate::pyobject::{
88
PyClassImpl, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
99
};
10-
use crate::slots::{SlotCall, SlotDescriptor};
10+
use crate::slots::{Callable, SlotDescriptor};
1111
use crate::vm::VirtualMachine;
1212

1313
pub struct PyFuncDef {
@@ -106,13 +106,13 @@ impl PyBuiltinFunction {
106106
}
107107
}
108108

109-
impl SlotCall for PyBuiltinFunction {
110-
fn call(zelf: PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
109+
impl Callable for PyBuiltinFunction {
110+
fn call(zelf: &PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
111111
(zelf.value.func)(vm, args)
112112
}
113113
}
114114

115-
#[pyimpl(with(SlotCall), flags(HAS_DICT))]
115+
#[pyimpl(with(Callable), flags(HAS_DICT))]
116116
impl PyBuiltinFunction {
117117
#[pyproperty(magic)]
118118
fn module(&self, vm: &VirtualMachine) -> PyObjectRef {
@@ -186,13 +186,13 @@ impl SlotDescriptor for PyBuiltinMethod {
186186
}
187187
}
188188

189-
impl SlotCall for PyBuiltinMethod {
190-
fn call(zelf: PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
189+
impl Callable for PyBuiltinMethod {
190+
fn call(zelf: &PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
191191
(zelf.value.func)(vm, args)
192192
}
193193
}
194194

195-
#[pyimpl(with(SlotDescriptor, SlotCall))]
195+
#[pyimpl(with(SlotDescriptor, Callable))]
196196
impl PyBuiltinMethod {
197197
#[pyproperty(magic)]
198198
fn name(&self) -> Option<PyStringRef> {

vm/src/obj/objfunction.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use crate::pyobject::{
1919
PyRef, PyResult, PyValue, TypeProtocol,
2020
};
2121
use crate::scope::Scope;
22-
use crate::slots::{SlotCall, SlotDescriptor};
22+
use crate::slots::{Callable, Comparable, PyComparisonOp, SlotDescriptor};
2323
use crate::VirtualMachine;
2424
use itertools::Itertools;
2525
#[cfg(feature = "jit")]
@@ -269,7 +269,7 @@ impl PyValue for PyFunction {
269269
}
270270
}
271271

272-
#[pyimpl(with(SlotDescriptor, SlotCall), flags(HAS_DICT))]
272+
#[pyimpl(with(SlotDescriptor, Callable), flags(HAS_DICT))]
273273
impl PyFunction {
274274
#[pyproperty(magic)]
275275
fn code(&self) -> PyCodeRef {
@@ -320,8 +320,8 @@ impl SlotDescriptor for PyFunction {
320320
}
321321
}
322322

323-
impl SlotCall for PyFunction {
324-
fn call(zelf: PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
323+
impl Callable for PyFunction {
324+
fn call(zelf: &PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
325325
zelf.invoke(args, vm)
326326
}
327327
}
@@ -334,14 +334,30 @@ pub struct PyBoundMethod {
334334
pub function: PyObjectRef,
335335
}
336336

337-
impl SlotCall for PyBoundMethod {
338-
fn call(zelf: PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
337+
impl Callable for PyBoundMethod {
338+
fn call(zelf: &PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
339339
let args = args.insert(zelf.object.clone());
340340
vm.invoke(&zelf.function, args)
341341
}
342342
}
343343

344-
#[pyimpl(with(SlotCall), flags(HAS_DICT))]
344+
impl Comparable for PyBoundMethod {
345+
fn cmp(
346+
zelf: PyRef<Self>,
347+
other: PyObjectRef,
348+
op: PyComparisonOp,
349+
_vm: &VirtualMachine,
350+
) -> PyResult<PyComparisonValue> {
351+
op.eq_only(|| {
352+
let other = class_or_notimplemented!(Self, other);
353+
Ok(PyComparisonValue::Implemented(
354+
zelf.function.is(&other.function) && zelf.object.is(&other.object),
355+
))
356+
})
357+
}
358+
}
359+
360+
#[pyimpl(with(Callable, Comparable), flags(HAS_DICT))]
345361
impl PyBoundMethod {
346362
pub fn new(object: PyObjectRef, function: PyObjectRef) -> Self {
347363
PyBoundMethod { object, function }
@@ -377,19 +393,6 @@ impl PyBoundMethod {
377393
fn module(&self, vm: &VirtualMachine) -> Option<PyObjectRef> {
378394
vm.get_attribute(self.function.clone(), "__module__").ok()
379395
}
380-
381-
#[pymethod(magic)]
382-
fn eq(&self, other: PyObjectRef) -> PyResult<PyComparisonValue> {
383-
let other = class_or_notimplemented!(Self, other);
384-
Ok(PyComparisonValue::Implemented(
385-
self.function.is(&other.function) && self.object.is(&other.object),
386-
))
387-
}
388-
389-
#[pymethod(magic)]
390-
fn ne(&self, other: PyObjectRef) -> PyResult<PyComparisonValue> {
391-
Ok(self.eq(other)?.map(|v| !v))
392-
}
393396
}
394397

395398
impl PyValue for PyBoundMethod {

vm/src/obj/objobject.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use crate::common::hash::PyHash;
77
use crate::function::{OptionalArg, PyFuncArgs};
88
use crate::obj::objtype::PyClass;
99
use crate::pyobject::{
10-
BorrowValue, IdProtocol, ItemProtocol, PyAttributes, PyClassImpl, PyComparisonValue, PyContext,
11-
PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol,
10+
BorrowValue, Either, IdProtocol, ItemProtocol, PyAttributes, PyClassImpl, PyComparisonValue,
11+
PyContext, PyObject, PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol,
1212
};
1313
use crate::slots::PyComparisonOp;
1414
use crate::vm::VirtualMachine;
@@ -44,6 +44,16 @@ impl PyBaseObject {
4444
other: PyObjectRef,
4545
op: PyComparisonOp,
4646
vm: &VirtualMachine,
47+
) -> PyResult<Either<PyObjectRef, PyComparisonValue>> {
48+
Self::cmp(zelf, other, op, vm).map(Either::B)
49+
}
50+
51+
#[inline(always)]
52+
fn cmp(
53+
zelf: PyObjectRef,
54+
other: PyObjectRef,
55+
op: PyComparisonOp,
56+
vm: &VirtualMachine,
4757
) -> PyResult<PyComparisonValue> {
4858
let res = match op {
4959
PyComparisonOp::Eq => {
@@ -76,47 +86,47 @@ impl PyBaseObject {
7686
other: PyObjectRef,
7787
vm: &VirtualMachine,
7888
) -> PyResult<PyComparisonValue> {
79-
Self::tp_cmp(zelf, other, PyComparisonOp::Eq, vm)
89+
Self::cmp(zelf, other, PyComparisonOp::Eq, vm)
8090
}
8191
#[pymethod(magic)]
8292
fn ne(
8393
zelf: PyObjectRef,
8494
other: PyObjectRef,
8595
vm: &VirtualMachine,
8696
) -> PyResult<PyComparisonValue> {
87-
Self::tp_cmp(zelf, other, PyComparisonOp::Ne, vm)
97+
Self::cmp(zelf, other, PyComparisonOp::Ne, vm)
8898
}
8999
#[pymethod(magic)]
90100
fn lt(
91101
zelf: PyObjectRef,
92102
other: PyObjectRef,
93103
vm: &VirtualMachine,
94104
) -> PyResult<PyComparisonValue> {
95-
Self::tp_cmp(zelf, other, PyComparisonOp::Lt, vm)
105+
Self::cmp(zelf, other, PyComparisonOp::Lt, vm)
96106
}
97107
#[pymethod(magic)]
98108
fn le(
99109
zelf: PyObjectRef,
100110
other: PyObjectRef,
101111
vm: &VirtualMachine,
102112
) -> PyResult<PyComparisonValue> {
103-
Self::tp_cmp(zelf, other, PyComparisonOp::Le, vm)
113+
Self::cmp(zelf, other, PyComparisonOp::Le, vm)
104114
}
105115
#[pymethod(magic)]
106116
fn ge(
107117
zelf: PyObjectRef,
108118
other: PyObjectRef,
109119
vm: &VirtualMachine,
110120
) -> PyResult<PyComparisonValue> {
111-
Self::tp_cmp(zelf, other, PyComparisonOp::Ge, vm)
121+
Self::cmp(zelf, other, PyComparisonOp::Ge, vm)
112122
}
113123
#[pymethod(magic)]
114124
fn gt(
115125
zelf: PyObjectRef,
116126
other: PyObjectRef,
117127
vm: &VirtualMachine,
118128
) -> PyResult<PyComparisonValue> {
119-
Self::tp_cmp(zelf, other, PyComparisonOp::Gt, vm)
129+
Self::cmp(zelf, other, PyComparisonOp::Gt, vm)
120130
}
121131

122132
#[pymethod(magic)]

vm/src/obj/objtype.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ use super::objtuple::PyTuple;
1414
use super::objweakref::PyWeak;
1515
use crate::function::{KwArgs, PyFuncArgs};
1616
use crate::pyobject::{
17-
BorrowValue, IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyLease,
17+
BorrowValue, Either, IdProtocol, PyAttributes, PyClassImpl, PyContext, PyIterable, PyLease,
1818
PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
1919
};
20-
use crate::slots::{self, PyClassSlots, PyTpFlags, SlotCall};
20+
use crate::slots::{self, Callable, PyClassSlots, PyTpFlags};
2121
use crate::vm::VirtualMachine;
2222
use itertools::Itertools;
2323
use std::ops::Deref;
@@ -150,6 +150,20 @@ impl PyClassRef {
150150
} as _;
151151
self.slots.hash.store(Some(func));
152152
}
153+
"__del__" => {
154+
let func: slots::DelFunc = |zelf, vm| {
155+
let magic = get_class_magic(&zelf, "__del__");
156+
vm.invoke(&magic, vec![zelf.clone()]).map(|_| ())
157+
} as _;
158+
self.slots.del.store(Some(func));
159+
}
160+
"__eq__" | "__ne__" | "__le__" | "__lt__" | "__ge__" | "__gt__" => {
161+
let func: slots::CmpFunc = |zelf, other, op, vm| {
162+
let magic = get_class_magic(&zelf, op.method_name());
163+
vm.invoke(&magic, vec![zelf, other]).map(Either::A)
164+
} as _;
165+
self.slots.cmp.store(Some(func))
166+
}
153167
_ => (),
154168
}
155169
}
@@ -165,7 +179,7 @@ fn get_class_magic(zelf: &PyObjectRef, name: &str) -> PyObjectRef {
165179
// attrs.get(name).unwrap().clone()
166180
}
167181

168-
#[pyimpl(with(SlotCall), flags(BASETYPE))]
182+
#[pyimpl(with(Callable), flags(BASETYPE))]
169183
impl PyClass {
170184
#[pyproperty(name = "__mro__")]
171185
fn get_mro(zelf: PyRef<Self>) -> PyTuple {
@@ -495,8 +509,8 @@ impl PyClass {
495509
}
496510
}
497511

498-
impl SlotCall for PyClass {
499-
fn call(zelf: PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
512+
impl Callable for PyClass {
513+
fn call(zelf: &PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
500514
vm_trace!("type_call: {:?}", zelf);
501515
let obj = call_tp_new(zelf.clone(), zelf.clone(), args.clone(), vm)?;
502516

vm/src/obj/objweakref.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::pyobject::{
55
IdProtocol, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
66
};
77
use crate::pyobjectrc::{PyObjectRc, PyObjectWeak};
8-
use crate::slots::{Comparable, Hashable, PyComparisonOp, SlotCall};
8+
use crate::slots::{Callable, Comparable, Hashable, PyComparisonOp};
99
use crate::vm::VirtualMachine;
1010

1111
use crossbeam_utils::atomic::AtomicCell;
@@ -38,14 +38,14 @@ impl PyValue for PyWeak {
3838

3939
pub type PyWeakRef = PyRef<PyWeak>;
4040

41-
impl SlotCall for PyWeak {
42-
fn call(zelf: PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
41+
impl Callable for PyWeak {
42+
fn call(zelf: &PyRef<Self>, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult {
4343
args.bind::<()>(vm)?;
4444
Ok(vm.unwrap_or_none(zelf.upgrade()))
4545
}
4646
}
4747

48-
#[pyimpl(with(SlotCall, Hashable, Comparable), flags(BASETYPE))]
48+
#[pyimpl(with(Callable, Hashable, Comparable), flags(BASETYPE))]
4949
impl PyWeak {
5050
// TODO callbacks
5151
#[pyslot]

vm/src/pyobjectrc.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,11 +146,12 @@ where
146146

147147
// CPython-compatible drop implementation
148148
let zelf = Self::into_ref(self.clone());
149-
if let Some(del_method) = zelf.inner.get_class_attr("__del__") {
149+
if let Some(del_slot) = zelf.class().first_in_mro(|cls| cls.slots.del.load()) {
150150
crate::vm::thread::with_vm(&zelf, |vm| {
151-
if let Err(e) = vm.invoke(&del_method, vec![zelf.clone()]) {
151+
if let Err(e) = del_slot(&zelf, vm) {
152152
// exception in del will be ignored but printed
153153
print!("Exception ignored in: ",);
154+
let del_method = zelf.get_class_attr("__del__").unwrap();
154155
let repr = vm.to_repr(&del_method);
155156
match repr {
156157
Ok(v) => println!("{}", v.to_string()),

0 commit comments

Comments
 (0)