Coverage Report

Created: 2026-10-31 06:21

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