Coverage Report

Created: 2025-07-04 06:49

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