/src/Python-3.8.3/Objects/methodobject.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /* Method object implementation */ |
3 | | |
4 | | #include "Python.h" |
5 | | #include "pycore_object.h" |
6 | | #include "pycore_pymem.h" |
7 | | #include "pycore_pystate.h" |
8 | | #include "structmember.h" |
9 | | |
10 | | /* Free list for method objects to safe malloc/free overhead |
11 | | * The m_self element is used to chain the objects. |
12 | | */ |
13 | | static PyCFunctionObject *free_list = NULL; |
14 | | static int numfree = 0; |
15 | | #ifndef PyCFunction_MAXFREELIST |
16 | 8.84k | #define PyCFunction_MAXFREELIST 256 |
17 | | #endif |
18 | | |
19 | | /* undefine macro trampoline to PyCFunction_NewEx */ |
20 | | #undef PyCFunction_New |
21 | | |
22 | | /* Forward declarations */ |
23 | | static PyObject * cfunction_vectorcall_FASTCALL( |
24 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); |
25 | | static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS( |
26 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); |
27 | | static PyObject * cfunction_vectorcall_NOARGS( |
28 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); |
29 | | static PyObject * cfunction_vectorcall_O( |
30 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames); |
31 | | |
32 | | |
33 | | PyObject * |
34 | | PyCFunction_New(PyMethodDef *ml, PyObject *self) |
35 | 0 | { |
36 | 0 | return PyCFunction_NewEx(ml, self, NULL); |
37 | 0 | } |
38 | | |
39 | | PyObject * |
40 | | PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module) |
41 | 16.8k | { |
42 | | /* Figure out correct vectorcall function to use */ |
43 | 16.8k | vectorcallfunc vectorcall; |
44 | 16.8k | switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS | METH_O | METH_KEYWORDS)) |
45 | 16.8k | { |
46 | 1.70k | case METH_VARARGS: |
47 | 4.40k | case METH_VARARGS | METH_KEYWORDS: |
48 | | /* For METH_VARARGS functions, it's more efficient to use tp_call |
49 | | * instead of vectorcall. */ |
50 | 4.40k | vectorcall = NULL; |
51 | 4.40k | break; |
52 | 1.39k | case METH_FASTCALL: |
53 | 1.39k | vectorcall = cfunction_vectorcall_FASTCALL; |
54 | 1.39k | break; |
55 | 3.18k | case METH_FASTCALL | METH_KEYWORDS: |
56 | 3.18k | vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS; |
57 | 3.18k | break; |
58 | 5.26k | case METH_NOARGS: |
59 | 5.26k | vectorcall = cfunction_vectorcall_NOARGS; |
60 | 5.26k | break; |
61 | 2.58k | case METH_O: |
62 | 2.58k | vectorcall = cfunction_vectorcall_O; |
63 | 2.58k | break; |
64 | 0 | default: |
65 | 0 | PyErr_Format(PyExc_SystemError, |
66 | 0 | "%s() method: bad call flags", ml->ml_name); |
67 | 0 | return NULL; |
68 | 16.8k | } |
69 | | |
70 | 16.8k | PyCFunctionObject *op; |
71 | 16.8k | op = free_list; |
72 | 16.8k | if (op != NULL) { |
73 | 8.84k | free_list = (PyCFunctionObject *)(op->m_self); |
74 | 8.84k | (void)PyObject_INIT(op, &PyCFunction_Type); |
75 | 8.84k | numfree--; |
76 | 8.84k | } |
77 | 7.98k | else { |
78 | 7.98k | op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type); |
79 | 7.98k | if (op == NULL) |
80 | 0 | return NULL; |
81 | 7.98k | } |
82 | 16.8k | op->m_weakreflist = NULL; |
83 | 16.8k | op->m_ml = ml; |
84 | 16.8k | Py_XINCREF(self); |
85 | 16.8k | op->m_self = self; |
86 | 16.8k | Py_XINCREF(module); |
87 | 16.8k | op->m_module = module; |
88 | 16.8k | op->vectorcall = vectorcall; |
89 | 16.8k | _PyObject_GC_TRACK(op); |
90 | 16.8k | return (PyObject *)op; |
91 | 16.8k | } |
92 | | |
93 | | PyCFunction |
94 | | PyCFunction_GetFunction(PyObject *op) |
95 | 0 | { |
96 | 0 | if (!PyCFunction_Check(op)) { |
97 | 0 | PyErr_BadInternalCall(); |
98 | 0 | return NULL; |
99 | 0 | } |
100 | 0 | return PyCFunction_GET_FUNCTION(op); |
101 | 0 | } |
102 | | |
103 | | PyObject * |
104 | | PyCFunction_GetSelf(PyObject *op) |
105 | 0 | { |
106 | 0 | if (!PyCFunction_Check(op)) { |
107 | 0 | PyErr_BadInternalCall(); |
108 | 0 | return NULL; |
109 | 0 | } |
110 | 0 | return PyCFunction_GET_SELF(op); |
111 | 0 | } |
112 | | |
113 | | int |
114 | | PyCFunction_GetFlags(PyObject *op) |
115 | 0 | { |
116 | 0 | if (!PyCFunction_Check(op)) { |
117 | 0 | PyErr_BadInternalCall(); |
118 | 0 | return -1; |
119 | 0 | } |
120 | 0 | return PyCFunction_GET_FLAGS(op); |
121 | 0 | } |
122 | | |
123 | | /* Methods (the standard built-in methods, that is) */ |
124 | | |
125 | | static void |
126 | | meth_dealloc(PyCFunctionObject *m) |
127 | 8.84k | { |
128 | 8.84k | _PyObject_GC_UNTRACK(m); |
129 | 8.84k | if (m->m_weakreflist != NULL) { |
130 | 0 | PyObject_ClearWeakRefs((PyObject*) m); |
131 | 0 | } |
132 | 8.84k | Py_XDECREF(m->m_self); |
133 | 8.84k | Py_XDECREF(m->m_module); |
134 | 8.84k | if (numfree < PyCFunction_MAXFREELIST) { |
135 | 8.84k | m->m_self = (PyObject *)free_list; |
136 | 8.84k | free_list = m; |
137 | 8.84k | numfree++; |
138 | 8.84k | } |
139 | 0 | else { |
140 | 0 | PyObject_GC_Del(m); |
141 | 0 | } |
142 | 8.84k | } |
143 | | |
144 | | static PyObject * |
145 | | meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored)) |
146 | 0 | { |
147 | 0 | _Py_IDENTIFIER(getattr); |
148 | |
|
149 | 0 | if (m->m_self == NULL || PyModule_Check(m->m_self)) |
150 | 0 | return PyUnicode_FromString(m->m_ml->ml_name); |
151 | | |
152 | 0 | return Py_BuildValue("N(Os)", _PyEval_GetBuiltinId(&PyId_getattr), |
153 | 0 | m->m_self, m->m_ml->ml_name); |
154 | 0 | } |
155 | | |
156 | | static PyMethodDef meth_methods[] = { |
157 | | {"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL}, |
158 | | {NULL, NULL} |
159 | | }; |
160 | | |
161 | | static PyObject * |
162 | | meth_get__text_signature__(PyCFunctionObject *m, void *closure) |
163 | 0 | { |
164 | 0 | return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); |
165 | 0 | } |
166 | | |
167 | | static PyObject * |
168 | | meth_get__doc__(PyCFunctionObject *m, void *closure) |
169 | 0 | { |
170 | 0 | return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc); |
171 | 0 | } |
172 | | |
173 | | static PyObject * |
174 | | meth_get__name__(PyCFunctionObject *m, void *closure) |
175 | 0 | { |
176 | 0 | return PyUnicode_FromString(m->m_ml->ml_name); |
177 | 0 | } |
178 | | |
179 | | static PyObject * |
180 | | meth_get__qualname__(PyCFunctionObject *m, void *closure) |
181 | 0 | { |
182 | | /* If __self__ is a module or NULL, return m.__name__ |
183 | | (e.g. len.__qualname__ == 'len') |
184 | | |
185 | | If __self__ is a type, return m.__self__.__qualname__ + '.' + m.__name__ |
186 | | (e.g. dict.fromkeys.__qualname__ == 'dict.fromkeys') |
187 | | |
188 | | Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__ |
189 | | (e.g. [].append.__qualname__ == 'list.append') */ |
190 | 0 | PyObject *type, *type_qualname, *res; |
191 | 0 | _Py_IDENTIFIER(__qualname__); |
192 | |
|
193 | 0 | if (m->m_self == NULL || PyModule_Check(m->m_self)) |
194 | 0 | return PyUnicode_FromString(m->m_ml->ml_name); |
195 | | |
196 | 0 | type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self); |
197 | |
|
198 | 0 | type_qualname = _PyObject_GetAttrId(type, &PyId___qualname__); |
199 | 0 | if (type_qualname == NULL) |
200 | 0 | return NULL; |
201 | | |
202 | 0 | if (!PyUnicode_Check(type_qualname)) { |
203 | 0 | PyErr_SetString(PyExc_TypeError, "<method>.__class__." |
204 | 0 | "__qualname__ is not a unicode object"); |
205 | 0 | Py_XDECREF(type_qualname); |
206 | 0 | return NULL; |
207 | 0 | } |
208 | | |
209 | 0 | res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name); |
210 | 0 | Py_DECREF(type_qualname); |
211 | 0 | return res; |
212 | 0 | } |
213 | | |
214 | | static int |
215 | | meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg) |
216 | 16.4k | { |
217 | 16.4k | Py_VISIT(m->m_self); |
218 | 16.4k | Py_VISIT(m->m_module); |
219 | 16.4k | return 0; |
220 | 16.4k | } |
221 | | |
222 | | static PyObject * |
223 | | meth_get__self__(PyCFunctionObject *m, void *closure) |
224 | 1 | { |
225 | 1 | PyObject *self; |
226 | | |
227 | 1 | self = PyCFunction_GET_SELF(m); |
228 | 1 | if (self == NULL) |
229 | 0 | self = Py_None; |
230 | 1 | Py_INCREF(self); |
231 | 1 | return self; |
232 | 1 | } |
233 | | |
234 | | static PyGetSetDef meth_getsets [] = { |
235 | | {"__doc__", (getter)meth_get__doc__, NULL, NULL}, |
236 | | {"__name__", (getter)meth_get__name__, NULL, NULL}, |
237 | | {"__qualname__", (getter)meth_get__qualname__, NULL, NULL}, |
238 | | {"__self__", (getter)meth_get__self__, NULL, NULL}, |
239 | | {"__text_signature__", (getter)meth_get__text_signature__, NULL, NULL}, |
240 | | {0} |
241 | | }; |
242 | | |
243 | | #define OFF(x) offsetof(PyCFunctionObject, x) |
244 | | |
245 | | static PyMemberDef meth_members[] = { |
246 | | {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED}, |
247 | | {NULL} |
248 | | }; |
249 | | |
250 | | static PyObject * |
251 | | meth_repr(PyCFunctionObject *m) |
252 | 0 | { |
253 | 0 | if (m->m_self == NULL || PyModule_Check(m->m_self)) |
254 | 0 | return PyUnicode_FromFormat("<built-in function %s>", |
255 | 0 | m->m_ml->ml_name); |
256 | 0 | return PyUnicode_FromFormat("<built-in method %s of %s object at %p>", |
257 | 0 | m->m_ml->ml_name, |
258 | 0 | m->m_self->ob_type->tp_name, |
259 | 0 | m->m_self); |
260 | 0 | } |
261 | | |
262 | | static PyObject * |
263 | | meth_richcompare(PyObject *self, PyObject *other, int op) |
264 | 0 | { |
265 | 0 | PyCFunctionObject *a, *b; |
266 | 0 | PyObject *res; |
267 | 0 | int eq; |
268 | |
|
269 | 0 | if ((op != Py_EQ && op != Py_NE) || |
270 | 0 | !PyCFunction_Check(self) || |
271 | 0 | !PyCFunction_Check(other)) |
272 | 0 | { |
273 | 0 | Py_RETURN_NOTIMPLEMENTED; |
274 | 0 | } |
275 | 0 | a = (PyCFunctionObject *)self; |
276 | 0 | b = (PyCFunctionObject *)other; |
277 | 0 | eq = a->m_self == b->m_self; |
278 | 0 | if (eq) |
279 | 0 | eq = a->m_ml->ml_meth == b->m_ml->ml_meth; |
280 | 0 | if (op == Py_EQ) |
281 | 0 | res = eq ? Py_True : Py_False; |
282 | 0 | else |
283 | 0 | res = eq ? Py_False : Py_True; |
284 | 0 | Py_INCREF(res); |
285 | 0 | return res; |
286 | 0 | } |
287 | | |
288 | | static Py_hash_t |
289 | | meth_hash(PyCFunctionObject *a) |
290 | 618 | { |
291 | 618 | Py_hash_t x, y; |
292 | 618 | x = _Py_HashPointer(a->m_self); |
293 | 618 | y = _Py_HashPointer((void*)(a->m_ml->ml_meth)); |
294 | 618 | x ^= y; |
295 | 618 | if (x == -1) |
296 | 0 | x = -2; |
297 | 618 | return x; |
298 | 618 | } |
299 | | |
300 | | |
301 | | PyTypeObject PyCFunction_Type = { |
302 | | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
303 | | "builtin_function_or_method", |
304 | | sizeof(PyCFunctionObject), |
305 | | 0, |
306 | | (destructor)meth_dealloc, /* tp_dealloc */ |
307 | | offsetof(PyCFunctionObject, vectorcall), /* tp_vectorcall_offset */ |
308 | | 0, /* tp_getattr */ |
309 | | 0, /* tp_setattr */ |
310 | | 0, /* tp_as_async */ |
311 | | (reprfunc)meth_repr, /* tp_repr */ |
312 | | 0, /* tp_as_number */ |
313 | | 0, /* tp_as_sequence */ |
314 | | 0, /* tp_as_mapping */ |
315 | | (hashfunc)meth_hash, /* tp_hash */ |
316 | | PyCFunction_Call, /* tp_call */ |
317 | | 0, /* tp_str */ |
318 | | PyObject_GenericGetAttr, /* tp_getattro */ |
319 | | 0, /* tp_setattro */ |
320 | | 0, /* tp_as_buffer */ |
321 | | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
322 | | _Py_TPFLAGS_HAVE_VECTORCALL, /* tp_flags */ |
323 | | 0, /* tp_doc */ |
324 | | (traverseproc)meth_traverse, /* tp_traverse */ |
325 | | 0, /* tp_clear */ |
326 | | meth_richcompare, /* tp_richcompare */ |
327 | | offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */ |
328 | | 0, /* tp_iter */ |
329 | | 0, /* tp_iternext */ |
330 | | meth_methods, /* tp_methods */ |
331 | | meth_members, /* tp_members */ |
332 | | meth_getsets, /* tp_getset */ |
333 | | 0, /* tp_base */ |
334 | | 0, /* tp_dict */ |
335 | | }; |
336 | | |
337 | | /* Clear out the free list */ |
338 | | |
339 | | int |
340 | | PyCFunction_ClearFreeList(void) |
341 | 0 | { |
342 | 0 | int freelist_size = numfree; |
343 | |
|
344 | 0 | while (free_list) { |
345 | 0 | PyCFunctionObject *v = free_list; |
346 | 0 | free_list = (PyCFunctionObject *)(v->m_self); |
347 | 0 | PyObject_GC_Del(v); |
348 | 0 | numfree--; |
349 | 0 | } |
350 | 0 | assert(numfree == 0); |
351 | 0 | return freelist_size; |
352 | 0 | } |
353 | | |
354 | | void |
355 | | PyCFunction_Fini(void) |
356 | 0 | { |
357 | 0 | (void)PyCFunction_ClearFreeList(); |
358 | 0 | } |
359 | | |
360 | | /* Print summary info about the state of the optimized allocator */ |
361 | | void |
362 | | _PyCFunction_DebugMallocStats(FILE *out) |
363 | 0 | { |
364 | 0 | _PyDebugAllocatorStats(out, |
365 | 0 | "free PyCFunctionObject", |
366 | 0 | numfree, sizeof(PyCFunctionObject)); |
367 | 0 | } |
368 | | |
369 | | |
370 | | /* Vectorcall functions for each of the PyCFunction calling conventions, |
371 | | * except for METH_VARARGS (possibly combined with METH_KEYWORDS) which |
372 | | * doesn't use vectorcall. |
373 | | * |
374 | | * First, common helpers |
375 | | */ |
376 | | static const char * |
377 | | get_name(PyObject *func) |
378 | 0 | { |
379 | 0 | assert(PyCFunction_Check(func)); |
380 | 0 | PyMethodDef *method = ((PyCFunctionObject *)func)->m_ml; |
381 | 0 | return method->ml_name; |
382 | 0 | } |
383 | | |
384 | | typedef void (*funcptr)(void); |
385 | | |
386 | | static inline int |
387 | | cfunction_check_kwargs(PyObject *func, PyObject *kwnames) |
388 | 25.8k | { |
389 | 25.8k | assert(!PyErr_Occurred()); |
390 | 25.8k | assert(PyCFunction_Check(func)); |
391 | 25.8k | if (kwnames && PyTuple_GET_SIZE(kwnames)) { |
392 | 0 | PyErr_Format(PyExc_TypeError, |
393 | 0 | "%.200s() takes no keyword arguments", get_name(func)); |
394 | 0 | return -1; |
395 | 0 | } |
396 | 25.8k | return 0; |
397 | 25.8k | } |
398 | | |
399 | | static inline funcptr |
400 | | cfunction_enter_call(PyObject *func) |
401 | 32.3k | { |
402 | 32.3k | if (Py_EnterRecursiveCall(" while calling a Python object")) { |
403 | 0 | return NULL; |
404 | 0 | } |
405 | 32.3k | return (funcptr)PyCFunction_GET_FUNCTION(func); |
406 | 32.3k | } |
407 | | |
408 | | /* Now the actual vectorcall functions */ |
409 | | static PyObject * |
410 | | cfunction_vectorcall_FASTCALL( |
411 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
412 | 10.7k | { |
413 | 10.7k | if (cfunction_check_kwargs(func, kwnames)) { |
414 | 0 | return NULL; |
415 | 0 | } |
416 | 10.7k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
417 | 10.7k | _PyCFunctionFast meth = (_PyCFunctionFast) |
418 | 10.7k | cfunction_enter_call(func); |
419 | 10.7k | if (meth == NULL) { |
420 | 0 | return NULL; |
421 | 0 | } |
422 | 10.7k | PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs); |
423 | 10.7k | Py_LeaveRecursiveCall(); |
424 | 10.7k | return result; |
425 | 10.7k | } |
426 | | |
427 | | static PyObject * |
428 | | cfunction_vectorcall_FASTCALL_KEYWORDS( |
429 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
430 | 6.52k | { |
431 | 6.52k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
432 | 6.52k | _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords) |
433 | 6.52k | cfunction_enter_call(func); |
434 | 6.52k | if (meth == NULL) { |
435 | 0 | return NULL; |
436 | 0 | } |
437 | 6.52k | PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames); |
438 | 6.52k | Py_LeaveRecursiveCall(); |
439 | 6.52k | return result; |
440 | 6.52k | } |
441 | | |
442 | | static PyObject * |
443 | | cfunction_vectorcall_NOARGS( |
444 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
445 | 9.33k | { |
446 | 9.33k | if (cfunction_check_kwargs(func, kwnames)) { |
447 | 0 | return NULL; |
448 | 0 | } |
449 | 9.33k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
450 | 9.33k | if (nargs != 0) { |
451 | 0 | PyErr_Format(PyExc_TypeError, |
452 | 0 | "%.200s() takes no arguments (%zd given)", get_name(func), nargs); |
453 | 0 | return NULL; |
454 | 0 | } |
455 | 9.33k | PyCFunction meth = (PyCFunction)cfunction_enter_call(func); |
456 | 9.33k | if (meth == NULL) { |
457 | 0 | return NULL; |
458 | 0 | } |
459 | 9.33k | PyObject *result = meth(PyCFunction_GET_SELF(func), NULL); |
460 | 9.33k | Py_LeaveRecursiveCall(); |
461 | 9.33k | return result; |
462 | 9.33k | } |
463 | | |
464 | | static PyObject * |
465 | | cfunction_vectorcall_O( |
466 | | PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames) |
467 | 5.75k | { |
468 | 5.75k | if (cfunction_check_kwargs(func, kwnames)) { |
469 | 0 | return NULL; |
470 | 0 | } |
471 | 5.75k | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
472 | 5.75k | if (nargs != 1) { |
473 | 0 | PyErr_Format(PyExc_TypeError, |
474 | 0 | "%.200s() takes exactly one argument (%zd given)", |
475 | 0 | get_name(func), nargs); |
476 | 0 | return NULL; |
477 | 0 | } |
478 | 5.75k | PyCFunction meth = (PyCFunction)cfunction_enter_call(func); |
479 | 5.75k | if (meth == NULL) { |
480 | 0 | return NULL; |
481 | 0 | } |
482 | 5.75k | PyObject *result = meth(PyCFunction_GET_SELF(func), args[0]); |
483 | 5.75k | Py_LeaveRecursiveCall(); |
484 | 5.75k | return result; |
485 | 5.75k | } |