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