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

FFI for PEP 590 Vectorcall #641

Merged
merged 1 commit into from
Oct 24, 2019
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
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).

## Unreleased

### Added

* FFI compatibility for PEP 590 Vectorcall.

## [0.8.1]

### Added
Expand Down
40 changes: 37 additions & 3 deletions src/ffi/methodobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,39 @@ pub unsafe fn PyCFunction_Check(op: *mut PyObject) -> c_int {
pub type PyCFunction =
unsafe extern "C" fn(slf: *mut PyObject, args: *mut PyObject) -> *mut PyObject;

#[cfg(all(Py_3_6, not(Py_LIMITED_API)))]
#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]
#[cfg_attr(Py_3_8, link_name = "_PyObject_Vectorcall")]
pub type PyObject_Vectorcall = unsafe extern "C" fn(
slf: *mut PyObject,
// positional and keyword arguments
args: *const *mut PyObject,
// number of position arguments in args, after which values are kwargs
nargs: crate::ffi::pyport::Py_ssize_t,
// tuple of kwargs, if given, or null
kwnames: *mut PyObject,
) -> *mut PyObject;

#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]
#[cfg_attr(Py_3_8, link_name = "PyVectorcall_Call")]
pub type PyVectorcall_Call = unsafe extern "C" fn(
obj: *mut PyObject,
tuple: *mut PyObject,
dict: *mut PyObject,
) -> *mut PyObject;

#[cfg(all(Py_3_7, not(Py_LIMITED_API)))]
const PY_VECTORCALL_ARGUMENTS_OFFSET: crate::ffi::pyport::Py_ssize_t =
1 << (8 * std::mem::size_of::<usize>() - 1);

#[cfg(all(Py_3_7, not(Py_LIMITED_API)))]
#[inline(always)]
pub unsafe fn PyVectorcall_NARGS(
n: crate::ffi::pyport::Py_ssize_t,
) -> crate::ffi::pyport::Py_ssize_t {
n & !PY_VECTORCALL_ARGUMENTS_OFFSET
}

#[cfg(all(Py_3_7, not(Py_LIMITED_API)))]
pub type _PyCFunctionFast = unsafe extern "C" fn(
slf: *mut PyObject,
args: *mut *mut PyObject,
Expand Down Expand Up @@ -102,8 +134,10 @@ slot like sq_contains. */

pub const METH_COEXIST: c_int = 0x0040;

#[cfg(all(Py_3_6, not(Py_LIMITED_API)))]
pub const METHOD_FASTCALL: c_int = 0x0080;
/* METH_FASTCALL indicates the PEP 590 Vectorcall calling format. It may
be specified alone or with METH_KEYWORDS. */
#[cfg(all(Py_3_7, not(Py_LIMITED_API)))]
pub const METH_FASTCALL: c_int = 0x0080;

#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
Expand Down
10 changes: 10 additions & 0 deletions src/ffi/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,10 @@ mod typeobject {
pub tp_basicsize: Py_ssize_t,
pub tp_itemsize: Py_ssize_t,
pub tp_dealloc: Option<object::destructor>,
#[cfg(not(Py_3_8))]
pub tp_print: Option<object::printfunc>,
#[cfg(Py_3_8)]
pub tp_vectorcall_offset: Py_ssize_t,
pub tp_getattr: Option<object::getattrfunc>,
pub tp_setattr: Option<object::setattrfunc>,
pub tp_as_async: *mut PyAsyncMethods,
Expand Down Expand Up @@ -529,7 +532,10 @@ mod typeobject {
tp_basicsize: 0,
tp_itemsize: 0,
tp_dealloc: None,
#[cfg(not(Py_3_8))]
tp_print: None,
#[cfg(Py_3_8)]
tp_vectorcall_offset: 0,
tp_getattr: None,
tp_setattr: None,
$tp_as_async: ptr::null_mut(),
Expand Down Expand Up @@ -847,6 +853,10 @@ pub const Py_TPFLAGS_HEAPTYPE: c_ulong = (1 << 9);
/// Set if the type allows subclassing
pub const Py_TPFLAGS_BASETYPE: c_ulong = (1 << 10);

/// Set if the type implements the vectorcall protocol (PEP 590)
#[cfg(all(Py_3_8, not(Py_LIMITED_API)))]
pub const _Py_TPFLAGS_HAVE_VECTORCALL: c_ulong = (1 << 11);

/// Set if the type is 'ready' -- fully initialized
pub const Py_TPFLAGS_READY: c_ulong = (1 << 12);

Expand Down