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