@@ -47,7 +47,7 @@ PyAPI_FUNC(int) _PyStack_UnpackDict(
4747/* Suggested size (number of positional arguments) for arrays of PyObject*
4848 allocated on a C stack to avoid allocating memory on the heap memory. Such
4949 array is used to pass positional arguments to call functions of the
50- _PyObject_FastCall () family.
50+ _PyObject_Vectorcall () family.
5151
5252 The size is chosen to not abuse the C stack and so limit the risk of stack
5353 overflow. The size is also chosen to allow using the small stack for most
@@ -56,50 +56,103 @@ PyAPI_FUNC(int) _PyStack_UnpackDict(
5656#define _PY_FASTCALL_SMALL_STACK 5
5757
5858/* Return 1 if callable supports FASTCALL calling convention for positional
59- arguments: see _PyObject_FastCallDict () and _PyObject_FastCallKeywords () */
59+ arguments: see _PyObject_Vectorcall () and _PyObject_FastCallDict () */
6060PyAPI_FUNC (int ) _PyObject_HasFastCall (PyObject * callable );
6161
62- /* Call the callable object 'callable' with the "fast call" calling convention:
63- args is a C array for positional arguments (nargs is the number of
64- positional arguments), kwargs is a dictionary for keyword arguments.
62+ PyAPI_FUNC ( PyObject * ) _Py_CheckFunctionResult ( PyObject * callable ,
63+ PyObject * result ,
64+ const char * where );
6565
66- If nargs is equal to zero, args can be NULL. kwargs can be NULL.
67- nargs must be greater or equal to zero.
66+ /* === Vectorcall protocol (PEP 590) ============================= */
6867
69- Return the result on success. Raise an exception and return NULL on
70- error. */
71- PyAPI_FUNC (PyObject * ) _PyObject_FastCallDict (
68+ /* Call callable using tp_call. Arguments are like _PyObject_Vectorcall()
69+ or _PyObject_FastCallDict() (both forms are supported),
70+ except that nargs is plainly the number of arguments without flags. */
71+ PyAPI_FUNC (PyObject * ) _PyObject_MakeTpCall (
7272 PyObject * callable ,
73- PyObject * const * args ,
74- Py_ssize_t nargs ,
75- PyObject * kwargs );
73+ PyObject * const * args , Py_ssize_t nargs ,
74+ PyObject * keywords );
7675
77- /* Call the callable object 'callable' with the "fast call" calling convention:
78- args is a C array for positional arguments followed by values of
79- keyword arguments. Keys of keyword arguments are stored as a tuple
80- of strings in kwnames. nargs is the number of positional parameters at
81- the beginning of stack. The size of kwnames gives the number of keyword
82- values in the stack after positional arguments.
76+ #define PY_VECTORCALL_ARGUMENTS_OFFSET ((size_t)1 << (8 * sizeof(size_t) - 1))
8377
84- kwnames must only contains str strings, no subclass, and all keys must
85- be unique.
78+ static inline Py_ssize_t
79+ PyVectorcall_NARGS (size_t n )
80+ {
81+ return n & ~PY_VECTORCALL_ARGUMENTS_OFFSET ;
82+ }
83+
84+ static inline vectorcallfunc
85+ _PyVectorcall_Function (PyObject * callable )
86+ {
87+ PyTypeObject * tp = Py_TYPE (callable );
88+ if (!PyType_HasFeature (tp , _Py_TPFLAGS_HAVE_VECTORCALL )) {
89+ return NULL ;
90+ }
91+ assert (PyCallable_Check (callable ));
92+ Py_ssize_t offset = tp -> tp_vectorcall_offset ;
93+ assert (offset > 0 );
94+ vectorcallfunc * ptr = (vectorcallfunc * )(((char * )callable ) + offset );
95+ return * ptr ;
96+ }
97+
98+ /* Call the callable object 'callable' with the "vectorcall" calling
99+ convention.
100+
101+ args is a C array for positional arguments.
102+
103+ nargsf is the number of positional arguments plus optionally the flag
104+ PY_VECTORCALL_ARGUMENTS_OFFSET which means that the caller is allowed to
105+ modify args[-1].
86106
87- If nargs is equal to zero and there is no keyword argument (kwnames is
88- NULL or its size is zero), args can be NULL.
107+ kwnames is a tuple of keyword names. The values of the keyword arguments
108+ are stored in "args" after the positional arguments (note that the number
109+ of keyword arguments does not change nargsf). kwnames can also be NULL if
110+ there are no keyword arguments.
111+
112+ keywords must only contains str strings (no subclass), and all keys must
113+ be unique.
89114
90115 Return the result on success. Raise an exception and return NULL on
91116 error. */
92- PyAPI_FUNC (PyObject * ) _PyObject_FastCallKeywords (
117+ static inline PyObject *
118+ _PyObject_Vectorcall (PyObject * callable , PyObject * const * args ,
119+ size_t nargsf , PyObject * kwnames )
120+ {
121+ assert (kwnames == NULL || PyTuple_Check (kwnames ));
122+ assert (args != NULL || PyVectorcall_NARGS (nargsf ) == 0 );
123+ vectorcallfunc func = _PyVectorcall_Function (callable );
124+ if (func == NULL ) {
125+ Py_ssize_t nargs = PyVectorcall_NARGS (nargsf );
126+ return _PyObject_MakeTpCall (callable , args , nargs , kwnames );
127+ }
128+ PyObject * res = func (callable , args , nargsf , kwnames );
129+ return _Py_CheckFunctionResult (callable , res , NULL );
130+ }
131+
132+ /* Same as _PyObject_Vectorcall except that keyword arguments are passed as
133+ dict, which may be NULL if there are no keyword arguments. */
134+ PyAPI_FUNC (PyObject * ) _PyObject_FastCallDict (
93135 PyObject * callable ,
94136 PyObject * const * args ,
95- Py_ssize_t nargs ,
96- PyObject * kwnames );
137+ size_t nargsf ,
138+ PyObject * kwargs );
97139
98- #define _PyObject_FastCall (func , args , nargs ) \
99- _PyObject_FastCallDict((func), (args), (nargs), NULL)
140+ /* Call "callable" (which must support vectorcall) with positional arguments
141+ "tuple" and keyword arguments "dict". "dict" may also be NULL */
142+ PyAPI_FUNC (PyObject * ) PyVectorcall_Call (PyObject * callable , PyObject * tuple , PyObject * dict );
100143
101- #define _PyObject_CallNoArg (func ) \
102- _PyObject_FastCallDict((func), NULL, 0, NULL)
144+ /* Same as _PyObject_Vectorcall except without keyword arguments */
145+ static inline PyObject *
146+ _PyObject_FastCall (PyObject * func , PyObject * const * args , Py_ssize_t nargs )
147+ {
148+ return _PyObject_Vectorcall (func , args , (size_t )nargs , NULL );
149+ }
150+
151+ /* Call a callable without any arguments */
152+ static inline PyObject *
153+ _PyObject_CallNoArg (PyObject * func ) {
154+ return _PyObject_Vectorcall (func , NULL , 0 , NULL );
155+ }
103156
104157PyAPI_FUNC (PyObject * ) _PyObject_Call_Prepend (
105158 PyObject * callable ,
@@ -113,10 +166,6 @@ PyAPI_FUNC(PyObject *) _PyObject_FastCall_Prepend(
113166 PyObject * const * args ,
114167 Py_ssize_t nargs );
115168
116- PyAPI_FUNC (PyObject * ) _Py_CheckFunctionResult (PyObject * callable ,
117- PyObject * result ,
118- const char * where );
119-
120169/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
121170 as the method name. */
122171PyAPI_FUNC (PyObject * ) _PyObject_CallMethodId (PyObject * obj ,
0 commit comments