xref: /third_party/python/Objects/methodobject.c (revision 7db96d56)
1
2/* Method object implementation */
3
4#include "Python.h"
5#include "pycore_ceval.h"         // _Py_EnterRecursiveCallTstate()
6#include "pycore_object.h"
7#include "pycore_pyerrors.h"
8#include "pycore_pystate.h"       // _PyThreadState_GET()
9#include "structmember.h"         // PyMemberDef
10
11/* undefine macro trampoline to PyCFunction_NewEx */
12#undef PyCFunction_New
13/* undefine macro trampoline to PyCMethod_New */
14#undef PyCFunction_NewEx
15
16/* Forward declarations */
17static PyObject * cfunction_vectorcall_FASTCALL(
18    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
19static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS(
20    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
21static PyObject * cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
22    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
23static PyObject * cfunction_vectorcall_NOARGS(
24    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
25static PyObject * cfunction_vectorcall_O(
26    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames);
27static PyObject * cfunction_call(
28    PyObject *func, PyObject *args, PyObject *kwargs);
29
30
31PyObject *
32PyCFunction_New(PyMethodDef *ml, PyObject *self)
33{
34    return PyCFunction_NewEx(ml, self, NULL);
35}
36
37PyObject *
38PyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
39{
40    return PyCMethod_New(ml, self, module, NULL);
41}
42
43PyObject *
44PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls)
45{
46    /* Figure out correct vectorcall function to use */
47    vectorcallfunc vectorcall;
48    switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
49                            METH_O | METH_KEYWORDS | METH_METHOD))
50    {
51        case METH_VARARGS:
52        case METH_VARARGS | METH_KEYWORDS:
53            /* For METH_VARARGS functions, it's more efficient to use tp_call
54             * instead of vectorcall. */
55            vectorcall = NULL;
56            break;
57        case METH_FASTCALL:
58            vectorcall = cfunction_vectorcall_FASTCALL;
59            break;
60        case METH_FASTCALL | METH_KEYWORDS:
61            vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS;
62            break;
63        case METH_NOARGS:
64            vectorcall = cfunction_vectorcall_NOARGS;
65            break;
66        case METH_O:
67            vectorcall = cfunction_vectorcall_O;
68            break;
69        case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
70            vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD;
71            break;
72        default:
73            PyErr_Format(PyExc_SystemError,
74                         "%s() method: bad call flags", ml->ml_name);
75            return NULL;
76    }
77
78    PyCFunctionObject *op = NULL;
79
80    if (ml->ml_flags & METH_METHOD) {
81        if (!cls) {
82            PyErr_SetString(PyExc_SystemError,
83                            "attempting to create PyCMethod with a METH_METHOD "
84                            "flag but no class");
85            return NULL;
86        }
87        PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type);
88        if (om == NULL) {
89            return NULL;
90        }
91        Py_INCREF(cls);
92        om->mm_class = cls;
93        op = (PyCFunctionObject *)om;
94    } else {
95        if (cls) {
96            PyErr_SetString(PyExc_SystemError,
97                            "attempting to create PyCFunction with class "
98                            "but no METH_METHOD flag");
99            return NULL;
100        }
101        op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
102        if (op == NULL) {
103            return NULL;
104        }
105    }
106
107    op->m_weakreflist = NULL;
108    op->m_ml = ml;
109    Py_XINCREF(self);
110    op->m_self = self;
111    Py_XINCREF(module);
112    op->m_module = module;
113    op->vectorcall = vectorcall;
114    _PyObject_GC_TRACK(op);
115    return (PyObject *)op;
116}
117
118PyCFunction
119PyCFunction_GetFunction(PyObject *op)
120{
121    if (!PyCFunction_Check(op)) {
122        PyErr_BadInternalCall();
123        return NULL;
124    }
125    return PyCFunction_GET_FUNCTION(op);
126}
127
128PyObject *
129PyCFunction_GetSelf(PyObject *op)
130{
131    if (!PyCFunction_Check(op)) {
132        PyErr_BadInternalCall();
133        return NULL;
134    }
135    return PyCFunction_GET_SELF(op);
136}
137
138int
139PyCFunction_GetFlags(PyObject *op)
140{
141    if (!PyCFunction_Check(op)) {
142        PyErr_BadInternalCall();
143        return -1;
144    }
145    return PyCFunction_GET_FLAGS(op);
146}
147
148PyTypeObject *
149PyCMethod_GetClass(PyObject *op)
150{
151    if (!PyCFunction_Check(op)) {
152        PyErr_BadInternalCall();
153        return NULL;
154    }
155    return PyCFunction_GET_CLASS(op);
156}
157
158/* Methods (the standard built-in methods, that is) */
159
160static void
161meth_dealloc(PyCFunctionObject *m)
162{
163    // The Py_TRASHCAN mechanism requires that we be able to
164    // call PyObject_GC_UnTrack twice on an object.
165    PyObject_GC_UnTrack(m);
166    Py_TRASHCAN_BEGIN(m, meth_dealloc);
167    if (m->m_weakreflist != NULL) {
168        PyObject_ClearWeakRefs((PyObject*) m);
169    }
170    // Dereference class before m_self: PyCFunction_GET_CLASS accesses
171    // PyMethodDef m_ml, which could be kept alive by m_self
172    Py_XDECREF(PyCFunction_GET_CLASS(m));
173    Py_XDECREF(m->m_self);
174    Py_XDECREF(m->m_module);
175    PyObject_GC_Del(m);
176    Py_TRASHCAN_END;
177}
178
179static PyObject *
180meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored))
181{
182    if (m->m_self == NULL || PyModule_Check(m->m_self))
183        return PyUnicode_FromString(m->m_ml->ml_name);
184
185    return Py_BuildValue("N(Os)", _PyEval_GetBuiltin(&_Py_ID(getattr)),
186                         m->m_self, m->m_ml->ml_name);
187}
188
189static PyMethodDef meth_methods[] = {
190    {"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL},
191    {NULL, NULL}
192};
193
194static PyObject *
195meth_get__text_signature__(PyCFunctionObject *m, void *closure)
196{
197    return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
198}
199
200static PyObject *
201meth_get__doc__(PyCFunctionObject *m, void *closure)
202{
203    return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
204}
205
206static PyObject *
207meth_get__name__(PyCFunctionObject *m, void *closure)
208{
209    return PyUnicode_FromString(m->m_ml->ml_name);
210}
211
212static PyObject *
213meth_get__qualname__(PyCFunctionObject *m, void *closure)
214{
215    /* If __self__ is a module or NULL, return m.__name__
216       (e.g. len.__qualname__ == 'len')
217
218       If __self__ is a type, return m.__self__.__qualname__ + '.' + m.__name__
219       (e.g. dict.fromkeys.__qualname__ == 'dict.fromkeys')
220
221       Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__
222       (e.g. [].append.__qualname__ == 'list.append') */
223    PyObject *type, *type_qualname, *res;
224
225    if (m->m_self == NULL || PyModule_Check(m->m_self))
226        return PyUnicode_FromString(m->m_ml->ml_name);
227
228    type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self);
229
230    type_qualname = PyObject_GetAttr(type, &_Py_ID(__qualname__));
231    if (type_qualname == NULL)
232        return NULL;
233
234    if (!PyUnicode_Check(type_qualname)) {
235        PyErr_SetString(PyExc_TypeError, "<method>.__class__."
236                        "__qualname__ is not a unicode object");
237        Py_XDECREF(type_qualname);
238        return NULL;
239    }
240
241    res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name);
242    Py_DECREF(type_qualname);
243    return res;
244}
245
246static int
247meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
248{
249    Py_VISIT(PyCFunction_GET_CLASS(m));
250    Py_VISIT(m->m_self);
251    Py_VISIT(m->m_module);
252    return 0;
253}
254
255static PyObject *
256meth_get__self__(PyCFunctionObject *m, void *closure)
257{
258    PyObject *self;
259
260    self = PyCFunction_GET_SELF(m);
261    if (self == NULL)
262        self = Py_None;
263    Py_INCREF(self);
264    return self;
265}
266
267static PyGetSetDef meth_getsets [] = {
268    {"__doc__",  (getter)meth_get__doc__,  NULL, NULL},
269    {"__name__", (getter)meth_get__name__, NULL, NULL},
270    {"__qualname__", (getter)meth_get__qualname__, NULL, NULL},
271    {"__self__", (getter)meth_get__self__, NULL, NULL},
272    {"__text_signature__", (getter)meth_get__text_signature__, NULL, NULL},
273    {0}
274};
275
276#define OFF(x) offsetof(PyCFunctionObject, x)
277
278static PyMemberDef meth_members[] = {
279    {"__module__",    T_OBJECT,     OFF(m_module), 0},
280    {NULL}
281};
282
283static PyObject *
284meth_repr(PyCFunctionObject *m)
285{
286    if (m->m_self == NULL || PyModule_Check(m->m_self))
287        return PyUnicode_FromFormat("<built-in function %s>",
288                                   m->m_ml->ml_name);
289    return PyUnicode_FromFormat("<built-in method %s of %s object at %p>",
290                               m->m_ml->ml_name,
291                               Py_TYPE(m->m_self)->tp_name,
292                               m->m_self);
293}
294
295static PyObject *
296meth_richcompare(PyObject *self, PyObject *other, int op)
297{
298    PyCFunctionObject *a, *b;
299    PyObject *res;
300    int eq;
301
302    if ((op != Py_EQ && op != Py_NE) ||
303        !PyCFunction_Check(self) ||
304        !PyCFunction_Check(other))
305    {
306        Py_RETURN_NOTIMPLEMENTED;
307    }
308    a = (PyCFunctionObject *)self;
309    b = (PyCFunctionObject *)other;
310    eq = a->m_self == b->m_self;
311    if (eq)
312        eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
313    if (op == Py_EQ)
314        res = eq ? Py_True : Py_False;
315    else
316        res = eq ? Py_False : Py_True;
317    Py_INCREF(res);
318    return res;
319}
320
321static Py_hash_t
322meth_hash(PyCFunctionObject *a)
323{
324    Py_hash_t x, y;
325    x = _Py_HashPointer(a->m_self);
326    y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
327    x ^= y;
328    if (x == -1)
329        x = -2;
330    return x;
331}
332
333
334PyTypeObject PyCFunction_Type = {
335    PyVarObject_HEAD_INIT(&PyType_Type, 0)
336    "builtin_function_or_method",
337    sizeof(PyCFunctionObject),
338    0,
339    (destructor)meth_dealloc,                   /* tp_dealloc */
340    offsetof(PyCFunctionObject, vectorcall),    /* tp_vectorcall_offset */
341    0,                                          /* tp_getattr */
342    0,                                          /* tp_setattr */
343    0,                                          /* tp_as_async */
344    (reprfunc)meth_repr,                        /* tp_repr */
345    0,                                          /* tp_as_number */
346    0,                                          /* tp_as_sequence */
347    0,                                          /* tp_as_mapping */
348    (hashfunc)meth_hash,                        /* tp_hash */
349    cfunction_call,                             /* tp_call */
350    0,                                          /* tp_str */
351    PyObject_GenericGetAttr,                    /* tp_getattro */
352    0,                                          /* tp_setattro */
353    0,                                          /* tp_as_buffer */
354    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
355    Py_TPFLAGS_HAVE_VECTORCALL,                 /* tp_flags */
356    0,                                          /* tp_doc */
357    (traverseproc)meth_traverse,                /* tp_traverse */
358    0,                                          /* tp_clear */
359    meth_richcompare,                           /* tp_richcompare */
360    offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */
361    0,                                          /* tp_iter */
362    0,                                          /* tp_iternext */
363    meth_methods,                               /* tp_methods */
364    meth_members,                               /* tp_members */
365    meth_getsets,                               /* tp_getset */
366    0,                                          /* tp_base */
367    0,                                          /* tp_dict */
368};
369
370PyTypeObject PyCMethod_Type = {
371    PyVarObject_HEAD_INIT(&PyType_Type, 0)
372    .tp_name = "builtin_method",
373    .tp_basicsize = sizeof(PyCMethodObject),
374    .tp_base = &PyCFunction_Type,
375};
376
377/* Vectorcall functions for each of the PyCFunction calling conventions,
378 * except for METH_VARARGS (possibly combined with METH_KEYWORDS) which
379 * doesn't use vectorcall.
380 *
381 * First, common helpers
382 */
383
384static inline int
385cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames)
386{
387    assert(!_PyErr_Occurred(tstate));
388    assert(PyCFunction_Check(func));
389    if (kwnames && PyTuple_GET_SIZE(kwnames)) {
390        PyObject *funcstr = _PyObject_FunctionStr(func);
391        if (funcstr != NULL) {
392            _PyErr_Format(tstate, PyExc_TypeError,
393                         "%U takes no keyword arguments", funcstr);
394            Py_DECREF(funcstr);
395        }
396        return -1;
397    }
398    return 0;
399}
400
401typedef void (*funcptr)(void);
402
403static inline funcptr
404cfunction_enter_call(PyThreadState *tstate, PyObject *func)
405{
406    if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
407        return NULL;
408    }
409    return (funcptr)PyCFunction_GET_FUNCTION(func);
410}
411
412/* Now the actual vectorcall functions */
413static PyObject *
414cfunction_vectorcall_FASTCALL(
415    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
416{
417    PyThreadState *tstate = _PyThreadState_GET();
418    if (cfunction_check_kwargs(tstate, func, kwnames)) {
419        return NULL;
420    }
421    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
422    _PyCFunctionFast meth = (_PyCFunctionFast)
423                            cfunction_enter_call(tstate, func);
424    if (meth == NULL) {
425        return NULL;
426    }
427    PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
428    _Py_LeaveRecursiveCallTstate(tstate);
429    return result;
430}
431
432static PyObject *
433cfunction_vectorcall_FASTCALL_KEYWORDS(
434    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
435{
436    PyThreadState *tstate = _PyThreadState_GET();
437    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
438    _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
439                                        cfunction_enter_call(tstate, func);
440    if (meth == NULL) {
441        return NULL;
442    }
443    PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
444    _Py_LeaveRecursiveCallTstate(tstate);
445    return result;
446}
447
448static PyObject *
449cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
450    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
451{
452    PyThreadState *tstate = _PyThreadState_GET();
453    PyTypeObject *cls = PyCFunction_GET_CLASS(func);
454    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
455    PyCMethod meth = (PyCMethod)cfunction_enter_call(tstate, func);
456    if (meth == NULL) {
457        return NULL;
458    }
459    PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames);
460    _Py_LeaveRecursiveCallTstate(tstate);
461    return result;
462}
463
464static PyObject *
465cfunction_vectorcall_NOARGS(
466    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
467{
468    PyThreadState *tstate = _PyThreadState_GET();
469    if (cfunction_check_kwargs(tstate, func, kwnames)) {
470        return NULL;
471    }
472    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
473    if (nargs != 0) {
474        PyObject *funcstr = _PyObject_FunctionStr(func);
475        if (funcstr != NULL) {
476            _PyErr_Format(tstate, PyExc_TypeError,
477                "%U takes no arguments (%zd given)", funcstr, nargs);
478            Py_DECREF(funcstr);
479        }
480        return NULL;
481    }
482    PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
483    if (meth == NULL) {
484        return NULL;
485    }
486    PyObject *result = _PyCFunction_TrampolineCall(
487        meth, PyCFunction_GET_SELF(func), NULL);
488    _Py_LeaveRecursiveCallTstate(tstate);
489    return result;
490}
491
492static PyObject *
493cfunction_vectorcall_O(
494    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
495{
496    PyThreadState *tstate = _PyThreadState_GET();
497    if (cfunction_check_kwargs(tstate, func, kwnames)) {
498        return NULL;
499    }
500    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
501    if (nargs != 1) {
502        PyObject *funcstr = _PyObject_FunctionStr(func);
503        if (funcstr != NULL) {
504            _PyErr_Format(tstate, PyExc_TypeError,
505                "%U takes exactly one argument (%zd given)", funcstr, nargs);
506            Py_DECREF(funcstr);
507        }
508        return NULL;
509    }
510    PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
511    if (meth == NULL) {
512        return NULL;
513    }
514    PyObject *result = _PyCFunction_TrampolineCall(
515        meth, PyCFunction_GET_SELF(func), args[0]);
516    _Py_LeaveRecursiveCallTstate(tstate);
517    return result;
518}
519
520
521static PyObject *
522cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
523{
524    assert(kwargs == NULL || PyDict_Check(kwargs));
525
526    PyThreadState *tstate = _PyThreadState_GET();
527    assert(!_PyErr_Occurred(tstate));
528
529    int flags = PyCFunction_GET_FLAGS(func);
530    if (!(flags & METH_VARARGS)) {
531        /* If this is not a METH_VARARGS function, delegate to vectorcall */
532        return PyVectorcall_Call(func, args, kwargs);
533    }
534
535    /* For METH_VARARGS, we cannot use vectorcall as the vectorcall pointer
536     * is NULL. This is intentional, since vectorcall would be slower. */
537    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
538    PyObject *self = PyCFunction_GET_SELF(func);
539
540    PyObject *result;
541    if (flags & METH_KEYWORDS) {
542        result = _PyCFunctionWithKeywords_TrampolineCall(
543            (*(PyCFunctionWithKeywords)(void(*)(void))meth),
544            self, args, kwargs);
545    }
546    else {
547        if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
548            _PyErr_Format(tstate, PyExc_TypeError,
549                          "%.200s() takes no keyword arguments",
550                          ((PyCFunctionObject*)func)->m_ml->ml_name);
551            return NULL;
552        }
553        result = _PyCFunction_TrampolineCall(meth, self, args);
554    }
555    return _Py_CheckFunctionResult(tstate, func, result, NULL);
556}
557
558#if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
559#include <emscripten.h>
560
561EM_JS(PyObject*, _PyCFunctionWithKeywords_TrampolineCall, (PyCFunctionWithKeywords func, PyObject *self, PyObject *args, PyObject *kw), {
562    return wasmTable.get(func)(self, args, kw);
563});
564#endif
565