bpo-36974: implement PEP 590 (GH-13185) · python/cpython@aacc77f
@@ -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.
51515252 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
57575858/* 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);
616162-/* 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);
656566- 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) ============================= */
686769- 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(
7272PyObject *callable,
73-PyObject *const *args,
74-Py_ssize_t nargs,
75-PyObject *kwargs);
73+PyObject *const *args, Py_ssize_t nargs,
74+PyObject *keywords);
767577-/* 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))
837784- 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].
8610687- 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.
8911490115 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(
93135PyObject *callable,
94136PyObject *const *args,
95-Py_ssize_t nargs,
96-PyObject *kwnames);
137+size_t nargsf,
138+PyObject *kwargs);
9713998-#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);
100143101-#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+}
103156104157PyAPI_FUNC(PyObject *) _PyObject_Call_Prepend(
105158PyObject *callable,
@@ -113,10 +166,6 @@ PyAPI_FUNC(PyObject *) _PyObject_FastCall_Prepend(
113166PyObject *const *args,
114167Py_ssize_t nargs);
115168116-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,