/home/mdboom/Work/builds/cpython/Objects/classobject.c
Line | Count | Source (jump to first uncovered line) |
1 | /* Class object implementation (dead now except for methods) */ |
2 | |
3 | #include "Python.h" |
4 | #include "pycore_call.h" // _PyObject_VectorcallTstate() |
5 | #include "pycore_object.h" |
6 | #include "pycore_pyerrors.h" |
7 | #include "pycore_pystate.h" // _PyThreadState_GET() |
8 | #include "structmember.h" // PyMemberDef |
9 | |
10 | #include "clinic/classobject.c.h" |
11 | |
12 | #define TP_DESCR_GET(t) ((t)->tp_descr_get) |
13 | |
14 | /*[clinic input] |
15 | class method "PyMethodObject *" "&PyMethod_Type" |
16 | [clinic start generated code]*/ |
17 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=b16e47edf6107c23]*/ |
18 | |
19 | |
20 | PyObject * |
21 | PyMethod_Function(PyObject *im) |
22 | { |
23 | if (!PyMethod_Check(im)) { Branch (23:9): [True: 0, False: 0]
|
24 | PyErr_BadInternalCall(); |
25 | return NULL; |
26 | } |
27 | return ((PyMethodObject *)im)->im_func; |
28 | } |
29 | |
30 | PyObject * |
31 | PyMethod_Self(PyObject *im) |
32 | { |
33 | if (!PyMethod_Check(im)) { Branch (33:9): [True: 0, False: 0]
|
34 | PyErr_BadInternalCall(); |
35 | return NULL; |
36 | } |
37 | return ((PyMethodObject *)im)->im_self; |
38 | } |
39 | |
40 | |
41 | static PyObject * |
42 | method_vectorcall(PyObject *method, PyObject *const *args, |
43 | size_t nargsf, PyObject *kwnames) |
44 | { |
45 | assert(Py_IS_TYPE(method, &PyMethod_Type)); |
46 | |
47 | PyThreadState *tstate = _PyThreadState_GET(); |
48 | PyObject *self = PyMethod_GET_SELF(method); |
49 | PyObject *func = PyMethod_GET_FUNCTION(method); |
50 | Py_ssize_t nargs = PyVectorcall_NARGS(nargsf); |
51 | |
52 | PyObject *result; |
53 | if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) { Branch (53:9): [True: 4.26M, False: 8.80M]
|
54 | /* PY_VECTORCALL_ARGUMENTS_OFFSET is set, so we are allowed to mutate the vector */ |
55 | PyObject **newargs = (PyObject**)args - 1; |
56 | nargs += 1; |
57 | PyObject *tmp = newargs[0]; |
58 | newargs[0] = self; |
59 | result = _PyObject_VectorcallTstate(tstate, func, newargs, |
60 | nargs, kwnames); |
61 | newargs[0] = tmp; |
62 | } |
63 | else { |
64 | Py_ssize_t nkwargs = (kwnames == NULL) ? 08.77M : PyTuple_GET_SIZE31.0k (kwnames); Branch (64:30): [True: 8.77M, False: 31.0k]
|
65 | Py_ssize_t totalargs = nargs + nkwargs; |
66 | if (totalargs == 0) { Branch (66:13): [True: 3.73M, False: 5.06M]
|
67 | return _PyObject_VectorcallTstate(tstate, func, &self, 1, NULL); |
68 | } |
69 | |
70 | PyObject *newargs_stack[_PY_FASTCALL_SMALL_STACK]; |
71 | PyObject **newargs; |
72 | if (totalargs <= (Py_ssize_t)Py_ARRAY_LENGTH(newargs_stack) - 1) { Branch (72:13): [True: 3.99M, False: 1.07M]
|
73 | newargs = newargs_stack; |
74 | } |
75 | else { |
76 | newargs = PyMem_Malloc((totalargs+1) * sizeof(PyObject *)); |
77 | if (newargs == NULL) { Branch (77:17): [True: 0, False: 1.07M]
|
78 | _PyErr_NoMemory(tstate); |
79 | return NULL; |
80 | } |
81 | } |
82 | /* use borrowed references */ |
83 | newargs[0] = self; |
84 | /* bpo-37138: since totalargs > 0, it's impossible that args is NULL. |
85 | * We need this, since calling memcpy() with a NULL pointer is |
86 | * undefined behaviour. */ |
87 | assert(args != NULL); |
88 | memcpy(newargs + 1, args, totalargs * sizeof(PyObject *)); |
89 | result = _PyObject_VectorcallTstate(tstate, func, |
90 | newargs, nargs+1, kwnames); |
91 | if (newargs != newargs_stack) { Branch (91:13): [True: 1.07M, False: 3.99M]
|
92 | PyMem_Free(newargs); |
93 | } |
94 | } |
95 | return result; |
96 | } |
97 | |
98 | |
99 | /* Method objects are used for bound instance methods returned by |
100 | instancename.methodname. ClassName.methodname returns an ordinary |
101 | function. |
102 | */ |
103 | |
104 | PyObject * |
105 | PyMethod_New(PyObject *func, PyObject *self) |
106 | { |
107 | if (self == NULL) { Branch (107:9): [True: 0, False: 19.6M]
|
108 | PyErr_BadInternalCall(); |
109 | return NULL; |
110 | } |
111 | PyMethodObject *im = PyObject_GC_New(PyMethodObject, &PyMethod_Type); |
112 | if (im == NULL) { Branch (112:9): [True: 0, False: 19.6M]
|
113 | return NULL; |
114 | } |
115 | im->im_weakreflist = NULL; |
116 | Py_INCREF(func); |
117 | im->im_func = func; |
118 | Py_INCREF(self); |
119 | im->im_self = self; |
120 | im->vectorcall = method_vectorcall; |
121 | _PyObject_GC_TRACK(im); |
122 | return (PyObject *)im; |
123 | } |
124 | |
125 | /*[clinic input] |
126 | method.__reduce__ |
127 | [clinic start generated code]*/ |
128 | |
129 | static PyObject * |
130 | method___reduce___impl(PyMethodObject *self) |
131 | /*[clinic end generated code: output=6c04506d0fa6fdcb input=143a0bf5e96de6e8]*/ |
132 | { |
133 | PyObject *funcself = PyMethod_GET_SELF(self); |
134 | PyObject *func = PyMethod_GET_FUNCTION(self); |
135 | PyObject *funcname = PyObject_GetAttr(func, &_Py_ID(__name__)); |
136 | if (funcname == NULL) { Branch (136:9): [True: 0, False: 574]
|
137 | return NULL; |
138 | } |
139 | return Py_BuildValue( |
140 | "N(ON)", _PyEval_GetBuiltin(&_Py_ID(getattr)), funcself, funcname); |
141 | } |
142 | |
143 | static PyMethodDef method_methods[] = { |
144 | METHOD___REDUCE___METHODDEF |
145 | {NULL, NULL} |
146 | }; |
147 | |
148 | /* Descriptors for PyMethod attributes */ |
149 | |
150 | /* im_func and im_self are stored in the PyMethod object */ |
151 | |
152 | #define MO_OFF(x) offsetof(PyMethodObject, x) |
153 | |
154 | static PyMemberDef method_memberlist[] = { |
155 | {"__func__", T_OBJECT, MO_OFF(im_func), READONLY, |
156 | "the function (or other callable) implementing a method"}, |
157 | {"__self__", T_OBJECT, MO_OFF(im_self), READONLY, |
158 | "the instance to which a method is bound"}, |
159 | {NULL} /* Sentinel */ |
160 | }; |
161 | |
162 | /* Christian Tismer argued convincingly that method attributes should |
163 | (nearly) always override function attributes. |
164 | The one exception is __doc__; there's a default __doc__ which |
165 | should only be used for the class, not for instances */ |
166 | |
167 | static PyObject * |
168 | method_get_doc(PyMethodObject *im, void *context) |
169 | { |
170 | return PyObject_GetAttr(im->im_func, &_Py_ID(__doc__)); |
171 | } |
172 | |
173 | static PyGetSetDef method_getset[] = { |
174 | {"__doc__", (getter)method_get_doc, NULL, NULL}, |
175 | {0} |
176 | }; |
177 | |
178 | static PyObject * |
179 | method_getattro(PyObject *obj, PyObject *name) |
180 | { |
181 | PyMethodObject *im = (PyMethodObject *)obj; |
182 | PyTypeObject *tp = Py_TYPE(obj); |
183 | PyObject *descr = NULL; |
184 | |
185 | { |
186 | if (tp->tp_dict == NULL) { Branch (186:13): [True: 0, False: 314k]
|
187 | if (PyType_Ready(tp) < 0) Branch (187:17): [True: 0, False: 0]
|
188 | return NULL; |
189 | } |
190 | descr = _PyType_Lookup(tp, name); |
191 | } |
192 | |
193 | if (descr != NULL) { Branch (193:9): [True: 224k, False: 90.4k]
|
194 | descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr)); |
195 | if (f != NULL) Branch (195:13): [True: 224k, False: 60]
|
196 | return f(descr, obj, (PyObject *)Py_TYPE(obj)); |
197 | else { |
198 | Py_INCREF(descr); |
199 | return descr; |
200 | } |
201 | } |
202 | |
203 | return PyObject_GetAttr(im->im_func, name); |
204 | } |
205 | |
206 | /*[clinic input] |
207 | @classmethod |
208 | method.__new__ as method_new |
209 | function: object |
210 | instance: object |
211 | / |
212 | |
213 | Create a bound instance method object. |
214 | [clinic start generated code]*/ |
215 | |
216 | static PyObject * |
217 | method_new_impl(PyTypeObject *type, PyObject *function, PyObject *instance) |
218 | /*[clinic end generated code: output=d33ef4ebf702e1f7 input=4e32facc3c3108ae]*/ |
219 | { |
220 | if (!PyCallable_Check(function)) { Branch (220:9): [True: 0, False: 959]
|
221 | PyErr_SetString(PyExc_TypeError, |
222 | "first argument must be callable"); |
223 | return NULL; |
224 | } |
225 | if (instance == NULL || instance == Py_None) { Branch (225:9): [True: 0, False: 959]
Branch (225:29): [True: 0, False: 959]
|
226 | PyErr_SetString(PyExc_TypeError, |
227 | "instance must not be None"); |
228 | return NULL; |
229 | } |
230 | |
231 | return PyMethod_New(function, instance); |
232 | } |
233 | |
234 | static void |
235 | method_dealloc(PyMethodObject *im) |
236 | { |
237 | _PyObject_GC_UNTRACK(im); |
238 | if (im->im_weakreflist != NULL) Branch (238:9): [True: 1, False: 19.6M]
|
239 | PyObject_ClearWeakRefs((PyObject *)im); |
240 | Py_DECREF(im->im_func); |
241 | Py_XDECREF(im->im_self); |
242 | PyObject_GC_Del(im); |
243 | } |
244 | |
245 | static PyObject * |
246 | method_richcompare(PyObject *self, PyObject *other, int op) |
247 | { |
248 | PyMethodObject *a, *b; |
249 | PyObject *res; |
250 | int eq; |
251 | |
252 | if ((op != Py_EQ && op != 41 Py_NE41 ) || Branch (252:10): [True: 41, False: 35]
Branch (252:25): [True: 8, False: 33]
|
253 | !68 PyMethod_Check(self) || Branch (253:9): [True: 0, False: 68]
|
254 | !68 PyMethod_Check68 (other)) Branch (254:9): [True: 5, False: 63]
|
255 | { |
256 | Py_RETURN_NOTIMPLEMENTED; |
257 | } |
258 | a = (PyMethodObject *)self; |
259 | b = (PyMethodObject *)other; |
260 | eq = PyObject_RichCompareBool(a->im_func, b->im_func, Py_EQ); |
261 | if (eq == 1) { Branch (261:9): [True: 61, False: 2]
|
262 | eq = (a->im_self == b->im_self); |
263 | } |
264 | else if (eq < 0) Branch (264:14): [True: 0, False: 2]
|
265 | return NULL; |
266 | if (op == Py_EQ) Branch (266:9): [True: 32, False: 31]
|
267 | res = eq ? Py_True : Py_False2 ; Branch (267:15): [True: 30, False: 2]
|
268 | else |
269 | res = eq ? Py_False : Py_True3 ; Branch (269:15): [True: 28, False: 3]
|
270 | Py_INCREF(res); |
271 | return res; |
272 | } |
273 | |
274 | static PyObject * |
275 | method_repr(PyMethodObject *a) |
276 | { |
277 | PyObject *self = a->im_self; |
278 | PyObject *func = a->im_func; |
279 | PyObject *funcname, *result; |
280 | const char *defname = "?"; |
281 | |
282 | if (_PyObject_LookupAttr(func, &_Py_ID(__qualname__), &funcname) < 0 || Branch (282:9): [True: 0, False: 1.76k]
|
283 | (funcname == NULL && Branch (283:10): [True: 3, False: 1.75k]
|
284 | _PyObject_LookupAttr(func, &3 _Py_ID3 (__name__), &funcname) < 0)) Branch (284:10): [True: 0, False: 3]
|
285 | { |
286 | return NULL; |
287 | } |
288 | |
289 | if (funcname != NULL && !1.76k PyUnicode_Check1.76k (funcname)) { Branch (289:9): [True: 1.76k, False: 2]
Branch (289:29): [True: 0, False: 1.76k]
|
290 | Py_DECREF(funcname); |
291 | funcname = NULL; |
292 | } |
293 | |
294 | /* XXX Shouldn't use repr()/%R here! */ |
295 | result = PyUnicode_FromFormat("<bound method %V of %R>", |
296 | funcname, defname, self); |
297 | |
298 | Py_XDECREF(funcname); |
299 | return result; |
300 | } |
301 | |
302 | static Py_hash_t |
303 | method_hash(PyMethodObject *a) |
304 | { |
305 | Py_hash_t x, y; |
306 | x = _Py_HashPointer(a->im_self); |
307 | y = PyObject_Hash(a->im_func); |
308 | if (y == -1) Branch (308:9): [True: 0, False: 66]
|
309 | return -1; |
310 | x = x ^ y; |
311 | if (x == -1) Branch (311:9): [True: 0, False: 66]
|
312 | x = -2; |
313 | return x; |
314 | } |
315 | |
316 | static int |
317 | method_traverse(PyMethodObject *im, visitproc visit, void *arg) |
318 | { |
319 | Py_VISIT(im->im_func); |
320 | Py_VISIT(im->im_self); |
321 | return 0; |
322 | } |
323 | |
324 | PyTypeObject PyMethod_Type = { |
325 | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
326 | .tp_name = "method", |
327 | .tp_basicsize = sizeof(PyMethodObject), |
328 | .tp_dealloc = (destructor)method_dealloc, |
329 | .tp_vectorcall_offset = offsetof(PyMethodObject, vectorcall), |
330 | .tp_repr = (reprfunc)method_repr, |
331 | .tp_hash = (hashfunc)method_hash, |
332 | .tp_call = PyVectorcall_Call, |
333 | .tp_getattro = method_getattro, |
334 | .tp_setattro = PyObject_GenericSetAttr, |
335 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | |
336 | Py_TPFLAGS_HAVE_VECTORCALL, |
337 | .tp_doc = method_new__doc__, |
338 | .tp_traverse = (traverseproc)method_traverse, |
339 | .tp_richcompare = method_richcompare, |
340 | .tp_weaklistoffset = offsetof(PyMethodObject, im_weakreflist), |
341 | .tp_methods = method_methods, |
342 | .tp_members = method_memberlist, |
343 | .tp_getset = method_getset, |
344 | .tp_new = method_new, |
345 | }; |
346 | |
347 | /* ------------------------------------------------------------------------ |
348 | * instance method |
349 | */ |
350 | |
351 | /*[clinic input] |
352 | class instancemethod "PyInstanceMethodObject *" "&PyInstanceMethod_Type" |
353 | [clinic start generated code]*/ |
354 | /*[clinic end generated code: output=da39a3ee5e6b4b0d input=28c9762a9016f4d2]*/ |
355 | |
356 | PyObject * |
357 | PyInstanceMethod_New(PyObject *func) { |
358 | PyInstanceMethodObject *method; |
359 | method = PyObject_GC_New(PyInstanceMethodObject, |
360 | &PyInstanceMethod_Type); |
361 | if (method == NULL) return NULL0 ; Branch (361:9): [True: 0, False: 2]
|
362 | Py_INCREF(func); |
363 | method->func = func; |
364 | _PyObject_GC_TRACK(method); |
365 | return (PyObject *)method; |
366 | } |
367 | |
368 | PyObject * |
369 | PyInstanceMethod_Function(PyObject *im) |
370 | { |
371 | if (!PyInstanceMethod_Check(im)) { Branch (371:9): [True: 0, False: 0]
|
372 | PyErr_BadInternalCall(); |
373 | return NULL; |
374 | } |
375 | return PyInstanceMethod_GET_FUNCTION(im); |
376 | } |
377 | |
378 | #define IMO_OFF(x) offsetof(PyInstanceMethodObject, x) |
379 | |
380 | static PyMemberDef instancemethod_memberlist[] = { |
381 | {"__func__", T_OBJECT, IMO_OFF(func), READONLY, |
382 | "the function (or other callable) implementing a method"}, |
383 | {NULL} /* Sentinel */ |
384 | }; |
385 | |
386 | static PyObject * |
387 | instancemethod_get_doc(PyObject *self, void *context) |
388 | { |
389 | return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), |
390 | &_Py_ID(__doc__)); |
391 | } |
392 | |
393 | static PyGetSetDef instancemethod_getset[] = { |
394 | {"__doc__", (getter)instancemethod_get_doc, NULL, NULL}, |
395 | {0} |
396 | }; |
397 | |
398 | static PyObject * |
399 | instancemethod_getattro(PyObject *self, PyObject *name) |
400 | { |
401 | PyTypeObject *tp = Py_TYPE(self); |
402 | PyObject *descr = NULL; |
403 | |
404 | if (tp->tp_dict == NULL) { Branch (404:9): [True: 0, False: 2]
|
405 | if (PyType_Ready(tp) < 0) Branch (405:13): [True: 0, False: 0]
|
406 | return NULL; |
407 | } |
408 | descr = _PyType_Lookup(tp, name); |
409 | |
410 | if (descr != NULL) { Branch (410:9): [True: 2, False: 0]
|
411 | descrgetfunc f = TP_DESCR_GET(Py_TYPE(descr)); |
412 | if (f != NULL) Branch (412:13): [True: 2, False: 0]
|
413 | return f(descr, self, (PyObject *)Py_TYPE(self)); |
414 | else { |
415 | Py_INCREF(descr); |
416 | return descr; |
417 | } |
418 | } |
419 | |
420 | return PyObject_GetAttr(PyInstanceMethod_GET_FUNCTION(self), name); |
421 | } |
422 | |
423 | static void |
424 | instancemethod_dealloc(PyObject *self) { |
425 | _PyObject_GC_UNTRACK(self); |
426 | Py_DECREF(PyInstanceMethod_GET_FUNCTION(self)); |
427 | PyObject_GC_Del(self); |
428 | } |
429 | |
430 | static int |
431 | instancemethod_traverse(PyObject *self, visitproc visit, void *arg) { |
432 | Py_VISIT(PyInstanceMethod_GET_FUNCTION(self)); |
433 | return 0; |
434 | } |
435 | |
436 | static PyObject * |
437 | instancemethod_call(PyObject *self, PyObject *arg, PyObject *kw) |
438 | { |
439 | return PyObject_Call(PyInstanceMethod_GET_FUNCTION(self), arg, kw); |
440 | } |
441 | |
442 | static PyObject * |
443 | instancemethod_descr_get(PyObject *descr, PyObject *obj, PyObject *type) { |
444 | PyObject *func = PyInstanceMethod_GET_FUNCTION(descr); |
445 | if (obj == NULL) { Branch (445:9): [True: 2, False: 4]
|
446 | Py_INCREF(func); |
447 | return func; |
448 | } |
449 | else |
450 | return PyMethod_New(func, obj); |
451 | } |
452 | |
453 | static PyObject * |
454 | instancemethod_richcompare(PyObject *self, PyObject *other, int op) |
455 | { |
456 | PyInstanceMethodObject *a, *b; |
457 | PyObject *res; |
458 | int eq; |
459 |
|
460 | if ((op != Py_EQ && op != Py_NE) || Branch (460:10): [True: 0, False: 0]
Branch (460:25): [True: 0, False: 0]
|
461 | !PyInstanceMethod_Check(self) || Branch (461:9): [True: 0, False: 0]
|
462 | !PyInstanceMethod_Check(other)) Branch (462:9): [True: 0, False: 0]
|
463 | { |
464 | Py_RETURN_NOTIMPLEMENTED; |
465 | } |
466 | a = (PyInstanceMethodObject *)self; |
467 | b = (PyInstanceMethodObject *)other; |
468 | eq = PyObject_RichCompareBool(a->func, b->func, Py_EQ); |
469 | if (eq < 0) Branch (469:9): [True: 0, False: 0]
|
470 | return NULL; |
471 | if (op == Py_EQ) Branch (471:9): [True: 0, False: 0]
|
472 | res = eq ? Py_True : Py_False; Branch (472:15): [True: 0, False: 0]
|
473 | else |
474 | res = eq ? Py_False : Py_True; Branch (474:15): [True: 0, False: 0]
|
475 | Py_INCREF(res); |
476 | return res; |
477 | } |
478 | |
479 | static PyObject * |
480 | instancemethod_repr(PyObject *self) |
481 | { |
482 | PyObject *func = PyInstanceMethod_Function(self); |
483 | PyObject *funcname, *result; |
484 | const char *defname = "?"; |
485 |
|
486 | if (func == NULL) { Branch (486:9): [True: 0, False: 0]
|
487 | PyErr_BadInternalCall(); |
488 | return NULL; |
489 | } |
490 | |
491 | if (_PyObject_LookupAttr(func, &_Py_ID(__name__), &funcname) < 0) { Branch (491:9): [True: 0, False: 0]
|
492 | return NULL; |
493 | } |
494 | if (funcname != NULL && !PyUnicode_Check(funcname)) { Branch (494:9): [True: 0, False: 0]
Branch (494:29): [True: 0, False: 0]
|
495 | Py_DECREF(funcname); |
496 | funcname = NULL; |
497 | } |
498 |
|
499 | result = PyUnicode_FromFormat("<instancemethod %V at %p>", |
500 | funcname, defname, self); |
501 |
|
502 | Py_XDECREF(funcname); |
503 | return result; |
504 | } |
505 | |
506 | /*[clinic input] |
507 | @classmethod |
508 | instancemethod.__new__ as instancemethod_new |
509 | function: object |
510 | / |
511 | |
512 | Bind a function to a class. |
513 | [clinic start generated code]*/ |
514 | |
515 | static PyObject * |
516 | instancemethod_new_impl(PyTypeObject *type, PyObject *function) |
517 | /*[clinic end generated code: output=5e0397b2bdb750be input=cfc54e8b973664a8]*/ |
518 | { |
519 | if (!PyCallable_Check(function)) { Branch (519:9): [True: 0, False: 2]
|
520 | PyErr_SetString(PyExc_TypeError, |
521 | "first argument must be callable"); |
522 | return NULL; |
523 | } |
524 | |
525 | return PyInstanceMethod_New(function); |
526 | } |
527 | |
528 | PyTypeObject PyInstanceMethod_Type = { |
529 | PyVarObject_HEAD_INIT(&PyType_Type, 0) |
530 | .tp_name = "instancemethod", |
531 | .tp_basicsize = sizeof(PyInstanceMethodObject), |
532 | .tp_dealloc = instancemethod_dealloc, |
533 | .tp_repr = (reprfunc)instancemethod_repr, |
534 | .tp_call = instancemethod_call, |
535 | .tp_getattro = instancemethod_getattro, |
536 | .tp_setattro = PyObject_GenericSetAttr, |
537 | .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, |
538 | .tp_doc = instancemethod_new__doc__, |
539 | .tp_traverse = instancemethod_traverse, |
540 | .tp_richcompare = instancemethod_richcompare, |
541 | .tp_members = instancemethod_memberlist, |
542 | .tp_getset = instancemethod_getset, |
543 | .tp_descr_get = instancemethod_descr_get, |
544 | .tp_new = instancemethod_new, |
545 | }; |