Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update definitions for objimpl.h #3403

Merged
merged 1 commit into from
Aug 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/3403.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add FFI definitions `PyObject_GC_IsTracked` and `PyObject_GC_IsFinalized` on Python 3.9 and up (PyPy 3.10 and up).
1 change: 1 addition & 0 deletions newsfragments/3403.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Disable removed FFI definitions `_Py_GetAllocatedBlocks`, `_PyObject_GC_Malloc`, and `_PyObject_GC_Calloc` on Python 3.11 and up.
2 changes: 2 additions & 0 deletions pyo3-ffi/src/cpython/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub(crate) mod listobject;
#[cfg(all(Py_3_9, not(PyPy)))]
pub(crate) mod methodobject;
pub(crate) mod object;
pub(crate) mod objimpl;
pub(crate) mod pydebug;
pub(crate) mod pyerrors;
#[cfg(all(Py_3_8, not(PyPy)))]
Expand Down Expand Up @@ -54,6 +55,7 @@ pub use self::listobject::*;
#[cfg(all(Py_3_9, not(PyPy)))]
pub use self::methodobject::*;
pub use self::object::*;
pub use self::objimpl::*;
pub use self::pydebug::*;
pub use self::pyerrors::*;
#[cfg(all(Py_3_8, not(PyPy)))]
Expand Down
71 changes: 71 additions & 0 deletions pyo3-ffi/src/cpython/objimpl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
use libc::size_t;
use std::os::raw::c_int;

#[cfg(not(PyPy))]
use std::os::raw::c_void;

use crate::object::*;

// skipped _PyObject_SIZE
// skipped _PyObject_VAR_SIZE

#[cfg(not(Py_3_11))]
extern "C" {
pub fn _Py_GetAllocatedBlocks() -> crate::Py_ssize_t;
}

#[cfg(not(PyPy))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyObjectArenaAllocator {
pub ctx: *mut c_void,
pub alloc: Option<extern "C" fn(ctx: *mut c_void, size: size_t) -> *mut c_void>,
pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void, size: size_t)>,
}

#[cfg(not(PyPy))]
impl Default for PyObjectArenaAllocator {
#[inline]
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}

extern "C" {
#[cfg(not(PyPy))]
pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
#[cfg(not(PyPy))]
pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator);

#[cfg(Py_3_9)]
pub fn PyObject_IS_GC(o: *mut PyObject) -> c_int;
}

#[inline]
#[cfg(not(Py_3_9))]
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
(crate::PyType_IS_GC(Py_TYPE(o)) != 0
&& match (*Py_TYPE(o)).tp_is_gc {
Some(tp_is_gc) => tp_is_gc(o) != 0,
None => true,
}) as c_int
}

#[cfg(not(Py_3_11))]
extern "C" {
pub fn _PyObject_GC_Malloc(size: size_t) -> *mut PyObject;
pub fn _PyObject_GC_Calloc(size: size_t) -> *mut PyObject;
}

#[inline]
pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {
((*t).tp_weaklistoffset > 0) as c_int
}

#[inline]
pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {
let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset;
o.offset(weaklistoffset) as *mut *mut PyObject
}

// skipped PyUnstable_Object_GC_NewWithExtraData
86 changes: 31 additions & 55 deletions pyo3-ffi/src/objimpl.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::object::*;
use crate::pyport::Py_ssize_t;
use libc::size_t;
use std::os::raw::{c_int, c_void};

use crate::object::*;
use crate::pyport::Py_ssize_t;

extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyObject_Malloc")]
pub fn PyObject_Malloc(size: size_t) -> *mut c_void;
Expand All @@ -12,8 +13,12 @@ extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyObject_Free")]
pub fn PyObject_Free(ptr: *mut c_void);

#[cfg(not(Py_LIMITED_API))]
pub fn _Py_GetAllocatedBlocks() -> Py_ssize_t;
// skipped PyObject_MALLOC
// skipped PyObject_REALLOC
// skipped PyObject_FREE
// skipped PyObject_Del
// skipped PyObject_DEL

#[cfg_attr(PyPy, link_name = "PyPyObject_Init")]
pub fn PyObject_Init(arg1: *mut PyObject, arg2: *mut PyTypeObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyObject_InitVar")]
Expand All @@ -22,11 +27,20 @@ extern "C" {
arg2: *mut PyTypeObject,
arg3: Py_ssize_t,
) -> *mut PyVarObject;

// skipped PyObject_INIT
// skipped PyObject_INIT_VAR

#[cfg_attr(PyPy, link_name = "_PyPyObject_New")]
pub fn _PyObject_New(arg1: *mut PyTypeObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "_PyPyObject_NewVar")]
pub fn _PyObject_NewVar(arg1: *mut PyTypeObject, arg2: Py_ssize_t) -> *mut PyVarObject;

// skipped PyObject_New
// skipped PyObject_NEW
// skipped PyObject_NewVar
// skipped PyObject_NEW_VAR

pub fn PyGC_Collect() -> Py_ssize_t;

#[cfg(Py_3_10)]
Expand All @@ -40,56 +54,20 @@ extern "C" {
#[cfg(Py_3_10)]
#[cfg_attr(PyPy, link_name = "PyPyGC_IsEnabled")]
pub fn PyGC_IsEnabled() -> c_int;
}

#[cfg(not(any(Py_LIMITED_API, PyPy)))]
#[repr(C)]
#[derive(Copy, Clone)]
pub struct PyObjectArenaAllocator {
pub ctx: *mut c_void,
pub alloc: Option<extern "C" fn(ctx: *mut c_void, size: size_t) -> *mut c_void>,
pub free: Option<extern "C" fn(ctx: *mut c_void, ptr: *mut c_void, size: size_t)>,
}

#[cfg(not(any(Py_LIMITED_API, PyPy)))]
impl Default for PyObjectArenaAllocator {
#[inline]
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
// skipped PyUnstable_GC_VisitObjects
}

extern "C" {
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
pub fn PyObject_GetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
#[cfg(not(any(Py_LIMITED_API, PyPy)))]
pub fn PyObject_SetArenaAllocator(allocator: *mut PyObjectArenaAllocator);
}

/// Test if a type has a GC head
#[inline]
pub unsafe fn PyType_IS_GC(t: *mut PyTypeObject) -> c_int {
PyType_HasFeature(t, Py_TPFLAGS_HAVE_GC)
}

/// Test if an object has a GC head
#[inline]
#[cfg(not(Py_LIMITED_API))]
pub unsafe fn PyObject_IS_GC(o: *mut PyObject) -> c_int {
(PyType_IS_GC(Py_TYPE(o)) != 0
&& match (*Py_TYPE(o)).tp_is_gc {
Some(tp_is_gc) => tp_is_gc(o) != 0,
None => true,
}) as c_int
}

extern "C" {
pub fn _PyObject_GC_Resize(arg1: *mut PyVarObject, arg2: Py_ssize_t) -> *mut PyVarObject;

#[cfg(not(Py_LIMITED_API))]
pub fn _PyObject_GC_Malloc(size: size_t) -> *mut PyObject;
#[cfg(not(Py_LIMITED_API))]
pub fn _PyObject_GC_Calloc(size: size_t) -> *mut PyObject;
// skipped PyObject_GC_Resize

#[cfg_attr(PyPy, link_name = "_PyPyObject_GC_New")]
pub fn _PyObject_GC_New(arg1: *mut PyTypeObject) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "_PyPyObject_GC_NewVar")]
Expand All @@ -98,18 +76,16 @@ extern "C" {
pub fn PyObject_GC_UnTrack(arg1: *mut c_void);
#[cfg_attr(PyPy, link_name = "PyPyObject_GC_Del")]
pub fn PyObject_GC_Del(arg1: *mut c_void);
}

/// Test if a type supports weak references
#[inline]
#[cfg(not(Py_LIMITED_API))]
pub unsafe fn PyType_SUPPORTS_WEAKREFS(t: *mut PyTypeObject) -> c_int {
((*t).tp_weaklistoffset > 0) as c_int
}
// skipped PyObject_GC_New
// skipped PyObject_GC_NewVar

#[inline]
#[cfg(not(Py_LIMITED_API))]
pub unsafe fn PyObject_GET_WEAKREFS_LISTPTR(o: *mut PyObject) -> *mut *mut PyObject {
let weaklistoffset = (*Py_TYPE(o)).tp_weaklistoffset;
o.offset(weaklistoffset) as *mut *mut PyObject
#[cfg(any(all(Py_3_9, not(PyPy)), Py_3_10))] // added in 3.9, or 3.10 on PyPy
#[cfg_attr(PyPy, link_name = "PyPyObject_GC_IsTracked")]
pub fn PyObject_GC_IsTracked(arg1: *mut PyObject) -> c_int;
#[cfg(any(all(Py_3_9, not(PyPy)), Py_3_10))] // added in 3.9, or 3.10 on PyPy
#[cfg_attr(PyPy, link_name = "PyPyObject_GC_IsFinalized")]
pub fn PyObject_GC_IsFinalized(arg1: *mut PyObject) -> c_int;
}

// skipped Py_VISIT