Remove Box from PyObject

This commit is contained in:
Joey Hain
2019-03-22 18:04:09 -07:00
parent 08520a68cf
commit bb161a5a67
4 changed files with 61 additions and 38 deletions

View File

@@ -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<Vec<PyClassRef>>) -> Option<(PyClassRef, Vec<Ve
for base in &bases {
let head = base[0].clone();
if !(&bases)
.iter()
.any(|x| x[1..].iter().any(|x| x.get_id() == head.get_id()))
{
if !(&bases).iter().any(|x| x[1..].iter().any(|x| x.is(&head))) {
next = Some(head);
break;
}
@@ -311,7 +302,7 @@ fn take_next_base(mut bases: Vec<Vec<PyClassRef>>) -> Option<(PyClassRef, Vec<Ve
if let Some(head) = next {
for item in &mut bases {
if item[0].get_id() == head.get_id() {
if item[0].is(&head) {
item.remove(0);
}
}
@@ -347,10 +338,10 @@ pub fn new(
let mros = bases.into_iter().map(|x| _mro(&x)).collect();
let mro = linearise_mro(mros).unwrap();
Ok(PyObject {
payload: Box::new(PyClass {
payload: PyClass {
name: String::from(name),
mro,
}),
},
dict: Some(RefCell::new(dict)),
typ,
}

View File

@@ -1,13 +1,13 @@
use crate::obj::objtype::PyClassRef;
use crate::pyobject::PyValue;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyRef, PyResult};
use crate::pyobject::{PyContext, PyObject, PyObjectPayload, PyObjectRef, PyRef, PyResult};
use crate::vm::VirtualMachine;
use std::rc::{Rc, Weak};
#[derive(Debug)]
pub struct PyWeak {
referent: Weak<PyObject>,
referent: Weak<PyObject<dyn PyObjectPayload>>,
}
impl PyWeak {

View File

@@ -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<PyObject>;
pub type PyObjectRef = Rc<PyObject<dyn PyObjectPayload>>;
/// 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<T = PyObjectRef> = Result<T, PyObjectRef>; // A valid value, o
/// faster, unordered, and only supports strings as keys.
pub type PyAttributes = HashMap<String, PyObjectRef>;
impl fmt::Display for PyObject {
impl fmt::Display for PyObject<dyn PyObjectPayload> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::TypeProtocol;
if let Some(PyClass { ref name, .. }) = self.payload::<PyClass>() {
@@ -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<PyClass>;
let type_type_ptr = PyObjectRef::into_raw(type_type.clone()) as *mut PyObject<PyClass>;
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<T>
where
T: ?Sized + PyObjectPayload,
{
pub typ: PyObjectRef,
pub dict: Option<RefCell<PyAttributes>>, // __dict__ member
pub payload: Box<dyn PyObjectPayload>,
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<T: ?Sized + PyObjectPayload> IdProtocol for PyObject<T> {
fn get_id(&self) -> usize {
&*self as &PyObject as *const PyObject as usize
self as *const _ as *const PyObject<Never> as usize
}
}
impl<T: ?Sized + IdProtocol> IdProtocol for Rc<T> {
fn get_id(&self) -> usize {
(**self).get_id()
}
}
impl<T: PyObjectPayload> IdProtocol for PyRef<T> {
fn get_id(&self) -> usize {
self.obj.get_id()
}
}
@@ -814,7 +838,10 @@ impl TypeProtocol for PyObjectRef {
}
}
impl TypeProtocol for PyObject {
impl<T> TypeProtocol for PyObject<T>
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<dyn PyObjectPayload> {
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<T: PyObjectPayload>(payload: T, typ: PyObjectRef) -> PyObjectRef {
impl<T> PyObject<T>
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<T: PyObjectPayload>(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<dyn PyObjectPayload> {
#[inline]
pub fn payload<T: PyObjectPayload>(&self) -> Option<&T> {
self.payload.as_any().downcast_ref()
@@ -1213,7 +1245,7 @@ impl FromPyObjectRef for PyRef<PyClass> {
#[cfg(test)]
mod tests {
use super::PyContext;
use super::*;
#[test]
fn test_type_type() {

View File

@@ -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)
}