You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
C API: What's the status of the half-private FASTCALL calling convention? #106023
In 2017, I added a new experimental FASTCALL calling convention. See my articles about it: The start of the FASTCALL project and FASTCALL microbenchmarks. It avoids the need to create a temporary tuple to pass positional arguments and the need to create a temporary dictionary to pass keyword arguments. I did my best to keep this API private. I added functions prefixed with _Py: _PyObject_Fastcall(). Cython is eager to always use the fastest code and quickly adopted this new METH_FASTCALL calling convention... oops, I forgot to add a _Py prefix since these METH constants don't start with Py.
In 2019, this calling convention was extended to support also method calls (pass the self argument): PEP 590 – Vectorcall: a fast calling protocol for CPython. This new API is public and standardized. For example, it added public PyVectorcall_Function() and PyObject_Vectorcall() functions.
In 2023, the FASTCALL API is still around in the public C API:
METH_FASTCALL
_PyObject_FastCall()
_PyObject_FastCallTstate()
_PyObject_FastCallDict()
_PyObject_FastCallDictTstate()
_PyStack_AsDict()
_PY_FASTCALL_SMALL_STACK
Can it be deprecated? Removed? I suppose that if we are in the unknown, the safe option is to start by deprecating it in Python 3.13 and plan its removal in Python 3.15.
Does vectorcall replace this completely? If that's the case, let's first remove all uses from CPython, and then decide.
If not, then it's probably genuinely useful for Cython or others. Let's move it to unstable API in that case. (Or even public?)
_PY_FASTCALL_SMALL_STACK is internal detail that's easy for users to replace (possibly with a more appropriate value). IMO it's safe to move to private headers.
Does vectorcall replace this completely? If that's the case, let's first remove all uses from CPython, and then decide.
_PyObject_FastCall(func, nargs, args) can be safely replaced with PyObject_Vectorcall(func, nargs, args, NULL).
PR #106257 removes _PyObject_FastCall() usage in CPython: replace it with PyObject_Vectorcall().
_PY_FASTCALL_SMALL_STACK is internal detail that's easy for users to replace (possibly with a more appropriate value). IMO it's safe to move to private headers.
PR #106258 removes the constant from the public C API.
In 2019, a commit implementing PEP 590 removed _PyObject_FastCallKeywords().
My recent commit 00e75a3 removed _PyObject_FastCallDict(). Oh, I didn't notice that I was removing a C function of the FastCall family. I planned to handle these differently.
When removing them, it would be nice to add them to What's New, mentioning that they were private but documenting what to call instead.
When you've inherited code that stops compiling, it's nice to have instructions like that.
I removed the FastCall C API and explained how to migrate in What's New in Python 3.13.
I removed _PyObject_FastCall(), _PyObject_FastCallDict(), _PY_FASTCALL_SMALL_STACK and _PyStack_AsDict() from the public C API. I removed _PyObject_FastCallTstate() and _PyObject_FastCallDictTstate() of the internal C API.
Activity
encukou commentedon Jun 27, 2023
Does vectorcall replace this completely? If that's the case, let's first remove all uses from CPython, and then decide.
If not, then it's probably genuinely useful for Cython or others. Let's move it to unstable API in that case. (Or even public?)
_PY_FASTCALL_SMALL_STACKis internal detail that's easy for users to replace (possibly with a more appropriate value). IMO it's safe to move to private headers.pythongh-106023: Update code using _PyObject_FastCall()
pythongh-106023: Update code using _PyObject_FastCall()
pythongh-106023: Update code using _PyObject_FastCall()
pythongh-106023: Remove _PY_FASTCALL_SMALL_STACK constant
vstinner commentedon Jun 30, 2023
_PyObject_FastCall(func, nargs, args)can be safely replaced withPyObject_Vectorcall(func, nargs, args, NULL).PR #106257 removes
_PyObject_FastCall()usage in CPython: replace it withPyObject_Vectorcall().PR #106258 removes the constant from the public C API.
gh-106023: Update code using _PyObject_FastCall() (#106257)
gh-106023: Remove _PY_FASTCALL_SMALL_STACK constant (#106258)
vstinner commentedon Jun 30, 2023
In 2019, a commit implementing PEP 590 removed _PyObject_FastCallKeywords().
My recent commit 00e75a3 removed _PyObject_FastCallDict(). Oh, I didn't notice that I was removing a C function of the FastCall family. I planned to handle these differently.
vstinner commentedon Jun 30, 2023
On PyPI top 5,000 projects, 10 projects use it. 3 of them are related to pydevd or copies of pydevd.
Usage:
vstinner commentedon Jun 30, 2023
PyObject_Vectorcall() is available since Python 3.8 and PyObject_VectorcallDict() is available since Python 3.9.
_PyObject_FastCall() and _PyObject_FastCallDict() are private functions. IMO it's ok to remove them.
The METH_FASTCALL calling convention remains useful and I don't see a need to remove.
pythongh-106023: Rename _PyObject_FastCallDictTstate()
pythongh-106023: Remove _PyObject_FastCall() function
1 remaining item
encukou commentedon Jun 30, 2023
When removing them, it would be nice to add them to What's New, mentioning that they were private but documenting what to call instead.
When you've inherited code that stops compiling, it's nice to have instructions like that.
gh-106023: Rename _PyObject_FastCallDictTstate() (#106264)
pythongh-106023: Remove _PyObject_FastCall() function
gh-106023: Remove _PyObject_FastCall() function (#106265)
pythongh-106023: Remove _PyObject_FastCallTstate()
pythongh-106023: Remove _PyObject_FastCallTstate() function
vstinner commentedon Jun 30, 2023
I removed the FastCall C API and explained how to migrate in What's New in Python 3.13.
I removed _PyObject_FastCall(), _PyObject_FastCallDict(), _PY_FASTCALL_SMALL_STACK and _PyStack_AsDict() from the public C API. I removed _PyObject_FastCallTstate() and _PyObject_FastCallDictTstate() of the internal C API.
The METH_FASTCALL constant stays for now.
gh-106023: Remove _PyObject_FastCallTstate() function (#106273)
gh-106023: Update What's New in 3.13: _PyObject_FastCall() (#117633)
Revert "pythongh-106023: Update What's New in 3.13: _PyObject_FastCal…
Revert "gh-106023: Update What's New in 3.13: _PyObject_FastCall() (#…
pythongh-106023: Update What's New in 3.13: _PyObject_FastCall() (pyt…
Revert "pythongh-106023: Update What's New in 3.13: _PyObject_FastCal…
Fix `_PyObject_FastCall` for Python 3.13 (#17502)