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() */

6060

PyAPI_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(

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);

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(

93135

PyObject *callable,

94136

PyObject *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+

}

103156104157

PyAPI_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);

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. */

122171

PyAPI_FUNC(PyObject *) _PyObject_CallMethodId(PyObject *obj,