use const_fn for type size and offset calculation

This commit is contained in:
Nikolay Kim 2017-07-21 09:48:48 -07:00
parent 2ee6419464
commit 98bdf63a4d
9 changed files with 44 additions and 66 deletions

View File

@ -1,10 +1,11 @@
# Python Class # Python Class
Python class generation is powered by unstable [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) and Python class generation is powered by unstable [Procedural Macros](https://doc.rust-lang.org/book/first-edition/procedural-macros.html) and
[Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) features, so you need to turn on `proc_macro` and `specialization` features: [Specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) and [Const fn](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md)
features, so you need to turn on `proc_macro` and `specialization` features:
```rust ```rust
#![feature(proc_macro, specialization)] #![feature(proc_macro, specialization, const_fn)]
extern crate pyo3; extern crate pyo3;
``` ```

View File

@ -106,9 +106,9 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
impl _pyo3::ToPyPointer for #cls { impl _pyo3::ToPyPointer for #cls {
#[inline] #[inline]
fn as_ptr(&self) -> *mut ffi::PyObject { fn as_ptr(&self) -> *mut ffi::PyObject {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
unsafe { unsafe {
{self as *const _ as *mut u8}.offset(-offset) as *mut ffi::PyObject {self as *const _ as *mut u8}
.offset(-<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ffi::PyObject
} }
} }
} }
@ -164,19 +164,12 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
const NAME: &'static str = #cls_name; const NAME: &'static str = #cls_name;
const DESCRIPTION: &'static str = #doc; const DESCRIPTION: &'static str = #doc;
#[inline] const SIZE: usize = Self::OFFSET as usize + std::mem::size_of::<#cls>();
fn size() -> usize { const OFFSET: isize = {
Self::offset() as usize + std::mem::size_of::<#cls>()
}
#[inline]
fn offset() -> isize {
let align = std::mem::align_of::<#cls>();
let bs = <#base as _pyo3::typeob::PyTypeInfo>::size();
// round base_size up to next multiple of align // round base_size up to next multiple of align
((bs + align - 1) / align * align) as isize ((<#base as _pyo3::typeob::PyTypeInfo>::SIZE + std::mem::align_of::<#cls>() - 1) /
} std::mem::align_of::<#cls>() * std::mem::align_of::<#cls>()) as isize
};
#[inline] #[inline]
unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject { unsafe fn type_object() -> &'static mut _pyo3::ffi::PyTypeObject {
@ -218,8 +211,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0; ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
if checked { if checked {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset(); let ptr = (ptr as *mut u8)
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls; .offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_ref().unwrap()) Some(ptr.as_ref().unwrap())
} else { } else {
None None
@ -233,8 +226,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
let ptr = ob.as_ptr(); let ptr = ob.as_ptr();
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object() if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
{ {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset(); let ptr = (ptr as *mut u8)
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls; .offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_ref().unwrap()) Some(ptr.as_ref().unwrap())
} else { } else {
None None
@ -245,15 +238,15 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
#[inline] #[inline]
unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self unsafe fn unchecked_downcast_from(ob: &_pyo3::PyObjectRef) -> &Self
{ {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset(); let ptr = (ob.as_ptr() as *mut u8)
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls; .offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
&*ptr &*ptr
} }
#[inline] #[inline]
unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self unsafe fn unchecked_mut_downcast_from(ob: &_pyo3::PyObjectRef) -> &mut Self
{ {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset(); let ptr = (ob.as_ptr() as *mut u8)
let ptr = (ob.as_ptr() as *mut u8).offset(offset) as *mut #cls; .offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
&mut *ptr &mut *ptr
} }
} }
@ -267,8 +260,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0; ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
if checked { if checked {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset(); let ptr = (ptr as *mut u8)
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls; .offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_mut().unwrap()) Some(ptr.as_mut().unwrap())
} else { } else {
None None
@ -281,8 +274,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
let ptr = ob.as_ptr(); let ptr = ob.as_ptr();
if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object() if (*ptr).ob_type == <#cls as _pyo3::typeob::PyTypeInfo>::type_object()
{ {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset(); let ptr = (ptr as *mut u8)
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls; .offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_mut().unwrap()) Some(ptr.as_mut().unwrap())
} else { } else {
None None

View File

@ -81,15 +81,14 @@ impl<T> PyObjectAlloc<T> for T where T: PyObjectWithFreeList {
ffi::PyType_GenericAlloc(<T as PyTypeInfo>::type_object(), 0) ffi::PyType_GenericAlloc(<T as PyTypeInfo>::type_object(), 0)
}; };
let offset = <T as PyTypeInfo>::offset(); let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::OFFSET) as *mut T;
let ptr = (obj as *mut u8).offset(offset) as *mut T;
std::ptr::write(ptr, value); std::ptr::write(ptr, value);
Ok(obj) Ok(obj)
} }
unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) { unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::offset()) as *mut T; let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::OFFSET) as *mut T;
std::ptr::drop_in_place(ptr); std::ptr::drop_in_place(ptr);
if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) { if let Some(obj) = <T as PyObjectWithFreeList>::get_free_list().insert(obj) {

View File

@ -205,17 +205,15 @@ impl<T> AsPyRef<T> for Py<T> where T: PyTypeInfo {
#[inline] #[inline]
default fn as_ref(&self, _py: Python) -> &T { default fn as_ref(&self, _py: Python) -> &T {
let offset = <T as PyTypeInfo>::offset();
unsafe { unsafe {
let ptr = (self.as_ptr() as *mut u8).offset(offset) as *mut T; let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
ptr.as_ref().unwrap() ptr.as_ref().unwrap()
} }
} }
#[inline] #[inline]
default fn as_mut(&self, _py: Python) -> &mut T { default fn as_mut(&self, _py: Python) -> &mut T {
let offset = <T as PyTypeInfo>::offset();
unsafe { unsafe {
let ptr = (self.as_ptr() as *mut u8).offset(offset) as *mut T; let ptr = (self.as_ptr() as *mut u8).offset(T::OFFSET) as *mut T;
ptr.as_mut().unwrap() ptr.as_mut().unwrap()
} }
} }

View File

@ -138,15 +138,9 @@ macro_rules! pyobject_nativetype(
impl $crate::typeob::PyTypeInfo for $name { impl $crate::typeob::PyTypeInfo for $name {
type Type = (); type Type = ();
const NAME: &'static str = stringify!($name); const NAME: &'static str = stringify!($name);
const SIZE: usize = $crate::std::mem::size_of::<$crate::ffi::PyObject>();
const OFFSET: isize = 0;
#[inline]
fn size() -> usize {
$crate::std::mem::size_of::<$crate::ffi::PyObject>()
}
#[inline]
fn offset() -> isize {
0
}
#[inline] #[inline]
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject { unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
&mut $crate::ffi::$typeobject &mut $crate::ffi::$typeobject

View File

@ -18,16 +18,18 @@ use class::methods::PyMethodDefType;
pub trait PyTypeInfo { pub trait PyTypeInfo {
/// Type of objects to store in PyObject struct /// Type of objects to store in PyObject struct
type Type; type Type;
/// Class name /// Class name
const NAME: &'static str; const NAME: &'static str;
/// Class doc string /// Class doc string
const DESCRIPTION: &'static str = "\0"; const DESCRIPTION: &'static str = "\0";
/// Size of the PyObject structure /// Size of the rust PyObject structure (PyObject + rust structure)
fn size() -> usize; const SIZE: usize;
/// `Type` instance offset inside PyObject structure /// `Type` instance offset inside PyObject structure
fn offset() -> isize; const OFFSET: isize;
/// PyTypeObject instance for this type /// PyTypeObject instance for this type
unsafe fn type_object() -> &'static mut ffi::PyTypeObject; unsafe fn type_object() -> &'static mut ffi::PyTypeObject;
@ -41,16 +43,9 @@ pub trait PyTypeInfo {
impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo { impl<'a, T: ?Sized> PyTypeInfo for &'a T where T: PyTypeInfo {
type Type = T::Type; type Type = T::Type;
const NAME: &'static str = T::NAME; const NAME: &'static str = T::NAME;
const DESCRIPTION: &'static str = T::DESCRIPTION;
#[inline] const SIZE: usize = T::SIZE;
default fn size() -> usize { const OFFSET: isize = T::OFFSET;
<T as PyTypeInfo>::size()
}
#[inline]
default fn offset() -> isize {
<T as PyTypeInfo>::offset()
}
#[inline] #[inline]
default unsafe fn type_object() -> &'static mut ffi::PyTypeObject { default unsafe fn type_object() -> &'static mut ffi::PyTypeObject {
@ -81,20 +76,18 @@ impl<T> PyObjectAlloc<T> for T where T : PyTypeInfo {
default unsafe fn alloc(py: Python, value: T) -> PyResult<*mut ffi::PyObject> { default unsafe fn alloc(py: Python, value: T) -> PyResult<*mut ffi::PyObject> {
// TODO: remove this // TODO: remove this
<T as PyTypeObject>::init_type(py); T::init_type(py);
let obj = ffi::PyType_GenericAlloc( let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
<Self as PyTypeInfo>::type_object(), 0);
let offset = <Self as PyTypeInfo>::offset(); let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
let ptr = (obj as *mut u8).offset(offset) as *mut T;
std::ptr::write(ptr, value); std::ptr::write(ptr, value);
Ok(obj) Ok(obj)
} }
default unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) { default unsafe fn dealloc(_py: Python, obj: *mut ffi::PyObject) {
let ptr = (obj as *mut u8).offset(<Self as PyTypeInfo>::offset()) as *mut T; let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
std::ptr::drop_in_place(ptr); std::ptr::drop_in_place(ptr);
let ty = ffi::Py_TYPE(obj); let ty = ffi::Py_TYPE(obj);
@ -165,7 +158,7 @@ pub fn initialize_type<'p, T>(py: Python<'p>,
type_object.tp_dealloc = Some(tp_dealloc_callback::<T>); type_object.tp_dealloc = Some(tp_dealloc_callback::<T>);
// type size // type size
type_object.tp_basicsize = <T as PyTypeInfo>::size() as ffi::Py_ssize_t; type_object.tp_basicsize = <T as PyTypeInfo>::SIZE as ffi::Py_ssize_t;
// GC support // GC support
<T as class::gc::PyGCProtocolImpl>::update_type_object(type_object); <T as class::gc::PyGCProtocolImpl>::update_type_object(type_object);

View File

@ -1,5 +1,5 @@
#![allow(dead_code, unused_variables)] #![allow(dead_code, unused_variables)]
#![feature(proc_macro, specialization)] #![feature(proc_macro, specialization, const_fn)]
extern crate pyo3; extern crate pyo3;

View File

@ -1,4 +1,4 @@
#![feature(proc_macro, specialization)] #![feature(proc_macro, specialization, const_fn)]
#![allow(dead_code, unused_variables)] #![allow(dead_code, unused_variables)]
extern crate pyo3; extern crate pyo3;

View File

@ -1,4 +1,4 @@
#![feature(proc_macro, specialization)] #![feature(proc_macro, specialization, const_fn)]
#![allow(dead_code, unused_variables)] #![allow(dead_code, unused_variables)]
extern crate pyo3; extern crate pyo3;