Merge pull request #2476 from pca006132/master

Optimize method call performance
This commit is contained in:
Noah
2021-03-07 19:19:28 -06:00
committed by GitHub
3 changed files with 21 additions and 8 deletions

View File

@@ -629,7 +629,7 @@ fn subtype_get_dict(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
// TODO: obj.class().as_pyref() need to be supported
let cls = obj.clone_class();
let ret = match find_base_dict_descr(&cls, vm) {
Some(descr) => vm.call_get_descriptor(descr, obj).unwrap_or_else(|| {
Some(descr) => vm.call_get_descriptor(descr, obj).unwrap_or_else(|_| {
Err(vm.new_type_error(format!(
"this __dict__ descriptor does not support '{}' objects",
cls.name

View File

@@ -26,6 +26,11 @@ where
}
}
macro_rules! count {
() => (0usize);
( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
}
// A tuple of values that each implement `IntoPyObject` represents a sequence of
// arguments that can be bound and passed to a built-in function.
macro_rules! into_func_args_from_tuple {
@@ -37,7 +42,9 @@ macro_rules! into_func_args_from_tuple {
#[inline]
fn into_args(self, vm: &VirtualMachine) -> FuncArgs {
let ($($n,)*) = self;
vec![$($n.into_pyobject(vm),)*].into()
let mut result = Vec::with_capacity(count!($($n,)*) + 1);
$(result.push($n.into_pyobject(vm), );)*
result.into()
}
}
};

View File

@@ -944,19 +944,25 @@ impl VirtualMachine {
descr: PyObjectRef,
obj: Option<PyObjectRef>,
cls: Option<PyObjectRef>,
) -> Option<PyResult> {
) -> Result<PyResult, PyObjectRef> {
let descr_get = descr.class().mro_find_map(|cls| cls.slots.descr_get.load());
descr_get.map(|descr_get| descr_get(descr, obj, cls, self))
match descr_get {
Some(descr_get) => Ok(descr_get(descr, obj, cls, self)),
None => Err(descr),
}
}
pub fn call_get_descriptor(&self, descr: PyObjectRef, obj: PyObjectRef) -> Option<PyResult> {
pub fn call_get_descriptor(
&self,
descr: PyObjectRef,
obj: PyObjectRef,
) -> Result<PyResult, PyObjectRef> {
let cls = obj.clone_class().into_object();
self.call_get_descriptor_specific(descr, Some(obj), Some(cls))
}
pub fn call_if_get_descriptor(&self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult {
self.call_get_descriptor(attr.clone(), obj)
.unwrap_or(Ok(attr))
self.call_get_descriptor(attr, obj).unwrap_or_else(Ok)
}
pub fn call_method<T>(&self, obj: &PyObjectRef, method_name: &str, args: T) -> PyResult
@@ -1257,7 +1263,7 @@ impl VirtualMachine {
if let Some(ref attr) = cls_attr {
if attr.class().has_attr("__set__") {
if let Some(r) = self.call_get_descriptor(attr.clone(), obj.clone()) {
if let Ok(r) = self.call_get_descriptor(attr.clone(), obj.clone()) {
return r.map(Some);
}
}