@@ -47,7 +47,7 @@ PyAPI_FUNC(int) _PyStack_UnpackDict(
47
47
/* Suggested size (number of positional arguments) for arrays of PyObject*
48
48
allocated on a C stack to avoid allocating memory on the heap memory. Such
49
49
array is used to pass positional arguments to call functions of the
50
- _PyObject_FastCall () family.
50
+ _PyObject_Vectorcall () family.
51
51
52
52
The size is chosen to not abuse the C stack and so limit the risk of stack
53
53
overflow. The size is also chosen to allow using the small stack for most
@@ -56,50 +56,103 @@ PyAPI_FUNC(int) _PyStack_UnpackDict(
56
56
#define _PY_FASTCALL_SMALL_STACK 5
57
57
58
58
/* 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 () */
60
60
PyAPI_FUNC (int ) _PyObject_HasFastCall (PyObject * callable );
61
61
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 );
65
65
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) ============================= */
68
67
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 (
72
72
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 );
76
75
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))
83
77
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].
86
106
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.
89
114
90
115
Return the result on success. Raise an exception and return NULL on
91
116
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 (
93
135
PyObject * callable ,
94
136
PyObject * const * args ,
95
- Py_ssize_t nargs ,
96
- PyObject * kwnames );
137
+ size_t nargsf ,
138
+ PyObject * kwargs );
97
139
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 );
100
143
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
+ }
103
156
104
157
PyAPI_FUNC (PyObject * ) _PyObject_Call_Prepend (
105
158
PyObject * callable ,
@@ -113,10 +166,6 @@ PyAPI_FUNC(PyObject *) _PyObject_FastCall_Prepend(
113
166
PyObject * const * args ,
114
167
Py_ssize_t nargs );
115
168
116
- PyAPI_FUNC (PyObject * ) _Py_CheckFunctionResult (PyObject * callable ,
117
- PyObject * result ,
118
- const char * where );
119
-
120
169
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
121
170
as the method name. */
122
171
PyAPI_FUNC (PyObject * ) _PyObject_CallMethodId (PyObject * obj ,
0 commit comments