Nuitka
The Python compiler
Loading...
Searching...
No Matches
CompiledMethodType.c
1// Copyright 2026, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
10// This file is included from another C file, help IDEs to still parse it on
11// its own.
12#ifdef __IDE_ONLY__
13#include "nuitka/freelists.h"
14#include "nuitka/prelude.h"
15#include <structmember.h>
16#endif
17
18#if _DEBUG_REFCOUNTS
19int count_active_Nuitka_Method_Type;
20int count_allocated_Nuitka_Method_Type;
21int count_released_Nuitka_Method_Type;
22#endif
23
24static PyObject *Nuitka_Method_get__doc__(PyObject *self, void *data) {
25 struct Nuitka_MethodObject *method = (struct Nuitka_MethodObject *)self;
26 PyObject *result = method->m_function->m_doc;
27
28 if (result == NULL) {
29 result = Py_None;
30 }
31
32 Py_INCREF(result);
33 return result;
34}
35
36static PyGetSetDef Nuitka_Method_tp_getset[] = {{(char *)"__doc__", Nuitka_Method_get__doc__, NULL, NULL}, {NULL}};
37
38#define OFF(x) offsetof(struct Nuitka_MethodObject, x)
39
40static PyMemberDef Nuitka_Method_members[] = {
41 {(char *)"im_class", T_OBJECT, OFF(m_class), READONLY | RESTRICTED, (char *)"the class associated with a method"},
42 {(char *)"im_func", T_OBJECT, OFF(m_function), READONLY | RESTRICTED,
43 (char *)"the function (or other callable) implementing a method"},
44 {(char *)"__func__", T_OBJECT, OFF(m_function), READONLY | RESTRICTED,
45 (char *)"the function (or other callable) implementing a method"},
46 {(char *)"im_self", T_OBJECT, OFF(m_object), READONLY | RESTRICTED,
47 (char *)"the instance to which a method is bound; None for unbound method"},
48 {(char *)"__self__", T_OBJECT, OFF(m_object), READONLY | RESTRICTED,
49 (char *)"the instance to which a method is bound; None for unbound method"},
50 {NULL}};
51
52static PyObject *Nuitka_Method_reduce(struct Nuitka_MethodObject *method, PyObject *unused) {
53 PyThreadState *tstate = PyThreadState_GET();
54
55#if PYTHON_VERSION < 0x300
56 // spell-checker: ignore instancemethod
57 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "can't pickle instancemethod objects");
58 return NULL;
59#else
60 PyObject *result = MAKE_TUPLE_EMPTY(tstate, 2);
61 PyTuple_SET_ITEM0(result, 0, LOOKUP_BUILTIN(const_str_plain_getattr));
62 PyObject *arg_tuple = MAKE_TUPLE2(tstate, method->m_object, method->m_function->m_name);
63 PyTuple_SET_ITEM(result, 1, arg_tuple);
64
65 CHECK_OBJECT_DEEP(result);
66
67 return result;
68#endif
69}
70
71static PyObject *Nuitka_Method_reduce_ex(struct Nuitka_MethodObject *method, PyObject *args) {
72 int proto;
73
74 if (!PyArg_ParseTuple(args, "|i:__reduce_ex__", &proto)) {
75 return NULL;
76 }
77
78 // Python API, spell-checker: ignore newobj
79
80#if PYTHON_VERSION < 0x300
81 PyObject *copy_reg = PyImport_ImportModule("copy_reg");
82
83 CHECK_OBJECT(copy_reg);
84 PyThreadState *tstate = PyThreadState_GET();
85
86 PyObject *newobj_func = LOOKUP_ATTRIBUTE(tstate, copy_reg, const_str_plain___newobj__);
87 Py_DECREF(copy_reg);
88 if (unlikely(newobj_func == NULL)) {
89 return NULL;
90 }
91
92 PyObject *result = MAKE_TUPLE_EMPTY(tstate, 5);
93 PyTuple_SET_ITEM(result, 0, newobj_func);
94 PyObject *type_tuple = MAKE_TUPLE1(tstate, (PyObject *)&Nuitka_Method_Type);
95 PyTuple_SET_ITEM(result, 1, type_tuple);
96 PyTuple_SET_ITEM_IMMORTAL(result, 2, Py_None);
97 PyTuple_SET_ITEM_IMMORTAL(result, 3, Py_None);
98 PyTuple_SET_ITEM_IMMORTAL(result, 4, Py_None);
99
100 CHECK_OBJECT_DEEP(result);
101
102 return result;
103#else
104 return Nuitka_Method_reduce(method, NULL);
105#endif
106}
107
108static PyObject *Nuitka_Method_deepcopy(struct Nuitka_MethodObject *method, PyObject *memo) {
109 assert(Nuitka_Method_Check((PyObject *)method));
110
111 static PyObject *module_copy = NULL;
112 static PyObject *deepcopy_function = NULL;
113
114 if (module_copy == NULL) {
115 module_copy = PyImport_ImportModule("copy");
116 CHECK_OBJECT(module_copy);
117
118 deepcopy_function = PyObject_GetAttrString(module_copy, "deepcopy");
119 CHECK_OBJECT(deepcopy_function);
120 }
121
122 PyObject *object = PyObject_CallFunctionObjArgs(deepcopy_function, method->m_object, memo, NULL);
123
124 if (unlikely(object == NULL)) {
125 return NULL;
126 }
127
128 PyObject *result = Nuitka_Method_New(method->m_function, object, method->m_class);
129 // Nuitka_Method_New took a reference to the object.
130 Py_DECREF(object);
131 return result;
132}
133
134static PyMethodDef Nuitka_Method_methods[] = {
135 {"__reduce__", (PyCFunction)Nuitka_Method_reduce, METH_NOARGS, NULL},
136 {"__reduce_ex__", (PyCFunction)Nuitka_Method_reduce_ex, METH_VARARGS, NULL},
137 {"__deepcopy__", (PyCFunction)Nuitka_Method_deepcopy, METH_O, NULL},
138 {NULL}};
139
140#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
141static PyObject *Nuitka_Method_tp_vectorcall(struct Nuitka_MethodObject *method, PyObject *const *stack, size_t nargs_f,
142 PyObject *kw_names) {
143 assert(Nuitka_Method_Check((PyObject *)method));
144 assert(kw_names == NULL || PyTuple_CheckExact(kw_names));
145 Py_ssize_t kwargs_count = (kw_names == NULL) ? 0 : PyTuple_GET_SIZE(kw_names);
146 Py_ssize_t nargs = PyVectorcall_NARGS(nargs_f);
147
148 assert(nargs >= 0);
149 assert((nargs == 0 && kwargs_count == 0) || stack != NULL);
150
151 PyThreadState *tstate = PyThreadState_GET();
152
153 if (method->m_object == NULL) {
154 if (unlikely(nargs < 1)) {
155 PyErr_Format(
156 PyExc_TypeError,
157 "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)",
158 GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function),
159 GET_CLASS_NAME(method->m_class));
160 return NULL;
161 } else {
162 PyObject *self = stack[0];
163 CHECK_OBJECT(self);
164
165 int result = PyObject_IsInstance(self, method->m_class);
166
167 if (unlikely(result < 0)) {
168 return NULL;
169 } else if (unlikely(result == 0)) {
170 PyErr_Format(PyExc_TypeError,
171 "unbound compiled_method %s%s must be called with %s instance as first argument (got %s "
172 "instance instead)",
173 GET_CALLABLE_NAME((PyObject *)method->m_function),
174 GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class),
175 GET_INSTANCE_CLASS_NAME(tstate, (PyObject *)self));
176
177 return NULL;
178 }
179 }
180
181 return Nuitka_CallFunctionVectorcall(tstate, method->m_function, stack, nargs,
182 kw_names ? &PyTuple_GET_ITEM(kw_names, 0) : NULL, kwargs_count);
183 }
184
185 Py_ssize_t totalargs = nargs + kwargs_count;
186
187 // Shortcut possible, no args.
188 if (totalargs == 0) {
189 return Nuitka_CallMethodFunctionNoArgs(tstate, method->m_function, method->m_object);
190 }
191
192 PyObject *result;
193
194 if (nargs_f & PY_VECTORCALL_ARGUMENTS_OFFSET) {
195 /* We are allowed to mutate the stack. TODO: Is this the normal case, so
196 we can consider the else branch irrelevant? Also does it not make sense
197 to check pos arg and kw counts and shortcut somewhat. */
198
199 PyObject **new_args = (PyObject **)stack - 1;
200
201 PyObject *tmp = new_args[0];
202 new_args[0] = method->m_object;
203
204 CHECK_OBJECTS(new_args, totalargs + 1);
205
206 result = Nuitka_CallFunctionVectorcall(tstate, method->m_function, new_args, nargs + 1,
207 kw_names ? &PyTuple_GET_ITEM(kw_names, 0) : NULL, kwargs_count);
208
209 CHECK_OBJECTS(new_args, totalargs + 1);
210
211 new_args[0] = tmp;
212 } else {
213 /* Definitely having args at this point. */
214 assert(stack != NULL);
215
216 NUITKA_DYNAMIC_ARRAY_DECL(new_args, PyObject *, totalargs + 1);
217 new_args[0] = method->m_object;
218 memcpy(&new_args[1], stack, totalargs * sizeof(PyObject *));
219
220 CHECK_OBJECTS(new_args, totalargs + 1);
221
222 result = Nuitka_CallFunctionVectorcall(tstate, method->m_function, new_args, nargs + 1,
223 kw_names ? &PyTuple_GET_ITEM(kw_names, 0) : NULL, kwargs_count);
224
225 CHECK_OBJECTS(new_args, totalargs + 1);
226 }
227
228 return result;
229}
230#endif
231
232static PyObject *Nuitka_Method_tp_call(struct Nuitka_MethodObject *method, PyObject *args, PyObject *kw) {
233 Py_ssize_t arg_count = PyTuple_GET_SIZE(args);
234
235 if (method->m_object == NULL) {
236 if (unlikely(arg_count < 1)) {
237 PyErr_Format(
238 PyExc_TypeError,
239 "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)",
240 GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function),
241 GET_CLASS_NAME(method->m_class));
242 return NULL;
243 } else {
244 PyObject *self = PyTuple_GET_ITEM(args, 0);
245 CHECK_OBJECT(self);
246
247 int result = PyObject_IsInstance(self, method->m_class);
248
249 if (unlikely(result < 0)) {
250 return NULL;
251 } else if (unlikely(result == 0)) {
252 PyThreadState *tstate = PyThreadState_GET();
253
254 PyErr_Format(PyExc_TypeError,
255 "unbound compiled_method %s%s must be called with %s instance as first argument (got %s "
256 "instance instead)",
257 GET_CALLABLE_NAME((PyObject *)method->m_function),
258 GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class),
259 GET_INSTANCE_CLASS_NAME(tstate, (PyObject *)self));
260
261 return NULL;
262 }
263 }
264
265 return Py_TYPE(method->m_function)->tp_call((PyObject *)method->m_function, args, kw);
266 } else {
267 PyThreadState *tstate = PyThreadState_GET();
268
269 if (kw == NULL) {
270 if (arg_count == 0) {
271 return Nuitka_CallMethodFunctionNoArgs(tstate, method->m_function, method->m_object);
272 } else {
273 return Nuitka_CallMethodFunctionPosArgs(tstate, method->m_function, method->m_object,
274 &PyTuple_GET_ITEM(args, 0), arg_count);
275 }
276 } else {
277 return Nuitka_CallMethodFunctionPosArgsKwArgs(tstate, method->m_function, method->m_object,
278 &PyTuple_GET_ITEM(args, 0), arg_count, kw);
279 }
280 }
281}
282
283#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
284static PyObject *Nuitka_Method_tp_descr_get(struct Nuitka_MethodObject *method, PyObject *object,
285 PyObject *class_object) {
286 // Don't rebind already bound methods.
287 if (method->m_object != NULL) {
288 Py_INCREF(method);
289 return (PyObject *)method;
290 }
291
292 if (method->m_class != NULL && class_object != NULL) {
293 // Quick subclass test, bound methods remain the same if the class is a sub class
294 int result = PyObject_IsSubclass(class_object, method->m_class);
295
296 if (unlikely(result < 0)) {
297 return NULL;
298 } else if (result == 0) {
299 Py_INCREF(method);
300 return (PyObject *)method;
301 }
302 }
303
304 return Nuitka_Method_New(method->m_function, object, class_object);
305}
306#endif
307
308static PyObject *Nuitka_Method_tp_getattro(struct Nuitka_MethodObject *method, PyObject *name) {
309 PyObject *descr = Nuitka_TypeLookup(&Nuitka_Method_Type, name);
310
311 if (descr != NULL) {
312 if (NuitkaType_HasFeatureClass(Py_TYPE(descr)) && (Py_TYPE(descr)->tp_descr_get != NULL)) {
313 return Py_TYPE(descr)->tp_descr_get(descr, (PyObject *)method, (PyObject *)Py_TYPE(method));
314 } else {
315 Py_INCREF(descr);
316 return descr;
317 }
318 }
319
320 // Delegate all other attributes to the underlying function.
321 // TODO: Could be a bit more direct here, and know this is generic lookup.
322 return PyObject_GetAttr((PyObject *)method->m_function, name);
323}
324
325static long Nuitka_Method_tp_traverse(struct Nuitka_MethodObject *method, visitproc visit, void *arg) {
326 Py_VISIT(method->m_function);
327 Py_VISIT(method->m_object);
328 Py_VISIT(method->m_class);
329
330 return 0;
331}
332
333// tp_repr slot, decide how a function shall be output
334static PyObject *Nuitka_Method_tp_repr(struct Nuitka_MethodObject *method) {
335 if (method->m_object == NULL) {
336#if PYTHON_VERSION < 0x300
337 return PyString_FromFormat("<unbound compiled_method %s.%s>", GET_CLASS_NAME(method->m_class),
338 Nuitka_String_AsString(method->m_function->m_name));
339#else
340 return PyUnicode_FromFormat("<compiled_function %s at %p>", Nuitka_String_AsString(method->m_function->m_name),
341 method->m_function);
342#endif
343 } else {
344 // Note: CPython uses repr of the object, although a comment despises
345 // it, we do it for compatibility.
346 PyObject *object_repr = PyObject_Repr(method->m_object);
347
348 if (object_repr == NULL) {
349 return NULL;
350 }
351#if PYTHON_VERSION < 0x300
352 else if (!PyString_Check(object_repr)) {
353 Py_DECREF(object_repr);
354 return NULL;
355 }
356#else
357 else if (!PyUnicode_Check(object_repr)) {
358 Py_DECREF(object_repr);
359 return NULL;
360 }
361#endif
362
363#if PYTHON_VERSION < 0x350
364 PyObject *result =
365 Nuitka_String_FromFormat("<bound compiled_method %s.%s of %s>", GET_CLASS_NAME(method->m_class),
366 Nuitka_String_AsString_Unchecked(method->m_function->m_name),
367 Nuitka_String_AsString_Unchecked(object_repr));
368#else
369 PyObject *result =
370 PyUnicode_FromFormat("<bound compiled_method %U of %U>", method->m_function->m_qualname, object_repr);
371#endif
372
373 Py_DECREF(object_repr);
374
375 return result;
376 }
377}
378
379#if PYTHON_VERSION < 0x300
380static int Nuitka_Method_tp_compare(struct Nuitka_MethodObject *a, struct Nuitka_MethodObject *b) {
381 if (a->m_function->m_counter < b->m_function->m_counter) {
382 return -1;
383 } else if (a->m_function->m_counter > b->m_function->m_counter) {
384 return 1;
385 } else if (a->m_object == b->m_object) {
386 return 0;
387 } else if (a->m_object == NULL) {
388 return -1;
389 } else if (b->m_object == NULL) {
390 return 1;
391 } else {
392 return PyObject_Compare(a->m_object, b->m_object);
393 }
394}
395#endif
396
397static PyObject *Nuitka_Method_tp_richcompare(struct Nuitka_MethodObject *a, struct Nuitka_MethodObject *b, int op) {
398 if (op != Py_EQ && op != Py_NE) {
399 Py_INCREF(Py_NotImplemented);
400 return Py_NotImplemented;
401 }
402
403 if (Nuitka_Method_Check((PyObject *)a) == false || Nuitka_Method_Check((PyObject *)b) == false) {
404 Py_INCREF(Py_NotImplemented);
405 return Py_NotImplemented;
406 }
407
408 bool b_res = a->m_function->m_counter == b->m_function->m_counter;
409
410 // If the underlying function objects are the same, check the objects, which
411 // may be NULL in case of unbound methods, which would be the same again.
412 if (b_res) {
413#if PYTHON_VERSION < 0x380
414 if (a->m_object == NULL) {
415 b_res = b->m_object == NULL;
416 } else if (b->m_object == NULL) {
417 b_res = false;
418 } else {
419 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(a->m_object, b->m_object);
420
421 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
422 return NULL;
423 }
424
425 b_res = nbool_res == NUITKA_BOOL_TRUE;
426 }
427#else
428 b_res = a->m_object == b->m_object;
429#endif
430 }
431
432 PyObject *result;
433
434 if (op == Py_EQ) {
435 result = BOOL_FROM(b_res);
436 } else {
437 result = BOOL_FROM(!b_res);
438 }
439
440 Py_INCREF_IMMORTAL(result);
441 return result;
442}
443
444static Py_hash_t Nuitka_Method_tp_hash(struct Nuitka_MethodObject *method) {
445 // Just give the hash of the method function, that ought to be good enough.
446 return method->m_function->m_counter;
447}
448
449// Freelist setup
450#define MAX_METHOD_FREE_LIST_COUNT 100
451static struct Nuitka_MethodObject *free_list_methods = NULL;
452static int free_list_methods_count = 0;
453
454static void Nuitka_Method_tp_dealloc(struct Nuitka_MethodObject *method) {
455#if _DEBUG_REFCOUNTS
456 count_active_Nuitka_Method_Type -= 1;
457 count_released_Nuitka_Method_Type += 1;
458#endif
459
460#ifndef __NUITKA_NO_ASSERT__
461 // Save the current exception, if any, we must to not corrupt it.
462 PyThreadState *tstate = PyThreadState_GET();
463
464 struct Nuitka_ExceptionPreservationItem saved_exception_state1;
465 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
466 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
467#endif
468
469 Nuitka_GC_UnTrack(method);
470
471 if (method->m_weakrefs != NULL) {
472 PyObject_ClearWeakRefs((PyObject *)method);
473 }
474
475 Py_XDECREF(method->m_object);
476 Py_XDECREF(method->m_class);
477
478 Py_DECREF((PyObject *)method->m_function);
479
480 /* Put the object into free list or release to GC */
481 releaseToFreeList(free_list_methods, method, MAX_METHOD_FREE_LIST_COUNT);
482
483#ifndef __NUITKA_NO_ASSERT__
484 struct Nuitka_ExceptionPreservationItem saved_exception_state2;
485 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
486 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
487
488 ASSERT_SAME_EXCEPTION_STATE(&saved_exception_state1, &saved_exception_state2);
489#endif
490}
491
492static PyObject *Nuitka_Method_tp_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
493 PyObject *func;
494 PyObject *self;
495 PyObject *class_object = NULL;
496
497 if (!_PyArg_NoKeywords("compiled_method", kw)) {
498 return NULL;
499 }
500
501 if (!PyArg_UnpackTuple(args, "compiled_method", 2, 3, &func, &self, &class_object)) {
502 return NULL;
503 }
504
505 CHECK_OBJECT(func);
506
507 if (!PyCallable_Check(func)) {
508 PyThreadState *tstate = PyThreadState_GET();
509
510 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "first argument must be callable");
511 return NULL;
512 }
513
514 if (self == Py_None) {
515 self = NULL;
516 }
517
518 if (self == NULL && class_object == NULL) {
519 PyThreadState *tstate = PyThreadState_GET();
520
521 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError, "unbound methods must have non-NULL im_class");
522 return NULL;
523 }
524
525 if (Nuitka_Method_Check(func)) {
526 return Nuitka_Method_New(((struct Nuitka_MethodObject *)func)->m_function, self, class_object);
527 }
528
529 if (Nuitka_Function_Check(func) == false) {
530 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE("Cannot create compiled_ method from type '%s'", func);
531 return NULL;
532 }
533
534 return Nuitka_Method_New((struct Nuitka_FunctionObject *)func, self, class_object);
535}
536
537PyTypeObject Nuitka_Method_Type = {
538 PyVarObject_HEAD_INIT(NULL, 0) "compiled_method",
539 sizeof(struct Nuitka_MethodObject),
540 0,
541 (destructor)Nuitka_Method_tp_dealloc, // tp_dealloc
542#if PYTHON_VERSION < 0x380 || defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
543 0, // tp_print
544#else
545 offsetof(struct Nuitka_MethodObject, m_vectorcall), // tp_vectorcall_offset
546#endif
547 0, // tp_getattr
548 0, // tp_setattr
549#if PYTHON_VERSION < 0x300
550 (cmpfunc)Nuitka_Method_tp_compare, // tp_compare
551#else
552 0,
553#endif
554 (reprfunc)Nuitka_Method_tp_repr, // tp_repr
555 0, // tp_as_number
556 0, // tp_as_sequence
557 0, // tp_as_mapping
558 (hashfunc)Nuitka_Method_tp_hash, // tp_hash
559 (ternaryfunc)Nuitka_Method_tp_call, // tp_call
560 0, // tp_str
561 (getattrofunc)Nuitka_Method_tp_getattro, // tp_getattro
562 0, // tp_setattro (PyObject_GenericSetAttr)
563 0, // tp_as_buffer
564 Py_TPFLAGS_DEFAULT | // tp_flags
565#if PYTHON_VERSION < 0x300
566 Py_TPFLAGS_HAVE_WEAKREFS |
567#endif
568#if PYTHON_VERSION >= 0x380
569 _Py_TPFLAGS_HAVE_VECTORCALL |
570#endif
571 Py_TPFLAGS_HAVE_GC,
572 0, // tp_doc
573 (traverseproc)Nuitka_Method_tp_traverse, // tp_traverse
574 0, // tp_clear
575 (richcmpfunc)Nuitka_Method_tp_richcompare, // tp_richcompare
576 offsetof(struct Nuitka_MethodObject, m_weakrefs), // tp_weaklistoffset
577 0, // tp_iter
578 0, // tp_iternext
579 Nuitka_Method_methods, // tp_methods
580 Nuitka_Method_members, // tp_members
581 Nuitka_Method_tp_getset, // tp_getset
582 0, // tp_base
583 0, // tp_dict
584#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
585 (descrgetfunc)Nuitka_Method_tp_descr_get, // tp_descr_get
586#else
587 0,
588#endif
589 0, // tp_descr_set
590 0, // tp_dictoffset
591 0, // tp_init
592 0, // tp_alloc
593 Nuitka_Method_tp_new, // tp_new
594 0, // tp_free
595 0, // tp_is_gc
596 0, // tp_bases
597 0, // tp_mro
598 0, // tp_cache
599 0, // tp_subclasses
600 0, // tp_weaklist
601 0, // tp_del
602 0 // tp_version_tag
603#if PYTHON_VERSION >= 0x300
604 ,
605 0 /* tp_finalizer */
606#endif
607};
608
609void _initCompiledMethodType(void) {
610 Nuitka_PyType_Ready(&Nuitka_Method_Type, &PyMethod_Type, false, true, false, false, false);
611}
612
613PyObject *Nuitka_Method_New(struct Nuitka_FunctionObject *function, PyObject *object, PyObject *class_object) {
614 struct Nuitka_MethodObject *result;
615
616#if _DEBUG_REFCOUNTS
617 count_active_Nuitka_Method_Type += 1;
618 count_allocated_Nuitka_Method_Type += 1;
619#endif
620
621 CHECK_OBJECT((PyObject *)function);
622 assert(Nuitka_Function_Check((PyObject *)function));
623 assert(_PyObject_GC_IS_TRACKED(function));
624
625 allocateFromFreeListFixed(free_list_methods, struct Nuitka_MethodObject, Nuitka_Method_Type);
626
627 if (unlikely(result == NULL)) {
628 PyErr_Format(PyExc_RuntimeError, "cannot create method %s", Nuitka_String_AsString(function->m_name));
629
630 return NULL;
631 }
632
633 Py_INCREF(function);
634 result->m_function = function;
635
636 result->m_object = object;
637 Py_XINCREF(object);
638 result->m_class = class_object;
639 Py_XINCREF(class_object);
640
641 result->m_weakrefs = NULL;
642
643#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
644 result->m_vectorcall = (vectorcallfunc)Nuitka_Method_tp_vectorcall;
645#endif
646
647 Nuitka_GC_Track(result);
648 return (PyObject *)result;
649}
650
651// Part of "Nuitka", an optimizing Python compiler that is compatible and
652// integrates with CPython, but also works on its own.
653//
654// Licensed under the GNU Affero General Public License, Version 3 (the "License");
655// you may not use this file except in compliance with the License.
656// You may obtain a copy of the License at
657//
658// http://www.gnu.org/licenses/agpl.txt
659//
660// Unless required by applicable law or agreed to in writing, software
661// distributed under the License is distributed on an "AS IS" BASIS,
662// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
663// See the License for the specific language governing permissions and
664// limitations under the License.
Definition exceptions.h:712
Definition compiled_function.h:22
Definition compiled_method.h:16