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
Receiving vector calls in the Py_LIMITED_API #93274
The PyType_FromSpec family of functions provides a convenient and forward-compatible way mechanism for creating new types. It could in principle also be used to create callables providing a PEP-590 vector call interface, which has significant performance benefits for binding libraries (see the related discussion here).
One can already specify a member named __vectorcalloffset__ in PyType_FromSpec. This isn't fully working in the limited API, however. I encountered the following problems.
The Py_TPFLAGS_HAVE_VECTORCALL flag is not part of the limited API.
The PyVectorcall_NARGS() helper function is not part of the limited API.
One would normally set tp_call to the compatibility dispatch routine PyVectorcall_Call. It is, however, also not part of the public ABI.
Leaving tp_call unspecified is not an option. PyType_Ready() even throws an exception in type_ready_pre_checks() when tp_call is unspecified.
Pitch
I propose the following changes:
Adding Py_TPFLAGS_HAVE_VECTORCALL, PyVectorcall_NARGS(), and PyVectorcall_Call() to the limited API.
Redundant, but nice: Setting tp_call to PyVectorcall_Call when PyType_Ready encounters a type that doesn't have this field set.
Note that vector calls can be received and performed. This issue is just about the receiving end.
Combined with exposing the call side of vectorcall (PyObject_Vectorcall, PyObject_VectorcallDict, PyObject_VectorcallMethod), it looks like there are enough changes here for a small PEP.
Setting __call__ on a class defines how the instances of that class are called. tp_vectorcall defines how a class object is called (the tp_vectorcall_offset of a metaclass is usually set to offsetof(PyTypeObject, tp_vectorcall)).
It would need to become something like:
cls->tp_call = ...
for inst in all instances of cls:
if isinstance(inst, type):
inst->tp_vectorcall = NULL;
else:
???
Activity
encukou commentedon Jun 7, 2022
Found one more wrinkle: we probably should disable setting
__call__from Python code for classes with vectorcall. See https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_vectorcall_offset.encukou commentedon Jun 7, 2022
Previous discussion on fixing up tp_call: https://mail.python.org/archives/list/python-dev@python.org/thread/KASUG5TENCSRHX5K4O6ZY4XRPHVUWFPY/#K2KBOTUW43YCYQ3CI7AI3WTRLWUF4YP3
[-]Receiving vector calls in the Py_LIMITED_API[/-][+]PEP: Receiving vector calls in the Py_LIMITED_API[/+][-]PEP: Receiving vector calls in the Py_LIMITED_API[/-][+]Receiving vector calls in the Py_LIMITED_API[/+]encukou commentedon Jun 7, 2022
Combined with exposing the call side of vectorcall (
PyObject_Vectorcall,PyObject_VectorcallDict,PyObject_VectorcallMethod), it looks like there are enough changes here for a small PEP.markshannon commentedon Jun 16, 2022
PEP 590 makes it clear that
tp_calland the vectorcall function must be consistent.That can be achieved two ways:
__call__cannot be set.__call__is set, then set the vectorcall function pointer toNULL.encukou commentedon Jun 17, 2022
The issue is that if the class is mutable,
__call__can be set from arbitrary Python code.markshannon commentedon Jun 17, 2022
Not a problem.
Somewhere in the bowels of typeobject.c there is code that sets
cls->tp_call, sobecomes
encukou commentedon Jun 17, 2022
Setting
__call__on a class defines how the instances of that class are called.tp_vectorcalldefines how a class object is called (thetp_vectorcall_offsetof a metaclass is usually set tooffsetof(PyTypeObject, tp_vectorcall)).It would need to become something like:
markshannon commentedon Jun 17, 2022
Indeed, as Victor points out, it isn't
tp_vectorcallthat needs to change, but whether it is valid.The code above should read:
markshannon commentedon Jun 17, 2022
We might need to invalidate sub-classes as well, it depends on whether
PyType_FromSpecallows sub-classing.2 remaining items
encukou commentedon Aug 5, 2022
PR: #95717
As for setting
tp_callautomatically, after reviewing the past discussions I prefer leaving this as is: it needs to be set it explicitly.gh-93274: Expose receiving vectorcall in the Limited API (GH-95717)
erlend-aasland commentedon Aug 8, 2022
AFAICS, this is now implemented. Unless you have further changes planned, let's close this issue.
encukou commentedon Aug 8, 2022
Next up in this bucket is making vectorcalls. Or see Discourse for a bigger bucket.
encukou commentedon Aug 8, 2022
The new tests broke buildbots. I'll revert & test more thoroughly.
Revert "pythongh-93274: Expose receiving vectorcall in the Limited API (
encukou commentedon Aug 9, 2022
Fixed in #95796
pythongh-93274: Make vectorcall safe on mutable classes & inherit it …
pythongh-93274: Expose receiving vectorcall in the Limited API (pytho…