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 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
#![feature(proc_macro, specialization)]
#![feature(proc_macro, specialization, const_fn)]
extern crate pyo3;
```

View File

@ -106,9 +106,9 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
impl _pyo3::ToPyPointer for #cls {
#[inline]
fn as_ptr(&self) -> *mut ffi::PyObject {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
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 DESCRIPTION: &'static str = #doc;
#[inline]
fn size() -> usize {
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();
const SIZE: usize = Self::OFFSET as usize + std::mem::size_of::<#cls>();
const OFFSET: isize = {
// 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]
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;
if checked {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls;
let ptr = (ptr as *mut u8)
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_ref().unwrap())
} else {
None
@ -233,8 +226,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
let ptr = ob.as_ptr();
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).offset(offset) as *mut #cls;
let ptr = (ptr as *mut u8)
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_ref().unwrap())
} else {
None
@ -245,15 +238,15 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
#[inline]
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).offset(offset) as *mut #cls;
let ptr = (ob.as_ptr() as *mut u8)
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
&*ptr
}
#[inline]
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).offset(offset) as *mut #cls;
let ptr = (ob.as_ptr() as *mut u8)
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
&mut *ptr
}
}
@ -267,8 +260,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
ptr, <#cls as _pyo3::typeob::PyTypeInfo>::type_object()) != 0;
if checked {
let offset = <#cls as _pyo3::typeob::PyTypeInfo>::offset();
let ptr = (ptr as *mut u8).offset(offset) as *mut #cls;
let ptr = (ptr as *mut u8)
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_mut().unwrap())
} else {
None
@ -281,8 +274,8 @@ fn impl_class(cls: &syn::Ident, base: &syn::Ident,
let ptr = ob.as_ptr();
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).offset(offset) as *mut #cls;
let ptr = (ptr as *mut u8)
.offset(<#cls as _pyo3::typeob::PyTypeInfo>::OFFSET) as *mut #cls;
Some(ptr.as_mut().unwrap())
} else {
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)
};
let offset = <T as PyTypeInfo>::offset();
let ptr = (obj as *mut u8).offset(offset) as *mut T;
let ptr = (obj as *mut u8).offset(<T as PyTypeInfo>::OFFSET) as *mut T;
std::ptr::write(ptr, value);
Ok(obj)
}
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);
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]
default fn as_ref(&self, _py: Python) -> &T {
let offset = <T as PyTypeInfo>::offset();
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()
}
}
#[inline]
default fn as_mut(&self, _py: Python) -> &mut T {
let offset = <T as PyTypeInfo>::offset();
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()
}
}

View File

@ -138,15 +138,9 @@ macro_rules! pyobject_nativetype(
impl $crate::typeob::PyTypeInfo for $name {
type Type = ();
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]
unsafe fn type_object() -> &'static mut $crate::ffi::PyTypeObject {
&mut $crate::ffi::$typeobject

View File

@ -18,16 +18,18 @@ use class::methods::PyMethodDefType;
pub trait PyTypeInfo {
/// Type of objects to store in PyObject struct
type Type;
/// Class name
const NAME: &'static str;
/// Class doc string
const DESCRIPTION: &'static str = "\0";
/// Size of the PyObject structure
fn size() -> usize;
/// Size of the rust PyObject structure (PyObject + rust structure)
const SIZE: usize;
/// `Type` instance offset inside PyObject structure
fn offset() -> isize;
const OFFSET: isize;
/// PyTypeObject instance for this type
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 {
type Type = T::Type;
const NAME: &'static str = T::NAME;
#[inline]
default fn size() -> usize {
<T as PyTypeInfo>::size()
}
#[inline]
default fn offset() -> isize {
<T as PyTypeInfo>::offset()
}
const DESCRIPTION: &'static str = T::DESCRIPTION;
const SIZE: usize = T::SIZE;
const OFFSET: isize = T::OFFSET;
#[inline]
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> {
// TODO: remove this
<T as PyTypeObject>::init_type(py);
T::init_type(py);
let obj = ffi::PyType_GenericAlloc(
<Self as PyTypeInfo>::type_object(), 0);
let obj = ffi::PyType_GenericAlloc(T::type_object(), 0);
let offset = <Self as PyTypeInfo>::offset();
let ptr = (obj as *mut u8).offset(offset) as *mut T;
let ptr = (obj as *mut u8).offset(T::OFFSET) as *mut T;
std::ptr::write(ptr, value);
Ok(obj)
}
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);
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 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
<T as class::gc::PyGCProtocolImpl>::update_type_object(type_object);

View File

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

View File

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

View File

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