mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
optimize tp_hash
This commit is contained in:
1 parent
5e69141884
commit
09ebd19857
4 files changed
+52
-38
No files matched your search
+26
-21
@@ -334,32 +334,37 @@ where
|
||||
let slot_ident = item_meta.slot_name()?;
|
||||
let slot_name = slot_ident.to_string();
|
||||
let tokens = {
|
||||
let transform = if ["new", "call"].contains(&slot_name.as_str()) {
|
||||
quote! { ::rustpython_vm::function::IntoPyNativeFunc::into_func }
|
||||
if slot_name == "new" {
|
||||
let into_func = quote_spanned! {ident.span() =>
|
||||
::rustpython_vm::function::IntoPyNativeFunc::into_func(Self::#ident)
|
||||
};
|
||||
quote! {
|
||||
slots.#slot_ident = Some(#into_func);
|
||||
}
|
||||
} else if slot_name == "cmp" {
|
||||
let into_func = quote_spanned! {ident.span() =>
|
||||
::std::boxed::Box::new(Self::#ident)
|
||||
};
|
||||
quote! {
|
||||
slots.#slot_ident = Some(#into_func);
|
||||
}
|
||||
} else {
|
||||
quote! { ::std::boxed::Box::new }
|
||||
};
|
||||
let into_func = quote_spanned! {ident.span() =>
|
||||
#transform(Self::#ident)
|
||||
};
|
||||
match slot_name.as_str() {
|
||||
"call" => quote! {
|
||||
slots.#slot_ident.store(Some(
|
||||
let into_func = if slot_name == "call" {
|
||||
quote_spanned! {ident.span() =>
|
||||
|zelf: ::rustpython_vm::pyobject::PyObjectRef, args: ::rustpython_vm::function::PyFuncArgs, vm: &::rustpython_vm::VirtualMachine| -> ::rustpython_vm::pyobject::PyResult {
|
||||
use ::rustpython_vm::pyobject::TryFromObject;
|
||||
let zelf = PyRef::<Self>::try_from_object(vm, zelf)?;
|
||||
Self::#ident(zelf, args, vm)
|
||||
} as _
|
||||
));
|
||||
},
|
||||
"descr_get" => quote! {
|
||||
slots.#slot_ident.store(Some(
|
||||
Self::#ident as _
|
||||
))
|
||||
},
|
||||
_ => quote! {
|
||||
slots.#slot_ident = Some(#into_func);
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
quote_spanned! {ident.span() =>
|
||||
Self::#ident
|
||||
}
|
||||
};
|
||||
quote! {
|
||||
slots.#slot_ident.store(Some(#into_func as _))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -702,7 +702,7 @@ pub fn new(
|
||||
if base.slots.flags.has_feature(PyTpFlags::HAS_DICT) {
|
||||
slots.flags |= PyTpFlags::HAS_DICT
|
||||
}
|
||||
for slot_name in ["__call__", "__get__"].iter() {
|
||||
for slot_name in ["__call__", "__get__", "__hash__"].iter() {
|
||||
if attrs.contains_key(*slot_name) {
|
||||
slots.update_slot_func(*slot_name);
|
||||
}
|
||||
|
||||
+19
-4
@@ -3,9 +3,10 @@ use std::cmp::Ordering;
|
||||
use crate::common::cell::PyRwLock;
|
||||
use crate::common::hash::PyHash;
|
||||
use crate::function::{OptionalArg, PyFuncArgs, PyNativeFunc};
|
||||
use crate::obj::objint::PyInt;
|
||||
use crate::pyobject::{
|
||||
IdProtocol, PyComparisonValue, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
|
||||
TypeProtocol,
|
||||
BorrowValue, IdProtocol, PyComparisonValue, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
TryFromObject, TypeProtocol,
|
||||
};
|
||||
use crate::VirtualMachine;
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
@@ -44,7 +45,7 @@ impl Default for PyTpFlags {
|
||||
type GenericMethod = fn(PyObjectRef, PyFuncArgs, &VirtualMachine) -> PyResult;
|
||||
type DescrGetFunc =
|
||||
fn(PyObjectRef, Option<PyObjectRef>, Option<PyObjectRef>, &VirtualMachine) -> PyResult;
|
||||
type HashFunc = Box<py_dyn_fn!(dyn Fn(PyObjectRef, &VirtualMachine) -> PyResult<PyHash>)>;
|
||||
type HashFunc = fn(PyObjectRef, &VirtualMachine) -> PyResult<PyHash>;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PyClassSlots {
|
||||
@@ -53,7 +54,7 @@ pub struct PyClassSlots {
|
||||
pub new: Option<PyNativeFunc>,
|
||||
pub call: AtomicCell<Option<GenericMethod>>,
|
||||
pub descr_get: AtomicCell<Option<DescrGetFunc>>,
|
||||
pub hash: Option<HashFunc>,
|
||||
pub hash: AtomicCell<Option<HashFunc>>,
|
||||
pub cmp: Option<CmpFunc>,
|
||||
}
|
||||
|
||||
@@ -97,6 +98,20 @@ impl PyClassSlots {
|
||||
} as _;
|
||||
self.descr_get.store(Some(func))
|
||||
}
|
||||
"__hash__" => {
|
||||
let func: HashFunc = |zelf, vm| {
|
||||
let magic = get_class_magic(&zelf, "__hash__");
|
||||
let hash_obj = vm.invoke(&magic, vec![zelf])?;
|
||||
match hash_obj.payload_if_subclass::<PyInt>(vm) {
|
||||
Some(py_int) => {
|
||||
Ok(rustpython_common::hash::hash_bigint(py_int.borrow_value()))
|
||||
}
|
||||
None => Err(vm
|
||||
.new_type_error("__hash__ method should return an integer".to_owned())),
|
||||
}
|
||||
} as _;
|
||||
self.hash.store(Some(func));
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
+6
-12
@@ -28,7 +28,7 @@ use crate::import;
|
||||
use crate::obj::objbool;
|
||||
use crate::obj::objcode::{PyCode, PyCodeRef};
|
||||
use crate::obj::objdict::PyDictRef;
|
||||
use crate::obj::objint::{PyInt, PyIntRef};
|
||||
use crate::obj::objint::PyIntRef;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist::PyList;
|
||||
use crate::obj::objmodule::{self, PyModule};
|
||||
@@ -1453,17 +1453,11 @@ impl VirtualMachine {
|
||||
}
|
||||
|
||||
pub fn _hash(&self, obj: &PyObjectRef) -> PyResult<rustpython_common::hash::PyHash> {
|
||||
if let Some(ref hash) = obj.lease_class().slots.hash {
|
||||
hash(obj.clone(), self)
|
||||
} else {
|
||||
let hash_obj = self.call_method(obj, "__hash__", vec![])?;
|
||||
match hash_obj.payload_if_subclass::<PyInt>(self) {
|
||||
Some(py_int) => Ok(rustpython_common::hash::hash_bigint(py_int.borrow_value())),
|
||||
None => {
|
||||
Err(self.new_type_error("__hash__ method should return an integer".to_owned()))
|
||||
}
|
||||
}
|
||||
}
|
||||
let hash = obj
|
||||
.class()
|
||||
.first_in_mro(|cls| cls.slots.hash.load())
|
||||
.unwrap(); // hash always exist
|
||||
hash(obj.clone(), self)
|
||||
}
|
||||
|
||||
// https://docs.python.org/3/reference/expressions.html#membership-test-operations
|
||||
|
||||
Reference in new issue
Block a user