Branch data Line data Source code
1 : :
2 : : /* Method object implementation */
3 : :
4 : : #include "Python.h"
5 : : #include "pycore_ceval.h" // _Py_EnterRecursiveCallTstate()
6 : : #include "pycore_object.h"
7 : : #include "pycore_pyerrors.h"
8 : : #include "pycore_pystate.h" // _PyThreadState_GET()
9 : : #include "structmember.h" // PyMemberDef
10 : :
11 : : /* undefine macro trampoline to PyCFunction_NewEx */
12 : : #undef PyCFunction_New
13 : : /* undefine macro trampoline to PyCMethod_New */
14 : : #undef PyCFunction_NewEx
15 : :
16 : : /* Forward declarations */
17 : : static PyObject * cfunction_vectorcall_FASTCALL(
18 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
19 : : static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS(
20 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
21 : : static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
22 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
23 : : static PyObject * cfunction_vectorcall_NOARGS(
24 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
25 : : static PyObject * cfunction_vectorcall_O(
26 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
27 : : static PyObject * cfunction_call(
28 : : PyObject *func, PyObject *args, PyObject *kwargs);
29 : :
30 : :
31 : : PyObject *
32 : 0 : PyCFunction_New(PyMethodDef *ml, PyObject *self)
33 : : {
34 : 0 : return PyCFunction_NewEx(ml, self, NULL);
35 : : }
36 : :
37 : : PyObject *
38 : 0 : PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
39 : : {
40 : 0 : return PyCMethod_New(ml, self, module, NULL);
41 : : }
42 : :
43 : : PyObject *
44 : 2230496 : PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls)
45 : : {
46 : : /* Figure out correct vectorcall function to use */
47 : : vectorcallfunc vectorcall;
48 [ + + + + : 2230496 : switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
+ + - ]
49 : : METH_O | METH_KEYWORDS | METH_METHOD))
50 : : {
51 : 12129 : case METH_VARARGS:
52 : : case METH_VARARGS | METH_KEYWORDS:
53 : : /* For METH_VARARGS functions, it's more efficient to use tp_call
54 : : * instead of vectorcall. */
55 : 12129 : vectorcall = NULL;
56 : 12129 : break;
57 : 4374 : case METH_FASTCALL:
58 : 4374 : vectorcall = cfunction_vectorcall_FASTCALL;
59 : 4374 : break;
60 : 7021 : case METH_FASTCALL | METH_KEYWORDS:
61 : 7021 : vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS;
62 : 7021 : break;
63 : 216875 : case METH_NOARGS:
64 : 216875 : vectorcall = cfunction_vectorcall_NOARGS;
65 : 216875 : break;
66 : 546344 : case METH_O:
67 : 546344 : vectorcall = cfunction_vectorcall_O;
68 : 546344 : break;
69 : 1443753 : case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
70 : 1443753 : vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD;
71 : 1443753 : break;
72 : 0 : default:
73 : 0 : PyErr_Format(PyExc_SystemError,
74 : : "%s() method: bad call flags", ml->ml_name);
75 : 0 : return NULL;
76 : : }
77 : :
78 : 2230496 : PyCFunctionObject *op = NULL;
79 : :
80 [ + + ]: 2230496 : if (ml->ml_flags & METH_METHOD) {
81 [ - + ]: 1443753 : if (!cls) {
82 : 0 : PyErr_SetString(PyExc_SystemError,
83 : : "attempting to create PyCMethod with a METH_METHOD "
84 : : "flag but no class");
85 : 0 : return NULL;
86 : : }
87 : 1443753 : PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type);
88 [ - + ]: 1443753 : if (om == NULL) {
89 : 0 : return NULL;
90 : : }
91 : 1443753 : om->mm_class = (PyTypeObject*)Py_NewRef(cls);
92 : 1443753 : op = (PyCFunctionObject *)om;
93 : : } else {
94 [ - + ]: 786743 : if (cls) {
95 : 0 : PyErr_SetString(PyExc_SystemError,
96 : : "attempting to create PyCFunction with class "
97 : : "but no METH_METHOD flag");
98 : 0 : return NULL;
99 : : }
100 : 786743 : op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
101 [ - + ]: 786743 : if (op == NULL) {
102 : 0 : return NULL;
103 : : }
104 : : }
105 : :
106 : 2230496 : op->m_weakreflist = NULL;
107 : 2230496 : op->m_ml = ml;
108 : 2230496 : op->m_self = Py_XNewRef(self);
109 : 2230496 : op->m_module = Py_XNewRef(module);
110 : 2230496 : op->vectorcall = vectorcall;
111 : 2230496 : _PyObject_GC_TRACK(op);
112 : 2230496 : return (PyObject *)op;
113 : : }
114 : :
115 : : PyCFunction
116 : 0 : PyCFunction_GetFunction(PyObject *op)
117 : : {
118 [ # # ]: 0 : if (!PyCFunction_Check(op)) {
119 : 0 : PyErr_BadInternalCall();
120 : 0 : return NULL;
121 : : }
122 : 0 : return PyCFunction_GET_FUNCTION(op);
123 : : }
124 : :
125 : : PyObject *
126 : 0 : PyCFunction_GetSelf(PyObject *op)
127 : : {
128 [ # # ]: 0 : if (!PyCFunction_Check(op)) {
129 : 0 : PyErr_BadInternalCall();
130 : 0 : return NULL;
131 : : }
132 : 0 : return PyCFunction_GET_SELF(op);
133 : : }
134 : :
135 : : int
136 : 0 : PyCFunction_GetFlags(PyObject *op)
137 : : {
138 [ # # ]: 0 : if (!PyCFunction_Check(op)) {
139 : 0 : PyErr_BadInternalCall();
140 : 0 : return -1;
141 : : }
142 : 0 : return PyCFunction_GET_FLAGS(op);
143 : : }
144 : :
145 : : PyTypeObject *
146 : 0 : PyCMethod_GetClass(PyObject *op)
147 : : {
148 [ # # ]: 0 : if (!PyCFunction_Check(op)) {
149 : 0 : PyErr_BadInternalCall();
150 : 0 : return NULL;
151 : : }
152 : 0 : return PyCFunction_GET_CLASS(op);
153 : : }
154 : :
155 : : /* Methods (the standard built-in methods, that is) */
156 : :
157 : : static void
158 : 2229599 : meth_dealloc(PyCFunctionObject *m)
159 : : {
160 : : // The Py_TRASHCAN mechanism requires that we be able to
161 : : // call PyObject_GC_UnTrack twice on an object.
162 : 2229599 : PyObject_GC_UnTrack(m);
163 [ + - - + ]: 2229599 : Py_TRASHCAN_BEGIN(m, meth_dealloc);
164 [ - + ]: 2229599 : if (m->m_weakreflist != NULL) {
165 : 0 : PyObject_ClearWeakRefs((PyObject*) m);
166 : : }
167 : : // Dereference class before m_self: PyCFunction_GET_CLASS accesses
168 : : // PyMethodDef m_ml, which could be kept alive by m_self
169 : 2229599 : Py_XDECREF(PyCFunction_GET_CLASS(m));
170 : 2229599 : Py_XDECREF(m->m_self);
171 : 2229599 : Py_XDECREF(m->m_module);
172 : 2229599 : PyObject_GC_Del(m);
173 [ + - ]: 2229599 : Py_TRASHCAN_END;
174 : 2229599 : }
175 : :
176 : : static PyObject *
177 : 0 : meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored))
178 : : {
179 [ # # # # ]: 0 : if (m->m_self == NULL || PyModule_Check(m->m_self))
180 : 0 : return PyUnicode_FromString(m->m_ml->ml_name);
181 : :
182 : 0 : return Py_BuildValue("N(Os)", _PyEval_GetBuiltin(&_Py_ID(getattr)),
183 : 0 : m->m_self, m->m_ml->ml_name);
184 : : }
185 : :
186 : : static PyMethodDef meth_methods[] = {
187 : : {"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL},
188 : : {NULL, NULL}
189 : : };
190 : :
191 : : static PyObject *
192 : 0 : meth_get__text_signature__(PyCFunctionObject *m, void *closure)
193 : : {
194 : 0 : return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
195 : : }
196 : :
197 : : static PyObject *
198 : 15 : meth_get__doc__(PyCFunctionObject *m, void *closure)
199 : : {
200 : 15 : return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
201 : : }
202 : :
203 : : static PyObject *
204 : 183 : meth_get__name__(PyCFunctionObject *m, void *closure)
205 : : {
206 : 183 : return PyUnicode_FromString(m->m_ml->ml_name);
207 : : }
208 : :
209 : : static PyObject *
210 : 35 : meth_get__qualname__(PyCFunctionObject *m, void *closure)
211 : : {
212 : : /* If __self__ is a module or NULL, return m.__name__
213 : : (e.g. len.__qualname__ == 'len')
214 : :
215 : : If __self__ is a type, return m.__self__.__qualname__ + '.' + m.__name__
216 : : (e.g. dict.fromkeys.__qualname__ == 'dict.fromkeys')
217 : :
218 : : Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__
219 : : (e.g. [].append.__qualname__ == 'list.append') */
220 : : PyObject *type, *type_qualname, *res;
221 : :
222 [ + - + - ]: 35 : if (m->m_self == NULL || PyModule_Check(m->m_self))
223 : 35 : return PyUnicode_FromString(m->m_ml->ml_name);
224 : :
225 [ # # ]: 0 : type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self);
226 : :
227 : 0 : type_qualname = PyObject_GetAttr(type, &_Py_ID(__qualname__));
228 [ # # ]: 0 : if (type_qualname == NULL)
229 : 0 : return NULL;
230 : :
231 [ # # ]: 0 : if (!PyUnicode_Check(type_qualname)) {
232 : 0 : PyErr_SetString(PyExc_TypeError, "<method>.__class__."
233 : : "__qualname__ is not a unicode object");
234 : 0 : Py_XDECREF(type_qualname);
235 : 0 : return NULL;
236 : : }
237 : :
238 : 0 : res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name);
239 : 0 : Py_DECREF(type_qualname);
240 : 0 : return res;
241 : : }
242 : :
243 : : static int
244 : 160398 : meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
245 : : {
246 [ + + - + ]: 160398 : Py_VISIT(PyCFunction_GET_CLASS(m));
247 [ + + - + ]: 160398 : Py_VISIT(m->m_self);
248 [ + + - + ]: 160398 : Py_VISIT(m->m_module);
249 : 160398 : return 0;
250 : : }
251 : :
252 : : static PyObject *
253 : 1 : meth_get__self__(PyCFunctionObject *m, void *closure)
254 : : {
255 : : PyObject *self;
256 : :
257 : 1 : self = PyCFunction_GET_SELF(m);
258 [ - + ]: 1 : if (self == NULL)
259 : 0 : self = Py_None;
260 : 1 : return Py_NewRef(self);
261 : : }
262 : :
263 : : static PyGetSetDef meth_getsets [] = {
264 : : {"__doc__", (getter)meth_get__doc__, NULL, NULL},
265 : : {"__name__", (getter)meth_get__name__, NULL, NULL},
266 : : {"__qualname__", (getter)meth_get__qualname__, NULL, NULL},
267 : : {"__self__", (getter)meth_get__self__, NULL, NULL},
268 : : {"__text_signature__", (getter)meth_get__text_signature__, NULL, NULL},
269 : : {0}
270 : : };
271 : :
272 : : #define OFF(x) offsetof(PyCFunctionObject, x)
273 : :
274 : : static PyMemberDef meth_members[] = {
275 : : {"__module__", T_OBJECT, OFF(m_module), 0},
276 : : {NULL}
277 : : };
278 : :
279 : : static PyObject *
280 : 0 : meth_repr(PyCFunctionObject *m)
281 : : {
282 [ # # # # ]: 0 : if (m->m_self == NULL || PyModule_Check(m->m_self))
283 : 0 : return PyUnicode_FromFormat("<built-in function %s>",
284 : 0 : m->m_ml->ml_name);
285 : 0 : return PyUnicode_FromFormat("<built-in method %s of %s object at %p>",
286 : 0 : m->m_ml->ml_name,
287 : 0 : Py_TYPE(m->m_self)->tp_name,
288 : : m->m_self);
289 : : }
290 : :
291 : : static PyObject *
292 : 45 : meth_richcompare(PyObject *self, PyObject *other, int op)
293 : : {
294 : : PyCFunctionObject *a, *b;
295 : : PyObject *res;
296 : : int eq;
297 : :
298 [ + + + - : 90 : if ((op != Py_EQ && op != Py_NE) ||
+ - ]
299 [ + + ]: 90 : !PyCFunction_Check(self) ||
300 : 45 : !PyCFunction_Check(other))
301 : : {
302 : 35 : Py_RETURN_NOTIMPLEMENTED;
303 : : }
304 : 10 : a = (PyCFunctionObject *)self;
305 : 10 : b = (PyCFunctionObject *)other;
306 : 10 : eq = a->m_self == b->m_self;
307 [ + + ]: 10 : if (eq)
308 : 2 : eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
309 [ + + ]: 10 : if (op == Py_EQ)
310 [ - + ]: 8 : res = eq ? Py_True : Py_False;
311 : : else
312 [ + - ]: 2 : res = eq ? Py_False : Py_True;
313 : 10 : return Py_NewRef(res);
314 : : }
315 : :
316 : : static Py_hash_t
317 : 1305 : meth_hash(PyCFunctionObject *a)
318 : : {
319 : : Py_hash_t x, y;
320 : 1305 : x = _Py_HashPointer(a->m_self);
321 : 1305 : y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
322 : 1305 : x ^= y;
323 [ - + ]: 1305 : if (x == -1)
324 : 0 : x = -2;
325 : 1305 : return x;
326 : : }
327 : :
328 : :
329 : : PyTypeObject PyCFunction_Type = {
330 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
331 : : "builtin_function_or_method",
332 : : sizeof(PyCFunctionObject),
333 : : 0,
334 : : (destructor)meth_dealloc, /* tp_dealloc */
335 : : offsetof(PyCFunctionObject, vectorcall), /* tp_vectorcall_offset */
336 : : 0, /* tp_getattr */
337 : : 0, /* tp_setattr */
338 : : 0, /* tp_as_async */
339 : : (reprfunc)meth_repr, /* tp_repr */
340 : : 0, /* tp_as_number */
341 : : 0, /* tp_as_sequence */
342 : : 0, /* tp_as_mapping */
343 : : (hashfunc)meth_hash, /* tp_hash */
344 : : cfunction_call, /* tp_call */
345 : : 0, /* tp_str */
346 : : PyObject_GenericGetAttr, /* tp_getattro */
347 : : 0, /* tp_setattro */
348 : : 0, /* tp_as_buffer */
349 : : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
350 : : Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */
351 : : 0, /* tp_doc */
352 : : (traverseproc)meth_traverse, /* tp_traverse */
353 : : 0, /* tp_clear */
354 : : meth_richcompare, /* tp_richcompare */
355 : : offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */
356 : : 0, /* tp_iter */
357 : : 0, /* tp_iternext */
358 : : meth_methods, /* tp_methods */
359 : : meth_members, /* tp_members */
360 : : meth_getsets, /* tp_getset */
361 : : 0, /* tp_base */
362 : : 0, /* tp_dict */
363 : : };
364 : :
365 : : PyTypeObject PyCMethod_Type = {
366 : : PyVarObject_HEAD_INIT(&PyType_Type, 0)
367 : : .tp_name = "builtin_method",
368 : : .tp_basicsize = sizeof(PyCMethodObject),
369 : : .tp_base = &PyCFunction_Type,
370 : : };
371 : :
372 : : /* Vectorcall functions for each of the PyCFunction calling conventions,
373 : : * except for METH_VARARGS (possibly combined with METH_KEYWORDS) which
374 : : * doesn't use vectorcall.
375 : : *
376 : : * First, common helpers
377 : : */
378 : :
379 : : static inline int
380 : 1009724 : cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames)
381 : : {
382 : : assert(!_PyErr_Occurred(tstate));
383 : : assert(PyCFunction_Check(func));
384 [ + + + - ]: 1009724 : if (kwnames && PyTuple_GET_SIZE(kwnames)) {
385 : 2 : PyObject *funcstr = _PyObject_FunctionStr(func);
386 [ + - ]: 2 : if (funcstr != NULL) {
387 : 2 : _PyErr_Format(tstate, PyExc_TypeError,
388 : : "%U takes no keyword arguments", funcstr);
389 : 2 : Py_DECREF(funcstr);
390 : : }
391 : 2 : return -1;
392 : : }
393 : 1009722 : return 0;
394 : : }
395 : :
396 : : typedef void (*funcptr)(void);
397 : :
398 : : static inline funcptr
399 : 2467917 : cfunction_enter_call(PyThreadState *tstate, PyObject *func)
400 : : {
401 [ - + ]: 2467917 : if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
402 : 0 : return NULL;
403 : : }
404 : 2467917 : return (funcptr)PyCFunction_GET_FUNCTION(func);
405 : : }
406 : :
407 : : /* Now the actual vectorcall functions */
408 : : static PyObject *
409 : 3249 : cfunction_vectorcall_FASTCALL(
410 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
411 : : {
412 : 3249 : PyThreadState *tstate = _PyThreadState_GET();
413 [ + + ]: 3249 : if (cfunction_check_kwargs(tstate, func, kwnames)) {
414 : 2 : return NULL;
415 : : }
416 : 3247 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
417 : : _PyCFunctionFast meth = (_PyCFunctionFast)
418 : 3247 : cfunction_enter_call(tstate, func);
419 [ - + ]: 3247 : if (meth == NULL) {
420 : 0 : return NULL;
421 : : }
422 : 3247 : PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
423 : 3247 : _Py_LeaveRecursiveCallTstate(tstate);
424 : 3247 : return result;
425 : : }
426 : :
427 : : static PyObject *
428 : 12637 : cfunction_vectorcall_FASTCALL_KEYWORDS(
429 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
430 : : {
431 : 12637 : PyThreadState *tstate = _PyThreadState_GET();
432 : 12637 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
433 : : _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
434 : 12637 : cfunction_enter_call(tstate, func);
435 [ - + ]: 12637 : if (meth == NULL) {
436 : 0 : return NULL;
437 : : }
438 : 12637 : PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
439 : 12637 : _Py_LeaveRecursiveCallTstate(tstate);
440 : 12637 : return result;
441 : : }
442 : :
443 : : static PyObject *
444 : 1445588 : cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
445 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
446 : : {
447 : 1445588 : PyThreadState *tstate = _PyThreadState_GET();
448 : 1445588 : PyTypeObject *cls = PyCFunction_GET_CLASS(func);
449 : 1445588 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
450 : 1445588 : PyCMethod meth = (PyCMethod)cfunction_enter_call(tstate, func);
451 [ - + ]: 1445588 : if (meth == NULL) {
452 : 0 : return NULL;
453 : : }
454 : 1445588 : PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames);
455 : 1445588 : _Py_LeaveRecursiveCallTstate(tstate);
456 : 1445588 : return result;
457 : : }
458 : :
459 : : static PyObject *
460 : 428179 : cfunction_vectorcall_NOARGS(
461 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
462 : : {
463 : 428179 : PyThreadState *tstate = _PyThreadState_GET();
464 [ - + ]: 428179 : if (cfunction_check_kwargs(tstate, func, kwnames)) {
465 : 0 : return NULL;
466 : : }
467 : 428179 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
468 [ - + ]: 428179 : if (nargs != 0) {
469 : 0 : PyObject *funcstr = _PyObject_FunctionStr(func);
470 [ # # ]: 0 : if (funcstr != NULL) {
471 : 0 : _PyErr_Format(tstate, PyExc_TypeError,
472 : : "%U takes no arguments (%zd given)", funcstr, nargs);
473 : 0 : Py_DECREF(funcstr);
474 : : }
475 : 0 : return NULL;
476 : : }
477 : 428179 : PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
478 [ - + ]: 428179 : if (meth == NULL) {
479 : 0 : return NULL;
480 : : }
481 : 428179 : PyObject *result = _PyCFunction_TrampolineCall(
482 : : meth, PyCFunction_GET_SELF(func), NULL);
483 : 428179 : _Py_LeaveRecursiveCallTstate(tstate);
484 : 428179 : return result;
485 : : }
486 : :
487 : : static PyObject *
488 : 578296 : cfunction_vectorcall_O(
489 : : PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
490 : : {
491 : 578296 : PyThreadState *tstate = _PyThreadState_GET();
492 [ - + ]: 578296 : if (cfunction_check_kwargs(tstate, func, kwnames)) {
493 : 0 : return NULL;
494 : : }
495 : 578296 : Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
496 [ + + ]: 578296 : if (nargs != 1) {
497 : 30 : PyObject *funcstr = _PyObject_FunctionStr(func);
498 [ + - ]: 30 : if (funcstr != NULL) {
499 : 30 : _PyErr_Format(tstate, PyExc_TypeError,
500 : : "%U takes exactly one argument (%zd given)", funcstr, nargs);
501 : 30 : Py_DECREF(funcstr);
502 : : }
503 : 30 : return NULL;
504 : : }
505 : 578266 : PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
506 [ - + ]: 578266 : if (meth == NULL) {
507 : 0 : return NULL;
508 : : }
509 : 578266 : PyObject *result = _PyCFunction_TrampolineCall(
510 : : meth, PyCFunction_GET_SELF(func), args[0]);
511 : 578266 : _Py_LeaveRecursiveCallTstate(tstate);
512 : 578266 : return result;
513 : : }
514 : :
515 : :
516 : : static PyObject *
517 : 353599 : cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
518 : : {
519 : : assert(kwargs == NULL || PyDict_Check(kwargs));
520 : :
521 : 353599 : PyThreadState *tstate = _PyThreadState_GET();
522 : : assert(!_PyErr_Occurred(tstate));
523 : :
524 : 353599 : int flags = PyCFunction_GET_FLAGS(func);
525 [ - + ]: 353599 : if (!(flags & METH_VARARGS)) {
526 : : /* If this is not a METH_VARARGS function, delegate to vectorcall */
527 : 0 : return PyVectorcall_Call(func, args, kwargs);
528 : : }
529 : :
530 : : /* For METH_VARARGS, we cannot use vectorcall as the vectorcall pointer
531 : : * is NULL. This is intentional, since vectorcall would be slower. */
532 : 353599 : PyCFunction meth = PyCFunction_GET_FUNCTION(func);
533 : 353599 : PyObject *self = PyCFunction_GET_SELF(func);
534 : :
535 : : PyObject *result;
536 [ + + ]: 353599 : if (flags & METH_KEYWORDS) {
537 : 248334 : result = _PyCFunctionWithKeywords_TrampolineCall(
538 : : (*(PyCFunctionWithKeywords)(void(*)(void))meth),
539 : : self, args, kwargs);
540 : : }
541 : : else {
542 [ + + - + ]: 105265 : if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
543 : 0 : _PyErr_Format(tstate, PyExc_TypeError,
544 : : "%.200s() takes no keyword arguments",
545 : 0 : ((PyCFunctionObject*)func)->m_ml->ml_name);
546 : 0 : return NULL;
547 : : }
548 : 105265 : result = _PyCFunction_TrampolineCall(meth, self, args);
549 : : }
550 : 353599 : return _Py_CheckFunctionResult(tstate, func, result, NULL);
551 : : }
552 : :
553 : : #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
554 : : #include <emscripten.h>
555 : :
556 : : EM_JS(PyObject*, _PyCFunctionWithKeywords_TrampolineCall, (PyCFunctionWithKeywords func, PyObject *self, PyObject *args, PyObject *kw), {
557 : : return wasmTable.get(func)(self, args, kw);
558 : : });
559 : : #endif
|