13#include "nuitka/freelists.h"
14#include "nuitka/prelude.h"
15#include <structmember.h>
19int count_active_Nuitka_Method_Type;
20int count_allocated_Nuitka_Method_Type;
21int count_released_Nuitka_Method_Type;
24static PyObject *Nuitka_Method_get__doc__(PyObject *self,
void *data) {
26 PyObject *result = method->m_function->m_doc;
36static PyGetSetDef Nuitka_Method_tp_getset[] = {{(
char *)
"__doc__", Nuitka_Method_get__doc__, NULL, NULL}, {NULL}};
38#define OFF(x) offsetof(struct Nuitka_MethodObject, x)
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"},
52static PyObject *Nuitka_Method_reduce(
struct Nuitka_MethodObject *method, PyObject *unused) {
53 PyThreadState *tstate = PyThreadState_GET();
55#if PYTHON_VERSION < 0x300
57 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
"can't pickle instancemethod objects");
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);
65 CHECK_OBJECT_DEEP(result);
71static PyObject *Nuitka_Method_reduce_ex(
struct Nuitka_MethodObject *method, PyObject *args) {
74 if (!PyArg_ParseTuple(args,
"|i:__reduce_ex__", &proto)) {
80#if PYTHON_VERSION < 0x300
81 PyObject *copy_reg = PyImport_ImportModule(
"copy_reg");
83 CHECK_OBJECT(copy_reg);
84 PyThreadState *tstate = PyThreadState_GET();
86 PyObject *newobj_func = LOOKUP_ATTRIBUTE(tstate, copy_reg, const_str_plain___newobj__);
88 if (unlikely(newobj_func == NULL)) {
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);
100 CHECK_OBJECT_DEEP(result);
104 return Nuitka_Method_reduce(method, NULL);
108static PyObject *Nuitka_Method_deepcopy(
struct Nuitka_MethodObject *method, PyObject *memo) {
109 assert(Nuitka_Method_Check((PyObject *)method));
111 static PyObject *module_copy = NULL;
112 static PyObject *deepcopy_function = NULL;
114 if (module_copy == NULL) {
115 module_copy = PyImport_ImportModule(
"copy");
116 CHECK_OBJECT(module_copy);
118 deepcopy_function = PyObject_GetAttrString(module_copy,
"deepcopy");
119 CHECK_OBJECT(deepcopy_function);
122 PyObject *
object = PyObject_CallFunctionObjArgs(deepcopy_function, method->m_object, memo, NULL);
124 if (unlikely(
object == NULL)) {
128 PyObject *result = Nuitka_Method_New(method->m_function,
object, method->m_class);
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},
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);
149 assert((nargs == 0 && kwargs_count == 0) || stack != NULL);
151 PyThreadState *tstate = PyThreadState_GET();
153 if (method->m_object == NULL) {
154 if (unlikely(nargs < 1)) {
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));
162 PyObject *self = stack[0];
165 int result = PyObject_IsInstance(self, method->m_class);
167 if (unlikely(result < 0)) {
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 "
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));
181 return Nuitka_CallFunctionVectorcall(tstate, method->m_function, stack, nargs,
182 kw_names ? &PyTuple_GET_ITEM(kw_names, 0) : NULL, kwargs_count);
185 Py_ssize_t totalargs = nargs + kwargs_count;
188 if (totalargs == 0) {
189 return Nuitka_CallMethodFunctionNoArgs(tstate, method->m_function, method->m_object);
194 if (nargs_f & PY_VECTORCALL_ARGUMENTS_OFFSET) {
199 PyObject **new_args = (PyObject **)stack - 1;
201 PyObject *tmp = new_args[0];
202 new_args[0] = method->m_object;
204 CHECK_OBJECTS(new_args, totalargs + 1);
206 result = Nuitka_CallFunctionVectorcall(tstate, method->m_function, new_args, nargs + 1,
207 kw_names ? &PyTuple_GET_ITEM(kw_names, 0) : NULL, kwargs_count);
209 CHECK_OBJECTS(new_args, totalargs + 1);
214 assert(stack != NULL);
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 *));
220 CHECK_OBJECTS(new_args, totalargs + 1);
222 result = Nuitka_CallFunctionVectorcall(tstate, method->m_function, new_args, nargs + 1,
223 kw_names ? &PyTuple_GET_ITEM(kw_names, 0) : NULL, kwargs_count);
225 CHECK_OBJECTS(new_args, totalargs + 1);
232static PyObject *Nuitka_Method_tp_call(
struct Nuitka_MethodObject *method, PyObject *args, PyObject *kw) {
233 Py_ssize_t arg_count = PyTuple_GET_SIZE(args);
235 if (method->m_object == NULL) {
236 if (unlikely(arg_count < 1)) {
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));
244 PyObject *self = PyTuple_GET_ITEM(args, 0);
247 int result = PyObject_IsInstance(self, method->m_class);
249 if (unlikely(result < 0)) {
251 }
else if (unlikely(result == 0)) {
252 PyThreadState *tstate = PyThreadState_GET();
254 PyErr_Format(PyExc_TypeError,
255 "unbound compiled_method %s%s must be called with %s instance as first argument (got %s "
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));
265 return Py_TYPE(method->m_function)->tp_call((PyObject *)method->m_function, args, kw);
267 PyThreadState *tstate = PyThreadState_GET();
270 if (arg_count == 0) {
271 return Nuitka_CallMethodFunctionNoArgs(tstate, method->m_function, method->m_object);
273 return Nuitka_CallMethodFunctionPosArgs(tstate, method->m_function, method->m_object,
274 &PyTuple_GET_ITEM(args, 0), arg_count);
277 return Nuitka_CallMethodFunctionPosArgsKwArgs(tstate, method->m_function, method->m_object,
278 &PyTuple_GET_ITEM(args, 0), arg_count, kw);
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) {
287 if (method->m_object != NULL) {
289 return (PyObject *)method;
292 if (method->m_class != NULL && class_object != NULL) {
294 int result = PyObject_IsSubclass(class_object, method->m_class);
296 if (unlikely(result < 0)) {
298 }
else if (result == 0) {
300 return (PyObject *)method;
304 return Nuitka_Method_New(method->m_function,
object, class_object);
308static PyObject *Nuitka_Method_tp_getattro(
struct Nuitka_MethodObject *method, PyObject *name) {
309 PyObject *descr = Nuitka_TypeLookup(&Nuitka_Method_Type, name);
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));
322 return PyObject_GetAttr((PyObject *)method->m_function, name);
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);
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));
340 return PyUnicode_FromFormat(
"<compiled_function %s at %p>", Nuitka_String_AsString(method->m_function->m_name),
346 PyObject *object_repr = PyObject_Repr(method->m_object);
348 if (object_repr == NULL) {
351#if PYTHON_VERSION < 0x300
352 else if (!PyString_Check(object_repr)) {
353 Py_DECREF(object_repr);
357 else if (!PyUnicode_Check(object_repr)) {
358 Py_DECREF(object_repr);
363#if PYTHON_VERSION < 0x350
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));
370 PyUnicode_FromFormat(
"<bound compiled_method %U of %U>", method->m_function->m_qualname, object_repr);
373 Py_DECREF(object_repr);
379#if PYTHON_VERSION < 0x300
381 if (a->m_function->m_counter < b->m_function->m_counter) {
383 }
else if (a->m_function->m_counter > b->m_function->m_counter) {
385 }
else if (a->m_object == b->m_object) {
387 }
else if (a->m_object == NULL) {
389 }
else if (b->m_object == NULL) {
392 return PyObject_Compare(a->m_object, b->m_object);
398 if (op != Py_EQ && op != Py_NE) {
399 Py_INCREF(Py_NotImplemented);
400 return Py_NotImplemented;
403 if (Nuitka_Method_Check((PyObject *)a) ==
false || Nuitka_Method_Check((PyObject *)b) ==
false) {
404 Py_INCREF(Py_NotImplemented);
405 return Py_NotImplemented;
408 bool b_res = a->m_function->m_counter == b->m_function->m_counter;
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) {
419 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(a->m_object, b->m_object);
421 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
425 b_res = nbool_res == NUITKA_BOOL_TRUE;
428 b_res = a->m_object == b->m_object;
435 result = BOOL_FROM(b_res);
437 result = BOOL_FROM(!b_res);
440 Py_INCREF_IMMORTAL(result);
446 return method->m_function->m_counter;
450#define MAX_METHOD_FREE_LIST_COUNT 100
452static int free_list_methods_count = 0;
456 count_active_Nuitka_Method_Type -= 1;
457 count_released_Nuitka_Method_Type += 1;
460#ifndef __NUITKA_NO_ASSERT__
462 PyThreadState *tstate = PyThreadState_GET();
465 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
466 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
469 Nuitka_GC_UnTrack(method);
471 if (method->m_weakrefs != NULL) {
472 PyObject_ClearWeakRefs((PyObject *)method);
475 Py_XDECREF(method->m_object);
476 Py_XDECREF(method->m_class);
478 Py_DECREF((PyObject *)method->m_function);
481 releaseToFreeList(free_list_methods, method, MAX_METHOD_FREE_LIST_COUNT);
483#ifndef __NUITKA_NO_ASSERT__
485 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
486 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
488 ASSERT_SAME_EXCEPTION_STATE(&saved_exception_state1, &saved_exception_state2);
492static PyObject *Nuitka_Method_tp_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
495 PyObject *class_object = NULL;
497 if (!_PyArg_NoKeywords(
"compiled_method", kw)) {
501 if (!PyArg_UnpackTuple(args,
"compiled_method", 2, 3, &func, &self, &class_object)) {
507 if (!PyCallable_Check(func)) {
508 PyThreadState *tstate = PyThreadState_GET();
510 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
"first argument must be callable");
514 if (self == Py_None) {
518 if (self == NULL && class_object == NULL) {
519 PyThreadState *tstate = PyThreadState_GET();
521 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
"unbound methods must have non-NULL im_class");
525 if (Nuitka_Method_Check(func)) {
526 return Nuitka_Method_New(((
struct Nuitka_MethodObject *)func)->m_function, self, class_object);
529 if (Nuitka_Function_Check(func) ==
false) {
530 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE(
"Cannot create compiled_ method from type '%s'", func);
537PyTypeObject Nuitka_Method_Type = {
538 PyVarObject_HEAD_INIT(NULL, 0)
"compiled_method",
541 (destructor)Nuitka_Method_tp_dealloc,
542#if PYTHON_VERSION < 0x380 || defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
549#if PYTHON_VERSION < 0x300
550 (cmpfunc)Nuitka_Method_tp_compare,
554 (reprfunc)Nuitka_Method_tp_repr,
558 (hashfunc)Nuitka_Method_tp_hash,
559 (ternaryfunc)Nuitka_Method_tp_call,
561 (getattrofunc)Nuitka_Method_tp_getattro,
565#if PYTHON_VERSION < 0x300
566 Py_TPFLAGS_HAVE_WEAKREFS |
568#if PYTHON_VERSION >= 0x380
569 _Py_TPFLAGS_HAVE_VECTORCALL |
573 (traverseproc)Nuitka_Method_tp_traverse,
575 (richcmpfunc)Nuitka_Method_tp_richcompare,
579 Nuitka_Method_methods,
580 Nuitka_Method_members,
581 Nuitka_Method_tp_getset,
584#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
585 (descrgetfunc)Nuitka_Method_tp_descr_get,
593 Nuitka_Method_tp_new,
603#
if PYTHON_VERSION >= 0x300
609void _initCompiledMethodType(
void) {
610 Nuitka_PyType_Ready(&Nuitka_Method_Type, &PyMethod_Type,
false,
true,
false,
false,
false);
613PyObject *Nuitka_Method_New(
struct Nuitka_FunctionObject *function, PyObject *
object, PyObject *class_object) {
617 count_active_Nuitka_Method_Type += 1;
618 count_allocated_Nuitka_Method_Type += 1;
621 CHECK_OBJECT((PyObject *)function);
622 assert(Nuitka_Function_Check((PyObject *)function));
623 assert(_PyObject_GC_IS_TRACKED(function));
625 allocateFromFreeListFixed(free_list_methods,
struct Nuitka_MethodObject, Nuitka_Method_Type);
627 if (unlikely(result == NULL)) {
628 PyErr_Format(PyExc_RuntimeError,
"cannot create method %s", Nuitka_String_AsString(function->m_name));
634 result->m_function = function;
636 result->m_object = object;
638 result->m_class = class_object;
639 Py_XINCREF(class_object);
641 result->m_weakrefs = NULL;
643#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
644 result->m_vectorcall = (vectorcallfunc)Nuitka_Method_tp_vectorcall;
647 Nuitka_GC_Track(result);
648 return (PyObject *)result;
Definition exceptions.h:712
Definition compiled_function.h:22
Definition compiled_method.h:16