mirror of https://github.com/python/cpython
gh-114626: add PyCFunctionFast and PyCFunctionFastWithKeywords (GH-114627)
Co-authored-by: Petr Viktorin <encukou@gmail.com>
This commit is contained in:
parent
32f8ab1ab6
commit
9e3729bbd7
|
@ -187,23 +187,23 @@ Implementing functions and methods
|
|||
PyObject *kwargs);
|
||||
|
||||
|
||||
.. c:type:: _PyCFunctionFast
|
||||
.. c:type:: PyCFunctionFast
|
||||
|
||||
Type of the functions used to implement Python callables in C
|
||||
with signature :c:macro:`METH_FASTCALL`.
|
||||
The function signature is::
|
||||
|
||||
PyObject *_PyCFunctionFast(PyObject *self,
|
||||
PyObject *PyCFunctionFast(PyObject *self,
|
||||
PyObject *const *args,
|
||||
Py_ssize_t nargs);
|
||||
|
||||
.. c:type:: _PyCFunctionFastWithKeywords
|
||||
.. c:type:: PyCFunctionFastWithKeywords
|
||||
|
||||
Type of the functions used to implement Python callables in C
|
||||
with signature :ref:`METH_FASTCALL | METH_KEYWORDS <METH_FASTCALL-METH_KEYWORDS>`.
|
||||
The function signature is::
|
||||
|
||||
PyObject *_PyCFunctionFastWithKeywords(PyObject *self,
|
||||
PyObject *PyCFunctionFastWithKeywords(PyObject *self,
|
||||
PyObject *const *args,
|
||||
Py_ssize_t nargs,
|
||||
PyObject *kwnames);
|
||||
|
@ -290,7 +290,7 @@ There are these calling conventions:
|
|||
.. c:macro:: METH_FASTCALL
|
||||
|
||||
Fast calling convention supporting only positional arguments.
|
||||
The methods have the type :c:type:`_PyCFunctionFast`.
|
||||
The methods have the type :c:type:`PyCFunctionFast`.
|
||||
The first parameter is *self*, the second parameter is a C array
|
||||
of :c:expr:`PyObject*` values indicating the arguments and the third
|
||||
parameter is the number of arguments (the length of the array).
|
||||
|
@ -306,7 +306,7 @@ There are these calling conventions:
|
|||
|
||||
:c:expr:`METH_FASTCALL | METH_KEYWORDS`
|
||||
Extension of :c:macro:`METH_FASTCALL` supporting also keyword arguments,
|
||||
with methods of type :c:type:`_PyCFunctionFastWithKeywords`.
|
||||
with methods of type :c:type:`PyCFunctionFastWithKeywords`.
|
||||
Keyword arguments are passed the same way as in the
|
||||
:ref:`vectorcall protocol <vectorcall>`:
|
||||
there is an additional fourth :c:expr:`PyObject*` parameter
|
||||
|
|
|
@ -42,6 +42,8 @@ function,PyBytes_Repr,3.2,,
|
|||
function,PyBytes_Size,3.2,,
|
||||
var,PyBytes_Type,3.2,,
|
||||
type,PyCFunction,3.2,,
|
||||
type,PyCFunctionFast,3.13,,
|
||||
type,PyCFunctionFastWithKeywords,3.13,,
|
||||
type,PyCFunctionWithKeywords,3.2,,
|
||||
function,PyCFunction_GetFlags,3.2,,
|
||||
function,PyCFunction_GetFunction,3.2,,
|
||||
|
|
|
@ -17,15 +17,22 @@ PyAPI_DATA(PyTypeObject) PyCFunction_Type;
|
|||
#define PyCFunction_Check(op) PyObject_TypeCheck((op), &PyCFunction_Type)
|
||||
|
||||
typedef PyObject *(*PyCFunction)(PyObject *, PyObject *);
|
||||
typedef PyObject *(*_PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t);
|
||||
typedef PyObject *(*PyCFunctionFast) (PyObject *, PyObject *const *, Py_ssize_t);
|
||||
typedef PyObject *(*PyCFunctionWithKeywords)(PyObject *, PyObject *,
|
||||
PyObject *);
|
||||
typedef PyObject *(*_PyCFunctionFastWithKeywords) (PyObject *,
|
||||
typedef PyObject *(*PyCFunctionFastWithKeywords) (PyObject *,
|
||||
PyObject *const *, Py_ssize_t,
|
||||
PyObject *);
|
||||
typedef PyObject *(*PyCMethod)(PyObject *, PyTypeObject *, PyObject *const *,
|
||||
size_t, PyObject *);
|
||||
|
||||
// For backwards compatibility. `METH_FASTCALL` was added to the stable API in
|
||||
// 3.10 alongside `_PyCFunctionFastWithKeywords` and `_PyCFunctionFast`.
|
||||
// Note that the underscore-prefixed names were documented in public docs;
|
||||
// people may be using them.
|
||||
typedef PyCFunctionFast _PyCFunctionFast;
|
||||
typedef PyCFunctionWithKeywords _PyCFunctionWithKeywords;
|
||||
|
||||
// Cast an function to the PyCFunction type to use it with PyMethodDef.
|
||||
//
|
||||
// This macro can be used to prevent compiler warnings if the first parameter
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Add ``PyCFunctionFast`` and ``PyCFunctionFastWithKeywords`` typedefs (identical to the existing ``_PyCFunctionFast`` and ``_PyCFunctionFastWithKeywords`` typedefs, just without a leading ``_`` prefix).
|
|
@ -2489,3 +2489,10 @@
|
|||
added = '3.13'
|
||||
[function.PyList_GetItemRef]
|
||||
added = '3.13'
|
||||
[typedef.PyCFunctionFast]
|
||||
added = '3.13'
|
||||
# "abi-only" since 3.10. (Callback type names aren't used in C code,
|
||||
# but this function signature was expected with METH_FASTCALL.)
|
||||
[typedef.PyCFunctionFastWithKeywords]
|
||||
added = '3.13'
|
||||
# "abi-only" since 3.10. (Same story as PyCFunctionFast.)
|
||||
|
|
|
@ -393,7 +393,7 @@ method_vectorcall_FASTCALL(
|
|||
if (method_check_args(func, args, nargs, kwnames)) {
|
||||
return NULL;
|
||||
}
|
||||
_PyCFunctionFast meth = (_PyCFunctionFast)
|
||||
PyCFunctionFast meth = (PyCFunctionFast)
|
||||
method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
|
@ -412,7 +412,7 @@ method_vectorcall_FASTCALL_KEYWORDS(
|
|||
if (method_check_args(func, args, nargs, NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
||||
PyCFunctionFastWithKeywords meth = (PyCFunctionFastWithKeywords)
|
||||
method_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
|
|
|
@ -417,7 +417,7 @@ cfunction_vectorcall_FASTCALL(
|
|||
return NULL;
|
||||
}
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
_PyCFunctionFast meth = (_PyCFunctionFast)
|
||||
PyCFunctionFast meth = (PyCFunctionFast)
|
||||
cfunction_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
|
@ -433,7 +433,7 @@ cfunction_vectorcall_FASTCALL_KEYWORDS(
|
|||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
|
||||
_PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
|
||||
PyCFunctionFastWithKeywords meth = (PyCFunctionFastWithKeywords)
|
||||
cfunction_enter_call(tstate, func);
|
||||
if (meth == NULL) {
|
||||
return NULL;
|
||||
|
@ -552,4 +552,3 @@ cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
|
|||
}
|
||||
return _Py_CheckFunctionResult(tstate, func, result, NULL);
|
||||
}
|
||||
|
||||
|
|
|
@ -3376,7 +3376,7 @@ dummy_func(
|
|||
STAT_INC(CALL, hit);
|
||||
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
|
||||
/* res = func(self, args, nargs) */
|
||||
res = ((_PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
res = ((PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyCFunction_GET_SELF(callable),
|
||||
args,
|
||||
total_args);
|
||||
|
@ -3407,8 +3407,8 @@ dummy_func(
|
|||
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS));
|
||||
STAT_INC(CALL, hit);
|
||||
/* res = func(self, args, nargs, kwnames) */
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunction_GET_FUNCTION(callable);
|
||||
res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
@ -3539,8 +3539,8 @@ dummy_func(
|
|||
DEOPT_IF(!Py_IS_TYPE(self, d_type));
|
||||
STAT_INC(CALL, hit);
|
||||
int nargs = total_args - 1;
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
res = cfunc(self, args + 1, nargs, NULL);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
||||
|
@ -3597,8 +3597,8 @@ dummy_func(
|
|||
PyObject *self = args[0];
|
||||
DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type));
|
||||
STAT_INC(CALL, hit);
|
||||
_PyCFunctionFast cfunc =
|
||||
(_PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFast cfunc =
|
||||
(PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
int nargs = total_args - 1;
|
||||
res = cfunc(self, args + 1, nargs);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
|
|
@ -2843,7 +2843,7 @@
|
|||
STAT_INC(CALL, hit);
|
||||
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
|
||||
/* res = func(self, args, nargs) */
|
||||
res = ((_PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
res = ((PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyCFunction_GET_SELF(callable),
|
||||
args,
|
||||
total_args);
|
||||
|
@ -2884,8 +2884,8 @@
|
|||
if (PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS)) goto deoptimize;
|
||||
STAT_INC(CALL, hit);
|
||||
/* res = func(self, args, nargs, kwnames) */
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunction_GET_FUNCTION(callable);
|
||||
res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
@ -3036,8 +3036,8 @@
|
|||
if (!Py_IS_TYPE(self, d_type)) goto deoptimize;
|
||||
STAT_INC(CALL, hit);
|
||||
int nargs = total_args - 1;
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
res = cfunc(self, args + 1, nargs, NULL);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
/* Free the arguments. */
|
||||
|
@ -3115,8 +3115,8 @@
|
|||
PyObject *self = args[0];
|
||||
if (!Py_IS_TYPE(self, method->d_common.d_type)) goto deoptimize;
|
||||
STAT_INC(CALL, hit);
|
||||
_PyCFunctionFast cfunc =
|
||||
(_PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFast cfunc =
|
||||
(PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
int nargs = total_args - 1;
|
||||
res = cfunc(self, args + 1, nargs);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
|
|
@ -1069,7 +1069,7 @@
|
|||
STAT_INC(CALL, hit);
|
||||
PyCFunction cfunc = PyCFunction_GET_FUNCTION(callable);
|
||||
/* res = func(self, args, nargs) */
|
||||
res = ((_PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
res = ((PyCFunctionFast)(void(*)(void))cfunc)(
|
||||
PyCFunction_GET_SELF(callable),
|
||||
args,
|
||||
total_args);
|
||||
|
@ -1115,8 +1115,8 @@
|
|||
DEOPT_IF(PyCFunction_GET_FLAGS(callable) != (METH_FASTCALL | METH_KEYWORDS), CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
/* res = func(self, args, nargs, kwnames) */
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))
|
||||
PyCFunction_GET_FUNCTION(callable);
|
||||
res = cfunc(PyCFunction_GET_SELF(callable), args, total_args, NULL);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
@ -1523,8 +1523,8 @@
|
|||
PyObject *self = args[0];
|
||||
DEOPT_IF(!Py_IS_TYPE(self, method->d_common.d_type), CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
_PyCFunctionFast cfunc =
|
||||
(_PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFast cfunc =
|
||||
(PyCFunctionFast)(void(*)(void))meth->ml_meth;
|
||||
int nargs = total_args - 1;
|
||||
res = cfunc(self, args + 1, nargs);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
|
@ -1568,8 +1568,8 @@
|
|||
DEOPT_IF(!Py_IS_TYPE(self, d_type), CALL);
|
||||
STAT_INC(CALL, hit);
|
||||
int nargs = total_args - 1;
|
||||
_PyCFunctionFastWithKeywords cfunc =
|
||||
(_PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
PyCFunctionFastWithKeywords cfunc =
|
||||
(PyCFunctionFastWithKeywords)(void(*)(void))meth->ml_meth;
|
||||
res = cfunc(self, args + 1, nargs, NULL);
|
||||
assert((res != NULL) ^ (_PyErr_Occurred(tstate) != NULL));
|
||||
/* Free the arguments. */
|
||||
|
|
Loading…
Reference in New Issue