https://github.com/python/cpython/commit/9e3729bbd77fb9dcaea6a06ac760160136d80b79
commit: 9e3729bbd77fb9dcaea6a06ac760160136d80b79
branch: main
author: David Hewitt <[email protected]>
committer: encukou <[email protected]>
date: 2024-02-15T11:05:20+01:00
summary:

gh-114626: add PyCFunctionFast and PyCFunctionFastWithKeywords (GH-114627)


Co-authored-by: Petr Viktorin <[email protected]>

files:
A Misc/NEWS.d/next/C API/2024-01-26-21-54-42.gh-issue-114626.SKhbh_.rst
M Doc/c-api/structures.rst
M Doc/data/stable_abi.dat
M Include/methodobject.h
M Misc/stable_abi.toml
M Objects/descrobject.c
M Objects/methodobject.c
M Python/bytecodes.c
M Python/executor_cases.c.h
M Python/generated_cases.c.h

diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst
index 77f2b6991d770e..e2943f18ddc601 100644
--- a/Doc/c-api/structures.rst
+++ b/Doc/c-api/structures.rst
@@ -187,26 +187,26 @@ 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 *const *args,
-                                 Py_ssize_t nargs);
+      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 *const *args,
-                                             Py_ssize_t nargs,
-                                             PyObject *kwnames);
+      PyObject *PyCFunctionFastWithKeywords(PyObject *self,
+                                            PyObject *const *args,
+                                            Py_ssize_t nargs,
+                                            PyObject *kwnames);
 
 .. c:type:: PyCMethod
 
@@ -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
diff --git a/Doc/data/stable_abi.dat b/Doc/data/stable_abi.dat
index def1903204add7..25629b4da053da 100644
--- a/Doc/data/stable_abi.dat
+++ b/Doc/data/stable_abi.dat
@@ -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,,
diff --git a/Include/methodobject.h b/Include/methodobject.h
index 2381e8482b82a8..452f891a7aba83 100644
--- a/Include/methodobject.h
+++ b/Include/methodobject.h
@@ -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 *,
-                                                   PyObject *const *, 
Py_ssize_t,
-                                                   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
diff --git a/Misc/NEWS.d/next/C 
API/2024-01-26-21-54-42.gh-issue-114626.SKhbh_.rst b/Misc/NEWS.d/next/C 
API/2024-01-26-21-54-42.gh-issue-114626.SKhbh_.rst
new file mode 100644
index 00000000000000..0da03ec122b555
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2024-01-26-21-54-42.gh-issue-114626.SKhbh_.rst     
@@ -0,0 +1 @@
+Add ``PyCFunctionFast`` and ``PyCFunctionFastWithKeywords`` typedefs 
(identical to the existing ``_PyCFunctionFast`` and 
``_PyCFunctionFastWithKeywords`` typedefs, just without a leading ``_`` prefix).
diff --git a/Misc/stable_abi.toml b/Misc/stable_abi.toml
index a9875f6ffd1a56..ca7cf02961571e 100644
--- a/Misc/stable_abi.toml
+++ b/Misc/stable_abi.toml
@@ -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.)
diff --git a/Objects/descrobject.c b/Objects/descrobject.c
index 8d771adf307dc4..805de2971ba475 100644
--- a/Objects/descrobject.c
+++ b/Objects/descrobject.c
@@ -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;
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index b40b2821c3880d..599fb05cb5874f 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -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);
 }
-
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index 28ade64e056ad7..6822e772e913e8 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -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));
diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h
index 7a0e0e43be019c..11e2a1fe85d51d 100644
--- a/Python/executor_cases.c.h
+++ b/Python/executor_cases.c.h
@@ -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));
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index 177bc327454f63..6c19adc60c690f 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -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. */

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to