From bb161a5a670e1b2ff2b429e8da1b1807bf98bed0 Mon Sep 17 00:00:00 2001 From: Joey Hain Date: Fri, 22 Mar 2019 18:04:09 -0700 Subject: [PATCH] Remove Box from PyObject --- vm/src/obj/objtype.rs | 17 +++------ vm/src/obj/objweakref.rs | 4 +-- vm/src/pyobject.rs | 76 ++++++++++++++++++++++++++++------------ vm/src/vm.rs | 2 +- 4 files changed, 61 insertions(+), 38 deletions(-) diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 78c946dbc..65a145888 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -35,12 +35,6 @@ impl PyValue for PyClass { } } -impl IdProtocol for PyClassRef { - fn get_id(&self) -> usize { - self.as_object().get_id() - } -} - impl TypeProtocol for PyClassRef { fn type_ref(&self) -> &PyObjectRef { &self.as_object().type_ref() @@ -300,10 +294,7 @@ fn take_next_base(mut bases: Vec>) -> Option<(PyClassRef, Vec>) -> Option<(PyClassRef, Vec, + referent: Weak>, } impl PyWeak { diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 5780cf620..10e398b2a 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -72,7 +72,7 @@ Basically reference counting, but then done by rust. /// this reference counting is accounted for by this type. Use the `.clone()` /// method to create a new reference and increment the amount of references /// to the python object by 1. -pub type PyObjectRef = Rc; +pub type PyObjectRef = Rc>; /// Use this type for function which return a python object or and exception. /// Both the python object and the python exception are `PyObjectRef` types @@ -83,7 +83,7 @@ pub type PyResult = Result; // A valid value, o /// faster, unordered, and only supports strings as keys. pub type PyAttributes = HashMap; -impl fmt::Display for PyObject { +impl fmt::Display for PyObject { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { use self::TypeProtocol; if let Some(PyClass { ref name, .. }) = self.payload::() { @@ -188,25 +188,25 @@ fn init_type_hierarchy() -> (PyObjectRef, PyObjectRef) { let object_type = PyObject { typ: mem::uninitialized(), // ! dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(PyClass { + payload: PyClass { name: String::from("object"), mro: vec![], - }), + }, } .into_ref(); let type_type = PyObject { typ: mem::uninitialized(), // ! dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(PyClass { + payload: PyClass { name: String::from("type"), mro: vec![FromPyObjectRef::from_pyobj(&object_type)], - }), + }, } .into_ref(); - let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; - let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; + let object_type_ptr = PyObjectRef::into_raw(object_type.clone()) as *mut PyObject; + let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject; ptr::write(&mut (*object_type_ptr).typ, type_type.clone()); ptr::write(&mut (*type_type_ptr).typ, type_type.clone()); @@ -628,7 +628,7 @@ impl PyContext { PyObject { typ: class, dict: Some(RefCell::new(dict)), - payload: Box::new(objobject::PyInstance), + payload: objobject::PyInstance, } .into_ref() } @@ -691,10 +691,13 @@ impl Default for PyContext { /// This is an actual python object. It consists of a `typ` which is the /// python class, and carries some rust payload optionally. This rust /// payload can be a rust float or rust int in case of float and int objects. -pub struct PyObject { +pub struct PyObject +where + T: ?Sized + PyObjectPayload, +{ pub typ: PyObjectRef, pub dict: Option>, // __dict__ member - pub payload: Box, + pub payload: T, } /// A reference to a Python object. @@ -788,9 +791,30 @@ pub trait IdProtocol { } } -impl IdProtocol for PyObjectRef { +#[derive(Debug)] +enum Never {} + +impl PyValue for Never { + fn class(_vm: &mut VirtualMachine) -> PyObjectRef { + unreachable!() + } +} + +impl IdProtocol for PyObject { fn get_id(&self) -> usize { - &*self as &PyObject as *const PyObject as usize + self as *const _ as *const PyObject as usize + } +} + +impl IdProtocol for Rc { + fn get_id(&self) -> usize { + (**self).get_id() + } +} + +impl IdProtocol for PyRef { + fn get_id(&self) -> usize { + self.obj.get_id() } } @@ -814,7 +838,10 @@ impl TypeProtocol for PyObjectRef { } } -impl TypeProtocol for PyObject { +impl TypeProtocol for PyObject +where + T: ?Sized + PyObjectPayload, +{ fn type_ref(&self) -> &PyObjectRef { &self.typ } @@ -953,9 +980,9 @@ impl BufferProtocol for PyObjectRef { } } -impl fmt::Debug for PyObject { +impl fmt::Debug for PyObject { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[PyObj {:?}]", self.payload) + write!(f, "[PyObj {:?}]", &self.payload) } } @@ -1127,21 +1154,24 @@ impl PyValue for PyIteratorValue { } } -impl PyObject { - pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { +impl PyObject +where + T: Sized + PyObjectPayload, +{ + pub fn new(payload: T, typ: PyObjectRef) -> PyObjectRef { PyObject { typ, dict: Some(RefCell::new(PyAttributes::new())), - payload: Box::new(payload), + payload, } .into_ref() } - pub fn new_without_dict(payload: T, typ: PyObjectRef) -> PyObjectRef { + pub fn new_without_dict(payload: T, typ: PyObjectRef) -> PyObjectRef { PyObject { typ, dict: None, - payload: Box::new(payload), + payload, } .into_ref() } @@ -1150,7 +1180,9 @@ impl PyObject { pub fn into_ref(self) -> PyObjectRef { Rc::new(self) } +} +impl PyObject { #[inline] pub fn payload(&self) -> Option<&T> { self.payload.as_any().downcast_ref() @@ -1213,7 +1245,7 @@ impl FromPyObjectRef for PyRef { #[cfg(test)] mod tests { - use super::PyContext; + use super::*; #[test] fn test_type_type() { diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 7f9b474d0..491d391ce 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -333,7 +333,7 @@ impl VirtualMachine { } // TODO: is it safe to just invoke __call__ otherwise? - trace!("invoke __call__ for: {:?}", func_ref.payload); + trace!("invoke __call__ for: {:?}", &func_ref.payload); self.call_method(&func_ref, "__call__", args) }