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