LCOV - code coverage report
Current view: | top level - Objects - methodobject.c (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 157 | 235 | 66.8 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 17 | 26 | 65.4 %
|  |  | Branches: | 65 | 123 | 52.8 %

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

Generated by: LCOV version 1.14