Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
allendowney
GitHub Repository: allendowney/cpython
Path: blob/main/Include/internal/pycore_call.h
12 views
1
#ifndef Py_INTERNAL_CALL_H
2
#define Py_INTERNAL_CALL_H
3
#ifdef __cplusplus
4
extern "C" {
5
#endif
6
7
#ifndef Py_BUILD_CORE
8
# error "this header requires Py_BUILD_CORE define"
9
#endif
10
11
#include "pycore_pystate.h" // _PyThreadState_GET()
12
13
/* Suggested size (number of positional arguments) for arrays of PyObject*
14
allocated on a C stack to avoid allocating memory on the heap memory. Such
15
array is used to pass positional arguments to call functions of the
16
PyObject_Vectorcall() family.
17
18
The size is chosen to not abuse the C stack and so limit the risk of stack
19
overflow. The size is also chosen to allow using the small stack for most
20
function calls of the Python standard library. On 64-bit CPU, it allocates
21
40 bytes on the stack. */
22
#define _PY_FASTCALL_SMALL_STACK 5
23
24
25
// Export for shared stdlib extensions like the math extension,
26
// function used via inlined _PyObject_VectorcallTstate() function.
27
PyAPI_FUNC(PyObject*) _Py_CheckFunctionResult(
28
PyThreadState *tstate,
29
PyObject *callable,
30
PyObject *result,
31
const char *where);
32
33
/* Convert keyword arguments from the FASTCALL (stack: C array, kwnames: tuple)
34
format to a Python dictionary ("kwargs" dict).
35
36
The type of kwnames keys is not checked. The final function getting
37
arguments is responsible to check if all keys are strings, for example using
38
PyArg_ParseTupleAndKeywords() or PyArg_ValidateKeywordArguments().
39
40
Duplicate keys are merged using the last value. If duplicate keys must raise
41
an exception, the caller is responsible to implement an explicit keys on
42
kwnames. */
43
extern PyObject* _PyStack_AsDict(PyObject *const *values, PyObject *kwnames);
44
45
extern PyObject* _PyObject_Call_Prepend(
46
PyThreadState *tstate,
47
PyObject *callable,
48
PyObject *obj,
49
PyObject *args,
50
PyObject *kwargs);
51
52
extern PyObject* _PyObject_VectorcallDictTstate(
53
PyThreadState *tstate,
54
PyObject *callable,
55
PyObject *const *args,
56
size_t nargsf,
57
PyObject *kwargs);
58
59
extern PyObject* _PyObject_Call(
60
PyThreadState *tstate,
61
PyObject *callable,
62
PyObject *args,
63
PyObject *kwargs);
64
65
extern PyObject * _PyObject_CallMethodFormat(
66
PyThreadState *tstate,
67
PyObject *callable,
68
const char *format,
69
...);
70
71
// Export for shared stdlib extensions like the array extension
72
PyAPI_FUNC(PyObject*) _PyObject_CallMethod(
73
PyObject *obj,
74
PyObject *name,
75
const char *format, ...);
76
77
/* Like PyObject_CallMethod(), but expect a _Py_Identifier*
78
as the method name. */
79
extern PyObject* _PyObject_CallMethodId(
80
PyObject *obj,
81
_Py_Identifier *name,
82
const char *format, ...);
83
84
extern PyObject* _PyObject_CallMethodIdObjArgs(
85
PyObject *obj,
86
_Py_Identifier *name,
87
...);
88
89
static inline PyObject *
90
_PyObject_VectorcallMethodId(
91
_Py_Identifier *name, PyObject *const *args,
92
size_t nargsf, PyObject *kwnames)
93
{
94
PyObject *oname = _PyUnicode_FromId(name); /* borrowed */
95
if (!oname) {
96
return _Py_NULL;
97
}
98
return PyObject_VectorcallMethod(oname, args, nargsf, kwnames);
99
}
100
101
static inline PyObject *
102
_PyObject_CallMethodIdNoArgs(PyObject *self, _Py_Identifier *name)
103
{
104
size_t nargsf = 1 | PY_VECTORCALL_ARGUMENTS_OFFSET;
105
return _PyObject_VectorcallMethodId(name, &self, nargsf, _Py_NULL);
106
}
107
108
static inline PyObject *
109
_PyObject_CallMethodIdOneArg(PyObject *self, _Py_Identifier *name, PyObject *arg)
110
{
111
PyObject *args[2] = {self, arg};
112
size_t nargsf = 2 | PY_VECTORCALL_ARGUMENTS_OFFSET;
113
assert(arg != NULL);
114
return _PyObject_VectorcallMethodId(name, args, nargsf, _Py_NULL);
115
}
116
117
118
/* === Vectorcall protocol (PEP 590) ============================= */
119
120
// Call callable using tp_call. Arguments are like PyObject_Vectorcall(),
121
// except that nargs is plainly the number of arguments without flags.
122
//
123
// Export for shared stdlib extensions like the math extension,
124
// function used via inlined _PyObject_VectorcallTstate() function.
125
PyAPI_FUNC(PyObject*) _PyObject_MakeTpCall(
126
PyThreadState *tstate,
127
PyObject *callable,
128
PyObject *const *args, Py_ssize_t nargs,
129
PyObject *keywords);
130
131
// Static inline variant of public PyVectorcall_Function().
132
static inline vectorcallfunc
133
_PyVectorcall_FunctionInline(PyObject *callable)
134
{
135
assert(callable != NULL);
136
137
PyTypeObject *tp = Py_TYPE(callable);
138
if (!PyType_HasFeature(tp, Py_TPFLAGS_HAVE_VECTORCALL)) {
139
return NULL;
140
}
141
assert(PyCallable_Check(callable));
142
143
Py_ssize_t offset = tp->tp_vectorcall_offset;
144
assert(offset > 0);
145
146
vectorcallfunc ptr;
147
memcpy(&ptr, (char *) callable + offset, sizeof(ptr));
148
return ptr;
149
}
150
151
152
/* Call the callable object 'callable' with the "vectorcall" calling
153
convention.
154
155
args is a C array for positional arguments.
156
157
nargsf is the number of positional arguments plus optionally the flag
158
PY_VECTORCALL_ARGUMENTS_OFFSET which means that the caller is allowed to
159
modify args[-1].
160
161
kwnames is a tuple of keyword names. The values of the keyword arguments
162
are stored in "args" after the positional arguments (note that the number
163
of keyword arguments does not change nargsf). kwnames can also be NULL if
164
there are no keyword arguments.
165
166
keywords must only contain strings and all keys must be unique.
167
168
Return the result on success. Raise an exception and return NULL on
169
error. */
170
static inline PyObject *
171
_PyObject_VectorcallTstate(PyThreadState *tstate, PyObject *callable,
172
PyObject *const *args, size_t nargsf,
173
PyObject *kwnames)
174
{
175
vectorcallfunc func;
176
PyObject *res;
177
178
assert(kwnames == NULL || PyTuple_Check(kwnames));
179
assert(args != NULL || PyVectorcall_NARGS(nargsf) == 0);
180
181
func = _PyVectorcall_FunctionInline(callable);
182
if (func == NULL) {
183
Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
184
return _PyObject_MakeTpCall(tstate, callable, args, nargs, kwnames);
185
}
186
res = func(callable, args, nargsf, kwnames);
187
return _Py_CheckFunctionResult(tstate, callable, res, NULL);
188
}
189
190
191
static inline PyObject *
192
_PyObject_CallNoArgsTstate(PyThreadState *tstate, PyObject *func) {
193
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
194
}
195
196
197
// Private static inline function variant of public PyObject_CallNoArgs()
198
static inline PyObject *
199
_PyObject_CallNoArgs(PyObject *func) {
200
EVAL_CALL_STAT_INC_IF_FUNCTION(EVAL_CALL_API, func);
201
PyThreadState *tstate = _PyThreadState_GET();
202
return _PyObject_VectorcallTstate(tstate, func, NULL, 0, NULL);
203
}
204
205
206
extern PyObject *const *
207
_PyStack_UnpackDict(PyThreadState *tstate,
208
PyObject *const *args, Py_ssize_t nargs,
209
PyObject *kwargs, PyObject **p_kwnames);
210
211
extern void _PyStack_UnpackDict_Free(
212
PyObject *const *stack,
213
Py_ssize_t nargs,
214
PyObject *kwnames);
215
216
extern void _PyStack_UnpackDict_FreeNoDecRef(
217
PyObject *const *stack,
218
PyObject *kwnames);
219
220
#ifdef __cplusplus
221
}
222
#endif
223
#endif /* !Py_INTERNAL_CALL_H */
224
225