LCOV - code coverage report
Current view: top level - Objects - methodobject.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 202 240 84.2 %
Date: 2022-07-20 13:12:14 Functions: 21 26 80.8 %
Branches: 93 123 75.6 %

           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                 :   31048570 : PyCMethod_New(PyMethodDef *ml, PyObject *self, PyObject *module, PyTypeObject *cls)
      45                 :            : {
      46                 :            :     /* Figure out correct vectorcall function to use */
      47                 :            :     vectorcallfunc vectorcall;
      48   [ +  +  +  +  :   31048570 :     switch (ml->ml_flags & (METH_VARARGS | METH_FASTCALL | METH_NOARGS |
                +  +  - ]
      49                 :            :                             METH_O | METH_KEYWORDS | METH_METHOD))
      50                 :            :     {
      51                 :    4651451 :         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                 :    4651451 :             vectorcall = NULL;
      56                 :    4651451 :             break;
      57                 :    4223359 :         case METH_FASTCALL:
      58                 :    4223359 :             vectorcall = cfunction_vectorcall_FASTCALL;
      59                 :    4223359 :             break;
      60                 :    2678717 :         case METH_FASTCALL | METH_KEYWORDS:
      61                 :    2678717 :             vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS;
      62                 :    2678717 :             break;
      63                 :    4951018 :         case METH_NOARGS:
      64                 :    4951018 :             vectorcall = cfunction_vectorcall_NOARGS;
      65                 :    4951018 :             break;
      66                 :   11818055 :         case METH_O:
      67                 :   11818055 :             vectorcall = cfunction_vectorcall_O;
      68                 :   11818055 :             break;
      69                 :    2725970 :         case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
      70                 :    2725970 :             vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD;
      71                 :    2725970 :             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                 :   31048570 :     PyCFunctionObject *op = NULL;
      79                 :            : 
      80         [ +  + ]:   31048570 :     if (ml->ml_flags & METH_METHOD) {
      81         [ -  + ]:    2725970 :         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                 :    2725970 :         PyCMethodObject *om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type);
      88         [ -  + ]:    2725970 :         if (om == NULL) {
      89                 :          0 :             return NULL;
      90                 :            :         }
      91                 :    2725970 :         Py_INCREF(cls);
      92                 :    2725970 :         om->mm_class = cls;
      93                 :    2725970 :         op = (PyCFunctionObject *)om;
      94                 :            :     } else {
      95         [ -  + ]:   28322600 :         if (cls) {
      96                 :          0 :             PyErr_SetString(PyExc_SystemError,
      97                 :            :                             "attempting to create PyCFunction with class "
      98                 :            :                             "but no METH_METHOD flag");
      99                 :          0 :             return NULL;
     100                 :            :         }
     101                 :   28322600 :         op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
     102         [ +  + ]:   28322600 :         if (op == NULL) {
     103                 :         33 :             return NULL;
     104                 :            :         }
     105                 :            :     }
     106                 :            : 
     107                 :   31048537 :     op->m_weakreflist = NULL;
     108                 :   31048537 :     op->m_ml = ml;
     109                 :   31048537 :     Py_XINCREF(self);
     110                 :   31048537 :     op->m_self = self;
     111                 :   31048537 :     Py_XINCREF(module);
     112                 :   31048537 :     op->m_module = module;
     113                 :   31048537 :     op->vectorcall = vectorcall;
     114                 :   31048537 :     _PyObject_GC_TRACK(op);
     115                 :   31048537 :     return (PyObject *)op;
     116                 :            : }
     117                 :            : 
     118                 :            : PyCFunction
     119                 :       1108 : PyCFunction_GetFunction(PyObject *op)
     120                 :            : {
     121         [ -  + ]:       1108 :     if (!PyCFunction_Check(op)) {
     122                 :          0 :         PyErr_BadInternalCall();
     123                 :          0 :         return NULL;
     124                 :            :     }
     125                 :       1108 :     return PyCFunction_GET_FUNCTION(op);
     126                 :            : }
     127                 :            : 
     128                 :            : PyObject *
     129                 :          0 : PyCFunction_GetSelf(PyObject *op)
     130                 :            : {
     131         [ #  # ]:          0 :     if (!PyCFunction_Check(op)) {
     132                 :          0 :         PyErr_BadInternalCall();
     133                 :          0 :         return NULL;
     134                 :            :     }
     135                 :          0 :     return PyCFunction_GET_SELF(op);
     136                 :            : }
     137                 :            : 
     138                 :            : int
     139                 :          0 : PyCFunction_GetFlags(PyObject *op)
     140                 :            : {
     141         [ #  # ]:          0 :     if (!PyCFunction_Check(op)) {
     142                 :          0 :         PyErr_BadInternalCall();
     143                 :          0 :         return -1;
     144                 :            :     }
     145                 :          0 :     return PyCFunction_GET_FLAGS(op);
     146                 :            : }
     147                 :            : 
     148                 :            : PyTypeObject *
     149                 :          0 : PyCMethod_GetClass(PyObject *op)
     150                 :            : {
     151         [ #  # ]:          0 :     if (!PyCFunction_Check(op)) {
     152                 :          0 :         PyErr_BadInternalCall();
     153                 :          0 :         return NULL;
     154                 :            :     }
     155                 :          0 :     return PyCFunction_GET_CLASS(op);
     156                 :            : }
     157                 :            : 
     158                 :            : /* Methods (the standard built-in methods, that is) */
     159                 :            : 
     160                 :            : static void
     161                 :   30960310 : meth_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                 :   30960310 :     PyObject_GC_UnTrack(m);
     166   [ +  -  +  + ]:   30960310 :     Py_TRASHCAN_BEGIN(m, meth_dealloc);
     167         [ +  + ]:   30939902 :     if (m->m_weakreflist != NULL) {
     168                 :          2 :         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                 :   30939902 :     Py_XDECREF(PyCFunction_GET_CLASS(m));
     173                 :   30939902 :     Py_XDECREF(m->m_self);
     174                 :   30939902 :     Py_XDECREF(m->m_module);
     175                 :   30939902 :     PyObject_GC_Del(m);
     176         [ +  - ]:   30939902 :     Py_TRASHCAN_END;
     177                 :   30960310 : }
     178                 :            : 
     179                 :            : static PyObject *
     180                 :      16502 : meth_reduce(PyCFunctionObject *m, PyObject *Py_UNUSED(ignored))
     181                 :            : {
     182   [ +  -  +  + ]:      16502 :     if (m->m_self == NULL || PyModule_Check(m->m_self))
     183                 :      16012 :         return PyUnicode_FromString(m->m_ml->ml_name);
     184                 :            : 
     185                 :        490 :     return Py_BuildValue("N(Os)", _PyEval_GetBuiltin(&_Py_ID(getattr)),
     186                 :        490 :                          m->m_self, m->m_ml->ml_name);
     187                 :            : }
     188                 :            : 
     189                 :            : static PyMethodDef meth_methods[] = {
     190                 :            :     {"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL},
     191                 :            :     {NULL, NULL}
     192                 :            : };
     193                 :            : 
     194                 :            : static PyObject *
     195                 :        215 : meth_get__text_signature__(PyCFunctionObject *m, void *closure)
     196                 :            : {
     197                 :        215 :     return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
     198                 :            : }
     199                 :            : 
     200                 :            : static PyObject *
     201                 :      11015 : meth_get__doc__(PyCFunctionObject *m, void *closure)
     202                 :            : {
     203                 :      11015 :     return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
     204                 :            : }
     205                 :            : 
     206                 :            : static PyObject *
     207                 :     172547 : meth_get__name__(PyCFunctionObject *m, void *closure)
     208                 :            : {
     209                 :     172547 :     return PyUnicode_FromString(m->m_ml->ml_name);
     210                 :            : }
     211                 :            : 
     212                 :            : static PyObject *
     213                 :       2847 : meth_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   [ +  -  +  + ]:       2847 :     if (m->m_self == NULL || PyModule_Check(m->m_self))
     226                 :       2035 :         return PyUnicode_FromString(m->m_ml->ml_name);
     227                 :            : 
     228         [ +  + ]:        812 :     type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self);
     229                 :            : 
     230                 :        812 :     type_qualname = PyObject_GetAttr(type, &_Py_ID(__qualname__));
     231         [ -  + ]:        812 :     if (type_qualname == NULL)
     232                 :          0 :         return NULL;
     233                 :            : 
     234         [ -  + ]:        812 :     if (!PyUnicode_Check(type_qualname)) {
     235                 :          0 :         PyErr_SetString(PyExc_TypeError, "<method>.__class__."
     236                 :            :                         "__qualname__ is not a unicode object");
     237                 :          0 :         Py_XDECREF(type_qualname);
     238                 :          0 :         return NULL;
     239                 :            :     }
     240                 :            : 
     241                 :        812 :     res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name);
     242                 :        812 :     Py_DECREF(type_qualname);
     243                 :        812 :     return res;
     244                 :            : }
     245                 :            : 
     246                 :            : static int
     247                 :   66462032 : meth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
     248                 :            : {
     249   [ +  +  -  + ]:   66462032 :     Py_VISIT(PyCFunction_GET_CLASS(m));
     250   [ +  +  -  + ]:   66462032 :     Py_VISIT(m->m_self);
     251   [ +  +  -  + ]:   66462032 :     Py_VISIT(m->m_module);
     252                 :   66462032 :     return 0;
     253                 :            : }
     254                 :            : 
     255                 :            : static PyObject *
     256                 :       4427 : meth_get__self__(PyCFunctionObject *m, void *closure)
     257                 :            : {
     258                 :            :     PyObject *self;
     259                 :            : 
     260                 :       4427 :     self = PyCFunction_GET_SELF(m);
     261         [ +  + ]:       4427 :     if (self == NULL)
     262                 :          2 :         self = Py_None;
     263                 :       4427 :     Py_INCREF(self);
     264                 :       4427 :     return self;
     265                 :            : }
     266                 :            : 
     267                 :            : static 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                 :            : 
     278                 :            : static PyMemberDef meth_members[] = {
     279                 :            :     {"__module__",    T_OBJECT,     OFF(m_module), 0},
     280                 :            :     {NULL}
     281                 :            : };
     282                 :            : 
     283                 :            : static PyObject *
     284                 :       4507 : meth_repr(PyCFunctionObject *m)
     285                 :            : {
     286   [ +  -  +  + ]:       4507 :     if (m->m_self == NULL || PyModule_Check(m->m_self))
     287                 :       4440 :         return PyUnicode_FromFormat("<built-in function %s>",
     288                 :       4440 :                                    m->m_ml->ml_name);
     289                 :        134 :     return PyUnicode_FromFormat("<built-in method %s of %s object at %p>",
     290                 :         67 :                                m->m_ml->ml_name,
     291                 :         67 :                                Py_TYPE(m->m_self)->tp_name,
     292                 :            :                                m->m_self);
     293                 :            : }
     294                 :            : 
     295                 :            : static PyObject *
     296                 :      28329 : meth_richcompare(PyObject *self, PyObject *other, int op)
     297                 :            : {
     298                 :            :     PyCFunctionObject *a, *b;
     299                 :            :     PyObject *res;
     300                 :            :     int eq;
     301                 :            : 
     302   [ +  +  +  +  :      56642 :     if ((op != Py_EQ && op != Py_NE) ||
                   +  - ]
     303         [ +  + ]:      56626 :         !PyCFunction_Check(self) ||
     304                 :      28313 :         !PyCFunction_Check(other))
     305                 :            :     {
     306                 :      20907 :         Py_RETURN_NOTIMPLEMENTED;
     307                 :            :     }
     308                 :       7422 :     a = (PyCFunctionObject *)self;
     309                 :       7422 :     b = (PyCFunctionObject *)other;
     310                 :       7422 :     eq = a->m_self == b->m_self;
     311         [ +  + ]:       7422 :     if (eq)
     312                 :       1139 :         eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
     313         [ +  + ]:       7422 :     if (op == Py_EQ)
     314         [ +  + ]:       6317 :         res = eq ? Py_True : Py_False;
     315                 :            :     else
     316         [ +  + ]:       1105 :         res = eq ? Py_False : Py_True;
     317                 :       7422 :     Py_INCREF(res);
     318                 :       7422 :     return res;
     319                 :            : }
     320                 :            : 
     321                 :            : static Py_hash_t
     322                 :     272790 : meth_hash(PyCFunctionObject *a)
     323                 :            : {
     324                 :            :     Py_hash_t x, y;
     325                 :     272790 :     x = _Py_HashPointer(a->m_self);
     326                 :     272790 :     y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
     327                 :     272790 :     x ^= y;
     328         [ -  + ]:     272790 :     if (x == -1)
     329                 :          0 :         x = -2;
     330                 :     272790 :     return x;
     331                 :            : }
     332                 :            : 
     333                 :            : 
     334                 :            : PyTypeObject 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                 :            : 
     370                 :            : PyTypeObject 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                 :            : 
     384                 :            : static inline int
     385                 :   48208815 : cfunction_check_kwargs(PyThreadState *tstate, PyObject *func, PyObject *kwnames)
     386                 :            : {
     387                 :            :     assert(!_PyErr_Occurred(tstate));
     388                 :            :     assert(PyCFunction_Check(func));
     389   [ +  +  +  + ]:   48208815 :     if (kwnames && PyTuple_GET_SIZE(kwnames)) {
     390                 :         56 :         PyObject *funcstr = _PyObject_FunctionStr(func);
     391         [ +  - ]:         56 :         if (funcstr != NULL) {
     392                 :         56 :             _PyErr_Format(tstate, PyExc_TypeError,
     393                 :            :                          "%U takes no keyword arguments", funcstr);
     394                 :         56 :             Py_DECREF(funcstr);
     395                 :            :         }
     396                 :         56 :         return -1;
     397                 :            :     }
     398                 :   48208759 :     return 0;
     399                 :            : }
     400                 :            : 
     401                 :            : typedef void (*funcptr)(void);
     402                 :            : 
     403                 :            : static inline funcptr
     404                 :   60083854 : cfunction_enter_call(PyThreadState *tstate, PyObject *func)
     405                 :            : {
     406         [ +  + ]:   60083854 :     if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
     407                 :         29 :         return NULL;
     408                 :            :     }
     409                 :   60083825 :     return (funcptr)PyCFunction_GET_FUNCTION(func);
     410                 :            : }
     411                 :            : 
     412                 :            : /* Now the actual vectorcall functions */
     413                 :            : static PyObject *
     414                 :    8465057 : cfunction_vectorcall_FASTCALL(
     415                 :            :     PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
     416                 :            : {
     417                 :    8465057 :     PyThreadState *tstate = _PyThreadState_GET();
     418         [ +  + ]:    8465057 :     if (cfunction_check_kwargs(tstate, func, kwnames)) {
     419                 :         14 :         return NULL;
     420                 :            :     }
     421                 :    8465043 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     422                 :            :     _PyCFunctionFast meth = (_PyCFunctionFast)
     423                 :    8465043 :                             cfunction_enter_call(tstate, func);
     424         [ -  + ]:    8465043 :     if (meth == NULL) {
     425                 :          0 :         return NULL;
     426                 :            :     }
     427                 :    8465043 :     PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
     428                 :    8465041 :     _Py_LeaveRecursiveCallTstate(tstate);
     429                 :    8465041 :     return result;
     430                 :            : }
     431                 :            : 
     432                 :            : static PyObject *
     433                 :    8550113 : cfunction_vectorcall_FASTCALL_KEYWORDS(
     434                 :            :     PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
     435                 :            : {
     436                 :    8550113 :     PyThreadState *tstate = _PyThreadState_GET();
     437                 :    8550113 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     438                 :            :     _PyCFunctionFastWithKeywords meth = (_PyCFunctionFastWithKeywords)
     439                 :    8550113 :                                         cfunction_enter_call(tstate, func);
     440         [ -  + ]:    8550113 :     if (meth == NULL) {
     441                 :          0 :         return NULL;
     442                 :            :     }
     443                 :    8550113 :     PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
     444                 :    8550108 :     _Py_LeaveRecursiveCallTstate(tstate);
     445                 :    8550108 :     return result;
     446                 :            : }
     447                 :            : 
     448                 :            : static PyObject *
     449                 :    3325428 : cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
     450                 :            :     PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
     451                 :            : {
     452                 :    3325428 :     PyThreadState *tstate = _PyThreadState_GET();
     453                 :    3325428 :     PyTypeObject *cls = PyCFunction_GET_CLASS(func);
     454                 :    3325428 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     455                 :    3325428 :     PyCMethod meth = (PyCMethod)cfunction_enter_call(tstate, func);
     456         [ -  + ]:    3325428 :     if (meth == NULL) {
     457                 :          0 :         return NULL;
     458                 :            :     }
     459                 :    3325428 :     PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames);
     460                 :    3325428 :     _Py_LeaveRecursiveCallTstate(tstate);
     461                 :    3325428 :     return result;
     462                 :            : }
     463                 :            : 
     464                 :            : static PyObject *
     465                 :   22747140 : cfunction_vectorcall_NOARGS(
     466                 :            :     PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
     467                 :            : {
     468                 :   22747140 :     PyThreadState *tstate = _PyThreadState_GET();
     469         [ +  + ]:   22747140 :     if (cfunction_check_kwargs(tstate, func, kwnames)) {
     470                 :         27 :         return NULL;
     471                 :            :     }
     472                 :   22747113 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     473         [ +  + ]:   22747113 :     if (nargs != 0) {
     474                 :        199 :         PyObject *funcstr = _PyObject_FunctionStr(func);
     475         [ +  - ]:        199 :         if (funcstr != NULL) {
     476                 :        199 :             _PyErr_Format(tstate, PyExc_TypeError,
     477                 :            :                 "%U takes no arguments (%zd given)", funcstr, nargs);
     478                 :        199 :             Py_DECREF(funcstr);
     479                 :            :         }
     480                 :        199 :         return NULL;
     481                 :            :     }
     482                 :   22746914 :     PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
     483         [ +  + ]:   22746914 :     if (meth == NULL) {
     484                 :          7 :         return NULL;
     485                 :            :     }
     486                 :   22746907 :     PyObject *result = _PyCFunction_TrampolineCall(
     487                 :            :         meth, PyCFunction_GET_SELF(func), NULL);
     488                 :   22746907 :     _Py_LeaveRecursiveCallTstate(tstate);
     489                 :   22746907 :     return result;
     490                 :            : }
     491                 :            : 
     492                 :            : static PyObject *
     493                 :   16996618 : cfunction_vectorcall_O(
     494                 :            :     PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
     495                 :            : {
     496                 :   16996618 :     PyThreadState *tstate = _PyThreadState_GET();
     497         [ +  + ]:   16996618 :     if (cfunction_check_kwargs(tstate, func, kwnames)) {
     498                 :         15 :         return NULL;
     499                 :            :     }
     500                 :   16996603 :     Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
     501         [ +  + ]:   16996603 :     if (nargs != 1) {
     502                 :        247 :         PyObject *funcstr = _PyObject_FunctionStr(func);
     503         [ +  - ]:        247 :         if (funcstr != NULL) {
     504                 :        247 :             _PyErr_Format(tstate, PyExc_TypeError,
     505                 :            :                 "%U takes exactly one argument (%zd given)", funcstr, nargs);
     506                 :        247 :             Py_DECREF(funcstr);
     507                 :            :         }
     508                 :        247 :         return NULL;
     509                 :            :     }
     510                 :   16996356 :     PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
     511         [ +  + ]:   16996356 :     if (meth == NULL) {
     512                 :         22 :         return NULL;
     513                 :            :     }
     514                 :   16996334 :     PyObject *result = _PyCFunction_TrampolineCall(
     515                 :            :         meth, PyCFunction_GET_SELF(func), args[0]);
     516                 :   16996330 :     _Py_LeaveRecursiveCallTstate(tstate);
     517                 :   16996330 :     return result;
     518                 :            : }
     519                 :            : 
     520                 :            : 
     521                 :            : static PyObject *
     522                 :   19665927 : cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
     523                 :            : {
     524                 :            :     assert(kwargs == NULL || PyDict_Check(kwargs));
     525                 :            : 
     526                 :   19665927 :     PyThreadState *tstate = _PyThreadState_GET();
     527                 :            :     assert(!_PyErr_Occurred(tstate));
     528                 :            : 
     529                 :   19665927 :     int flags = PyCFunction_GET_FLAGS(func);
     530         [ -  + ]:   19665927 :     if (!(flags & METH_VARARGS)) {
     531                 :            :         /* If this is not a METH_VARARGS function, delegate to vectorcall */
     532                 :          0 :         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                 :   19665927 :     PyCFunction meth = PyCFunction_GET_FUNCTION(func);
     538                 :   19665927 :     PyObject *self = PyCFunction_GET_SELF(func);
     539                 :            : 
     540                 :            :     PyObject *result;
     541         [ +  + ]:   19665927 :     if (flags & METH_KEYWORDS) {
     542                 :   15545483 :         result = _PyCFunctionWithKeywords_TrampolineCall(
     543                 :            :             (*(PyCFunctionWithKeywords)(void(*)(void))meth),
     544                 :            :             self, args, kwargs);
     545                 :            :     }
     546                 :            :     else {
     547   [ +  +  +  + ]:    4120444 :         if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
     548                 :          5 :             _PyErr_Format(tstate, PyExc_TypeError,
     549                 :            :                           "%.200s() takes no keyword arguments",
     550                 :          5 :                           ((PyCFunctionObject*)func)->m_ml->ml_name);
     551                 :          5 :             return NULL;
     552                 :            :         }
     553                 :    4120439 :         result = _PyCFunction_TrampolineCall(meth, self, args);
     554                 :            :     }
     555                 :   19665915 :     return _Py_CheckFunctionResult(tstate, func, result, NULL);
     556                 :            : }
     557                 :            : 
     558                 :            : #if defined(__EMSCRIPTEN__) && defined(PY_CALL_TRAMPOLINE)
     559                 :            : #include <emscripten.h>
     560                 :            : 
     561                 :            : EM_JS(PyObject*, _PyCFunctionWithKeywords_TrampolineCall, (PyCFunctionWithKeywords func, PyObject *self, PyObject *args, PyObject *kw), {
     562                 :            :     return wasmTable.get(func)(self, args, kw);
     563                 :            : });
     564                 :            : #endif

Generated by: LCOV version 1.14