From 7894627b9d91a697f35630e3871123f84dceeb24 Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 11 Mar 2019 10:22:53 +0000 Subject: [PATCH 1/3] Use extend_class in objtype. --- vm/src/obj/objtype.rs | 42 +++++++++++++----------------------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 5a975556fc..a2042ec860 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -41,39 +41,23 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type: } } -pub fn init(context: &PyContext) { - let type_type = &context.type_type; - +pub fn init(ctx: &PyContext) { let type_doc = "type(object_or_name, bases, dict)\n\ type(object) -> the object's type\n\ type(name, bases, dict) -> a new type"; - context.set_attr(&type_type, "__call__", context.new_rustfunc(type_call)); - context.set_attr(&type_type, "__new__", context.new_rustfunc(type_new)); - context.set_attr(&type_type, "__mro__", context.new_property(type_mro)); - context.set_attr(&type_type, "__repr__", context.new_rustfunc(type_repr)); - context.set_attr( - &type_type, - "__prepare__", - context.new_rustfunc(type_prepare), - ); - context.set_attr( - &type_type, - "__getattribute__", - context.new_rustfunc(type_getattribute), - ); - context.set_attr( - &type_type, - "__instancecheck__", - context.new_rustfunc(type_instance_check), - ); - context.set_attr( - &type_type, - "__subclasscheck__", - context.new_rustfunc(type_subclass_check), - ); - context.set_attr(&type_type, "__doc__", context.new_str(type_doc.to_string())); - context.set_attr(&type_type, "__dir__", context.new_rustfunc(type_dir)); + extend_class!(&ctx, &ctx.type_type, { + "__call__" => ctx.new_rustfunc(type_call), + "__new__" => ctx.new_rustfunc(type_new), + "__mro__" => ctx.new_property(type_mro), + "__repr__" => ctx.new_rustfunc(type_repr), + "__prepare__" => ctx.new_rustfunc(type_prepare), + "__getattribute__" => ctx.new_rustfunc(type_getattribute), + "__instancecheck__" => ctx.new_rustfunc(type_instance_check), + "__subclasscheck__" => ctx.new_rustfunc(type_subclass_check), + "__doc__" => ctx.new_str(type_doc.to_string()), + "__dir__" => ctx.new_rustfunc(type_dir), + }); } fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { From 4d779bbf98f74200e68638ed56fd0277817fc3df Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 11 Mar 2019 10:31:22 +0000 Subject: [PATCH 2/3] isinstance/issubclass - avoid expensive construction of full mro. --- vm/src/obj/objtype.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index a2042ec860..993026407a 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -81,8 +81,7 @@ fn _mro(cls: PyObjectRef) -> Option> { /// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only /// use this if `cls` is known to have not overridden the base __instancecheck__ magic method. pub fn isinstance(obj: &PyObjectRef, cls: &PyObjectRef) -> bool { - let mro = _mro(obj.typ()).unwrap(); - mro.into_iter().any(|c| c.is(&cls)) + issubclass(&obj.typ(), &cls) } fn type_instance_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { @@ -98,8 +97,8 @@ fn type_instance_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { /// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic /// method. pub fn issubclass(subclass: &PyObjectRef, cls: &PyObjectRef) -> bool { - let mro = _mro(subclass.clone()).unwrap(); - mro.into_iter().any(|c| c.is(&cls)) + let ref mro = subclass.payload::().unwrap().mro; + subclass.is(&cls) || mro.iter().any(|c| c.is(&cls)) } fn type_subclass_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { From d7e1d694300819233f4c11e4a36578b87fee457d Mon Sep 17 00:00:00 2001 From: Adam Kelly Date: Mon, 11 Mar 2019 11:44:25 +0000 Subject: [PATCH 3/3] Avoid additional clone in objtype::subinstance. --- vm/src/obj/objtype.rs | 2 +- vm/src/pyobject.rs | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 993026407a..a8f86394ad 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -81,7 +81,7 @@ fn _mro(cls: PyObjectRef) -> Option> { /// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only /// use this if `cls` is known to have not overridden the base __instancecheck__ magic method. pub fn isinstance(obj: &PyObjectRef, cls: &PyObjectRef) -> bool { - issubclass(&obj.typ(), &cls) + issubclass(obj.type_ref(), &cls) } fn type_instance_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 23c269324a..6fbf3114cb 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -761,19 +761,22 @@ pub trait FromPyObjectRef { } pub trait TypeProtocol { - fn typ(&self) -> PyObjectRef; + fn typ(&self) -> PyObjectRef { + self.type_ref().clone() + } + fn type_ref(&self) -> &PyObjectRef; } impl TypeProtocol for PyObjectRef { - fn typ(&self) -> PyObjectRef { - (**self).typ() + fn type_ref(&self) -> &PyObjectRef { + (**self).type_ref() } } impl TypeProtocol for PyObject { - fn typ(&self) -> PyObjectRef { + fn type_ref(&self) -> &PyObjectRef { match self.typ { - Some(ref typ) => typ.clone(), + Some(ref typ) => &typ, None => panic!("Object {:?} doesn't have a type!", self), } }