13#include "nuitka/freelists.h"
14#include "nuitka/prelude.h"
15#include <structmember.h>
18static PyObject *Nuitka_Method_get__doc__(PyObject *self,
void *data) {
20 PyObject *result = method->m_function->m_doc;
30static PyGetSetDef Nuitka_Method_tp_getset[] = {{(
char *)
"__doc__", Nuitka_Method_get__doc__, NULL, NULL}, {NULL}};
32#define OFF(x) offsetof(struct Nuitka_MethodObject, x)
34static PyMemberDef Nuitka_Method_members[] = {
35 {(
char *)
"im_class", T_OBJECT, OFF(m_class), READONLY | RESTRICTED, (
char *)
"the class associated with a method"},
36 {(
char *)
"im_func", T_OBJECT, OFF(m_function), READONLY | RESTRICTED,
37 (
char *)
"the function (or other callable) implementing a method"},
38 {(
char *)
"__func__", T_OBJECT, OFF(m_function), READONLY | RESTRICTED,
39 (
char *)
"the function (or other callable) implementing a method"},
40 {(
char *)
"im_self", T_OBJECT, OFF(m_object), READONLY | RESTRICTED,
41 (
char *)
"the instance to which a method is bound; None for unbound method"},
42 {(
char *)
"__self__", T_OBJECT, OFF(m_object), READONLY | RESTRICTED,
43 (
char *)
"the instance to which a method is bound; None for unbound method"},
46static PyObject *Nuitka_Method_reduce(
struct Nuitka_MethodObject *method, PyObject *unused) {
47 PyThreadState *tstate = PyThreadState_GET();
49#if PYTHON_VERSION < 0x300
51 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
"can't pickle instancemethod objects");
54 PyObject *result = MAKE_TUPLE_EMPTY(tstate, 2);
55 PyTuple_SET_ITEM0(result, 0, LOOKUP_BUILTIN(const_str_plain_getattr));
56 PyObject *arg_tuple = MAKE_TUPLE2(tstate, method->m_object, method->m_function->m_name);
57 PyTuple_SET_ITEM(result, 1, arg_tuple);
59 CHECK_OBJECT_DEEP(result);
65static PyObject *Nuitka_Method_reduce_ex(
struct Nuitka_MethodObject *method, PyObject *args) {
68 if (!PyArg_ParseTuple(args,
"|i:__reduce_ex__", &proto)) {
74#if PYTHON_VERSION < 0x300
75 PyObject *copy_reg = PyImport_ImportModule(
"copy_reg");
77 CHECK_OBJECT(copy_reg);
78 PyThreadState *tstate = PyThreadState_GET();
80 PyObject *newobj_func = LOOKUP_ATTRIBUTE(tstate, copy_reg, const_str_plain___newobj__);
82 if (unlikely(newobj_func == NULL)) {
86 PyObject *result = MAKE_TUPLE_EMPTY(tstate, 5);
87 PyTuple_SET_ITEM(result, 0, newobj_func);
88 PyObject *type_tuple = MAKE_TUPLE1(tstate, (PyObject *)&Nuitka_Method_Type);
89 PyTuple_SET_ITEM(result, 1, type_tuple);
90 PyTuple_SET_ITEM_IMMORTAL(result, 2, Py_None);
91 PyTuple_SET_ITEM_IMMORTAL(result, 3, Py_None);
92 PyTuple_SET_ITEM_IMMORTAL(result, 4, Py_None);
94 CHECK_OBJECT_DEEP(result);
98 return Nuitka_Method_reduce(method, NULL);
102static PyObject *Nuitka_Method_deepcopy(
struct Nuitka_MethodObject *method, PyObject *memo) {
103 assert(Nuitka_Method_Check((PyObject *)method));
105 static PyObject *module_copy = NULL;
106 static PyObject *deepcopy_function = NULL;
108 if (module_copy == NULL) {
109 module_copy = PyImport_ImportModule(
"copy");
110 CHECK_OBJECT(module_copy);
112 deepcopy_function = PyObject_GetAttrString(module_copy,
"deepcopy");
113 CHECK_OBJECT(deepcopy_function);
116 PyObject *
object = PyObject_CallFunctionObjArgs(deepcopy_function, method->m_object, memo, NULL);
118 if (unlikely(
object == NULL)) {
122 PyObject *result = Nuitka_Method_New(method->m_function,
object, method->m_class);
128static PyMethodDef Nuitka_Method_methods[] = {
129 {
"__reduce__", (PyCFunction)Nuitka_Method_reduce, METH_NOARGS, NULL},
130 {
"__reduce_ex__", (PyCFunction)Nuitka_Method_reduce_ex, METH_VARARGS, NULL},
131 {
"__deepcopy__", (PyCFunction)Nuitka_Method_deepcopy, METH_O, NULL},
134#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
135static PyObject *Nuitka_Method_tp_vectorcall(
struct Nuitka_MethodObject *method, PyObject *
const *stack,
size_t nargsf,
137 assert(Nuitka_Method_Check((PyObject *)method));
138 assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
139 Py_ssize_t nkwargs = (kwnames == NULL) ? 0 : PyTuple_GET_SIZE(kwnames);
140 Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
143 assert((nargs == 0 && nkwargs == 0) || stack != NULL);
145 Py_ssize_t totalargs = nargs + nkwargs;
148 if (totalargs == 0) {
149 return Nuitka_CallMethodFunctionNoArgs(PyThreadState_GET(), method->m_function, method->m_object);
154 if (nargsf & PY_VECTORCALL_ARGUMENTS_OFFSET) {
159 PyObject **new_args = (PyObject **)stack - 1;
161 PyObject *tmp = new_args[0];
162 new_args[0] = method->m_object;
164 CHECK_OBJECTS(new_args, totalargs + 1);
166 result = Nuitka_CallFunctionVectorcall(PyThreadState_GET(), method->m_function, new_args, nargs + 1,
167 kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs);
169 CHECK_OBJECTS(new_args, totalargs + 1);
174 assert(stack != NULL);
176 NUITKA_DYNAMIC_ARRAY_DECL(new_args, PyObject *, totalargs + 1);
177 new_args[0] = method->m_object;
178 memcpy(&new_args[1], stack, totalargs *
sizeof(PyObject *));
180 CHECK_OBJECTS(new_args, totalargs + 1);
182 result = Nuitka_CallFunctionVectorcall(PyThreadState_GET(), method->m_function, new_args, nargs + 1,
183 kwnames ? &PyTuple_GET_ITEM(kwnames, 0) : NULL, nkwargs);
185 CHECK_OBJECTS(new_args, totalargs + 1);
192static PyObject *Nuitka_Method_tp_call(
struct Nuitka_MethodObject *method, PyObject *args, PyObject *kw) {
193 Py_ssize_t arg_count = PyTuple_GET_SIZE(args);
195 if (method->m_object == NULL) {
196 if (unlikely(arg_count < 1)) {
199 "unbound compiled_method %s%s must be called with %s instance as first argument (got nothing instead)",
200 GET_CALLABLE_NAME((PyObject *)method->m_function), GET_CALLABLE_DESC((PyObject *)method->m_function),
201 GET_CLASS_NAME(method->m_class));
204 PyObject *self = PyTuple_GET_ITEM(args, 0);
207 int result = PyObject_IsInstance(self, method->m_class);
209 if (unlikely(result < 0)) {
211 }
else if (unlikely(result == 0)) {
212 PyThreadState *tstate = PyThreadState_GET();
214 PyErr_Format(PyExc_TypeError,
215 "unbound compiled_method %s%s must be called with %s instance as first argument (got %s "
217 GET_CALLABLE_NAME((PyObject *)method->m_function),
218 GET_CALLABLE_DESC((PyObject *)method->m_function), GET_CLASS_NAME(method->m_class),
219 GET_INSTANCE_CLASS_NAME(tstate, (PyObject *)self));
225 return Py_TYPE(method->m_function)->tp_call((PyObject *)method->m_function, args, kw);
227 PyThreadState *tstate = PyThreadState_GET();
230 if (arg_count == 0) {
231 return Nuitka_CallMethodFunctionNoArgs(tstate, method->m_function, method->m_object);
233 return Nuitka_CallMethodFunctionPosArgs(tstate, method->m_function, method->m_object,
234 &PyTuple_GET_ITEM(args, 0), arg_count);
237 return Nuitka_CallMethodFunctionPosArgsKwArgs(tstate, method->m_function, method->m_object,
238 &PyTuple_GET_ITEM(args, 0), arg_count, kw);
243#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
244static PyObject *Nuitka_Method_tp_descr_get(
struct Nuitka_MethodObject *method, PyObject *
object,
245 PyObject *class_object) {
247 if (method->m_object != NULL) {
249 return (PyObject *)method;
252 if (method->m_class != NULL && class_object != NULL) {
254 int result = PyObject_IsSubclass(class_object, method->m_class);
256 if (unlikely(result < 0)) {
258 }
else if (result == 0) {
260 return (PyObject *)method;
264 return Nuitka_Method_New(method->m_function,
object, class_object);
268static PyObject *Nuitka_Method_tp_getattro(
struct Nuitka_MethodObject *method, PyObject *name) {
269 PyObject *descr = Nuitka_TypeLookup(&Nuitka_Method_Type, name);
272 if (NuitkaType_HasFeatureClass(Py_TYPE(descr)) && (Py_TYPE(descr)->tp_descr_get != NULL)) {
273 return Py_TYPE(descr)->tp_descr_get(descr, (PyObject *)method, (PyObject *)Py_TYPE(method));
282 return PyObject_GetAttr((PyObject *)method->m_function, name);
285static long Nuitka_Method_tp_traverse(
struct Nuitka_MethodObject *method, visitproc visit,
void *arg) {
286 Py_VISIT(method->m_function);
287 Py_VISIT(method->m_object);
288 Py_VISIT(method->m_class);
295 if (method->m_object == NULL) {
296#if PYTHON_VERSION < 0x300
297 return PyString_FromFormat(
"<unbound compiled_method %s.%s>", GET_CLASS_NAME(method->m_class),
298 Nuitka_String_AsString(method->m_function->m_name));
300 return PyUnicode_FromFormat(
"<compiled_function %s at %p>", Nuitka_String_AsString(method->m_function->m_name),
306 PyObject *object_repr = PyObject_Repr(method->m_object);
308 if (object_repr == NULL) {
311#if PYTHON_VERSION < 0x300
312 else if (!PyString_Check(object_repr)) {
313 Py_DECREF(object_repr);
317 else if (!PyUnicode_Check(object_repr)) {
318 Py_DECREF(object_repr);
323#if PYTHON_VERSION < 0x350
325 Nuitka_String_FromFormat(
"<bound compiled_method %s.%s of %s>", GET_CLASS_NAME(method->m_class),
326 Nuitka_String_AsString_Unchecked(method->m_function->m_name),
327 Nuitka_String_AsString_Unchecked(object_repr));
330 PyUnicode_FromFormat(
"<bound compiled_method %U of %U>", method->m_function->m_qualname, object_repr);
333 Py_DECREF(object_repr);
339#if PYTHON_VERSION < 0x300
341 if (a->m_function->m_counter < b->m_function->m_counter) {
343 }
else if (a->m_function->m_counter > b->m_function->m_counter) {
345 }
else if (a->m_object == b->m_object) {
347 }
else if (a->m_object == NULL) {
349 }
else if (b->m_object == NULL) {
352 return PyObject_Compare(a->m_object, b->m_object);
358 if (op != Py_EQ && op != Py_NE) {
359 Py_INCREF(Py_NotImplemented);
360 return Py_NotImplemented;
363 if (Nuitka_Method_Check((PyObject *)a) ==
false || Nuitka_Method_Check((PyObject *)b) ==
false) {
364 Py_INCREF(Py_NotImplemented);
365 return Py_NotImplemented;
368 bool b_res = a->m_function->m_counter == b->m_function->m_counter;
373#if PYTHON_VERSION < 0x380
374 if (a->m_object == NULL) {
375 b_res = b->m_object == NULL;
376 }
else if (b->m_object == NULL) {
379 nuitka_bool nbool_res = RICH_COMPARE_EQ_NBOOL_OBJECT_OBJECT(a->m_object, b->m_object);
381 if (unlikely(nbool_res == NUITKA_BOOL_EXCEPTION)) {
385 b_res = nbool_res == NUITKA_BOOL_TRUE;
388 b_res = a->m_object == b->m_object;
395 result = BOOL_FROM(b_res);
397 result = BOOL_FROM(!b_res);
400 Py_INCREF_IMMORTAL(result);
406 return method->m_function->m_counter;
410#define MAX_METHOD_FREE_LIST_COUNT 100
412static int free_list_methods_count = 0;
415#ifndef __NUITKA_NO_ASSERT__
417 PyThreadState *tstate = PyThreadState_GET();
420 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
421 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state1);
424 Nuitka_GC_UnTrack(method);
426 if (method->m_weakrefs != NULL) {
427 PyObject_ClearWeakRefs((PyObject *)method);
430 Py_XDECREF(method->m_object);
431 Py_XDECREF(method->m_class);
433 Py_DECREF((PyObject *)method->m_function);
436 releaseToFreeList(free_list_methods, method, MAX_METHOD_FREE_LIST_COUNT);
438#ifndef __NUITKA_NO_ASSERT__
440 FETCH_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
441 RESTORE_ERROR_OCCURRED_STATE(tstate, &saved_exception_state2);
443 ASSERT_SAME_EXCEPTION_STATE(&saved_exception_state1, &saved_exception_state2);
447static PyObject *Nuitka_Method_tp_new(PyTypeObject *type, PyObject *args, PyObject *kw) {
450 PyObject *class_object = NULL;
452 if (!_PyArg_NoKeywords(
"compiled_method", kw)) {
456 if (!PyArg_UnpackTuple(args,
"compiled_method", 2, 3, &func, &self, &class_object)) {
462 if (!PyCallable_Check(func)) {
463 PyThreadState *tstate = PyThreadState_GET();
465 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
"first argument must be callable");
469 if (self == Py_None) {
473 if (self == NULL && class_object == NULL) {
474 PyThreadState *tstate = PyThreadState_GET();
476 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_TypeError,
"unbound methods must have non-NULL im_class");
480 if (Nuitka_Method_Check(func)) {
481 return Nuitka_Method_New(((
struct Nuitka_MethodObject *)func)->m_function, self, class_object);
484 if (Nuitka_Function_Check(func) ==
false) {
485 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT_NICE(
"Cannot create compiled_ method from type '%s'", func);
492PyTypeObject Nuitka_Method_Type = {
493 PyVarObject_HEAD_INIT(NULL, 0)
"compiled_method",
496 (destructor)Nuitka_Method_tp_dealloc,
497#if PYTHON_VERSION < 0x380 || defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
504#if PYTHON_VERSION < 0x300
505 (cmpfunc)Nuitka_Method_tp_compare,
509 (reprfunc)Nuitka_Method_tp_repr,
513 (hashfunc)Nuitka_Method_tp_hash,
514 (ternaryfunc)Nuitka_Method_tp_call,
516 (getattrofunc)Nuitka_Method_tp_getattro,
520#if PYTHON_VERSION < 0x300
521 Py_TPFLAGS_HAVE_WEAKREFS |
523#if PYTHON_VERSION >= 0x380
524 _Py_TPFLAGS_HAVE_VECTORCALL |
528 (traverseproc)Nuitka_Method_tp_traverse,
530 (richcmpfunc)Nuitka_Method_tp_richcompare,
534 Nuitka_Method_methods,
535 Nuitka_Method_members,
536 Nuitka_Method_tp_getset,
539#if PYTHON_VERSION < 0x3a0 || PYTHON_VERSION >= 0x3d0
540 (descrgetfunc)Nuitka_Method_tp_descr_get,
548 Nuitka_Method_tp_new,
558#
if PYTHON_VERSION >= 0x300
564void _initCompiledMethodType(
void) {
565 Nuitka_PyType_Ready(&Nuitka_Method_Type, &PyMethod_Type,
false,
true,
false,
false,
false);
568PyObject *Nuitka_Method_New(
struct Nuitka_FunctionObject *function, PyObject *
object, PyObject *class_object) {
571 CHECK_OBJECT((PyObject *)function);
572 assert(Nuitka_Function_Check((PyObject *)function));
573 assert(_PyObject_GC_IS_TRACKED(function));
575 allocateFromFreeListFixed(free_list_methods,
struct Nuitka_MethodObject, Nuitka_Method_Type);
577 if (unlikely(result == NULL)) {
578 PyErr_Format(PyExc_RuntimeError,
"cannot create method %s", Nuitka_String_AsString(function->m_name));
584 result->m_function = function;
586 result->m_object = object;
588 result->m_class = class_object;
589 Py_XINCREF(class_object);
591 result->m_weakrefs = NULL;
593#if PYTHON_VERSION >= 0x380 && !defined(_NUITKA_EXPERIMENTAL_DISABLE_VECTORCALL_SLOT)
594 result->m_vectorcall = (vectorcallfunc)Nuitka_Method_tp_vectorcall;
597 Nuitka_GC_Track(result);
598 return (PyObject *)result;
Definition exceptions.h:712
Definition compiled_function.h:22
Definition compiled_method.h:16