mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Don't allocate for PyNativeFunc when it's just a fn pointer
This commit is contained in:
7 files changed
+40
-14
No files matched your search
Generated
+7
@@ -1645,6 +1645,7 @@ dependencies = [
|
||||
"sha-1",
|
||||
"sha2",
|
||||
"sha3",
|
||||
"smallbox",
|
||||
"socket2",
|
||||
"statrs",
|
||||
"subprocess",
|
||||
@@ -1818,6 +1819,12 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||
|
||||
[[package]]
|
||||
name = "smallbox"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa0eec6425219a55511a35afac416a2eecc62f5fa1bec14f9b97de0caa7daebe"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.2.0"
|
||||
|
||||
@@ -458,7 +458,7 @@ fn extract_impl_items(mut items: Vec<ItemSig>) -> Result<TokenStream2, Diagnosti
|
||||
let transform = if vec!["new", "call"].contains(&slot_ident.to_string().as_str()) {
|
||||
quote! { ::rustpython_vm::function::IntoPyNativeFunc::into_func }
|
||||
} else {
|
||||
quote! { Box::new }
|
||||
quote! { ::rustpython_vm::__exports::smallbox! }
|
||||
};
|
||||
let into_func = quote_spanned! {item_ident.span()=>
|
||||
#transform(Self::#item_ident)
|
||||
|
||||
@@ -72,6 +72,7 @@ is-macro = "0.1"
|
||||
result-like = "^0.2.1"
|
||||
foreign-types = "0.3"
|
||||
num_enum = "0.4"
|
||||
smallbox = "0.8"
|
||||
|
||||
flame = { version = "0.2", optional = true }
|
||||
flamer = { version = "0.3", optional = true }
|
||||
|
||||
+20
-4
@@ -4,6 +4,7 @@ use std::ops::RangeInclusive;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
use result_like::impl_option_like;
|
||||
use smallbox::{smallbox, space::S1, SmallBox};
|
||||
|
||||
use crate::exceptions::PyBaseExceptionRef;
|
||||
use crate::obj::objtuple::PyTuple;
|
||||
@@ -453,8 +454,11 @@ tuple_from_py_func_args!(A, B, C, D);
|
||||
tuple_from_py_func_args!(A, B, C, D, E);
|
||||
tuple_from_py_func_args!(A, B, C, D, E, F);
|
||||
|
||||
/// A container that can hold a `dyn Fn*` trait object, but doesn't allocate if it's only a fn() pointer
|
||||
pub type FunctionBox<T> = SmallBox<T, S1>;
|
||||
|
||||
/// A built-in Python function.
|
||||
pub type PyNativeFunc = Box<dyn Fn(&VirtualMachine, PyFuncArgs) -> PyResult + 'static>;
|
||||
pub type PyNativeFunc = FunctionBox<dyn Fn(&VirtualMachine, PyFuncArgs) -> PyResult + 'static>;
|
||||
|
||||
/// Implemented by types that are or can generate built-in functions.
|
||||
///
|
||||
@@ -479,7 +483,7 @@ where
|
||||
F: Fn(&VirtualMachine, PyFuncArgs) -> PyResult + 'static,
|
||||
{
|
||||
fn into_func(self) -> PyNativeFunc {
|
||||
Box::new(self)
|
||||
smallbox!(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -499,7 +503,7 @@ macro_rules! into_py_native_func_tuple {
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_func(self) -> PyNativeFunc {
|
||||
Box::new(move |vm, args| {
|
||||
smallbox!(move |vm: &VirtualMachine, args: PyFuncArgs| {
|
||||
let ($($n,)*) = args.bind::<($($T,)*)>(vm)?;
|
||||
|
||||
(self)($($n,)* vm).into_pyobject(vm)
|
||||
@@ -515,7 +519,7 @@ macro_rules! into_py_native_func_tuple {
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_func(self) -> PyNativeFunc {
|
||||
Box::new(move |vm, args| {
|
||||
smallbox!(move |vm: &VirtualMachine, args: PyFuncArgs| {
|
||||
let (zelf, $($n,)*) = args.bind::<(PyRef<S>, $($T,)*)>(vm)?;
|
||||
|
||||
(self)(&zelf, $($n,)* vm).into_pyobject(vm)
|
||||
@@ -597,3 +601,15 @@ pub fn single_or_tuple_any<T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>>(
|
||||
};
|
||||
checker.check(obj)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn test_functionbox_noalloc() {
|
||||
fn py_func(_b: bool, _vm: &crate::VirtualMachine) -> i32 {
|
||||
1
|
||||
}
|
||||
let f = super::IntoPyNativeFunc::into_func(py_func);
|
||||
assert!(!f.is_heap());
|
||||
}
|
||||
}
|
||||
@@ -88,4 +88,5 @@ pub use rustpython_bytecode::*;
|
||||
#[doc(hidden)]
|
||||
pub mod __exports {
|
||||
pub use maplit::hashmap;
|
||||
pub use smallbox::smallbox;
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
*/
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::{OptionalArg, OwnedParam, RefParam};
|
||||
use crate::function::{FunctionBox, OptionalArg, OwnedParam, RefParam};
|
||||
use crate::pyobject::{
|
||||
IntoPyObject, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
TypeProtocol,
|
||||
@@ -10,8 +10,9 @@ use crate::pyobject::{
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyGetterFunc = Box<dyn Fn(&VirtualMachine, PyObjectRef) -> PyResult>;
|
||||
pub type PySetterFunc = Box<dyn Fn(&VirtualMachine, PyObjectRef, PyObjectRef) -> PyResult<()>>;
|
||||
pub type PyGetterFunc = FunctionBox<dyn Fn(&VirtualMachine, PyObjectRef) -> PyResult>;
|
||||
pub type PySetterFunc =
|
||||
FunctionBox<dyn Fn(&VirtualMachine, PyObjectRef, PyObjectRef) -> PyResult<()>>;
|
||||
|
||||
pub trait IntoPyGetterFunc<T> {
|
||||
fn into_getter(self) -> PyGetterFunc;
|
||||
@@ -24,7 +25,7 @@ where
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_getter(self) -> PyGetterFunc {
|
||||
Box::new(move |vm, obj| {
|
||||
smallbox::smallbox!(move |vm: &VirtualMachine, obj| {
|
||||
let obj = T::try_from_object(vm, obj)?;
|
||||
(self)(obj, vm).into_pyobject(vm)
|
||||
})
|
||||
@@ -38,7 +39,7 @@ where
|
||||
R: IntoPyObject,
|
||||
{
|
||||
fn into_getter(self) -> PyGetterFunc {
|
||||
Box::new(move |vm, obj| {
|
||||
smallbox::smallbox!(move |vm: &VirtualMachine, obj| {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
(self)(&zelf, vm).into_pyobject(vm)
|
||||
})
|
||||
@@ -95,7 +96,7 @@ where
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn into_setter(self) -> PySetterFunc {
|
||||
Box::new(move |vm, obj, value| {
|
||||
smallbox::smallbox!(move |vm: &VirtualMachine, obj, value| {
|
||||
let obj = T::try_from_object(vm, obj)?;
|
||||
let value = V::try_from_object(vm, value)?;
|
||||
(self)(obj, value, vm).into_noresult()
|
||||
@@ -111,7 +112,7 @@ where
|
||||
R: IntoPyNoResult,
|
||||
{
|
||||
fn into_setter(self) -> PySetterFunc {
|
||||
Box::new(move |vm, obj, value| {
|
||||
smallbox::smallbox!(move |vm: &VirtualMachine, obj, value| {
|
||||
let zelf = PyRef::<S>::try_from_object(vm, obj)?;
|
||||
let value = V::try_from_object(vm, value)?;
|
||||
(self)(&zelf, value, vm).into_noresult()
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
|
||||
use crate::function::{FunctionBox, OptionalArg, PyFuncArgs, PyNativeFunc};
|
||||
use crate::pyobject::{IdProtocol, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject};
|
||||
use crate::VirtualMachine;
|
||||
|
||||
@@ -44,7 +44,7 @@ pub trait SlotCall: PyValue {
|
||||
fn call(&self, args: PyFuncArgs, vm: &VirtualMachine) -> PyResult;
|
||||
}
|
||||
|
||||
pub type PyDescrGetFunc = Box<
|
||||
pub type PyDescrGetFunc = FunctionBox<
|
||||
dyn Fn(&VirtualMachine, PyObjectRef, Option<PyObjectRef>, OptionalArg<PyObjectRef>) -> PyResult,
|
||||
>;
|
||||
|
||||
|
||||
Reference in new issue
Block a user