Coverage Report

Created: 2026-10-17 06:15

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
166M
{
49
    /* Figure out correct vectorcall function to use */
50
166M
    vectorcallfunc vectorcall;
51
166M
    switch (ml->ml_flags & _Py_METH_CALL_FLAGS)
52
166M
    {
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
51.5M
        case METH_FASTCALL:
60
51.5M
            vectorcall = cfunction_vectorcall_FASTCALL;
61
51.5M
            break;
62
24.6M
        case METH_FASTCALL | METH_KEYWORDS:
63
24.6M
            vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS;
64
24.6M
            break;
65
44.8M
        case METH_NOARGS:
66
44.8M
            vectorcall = cfunction_vectorcall_NOARGS;
67
44.8M
            break;
68
34.8M
        case METH_O:
69
34.8M
            vectorcall = cfunction_vectorcall_O;
70
34.8M
            break;
71
10.4M
        case METH_METHOD | METH_FASTCALL | METH_KEYWORDS:
72
10.4M
            vectorcall = cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD;
73
10.4M
            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
166M
    }
79
80
166M
    PyCFunctionObject *op = NULL;
81
82
166M
    if (ml->ml_flags & METH_METHOD) {
83
10.4M
        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
10.4M
        PyCMethodObject *om = _Py_FREELIST_POP(PyCMethodObject, pycmethodobject);
90
10.4M
        if (om == NULL) {
91
367
            om = PyObject_GC_New(PyCMethodObject, &PyCMethod_Type);
92
367
            if (om == NULL) {
93
0
                return NULL;
94
0
            }
95
367
        }
96
10.4M
        om->mm_class = (PyTypeObject*)Py_NewRef(cls);
97
10.4M
        op = (PyCFunctionObject *)om;
98
155M
    } else {
99
155M
        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
155M
        op = _Py_FREELIST_POP(PyCFunctionObject, pycfunctionobject);
106
155M
        if (op == NULL) {
107
105k
            op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
108
105k
            if (op == NULL) {
109
0
                return NULL;
110
0
            }
111
105k
        }
112
155M
    }
113
114
166M
    op->m_weakreflist = NULL;
115
166M
    op->m_ml = ml;
116
166M
    op->m_self = Py_XNewRef(self);
117
166M
    op->m_module = Py_XNewRef(module);
118
166M
    op->vectorcall = vectorcall;
119
166M
    _PyObject_GC_TRACK(op);
120
166M
    return (PyObject *)op;
121
166M
}
122
123
PyCFunction
124
PyCFunction_GetFunction(PyObject *op)
125
3.81k
{
126
3.81k
    if (!PyCFunction_Check(op)) {
127
0
        PyErr_BadInternalCall();
128
0
        return NULL;
129
0
    }
130
3.81k
    return PyCFunction_GET_FUNCTION(op);
131
3.81k
}
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
166M
{
168
166M
    PyCFunctionObject *m = _PyCFunctionObject_CAST(self);
169
166M
    PyObject_GC_UnTrack(m);
170
166M
    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
166M
    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
166M
    Py_XDECREF(PyCFunction_GET_CLASS(m));
178
166M
    Py_XDECREF(m->m_self);
179
166M
    Py_XDECREF(m->m_module);
180
166M
    if (ml_flags & METH_METHOD) {
181
10.4M
        assert(Py_IS_TYPE(self, &PyCMethod_Type));
182
10.4M
        _Py_FREELIST_FREE(pycmethodobject, m, PyObject_GC_Del);
183
10.4M
    }
184
155M
    else {
185
155M
        assert(Py_IS_TYPE(self, &PyCFunction_Type));
186
155M
        _Py_FREELIST_FREE(pycfunctionobject, m, PyObject_GC_Del);
187
155M
    }
188
166M
}
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.50M
{
267
1.50M
    PyCFunctionObject *m = _PyCFunctionObject_CAST(self);
268
1.50M
    Py_VISIT(PyCFunction_GET_CLASS(m));
269
1.50M
    Py_VISIT(m->m_self);
270
1.50M
    Py_VISIT(m->m_module);
271
1.50M
    return 0;
272
1.50M
}
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
42.6k
{
319
42.6k
    PyCFunctionObject *a, *b;
320
42.6k
    PyObject *res;
321
42.6k
    int eq;
322
323
42.6k
    if ((op != Py_EQ && op != Py_NE) ||
324
42.6k
        !PyCFunction_Check(self) ||
325
42.6k
        !PyCFunction_Check(other))
326
42.5k
    {
327
42.5k
        Py_RETURN_NOTIMPLEMENTED;
328
42.5k
    }
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
42.6k
}
340
341
static Py_hash_t
342
meth_hash(PyObject *self)
343
3.28k
{
344
3.28k
    PyCFunctionObject *a = _PyCFunctionObject_CAST(self);
345
3.28k
    Py_hash_t x = PyObject_GenericHash(a->m_self);
346
3.28k
    Py_hash_t y = Py_HashPointer((void*)(a->m_ml->ml_meth));
347
3.28k
    x ^= y;
348
3.28k
    if (x == -1) {
349
0
        x = -2;
350
0
    }
351
3.28k
    return x;
352
3.28k
}
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
122M
{
408
122M
    assert(!_PyErr_Occurred(tstate));
409
122M
    assert(PyCFunction_Check(func));
410
122M
    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
122M
    return 0;
420
122M
}
421
422
typedef void (*funcptr)(void);
423
424
static inline funcptr
425
cfunction_enter_call(PyThreadState *tstate, PyObject *func)
426
154M
{
427
154M
    if (_Py_EnterRecursiveCallTstate(tstate, " while calling a Python object")) {
428
0
        return NULL;
429
0
    }
430
154M
    return (funcptr)PyCFunction_GET_FUNCTION(func);
431
154M
}
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
821k
{
438
821k
    PyThreadState *tstate = _PyThreadState_GET();
439
821k
    if (cfunction_check_kwargs(tstate, func, kwnames)) {
440
0
        return NULL;
441
0
    }
442
821k
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
443
821k
    PyCFunctionFast meth = (PyCFunctionFast)
444
821k
                            cfunction_enter_call(tstate, func);
445
821k
    if (meth == NULL) {
446
0
        return NULL;
447
0
    }
448
821k
    PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs);
449
821k
    _Py_LeaveRecursiveCallTstate(tstate);
450
821k
    return result;
451
821k
}
452
453
static PyObject *
454
cfunction_vectorcall_FASTCALL_KEYWORDS(
455
    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
456
6.22M
{
457
6.22M
    PyThreadState *tstate = _PyThreadState_GET();
458
6.22M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
459
6.22M
    PyCFunctionFastWithKeywords meth = (PyCFunctionFastWithKeywords)
460
6.22M
                                        cfunction_enter_call(tstate, func);
461
6.22M
    if (meth == NULL) {
462
0
        return NULL;
463
0
    }
464
6.22M
    PyObject *result = meth(PyCFunction_GET_SELF(func), args, nargs, kwnames);
465
6.22M
    _Py_LeaveRecursiveCallTstate(tstate);
466
6.22M
    return result;
467
6.22M
}
468
469
static PyObject *
470
cfunction_vectorcall_FASTCALL_KEYWORDS_METHOD(
471
    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
472
25.7M
{
473
25.7M
    PyThreadState *tstate = _PyThreadState_GET();
474
25.7M
    PyTypeObject *cls = PyCFunction_GET_CLASS(func);
475
25.7M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
476
25.7M
    PyCMethod meth = (PyCMethod)cfunction_enter_call(tstate, func);
477
25.7M
    if (meth == NULL) {
478
0
        return NULL;
479
0
    }
480
25.7M
    PyObject *result = meth(PyCFunction_GET_SELF(func), cls, args, nargs, kwnames);
481
25.7M
    _Py_LeaveRecursiveCallTstate(tstate);
482
25.7M
    return result;
483
25.7M
}
484
485
static PyObject *
486
cfunction_vectorcall_NOARGS(
487
    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
488
45.3M
{
489
45.3M
    PyThreadState *tstate = _PyThreadState_GET();
490
45.3M
    if (cfunction_check_kwargs(tstate, func, kwnames)) {
491
0
        return NULL;
492
0
    }
493
45.3M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
494
45.3M
    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.3M
    PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
504
45.3M
    if (meth == NULL) {
505
0
        return NULL;
506
0
    }
507
45.3M
    PyObject *result = _PyCFunction_TrampolineCall(
508
45.3M
        meth, PyCFunction_GET_SELF(func), NULL);
509
45.3M
    _Py_LeaveRecursiveCallTstate(tstate);
510
45.3M
    return result;
511
45.3M
}
512
513
static PyObject *
514
cfunction_vectorcall_O(
515
    PyObject *func, PyObject *const *args, size_t nargsf, PyObject *kwnames)
516
76.2M
{
517
76.2M
    PyThreadState *tstate = _PyThreadState_GET();
518
76.2M
    if (cfunction_check_kwargs(tstate, func, kwnames)) {
519
0
        return NULL;
520
0
    }
521
76.2M
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
522
76.2M
    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
76.2M
    PyCFunction meth = (PyCFunction)cfunction_enter_call(tstate, func);
532
76.2M
    if (meth == NULL) {
533
0
        return NULL;
534
0
    }
535
76.2M
    PyObject *result = _PyCFunction_TrampolineCall(
536
76.2M
        meth, PyCFunction_GET_SELF(func), args[0]);
537
76.2M
    _Py_LeaveRecursiveCallTstate(tstate);
538
76.2M
    return result;
539
76.2M
}
540
541
542
static PyObject *
543
cfunction_call(PyObject *func, PyObject *args, PyObject *kwargs)
544
3.93k
{
545
3.93k
    assert(kwargs == NULL || PyDict_Check(kwargs));
546
547
3.93k
    PyThreadState *tstate = _PyThreadState_GET();
548
3.93k
    assert(!_PyErr_Occurred(tstate));
549
550
3.93k
    int flags = PyCFunction_GET_FLAGS(func);
551
3.93k
    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.93k
    PyCFunction meth = PyCFunction_GET_FUNCTION(func);
559
3.93k
    PyObject *self = PyCFunction_GET_SELF(func);
560
561
3.93k
    PyObject *result;
562
3.93k
    if (flags & METH_KEYWORDS) {
563
3.90k
        result = _PyCFunctionWithKeywords_TrampolineCall(
564
3.90k
            *_PyCFunctionWithKeywords_CAST(meth),
565
3.90k
            self, args, kwargs);
566
3.90k
    }
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.93k
    return _Py_CheckFunctionResult(tstate, func, result, NULL);
577
3.93k
}