ยปCore Development>Code coverage>Objects/methodobject.c

Python code coverage for Objects/methodobject.c

#countcontent
1n/a
2n/a/* Method object implementation */
3n/a
4n/a#include "Python.h"
5n/a#include "structmember.h"
6n/a
7n/a/* Free list for method objects to safe malloc/free overhead
8n/a * The m_self element is used to chain the objects.
9n/a */
10n/astatic PyCFunctionObject *free_list = NULL;
11n/astatic int numfree = 0;
12n/a#ifndef PyCFunction_MAXFREELIST
13n/a#define PyCFunction_MAXFREELIST 256
14n/a#endif
15n/a
16n/a/* undefine macro trampoline to PyCFunction_NewEx */
17n/a#undef PyCFunction_New
18n/a
19n/aPyAPI_FUNC(PyObject *)
20n/aPyCFunction_New(PyMethodDef *ml, PyObject *self)
21n/a{
22n/a return PyCFunction_NewEx(ml, self, NULL);
23n/a}
24n/a
25n/aPyObject *
26n/aPyCFunction_NewEx(PyMethodDef *ml, PyObject *self, PyObject *module)
27n/a{
28n/a PyCFunctionObject *op;
29n/a op = free_list;
30n/a if (op != NULL) {
31n/a free_list = (PyCFunctionObject *)(op->m_self);
32n/a (void)PyObject_INIT(op, &PyCFunction_Type);
33n/a numfree--;
34n/a }
35n/a else {
36n/a op = PyObject_GC_New(PyCFunctionObject, &PyCFunction_Type);
37n/a if (op == NULL)
38n/a return NULL;
39n/a }
40n/a op->m_weakreflist = NULL;
41n/a op->m_ml = ml;
42n/a Py_XINCREF(self);
43n/a op->m_self = self;
44n/a Py_XINCREF(module);
45n/a op->m_module = module;
46n/a _PyObject_GC_TRACK(op);
47n/a return (PyObject *)op;
48n/a}
49n/a
50n/aPyCFunction
51n/aPyCFunction_GetFunction(PyObject *op)
52n/a{
53n/a if (!PyCFunction_Check(op)) {
54n/a PyErr_BadInternalCall();
55n/a return NULL;
56n/a }
57n/a return PyCFunction_GET_FUNCTION(op);
58n/a}
59n/a
60n/aPyObject *
61n/aPyCFunction_GetSelf(PyObject *op)
62n/a{
63n/a if (!PyCFunction_Check(op)) {
64n/a PyErr_BadInternalCall();
65n/a return NULL;
66n/a }
67n/a return PyCFunction_GET_SELF(op);
68n/a}
69n/a
70n/aint
71n/aPyCFunction_GetFlags(PyObject *op)
72n/a{
73n/a if (!PyCFunction_Check(op)) {
74n/a PyErr_BadInternalCall();
75n/a return -1;
76n/a }
77n/a return PyCFunction_GET_FLAGS(op);
78n/a}
79n/a
80n/astatic PyObject *
81n/acfunction_call_varargs(PyObject *func, PyObject *args, PyObject *kwargs)
82n/a{
83n/a assert(!PyErr_Occurred());
84n/a
85n/a PyCFunction meth = PyCFunction_GET_FUNCTION(func);
86n/a PyObject *self = PyCFunction_GET_SELF(func);
87n/a PyObject *result;
88n/a
89n/a if (PyCFunction_GET_FLAGS(func) & METH_KEYWORDS) {
90n/a if (Py_EnterRecursiveCall(" while calling a Python object")) {
91n/a return NULL;
92n/a }
93n/a
94n/a result = (*(PyCFunctionWithKeywords)meth)(self, args, kwargs);
95n/a
96n/a Py_LeaveRecursiveCall();
97n/a }
98n/a else {
99n/a if (kwargs != NULL && PyDict_Size(kwargs) != 0) {
100n/a PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments",
101n/a ((PyCFunctionObject*)func)->m_ml->ml_name);
102n/a return NULL;
103n/a }
104n/a
105n/a if (Py_EnterRecursiveCall(" while calling a Python object")) {
106n/a return NULL;
107n/a }
108n/a
109n/a result = (*meth)(self, args);
110n/a
111n/a Py_LeaveRecursiveCall();
112n/a }
113n/a
114n/a return _Py_CheckFunctionResult(func, result, NULL);
115n/a}
116n/a
117n/a
118n/aPyObject *
119n/aPyCFunction_Call(PyObject *func, PyObject *args, PyObject *kwargs)
120n/a{
121n/a /* first try METH_VARARGS to pass directly args tuple unchanged.
122n/a _PyMethodDef_RawFastCallDict() creates a new temporary tuple
123n/a for METH_VARARGS. */
124n/a if (PyCFunction_GET_FLAGS(func) & METH_VARARGS) {
125n/a return cfunction_call_varargs(func, args, kwargs);
126n/a }
127n/a else {
128n/a return _PyCFunction_FastCallDict(func,
129n/a &PyTuple_GET_ITEM(args, 0),
130n/a PyTuple_GET_SIZE(args),
131n/a kwargs);
132n/a }
133n/a}
134n/a
135n/aPyObject *
136n/a_PyMethodDef_RawFastCallDict(PyMethodDef *method, PyObject *self, PyObject **args,
137n/a Py_ssize_t nargs, PyObject *kwargs)
138n/a{
139n/a /* _PyMethodDef_RawFastCallDict() must not be called with an exception set,
140n/a because it can clear it (directly or indirectly) and so the
141n/a caller loses its exception */
142n/a assert(!PyErr_Occurred());
143n/a
144n/a assert(method != NULL);
145n/a assert(nargs >= 0);
146n/a assert(nargs == 0 || args != NULL);
147n/a assert(kwargs == NULL || PyDict_Check(kwargs));
148n/a
149n/a PyCFunction meth = method->ml_meth;
150n/a int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
151n/a PyObject *result = NULL;
152n/a
153n/a if (Py_EnterRecursiveCall(" while calling a Python object")) {
154n/a return NULL;
155n/a }
156n/a
157n/a switch (flags)
158n/a {
159n/a case METH_NOARGS:
160n/a if (nargs != 0) {
161n/a PyErr_Format(PyExc_TypeError,
162n/a "%.200s() takes no arguments (%zd given)",
163n/a method->ml_name, nargs);
164n/a goto exit;
165n/a }
166n/a
167n/a if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
168n/a goto no_keyword_error;
169n/a }
170n/a
171n/a result = (*meth) (self, NULL);
172n/a break;
173n/a
174n/a case METH_O:
175n/a if (nargs != 1) {
176n/a PyErr_Format(PyExc_TypeError,
177n/a "%.200s() takes exactly one argument (%zd given)",
178n/a method->ml_name, nargs);
179n/a goto exit;
180n/a }
181n/a
182n/a if (kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
183n/a goto no_keyword_error;
184n/a }
185n/a
186n/a result = (*meth) (self, args[0]);
187n/a break;
188n/a
189n/a case METH_VARARGS:
190n/a if (!(flags & METH_KEYWORDS)
191n/a && kwargs != NULL && PyDict_GET_SIZE(kwargs) != 0) {
192n/a goto no_keyword_error;
193n/a }
194n/a /* fall through next case */
195n/a
196n/a case METH_VARARGS | METH_KEYWORDS:
197n/a {
198n/a /* Slow-path: create a temporary tuple for positional arguments */
199n/a PyObject *argstuple = _PyStack_AsTuple(args, nargs);
200n/a if (argstuple == NULL) {
201n/a goto exit;
202n/a }
203n/a
204n/a if (flags & METH_KEYWORDS) {
205n/a result = (*(PyCFunctionWithKeywords)meth) (self, argstuple, kwargs);
206n/a }
207n/a else {
208n/a result = (*meth) (self, argstuple);
209n/a }
210n/a Py_DECREF(argstuple);
211n/a break;
212n/a }
213n/a
214n/a case METH_FASTCALL:
215n/a {
216n/a PyObject **stack;
217n/a PyObject *kwnames;
218n/a _PyCFunctionFast fastmeth = (_PyCFunctionFast)meth;
219n/a
220n/a if (_PyStack_UnpackDict(args, nargs, kwargs, &stack, &kwnames) < 0) {
221n/a goto exit;
222n/a }
223n/a
224n/a result = (*fastmeth) (self, stack, nargs, kwnames);
225n/a if (stack != args) {
226n/a PyMem_Free(stack);
227n/a }
228n/a Py_XDECREF(kwnames);
229n/a break;
230n/a }
231n/a
232n/a default:
233n/a PyErr_SetString(PyExc_SystemError,
234n/a "Bad call flags in _PyMethodDef_RawFastCallDict. "
235n/a "METH_OLDARGS is no longer supported!");
236n/a goto exit;
237n/a }
238n/a
239n/a goto exit;
240n/a
241n/ano_keyword_error:
242n/a PyErr_Format(PyExc_TypeError,
243n/a "%.200s() takes no keyword arguments",
244n/a method->ml_name, nargs);
245n/a
246n/aexit:
247n/a Py_LeaveRecursiveCall();
248n/a return result;
249n/a}
250n/a
251n/aPyObject *
252n/a_PyCFunction_FastCallDict(PyObject *func, PyObject **args, Py_ssize_t nargs,
253n/a PyObject *kwargs)
254n/a{
255n/a PyObject *result;
256n/a
257n/a assert(func != NULL);
258n/a assert(PyCFunction_Check(func));
259n/a
260n/a result = _PyMethodDef_RawFastCallDict(((PyCFunctionObject*)func)->m_ml,
261n/a PyCFunction_GET_SELF(func),
262n/a args, nargs, kwargs);
263n/a result = _Py_CheckFunctionResult(func, result, NULL);
264n/a return result;
265n/a}
266n/a
267n/aPyObject *
268n/a_PyMethodDef_RawFastCallKeywords(PyMethodDef *method, PyObject *self, PyObject **args,
269n/a Py_ssize_t nargs, PyObject *kwnames)
270n/a{
271n/a /* _PyMethodDef_RawFastCallKeywords() must not be called with an exception set,
272n/a because it can clear it (directly or indirectly) and so the
273n/a caller loses its exception */
274n/a assert(!PyErr_Occurred());
275n/a
276n/a assert(method != NULL);
277n/a assert(nargs >= 0);
278n/a assert(kwnames == NULL || PyTuple_CheckExact(kwnames));
279n/a /* kwnames must only contains str strings, no subclass, and all keys must
280n/a be unique */
281n/a
282n/a PyCFunction meth = method->ml_meth;
283n/a int flags = method->ml_flags & ~(METH_CLASS | METH_STATIC | METH_COEXIST);
284n/a Py_ssize_t nkwargs = kwnames == NULL ? 0 : PyTuple_Size(kwnames);
285n/a PyObject *result = NULL;
286n/a
287n/a if (Py_EnterRecursiveCall(" while calling a Python object")) {
288n/a return NULL;
289n/a }
290n/a
291n/a switch (flags)
292n/a {
293n/a case METH_NOARGS:
294n/a if (nargs != 0) {
295n/a PyErr_Format(PyExc_TypeError,
296n/a "%.200s() takes no arguments (%zd given)",
297n/a method->ml_name, nargs);
298n/a goto exit;
299n/a }
300n/a
301n/a if (nkwargs) {
302n/a goto no_keyword_error;
303n/a }
304n/a
305n/a result = (*meth) (self, NULL);
306n/a break;
307n/a
308n/a case METH_O:
309n/a if (nargs != 1) {
310n/a PyErr_Format(PyExc_TypeError,
311n/a "%.200s() takes exactly one argument (%zd given)",
312n/a method->ml_name, nargs);
313n/a goto exit;
314n/a }
315n/a
316n/a if (nkwargs) {
317n/a goto no_keyword_error;
318n/a }
319n/a
320n/a result = (*meth) (self, args[0]);
321n/a break;
322n/a
323n/a case METH_FASTCALL:
324n/a /* Fast-path: avoid temporary dict to pass keyword arguments */
325n/a result = ((_PyCFunctionFast)meth) (self, args, nargs, kwnames);
326n/a break;
327n/a
328n/a case METH_VARARGS:
329n/a case METH_VARARGS | METH_KEYWORDS:
330n/a {
331n/a /* Slow-path: create a temporary tuple for positional arguments
332n/a and a temporary dict for keyword arguments */
333n/a PyObject *argtuple;
334n/a
335n/a if (!(flags & METH_KEYWORDS) && nkwargs) {
336n/a goto no_keyword_error;
337n/a }
338n/a
339n/a argtuple = _PyStack_AsTuple(args, nargs);
340n/a if (argtuple == NULL) {
341n/a goto exit;
342n/a }
343n/a
344n/a if (flags & METH_KEYWORDS) {
345n/a PyObject *kwdict;
346n/a
347n/a if (nkwargs > 0) {
348n/a kwdict = _PyStack_AsDict(args + nargs, kwnames);
349n/a if (kwdict == NULL) {
350n/a Py_DECREF(argtuple);
351n/a goto exit;
352n/a }
353n/a }
354n/a else {
355n/a kwdict = NULL;
356n/a }
357n/a
358n/a result = (*(PyCFunctionWithKeywords)meth) (self, argtuple, kwdict);
359n/a Py_XDECREF(kwdict);
360n/a }
361n/a else {
362n/a result = (*meth) (self, argtuple);
363n/a }
364n/a Py_DECREF(argtuple);
365n/a break;
366n/a }
367n/a
368n/a default:
369n/a PyErr_SetString(PyExc_SystemError,
370n/a "Bad call flags in _PyCFunction_FastCallKeywords. "
371n/a "METH_OLDARGS is no longer supported!");
372n/a goto exit;
373n/a }
374n/a
375n/a goto exit;
376n/a
377n/ano_keyword_error:
378n/a PyErr_Format(PyExc_TypeError,
379n/a "%.200s() takes no keyword arguments",
380n/a method->ml_name);
381n/a
382n/aexit:
383n/a Py_LeaveRecursiveCall();
384n/a return result;
385n/a}
386n/a
387n/aPyObject *
388n/a_PyCFunction_FastCallKeywords(PyObject *func, PyObject **args,
389n/a Py_ssize_t nargs, PyObject *kwnames)
390n/a{
391n/a PyObject *result;
392n/a
393n/a assert(func != NULL);
394n/a assert(PyCFunction_Check(func));
395n/a
396n/a result = _PyMethodDef_RawFastCallKeywords(((PyCFunctionObject*)func)->m_ml,
397n/a PyCFunction_GET_SELF(func),
398n/a args, nargs, kwnames);
399n/a result = _Py_CheckFunctionResult(func, result, NULL);
400n/a return result;
401n/a}
402n/a
403n/a/* Methods (the standard built-in methods, that is) */
404n/a
405n/astatic void
406n/ameth_dealloc(PyCFunctionObject *m)
407n/a{
408n/a _PyObject_GC_UNTRACK(m);
409n/a if (m->m_weakreflist != NULL) {
410n/a PyObject_ClearWeakRefs((PyObject*) m);
411n/a }
412n/a Py_XDECREF(m->m_self);
413n/a Py_XDECREF(m->m_module);
414n/a if (numfree < PyCFunction_MAXFREELIST) {
415n/a m->m_self = (PyObject *)free_list;
416n/a free_list = m;
417n/a numfree++;
418n/a }
419n/a else {
420n/a PyObject_GC_Del(m);
421n/a }
422n/a}
423n/a
424n/astatic PyObject *
425n/ameth_reduce(PyCFunctionObject *m)
426n/a{
427n/a PyObject *builtins;
428n/a PyObject *getattr;
429n/a _Py_IDENTIFIER(getattr);
430n/a
431n/a if (m->m_self == NULL || PyModule_Check(m->m_self))
432n/a return PyUnicode_FromString(m->m_ml->ml_name);
433n/a
434n/a builtins = PyEval_GetBuiltins();
435n/a getattr = _PyDict_GetItemId(builtins, &PyId_getattr);
436n/a return Py_BuildValue("O(Os)", getattr, m->m_self, m->m_ml->ml_name);
437n/a}
438n/a
439n/astatic PyMethodDef meth_methods[] = {
440n/a {"__reduce__", (PyCFunction)meth_reduce, METH_NOARGS, NULL},
441n/a {NULL, NULL}
442n/a};
443n/a
444n/astatic PyObject *
445n/ameth_get__text_signature__(PyCFunctionObject *m, void *closure)
446n/a{
447n/a return _PyType_GetTextSignatureFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
448n/a}
449n/a
450n/astatic PyObject *
451n/ameth_get__doc__(PyCFunctionObject *m, void *closure)
452n/a{
453n/a return _PyType_GetDocFromInternalDoc(m->m_ml->ml_name, m->m_ml->ml_doc);
454n/a}
455n/a
456n/astatic PyObject *
457n/ameth_get__name__(PyCFunctionObject *m, void *closure)
458n/a{
459n/a return PyUnicode_FromString(m->m_ml->ml_name);
460n/a}
461n/a
462n/astatic PyObject *
463n/ameth_get__qualname__(PyCFunctionObject *m, void *closure)
464n/a{
465n/a /* If __self__ is a module or NULL, return m.__name__
466n/a (e.g. len.__qualname__ == 'len')
467n/a
468n/a If __self__ is a type, return m.__self__.__qualname__ + '.' + m.__name__
469n/a (e.g. dict.fromkeys.__qualname__ == 'dict.fromkeys')
470n/a
471n/a Otherwise return type(m.__self__).__qualname__ + '.' + m.__name__
472n/a (e.g. [].append.__qualname__ == 'list.append') */
473n/a PyObject *type, *type_qualname, *res;
474n/a _Py_IDENTIFIER(__qualname__);
475n/a
476n/a if (m->m_self == NULL || PyModule_Check(m->m_self))
477n/a return PyUnicode_FromString(m->m_ml->ml_name);
478n/a
479n/a type = PyType_Check(m->m_self) ? m->m_self : (PyObject*)Py_TYPE(m->m_self);
480n/a
481n/a type_qualname = _PyObject_GetAttrId(type, &PyId___qualname__);
482n/a if (type_qualname == NULL)
483n/a return NULL;
484n/a
485n/a if (!PyUnicode_Check(type_qualname)) {
486n/a PyErr_SetString(PyExc_TypeError, "<method>.__class__."
487n/a "__qualname__ is not a unicode object");
488n/a Py_XDECREF(type_qualname);
489n/a return NULL;
490n/a }
491n/a
492n/a res = PyUnicode_FromFormat("%S.%s", type_qualname, m->m_ml->ml_name);
493n/a Py_DECREF(type_qualname);
494n/a return res;
495n/a}
496n/a
497n/astatic int
498n/ameth_traverse(PyCFunctionObject *m, visitproc visit, void *arg)
499n/a{
500n/a Py_VISIT(m->m_self);
501n/a Py_VISIT(m->m_module);
502n/a return 0;
503n/a}
504n/a
505n/astatic PyObject *
506n/ameth_get__self__(PyCFunctionObject *m, void *closure)
507n/a{
508n/a PyObject *self;
509n/a
510n/a self = PyCFunction_GET_SELF(m);
511n/a if (self == NULL)
512n/a self = Py_None;
513n/a Py_INCREF(self);
514n/a return self;
515n/a}
516n/a
517n/astatic PyGetSetDef meth_getsets [] = {
518n/a {"__doc__", (getter)meth_get__doc__, NULL, NULL},
519n/a {"__name__", (getter)meth_get__name__, NULL, NULL},
520n/a {"__qualname__", (getter)meth_get__qualname__, NULL, NULL},
521n/a {"__self__", (getter)meth_get__self__, NULL, NULL},
522n/a {"__text_signature__", (getter)meth_get__text_signature__, NULL, NULL},
523n/a {0}
524n/a};
525n/a
526n/a#define OFF(x) offsetof(PyCFunctionObject, x)
527n/a
528n/astatic PyMemberDef meth_members[] = {
529n/a {"__module__", T_OBJECT, OFF(m_module), PY_WRITE_RESTRICTED},
530n/a {NULL}
531n/a};
532n/a
533n/astatic PyObject *
534n/ameth_repr(PyCFunctionObject *m)
535n/a{
536n/a if (m->m_self == NULL || PyModule_Check(m->m_self))
537n/a return PyUnicode_FromFormat("<built-in function %s>",
538n/a m->m_ml->ml_name);
539n/a return PyUnicode_FromFormat("<built-in method %s of %s object at %p>",
540n/a m->m_ml->ml_name,
541n/a m->m_self->ob_type->tp_name,
542n/a m->m_self);
543n/a}
544n/a
545n/astatic PyObject *
546n/ameth_richcompare(PyObject *self, PyObject *other, int op)
547n/a{
548n/a PyCFunctionObject *a, *b;
549n/a PyObject *res;
550n/a int eq;
551n/a
552n/a if ((op != Py_EQ && op != Py_NE) ||
553n/a !PyCFunction_Check(self) ||
554n/a !PyCFunction_Check(other))
555n/a {
556n/a Py_RETURN_NOTIMPLEMENTED;
557n/a }
558n/a a = (PyCFunctionObject *)self;
559n/a b = (PyCFunctionObject *)other;
560n/a eq = a->m_self == b->m_self;
561n/a if (eq)
562n/a eq = a->m_ml->ml_meth == b->m_ml->ml_meth;
563n/a if (op == Py_EQ)
564n/a res = eq ? Py_True : Py_False;
565n/a else
566n/a res = eq ? Py_False : Py_True;
567n/a Py_INCREF(res);
568n/a return res;
569n/a}
570n/a
571n/astatic Py_hash_t
572n/ameth_hash(PyCFunctionObject *a)
573n/a{
574n/a Py_hash_t x, y;
575n/a if (a->m_self == NULL)
576n/a x = 0;
577n/a else {
578n/a x = PyObject_Hash(a->m_self);
579n/a if (x == -1)
580n/a return -1;
581n/a }
582n/a y = _Py_HashPointer((void*)(a->m_ml->ml_meth));
583n/a if (y == -1)
584n/a return -1;
585n/a x ^= y;
586n/a if (x == -1)
587n/a x = -2;
588n/a return x;
589n/a}
590n/a
591n/a
592n/aPyTypeObject PyCFunction_Type = {
593n/a PyVarObject_HEAD_INIT(&PyType_Type, 0)
594n/a "builtin_function_or_method",
595n/a sizeof(PyCFunctionObject),
596n/a 0,
597n/a (destructor)meth_dealloc, /* tp_dealloc */
598n/a 0, /* tp_print */
599n/a 0, /* tp_getattr */
600n/a 0, /* tp_setattr */
601n/a 0, /* tp_reserved */
602n/a (reprfunc)meth_repr, /* tp_repr */
603n/a 0, /* tp_as_number */
604n/a 0, /* tp_as_sequence */
605n/a 0, /* tp_as_mapping */
606n/a (hashfunc)meth_hash, /* tp_hash */
607n/a PyCFunction_Call, /* tp_call */
608n/a 0, /* tp_str */
609n/a PyObject_GenericGetAttr, /* tp_getattro */
610n/a 0, /* tp_setattro */
611n/a 0, /* tp_as_buffer */
612n/a Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
613n/a 0, /* tp_doc */
614n/a (traverseproc)meth_traverse, /* tp_traverse */
615n/a 0, /* tp_clear */
616n/a meth_richcompare, /* tp_richcompare */
617n/a offsetof(PyCFunctionObject, m_weakreflist), /* tp_weaklistoffset */
618n/a 0, /* tp_iter */
619n/a 0, /* tp_iternext */
620n/a meth_methods, /* tp_methods */
621n/a meth_members, /* tp_members */
622n/a meth_getsets, /* tp_getset */
623n/a 0, /* tp_base */
624n/a 0, /* tp_dict */
625n/a};
626n/a
627n/a/* Clear out the free list */
628n/a
629n/aint
630n/aPyCFunction_ClearFreeList(void)
631n/a{
632n/a int freelist_size = numfree;
633n/a
634n/a while (free_list) {
635n/a PyCFunctionObject *v = free_list;
636n/a free_list = (PyCFunctionObject *)(v->m_self);
637n/a PyObject_GC_Del(v);
638n/a numfree--;
639n/a }
640n/a assert(numfree == 0);
641n/a return freelist_size;
642n/a}
643n/a
644n/avoid
645n/aPyCFunction_Fini(void)
646n/a{
647n/a (void)PyCFunction_ClearFreeList();
648n/a}
649n/a
650n/a/* Print summary info about the state of the optimized allocator */
651n/avoid
652n/a_PyCFunction_DebugMallocStats(FILE *out)
653n/a{
654n/a _PyDebugAllocatorStats(out,
655n/a "free PyCFunctionObject",
656n/a numfree, sizeof(PyCFunctionObject));
657n/a}