Coverage Report

Created: 2025-07-04 06:49

/src/cpython/Objects/tupleobject.c
Line
Count
Source (jump to first uncovered line)
1
/* Tuple object implementation */
2
3
#include "Python.h"
4
#include "pycore_abstract.h"      // _PyIndex_Check()
5
#include "pycore_ceval.h"         // _PyEval_GetBuiltin()
6
#include "pycore_freelist.h"      // _Py_FREELIST_PUSH()
7
#include "pycore_gc.h"            // _PyObject_GC_IS_TRACKED()
8
#include "pycore_list.h"          // _Py_memory_repeat()
9
#include "pycore_modsupport.h"    // _PyArg_NoKwnames()
10
#include "pycore_object.h"        // _PyObject_GC_TRACK()
11
#include "pycore_stackref.h"      // PyStackRef_AsPyObjectSteal()
12
#include "pycore_tuple.h"         // _PyTupleIterObject
13
14
15
/*[clinic input]
16
class tuple "PyTupleObject *" "&PyTuple_Type"
17
[clinic start generated code]*/
18
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f051ba3cfdf9a189]*/
19
20
#include "clinic/tupleobject.c.h"
21
22
23
static inline int maybe_freelist_push(PyTupleObject *);
24
25
26
/* Allocate an uninitialized tuple object. Before making it public, following
27
   steps must be done:
28
29
   - Initialize its items.
30
   - Call _PyObject_GC_TRACK() on it.
31
32
   Because the empty tuple is always reused and it's already tracked by GC,
33
   this function must not be called with size == 0 (unless from PyTuple_New()
34
   which wraps this function).
35
*/
36
static PyTupleObject *
37
tuple_alloc(Py_ssize_t size)
38
423M
{
39
423M
    if (size < 0) {
40
0
        PyErr_BadInternalCall();
41
0
        return NULL;
42
0
    }
43
423M
    assert(size != 0);    // The empty tuple is statically allocated.
44
423M
    Py_ssize_t index = size - 1;
45
423M
    if (index < PyTuple_MAXSAVESIZE) {
46
423M
        PyTupleObject *op = _Py_FREELIST_POP(PyTupleObject, tuples[index]);
47
423M
        if (op != NULL) {
48
348M
            _PyTuple_RESET_HASH_CACHE(op);
49
348M
            return op;
50
348M
        }
51
423M
    }
52
    /* Check for overflow */
53
74.8M
    if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) -
54
74.8M
                sizeof(PyObject *))) / sizeof(PyObject *)) {
55
0
        return (PyTupleObject *)PyErr_NoMemory();
56
0
    }
57
74.8M
    PyTupleObject *result = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
58
74.8M
    if (result != NULL) {
59
74.8M
        _PyTuple_RESET_HASH_CACHE(result);
60
74.8M
    }
61
74.8M
    return result;
62
74.8M
}
63
64
// The empty tuple singleton is not tracked by the GC.
65
// It does not contain any Python object.
66
// Note that tuple subclasses have their own empty instances.
67
68
static inline PyObject *
69
tuple_get_empty(void)
70
69.7M
{
71
69.7M
    return (PyObject *)&_Py_SINGLETON(tuple_empty);
72
69.7M
}
73
74
PyObject *
75
PyTuple_New(Py_ssize_t size)
76
78.2M
{
77
78.2M
    PyTupleObject *op;
78
78.2M
    if (size == 0) {
79
12.9k
        return tuple_get_empty();
80
12.9k
    }
81
78.2M
    op = tuple_alloc(size);
82
78.2M
    if (op == NULL) {
83
0
        return NULL;
84
0
    }
85
290M
    for (Py_ssize_t i = 0; i < size; i++) {
86
212M
        op->ob_item[i] = NULL;
87
212M
    }
88
78.2M
    _PyObject_GC_TRACK(op);
89
78.2M
    return (PyObject *) op;
90
78.2M
}
91
92
Py_ssize_t
93
PyTuple_Size(PyObject *op)
94
7.55M
{
95
7.55M
    if (!PyTuple_Check(op)) {
96
0
        PyErr_BadInternalCall();
97
0
        return -1;
98
0
    }
99
7.55M
    else
100
7.55M
        return Py_SIZE(op);
101
7.55M
}
102
103
PyObject *
104
PyTuple_GetItem(PyObject *op, Py_ssize_t i)
105
36.6M
{
106
36.6M
    if (!PyTuple_Check(op)) {
107
0
        PyErr_BadInternalCall();
108
0
        return NULL;
109
0
    }
110
36.6M
    if (i < 0 || i >= Py_SIZE(op)) {
111
0
        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
112
0
        return NULL;
113
0
    }
114
36.6M
    return ((PyTupleObject *)op) -> ob_item[i];
115
36.6M
}
116
117
int
118
PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
119
73.9k
{
120
73.9k
    PyObject **p;
121
73.9k
    if (!PyTuple_Check(op) || Py_REFCNT(op) != 1) {
122
0
        Py_XDECREF(newitem);
123
0
        PyErr_BadInternalCall();
124
0
        return -1;
125
0
    }
126
73.9k
    if (i < 0 || i >= Py_SIZE(op)) {
127
0
        Py_XDECREF(newitem);
128
0
        PyErr_SetString(PyExc_IndexError,
129
0
                        "tuple assignment index out of range");
130
0
        return -1;
131
0
    }
132
73.9k
    p = ((PyTupleObject *)op) -> ob_item + i;
133
73.9k
    Py_XSETREF(*p, newitem);
134
73.9k
    return 0;
135
73.9k
}
136
137
void
138
_PyTuple_MaybeUntrack(PyObject *op)
139
81.5M
{
140
81.5M
    PyTupleObject *t;
141
81.5M
    Py_ssize_t i, n;
142
143
81.5M
    if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
144
0
        return;
145
81.5M
    t = (PyTupleObject *) op;
146
81.5M
    n = Py_SIZE(t);
147
240M
    for (i = 0; i < n; i++) {
148
161M
        PyObject *elt = PyTuple_GET_ITEM(t, i);
149
        /* Tuple with NULL elements aren't
150
           fully constructed, don't untrack
151
           them yet. */
152
161M
        if (!elt ||
153
161M
            _PyObject_GC_MAY_BE_TRACKED(elt))
154
2.09M
            return;
155
161M
    }
156
79.4M
    _PyObject_GC_UNTRACK(op);
157
79.4M
}
158
159
PyObject *
160
PyTuple_Pack(Py_ssize_t n, ...)
161
7.54M
{
162
7.54M
    Py_ssize_t i;
163
7.54M
    PyObject *o;
164
7.54M
    PyObject **items;
165
7.54M
    va_list vargs;
166
167
7.54M
    if (n == 0) {
168
0
        return tuple_get_empty();
169
0
    }
170
171
7.54M
    va_start(vargs, n);
172
7.54M
    PyTupleObject *result = tuple_alloc(n);
173
7.54M
    if (result == NULL) {
174
0
        va_end(vargs);
175
0
        return NULL;
176
0
    }
177
7.54M
    items = result->ob_item;
178
22.6M
    for (i = 0; i < n; i++) {
179
15.1M
        o = va_arg(vargs, PyObject *);
180
15.1M
        items[i] = Py_NewRef(o);
181
15.1M
    }
182
7.54M
    va_end(vargs);
183
7.54M
    _PyObject_GC_TRACK(result);
184
7.54M
    return (PyObject *)result;
185
7.54M
}
186
187
188
/* Methods */
189
190
static void
191
tuple_dealloc(PyObject *self)
192
425M
{
193
425M
    PyTupleObject *op = _PyTuple_CAST(self);
194
425M
    if (Py_SIZE(op) == 0) {
195
        /* The empty tuple is statically allocated. */
196
0
        if (op == &_Py_SINGLETON(tuple_empty)) {
197
#ifdef Py_DEBUG
198
            _Py_FatalRefcountError("deallocating the empty tuple singleton");
199
#else
200
0
            return;
201
0
#endif
202
0
        }
203
#ifdef Py_DEBUG
204
        /* tuple subclasses have their own empty instances. */
205
        assert(!PyTuple_CheckExact(op));
206
#endif
207
0
    }
208
209
425M
    PyObject_GC_UnTrack(op);
210
211
425M
    Py_ssize_t i = Py_SIZE(op);
212
1.40G
    while (--i >= 0) {
213
978M
        Py_XDECREF(op->ob_item[i]);
214
978M
    }
215
    // This will abort on the empty singleton (if there is one).
216
425M
    if (!maybe_freelist_push(op)) {
217
76.7M
        Py_TYPE(op)->tp_free((PyObject *)op);
218
76.7M
    }
219
425M
}
220
221
static PyObject *
222
tuple_repr(PyObject *self)
223
0
{
224
0
    PyTupleObject *v = _PyTuple_CAST(self);
225
0
    Py_ssize_t n = PyTuple_GET_SIZE(v);
226
0
    if (n == 0) {
227
0
        return PyUnicode_FromString("()");
228
0
    }
229
230
    /* While not mutable, it is still possible to end up with a cycle in a
231
       tuple through an object that stores itself within a tuple (and thus
232
       infinitely asks for the repr of itself). This should only be
233
       possible within a type. */
234
0
    int res = Py_ReprEnter((PyObject *)v);
235
0
    if (res != 0) {
236
0
        return res > 0 ? PyUnicode_FromString("(...)") : NULL;
237
0
    }
238
239
0
    Py_ssize_t prealloc;
240
0
    if (n > 1) {
241
        // "(" + "1" + ", 2" * (len - 1) + ")"
242
0
        prealloc = 1 + 1 + (2 + 1) * (n - 1) + 1;
243
0
    }
244
0
    else {
245
        // "(1,)"
246
0
        prealloc = 4;
247
0
    }
248
0
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(prealloc);
249
0
    if (writer == NULL) {
250
0
        goto error;
251
0
    }
252
253
0
    if (PyUnicodeWriter_WriteChar(writer, '(') < 0) {
254
0
        goto error;
255
0
    }
256
257
    /* Do repr() on each element. */
258
0
    for (Py_ssize_t i = 0; i < n; ++i) {
259
0
        if (i > 0) {
260
0
            if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
261
0
                goto error;
262
0
            }
263
0
            if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) {
264
0
                goto error;
265
0
            }
266
0
        }
267
268
0
        if (PyUnicodeWriter_WriteRepr(writer, v->ob_item[i]) < 0) {
269
0
            goto error;
270
0
        }
271
0
    }
272
273
0
    if (n == 1) {
274
0
        if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
275
0
            goto error;
276
0
        }
277
0
    }
278
0
    if (PyUnicodeWriter_WriteChar(writer, ')') < 0) {
279
0
        goto error;
280
0
    }
281
282
0
    Py_ReprLeave((PyObject *)v);
283
0
    return PyUnicodeWriter_Finish(writer);
284
285
0
error:
286
0
    PyUnicodeWriter_Discard(writer);
287
0
    Py_ReprLeave((PyObject *)v);
288
0
    return NULL;
289
0
}
290
291
292
/* Hash for tuples. This is a slightly simplified version of the xxHash
293
   non-cryptographic hash:
294
   - we do not use any parallelism, there is only 1 accumulator.
295
   - we drop the final mixing since this is just a permutation of the
296
     output space: it does not help against collisions.
297
   - at the end, we mangle the length with a single constant.
298
   For the xxHash specification, see
299
   https://github.com/Cyan4973/xxHash/blob/master/doc/xxhash_spec.md
300
301
   The constants for the hash function are defined in pycore_tuple.h.
302
*/
303
304
static Py_hash_t
305
tuple_hash(PyObject *op)
306
667k
{
307
667k
    PyTupleObject *v = _PyTuple_CAST(op);
308
309
667k
    Py_uhash_t acc = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->ob_hash);
310
667k
    if (acc != (Py_uhash_t)-1) {
311
100k
        return acc;
312
100k
    }
313
314
566k
    Py_ssize_t len = Py_SIZE(v);
315
566k
    PyObject **item = v->ob_item;
316
566k
    acc = _PyTuple_HASH_XXPRIME_5;
317
2.28M
    for (Py_ssize_t i = 0; i < len; i++) {
318
1.72M
        Py_uhash_t lane = PyObject_Hash(item[i]);
319
1.72M
        if (lane == (Py_uhash_t)-1) {
320
0
            return -1;
321
0
        }
322
1.72M
        acc += lane * _PyTuple_HASH_XXPRIME_2;
323
1.72M
        acc = _PyTuple_HASH_XXROTATE(acc);
324
1.72M
        acc *= _PyTuple_HASH_XXPRIME_1;
325
1.72M
    }
326
327
    /* Add input length, mangled to keep the historical value of hash(()). */
328
566k
    acc += len ^ (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL);
329
330
566k
    if (acc == (Py_uhash_t)-1) {
331
0
        acc = 1546275796;
332
0
    }
333
334
566k
    FT_ATOMIC_STORE_SSIZE_RELAXED(v->ob_hash, acc);
335
336
566k
    return acc;
337
566k
}
338
339
static Py_ssize_t
340
tuple_length(PyObject *self)
341
819k
{
342
819k
    PyTupleObject *a = _PyTuple_CAST(self);
343
819k
    return Py_SIZE(a);
344
819k
}
345
346
static int
347
tuple_contains(PyObject *self, PyObject *el)
348
3.86M
{
349
3.86M
    PyTupleObject *a = _PyTuple_CAST(self);
350
3.86M
    int cmp = 0;
351
10.1M
    for (Py_ssize_t i = 0; cmp == 0 && i < Py_SIZE(a); ++i) {
352
6.31M
        cmp = PyObject_RichCompareBool(PyTuple_GET_ITEM(a, i), el, Py_EQ);
353
6.31M
    }
354
3.86M
    return cmp;
355
3.86M
}
356
357
static PyObject *
358
tuple_item(PyObject *op, Py_ssize_t i)
359
18.2M
{
360
18.2M
    PyTupleObject *a = _PyTuple_CAST(op);
361
18.2M
    if (i < 0 || i >= Py_SIZE(a)) {
362
16
        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
363
16
        return NULL;
364
16
    }
365
18.2M
    return Py_NewRef(a->ob_item[i]);
366
18.2M
}
367
368
PyObject *
369
_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
370
243M
{
371
243M
    if (n == 0) {
372
69.7M
        return tuple_get_empty();
373
69.7M
    }
374
375
173M
    PyTupleObject *tuple = tuple_alloc(n);
376
173M
    if (tuple == NULL) {
377
0
        return NULL;
378
0
    }
379
173M
    PyObject **dst = tuple->ob_item;
380
546M
    for (Py_ssize_t i = 0; i < n; i++) {
381
373M
        PyObject *item = src[i];
382
373M
        dst[i] = Py_NewRef(item);
383
373M
    }
384
173M
    _PyObject_GC_TRACK(tuple);
385
173M
    return (PyObject *)tuple;
386
173M
}
387
388
PyObject *
389
_PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
390
164M
{
391
164M
    if (n == 0) {
392
0
        return tuple_get_empty();
393
0
    }
394
164M
    PyTupleObject *tuple = tuple_alloc(n);
395
164M
    if (tuple == NULL) {
396
0
        return NULL;
397
0
    }
398
164M
    PyObject **dst = tuple->ob_item;
399
536M
    for (Py_ssize_t i = 0; i < n; i++) {
400
371M
        dst[i] = PyStackRef_AsPyObjectSteal(src[i]);
401
371M
    }
402
164M
    _PyObject_GC_TRACK(tuple);
403
164M
    return (PyObject *)tuple;
404
164M
}
405
406
PyObject *
407
_PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n)
408
195
{
409
195
    if (n == 0) {
410
0
        return tuple_get_empty();
411
0
    }
412
195
    PyTupleObject *tuple = tuple_alloc(n);
413
195
    if (tuple == NULL) {
414
0
        for (Py_ssize_t i = 0; i < n; i++) {
415
0
            Py_DECREF(src[i]);
416
0
        }
417
0
        return NULL;
418
0
    }
419
195
    PyObject **dst = tuple->ob_item;
420
939
    for (Py_ssize_t i = 0; i < n; i++) {
421
744
        PyObject *item = src[i];
422
744
        dst[i] = item;
423
744
    }
424
195
    _PyObject_GC_TRACK(tuple);
425
195
    return (PyObject *)tuple;
426
195
}
427
428
static PyObject *
429
tuple_slice(PyTupleObject *a, Py_ssize_t ilow,
430
           Py_ssize_t ihigh)
431
25.9M
{
432
25.9M
    if (ilow < 0)
433
0
        ilow = 0;
434
25.9M
    if (ihigh > Py_SIZE(a))
435
0
        ihigh = Py_SIZE(a);
436
25.9M
    if (ihigh < ilow)
437
0
        ihigh = ilow;
438
25.9M
    if (ilow == 0 && ihigh == Py_SIZE(a) && PyTuple_CheckExact(a)) {
439
0
        return Py_NewRef(a);
440
0
    }
441
25.9M
    return _PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow);
442
25.9M
}
443
444
PyObject *
445
PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)
446
25.9M
{
447
25.9M
    if (op == NULL || !PyTuple_Check(op)) {
448
0
        PyErr_BadInternalCall();
449
0
        return NULL;
450
0
    }
451
25.9M
    return tuple_slice((PyTupleObject *)op, i, j);
452
25.9M
}
453
454
static PyObject *
455
tuple_concat(PyObject *aa, PyObject *bb)
456
34
{
457
34
    PyTupleObject *a = _PyTuple_CAST(aa);
458
34
    if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) {
459
14
        return Py_NewRef(bb);
460
14
    }
461
20
    if (!PyTuple_Check(bb)) {
462
0
        PyErr_Format(PyExc_TypeError,
463
0
             "can only concatenate tuple (not \"%.200s\") to tuple",
464
0
                 Py_TYPE(bb)->tp_name);
465
0
        return NULL;
466
0
    }
467
20
    PyTupleObject *b = (PyTupleObject *)bb;
468
469
20
    if (Py_SIZE(b) == 0 && PyTuple_CheckExact(a)) {
470
0
        return Py_NewRef(a);
471
0
    }
472
20
    assert((size_t)Py_SIZE(a) + (size_t)Py_SIZE(b) < PY_SSIZE_T_MAX);
473
20
    Py_ssize_t size = Py_SIZE(a) + Py_SIZE(b);
474
20
    if (size == 0) {
475
0
        return tuple_get_empty();
476
0
    }
477
478
20
    PyTupleObject *np = tuple_alloc(size);
479
20
    if (np == NULL) {
480
0
        return NULL;
481
0
    }
482
483
20
    PyObject **src = a->ob_item;
484
20
    PyObject **dest = np->ob_item;
485
164
    for (Py_ssize_t i = 0; i < Py_SIZE(a); i++) {
486
144
        PyObject *v = src[i];
487
144
        dest[i] = Py_NewRef(v);
488
144
    }
489
490
20
    src = b->ob_item;
491
20
    dest = np->ob_item + Py_SIZE(a);
492
46
    for (Py_ssize_t i = 0; i < Py_SIZE(b); i++) {
493
26
        PyObject *v = src[i];
494
26
        dest[i] = Py_NewRef(v);
495
26
    }
496
497
20
    _PyObject_GC_TRACK(np);
498
20
    return (PyObject *)np;
499
20
}
500
501
static PyObject *
502
tuple_repeat(PyObject *self, Py_ssize_t n)
503
0
{
504
0
    PyTupleObject *a = _PyTuple_CAST(self);
505
0
    const Py_ssize_t input_size = Py_SIZE(a);
506
0
    if (input_size == 0 || n == 1) {
507
0
        if (PyTuple_CheckExact(a)) {
508
            /* Since tuples are immutable, we can return a shared
509
               copy in this case */
510
0
            return Py_NewRef(a);
511
0
        }
512
0
    }
513
0
    if (input_size == 0 || n <= 0) {
514
0
        return tuple_get_empty();
515
0
    }
516
0
    assert(n>0);
517
518
0
    if (input_size > PY_SSIZE_T_MAX / n)
519
0
        return PyErr_NoMemory();
520
0
    Py_ssize_t output_size = input_size * n;
521
522
0
    PyTupleObject *np = tuple_alloc(output_size);
523
0
    if (np == NULL)
524
0
        return NULL;
525
526
0
    PyObject **dest = np->ob_item;
527
0
    if (input_size == 1) {
528
0
        PyObject *elem = a->ob_item[0];
529
0
        _Py_RefcntAdd(elem, n);
530
0
        PyObject **dest_end = dest + output_size;
531
0
        while (dest < dest_end) {
532
0
            *dest++ = elem;
533
0
        }
534
0
    }
535
0
    else {
536
0
        PyObject **src = a->ob_item;
537
0
        PyObject **src_end = src + input_size;
538
0
        while (src < src_end) {
539
0
            _Py_RefcntAdd(*src, n);
540
0
            *dest++ = *src++;
541
0
        }
542
543
0
        _Py_memory_repeat((char *)np->ob_item, sizeof(PyObject *)*output_size,
544
0
                          sizeof(PyObject *)*input_size);
545
0
    }
546
0
    _PyObject_GC_TRACK(np);
547
0
    return (PyObject *) np;
548
0
}
549
550
/*[clinic input]
551
tuple.index
552
553
    value: object
554
    start: slice_index(accept={int}) = 0
555
    stop: slice_index(accept={int}, c_default="PY_SSIZE_T_MAX") = sys.maxsize
556
    /
557
558
Return first index of value.
559
560
Raises ValueError if the value is not present.
561
[clinic start generated code]*/
562
563
static PyObject *
564
tuple_index_impl(PyTupleObject *self, PyObject *value, Py_ssize_t start,
565
                 Py_ssize_t stop)
566
/*[clinic end generated code: output=07b6f9f3cb5c33eb input=fb39e9874a21fe3f]*/
567
0
{
568
0
    Py_ssize_t i;
569
570
0
    if (start < 0) {
571
0
        start += Py_SIZE(self);
572
0
        if (start < 0)
573
0
            start = 0;
574
0
    }
575
0
    if (stop < 0) {
576
0
        stop += Py_SIZE(self);
577
0
    }
578
0
    else if (stop > Py_SIZE(self)) {
579
0
        stop = Py_SIZE(self);
580
0
    }
581
0
    for (i = start; i < stop; i++) {
582
0
        int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ);
583
0
        if (cmp > 0)
584
0
            return PyLong_FromSsize_t(i);
585
0
        else if (cmp < 0)
586
0
            return NULL;
587
0
    }
588
0
    PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple");
589
0
    return NULL;
590
0
}
591
592
/*[clinic input]
593
tuple.count
594
595
     value: object
596
     /
597
598
Return number of occurrences of value.
599
[clinic start generated code]*/
600
601
static PyObject *
602
tuple_count_impl(PyTupleObject *self, PyObject *value)
603
/*[clinic end generated code: output=cf02888d4bc15d7a input=531721aff65bd772]*/
604
0
{
605
0
    Py_ssize_t count = 0;
606
0
    Py_ssize_t i;
607
608
0
    for (i = 0; i < Py_SIZE(self); i++) {
609
0
        int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ);
610
0
        if (cmp > 0)
611
0
            count++;
612
0
        else if (cmp < 0)
613
0
            return NULL;
614
0
    }
615
0
    return PyLong_FromSsize_t(count);
616
0
}
617
618
static int
619
tuple_traverse(PyObject *self, visitproc visit, void *arg)
620
9.96M
{
621
9.96M
    PyTupleObject *o = _PyTuple_CAST(self);
622
45.6M
    for (Py_ssize_t i = Py_SIZE(o); --i >= 0; ) {
623
35.6M
        Py_VISIT(o->ob_item[i]);
624
35.6M
    }
625
9.96M
    return 0;
626
9.96M
}
627
628
static PyObject *
629
tuple_richcompare(PyObject *v, PyObject *w, int op)
630
3.46M
{
631
3.46M
    PyTupleObject *vt, *wt;
632
3.46M
    Py_ssize_t i;
633
3.46M
    Py_ssize_t vlen, wlen;
634
635
3.46M
    if (!PyTuple_Check(v) || !PyTuple_Check(w))
636
0
        Py_RETURN_NOTIMPLEMENTED;
637
638
3.46M
    vt = (PyTupleObject *)v;
639
3.46M
    wt = (PyTupleObject *)w;
640
641
3.46M
    vlen = Py_SIZE(vt);
642
3.46M
    wlen = Py_SIZE(wt);
643
644
    /* Note:  the corresponding code for lists has an "early out" test
645
     * here when op is EQ or NE and the lengths differ.  That pays there,
646
     * but Tim was unable to find any real code where EQ/NE tuple
647
     * compares don't have the same length, so testing for it here would
648
     * have cost without benefit.
649
     */
650
651
    /* Search for the first index where items are different.
652
     * Note that because tuples are immutable, it's safe to reuse
653
     * vlen and wlen across the comparison calls.
654
     */
655
4.93M
    for (i = 0; i < vlen && i < wlen; i++) {
656
4.43M
        int k = PyObject_RichCompareBool(vt->ob_item[i],
657
4.43M
                                         wt->ob_item[i], Py_EQ);
658
4.43M
        if (k < 0)
659
0
            return NULL;
660
4.43M
        if (!k)
661
2.96M
            break;
662
4.43M
    }
663
664
3.46M
    if (i >= vlen || i >= wlen) {
665
        /* No more items to compare -- compare sizes */
666
498k
        Py_RETURN_RICHCOMPARE(vlen, wlen, op);
667
498k
    }
668
669
    /* We have an item that differs -- shortcuts for EQ/NE */
670
2.96M
    if (op == Py_EQ) {
671
232
        Py_RETURN_FALSE;
672
232
    }
673
2.96M
    if (op == Py_NE) {
674
63
        Py_RETURN_TRUE;
675
63
    }
676
677
    /* Compare the final item again using the proper operator */
678
2.96M
    return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
679
2.96M
}
680
681
static PyObject *
682
tuple_subtype_new(PyTypeObject *type, PyObject *iterable);
683
684
/*[clinic input]
685
@classmethod
686
tuple.__new__ as tuple_new
687
    iterable: object(c_default="NULL") = ()
688
    /
689
690
Built-in immutable sequence.
691
692
If no argument is given, the constructor returns an empty tuple.
693
If iterable is specified the tuple is initialized from iterable's items.
694
695
If the argument is a tuple, the return value is the same object.
696
[clinic start generated code]*/
697
698
static PyObject *
699
tuple_new_impl(PyTypeObject *type, PyObject *iterable)
700
/*[clinic end generated code: output=4546d9f0d469bce7 input=86963bcde633b5a2]*/
701
3.96M
{
702
3.96M
    if (type != &PyTuple_Type)
703
1.98M
        return tuple_subtype_new(type, iterable);
704
705
1.98M
    if (iterable == NULL) {
706
0
        return tuple_get_empty();
707
0
    }
708
1.98M
    else {
709
1.98M
        return PySequence_Tuple(iterable);
710
1.98M
    }
711
1.98M
}
712
713
static PyObject *
714
tuple_vectorcall(PyObject *type, PyObject * const*args,
715
                 size_t nargsf, PyObject *kwnames)
716
69
{
717
69
    if (!_PyArg_NoKwnames("tuple", kwnames)) {
718
0
        return NULL;
719
0
    }
720
721
69
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
722
69
    if (!_PyArg_CheckPositional("tuple", nargs, 0, 1)) {
723
0
        return NULL;
724
0
    }
725
726
69
    if (nargs) {
727
69
        return tuple_new_impl(_PyType_CAST(type), args[0]);
728
69
    }
729
0
    else {
730
0
        return tuple_get_empty();
731
0
    }
732
69
}
733
734
static PyObject *
735
tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
736
1.98M
{
737
1.98M
    PyObject *tmp, *newobj, *item;
738
1.98M
    Py_ssize_t i, n;
739
740
1.98M
    assert(PyType_IsSubtype(type, &PyTuple_Type));
741
    // tuple subclasses must implement the GC protocol
742
1.98M
    assert(_PyType_IS_GC(type));
743
744
1.98M
    tmp = tuple_new_impl(&PyTuple_Type, iterable);
745
1.98M
    if (tmp == NULL)
746
0
        return NULL;
747
1.98M
    assert(PyTuple_Check(tmp));
748
    /* This may allocate an empty tuple that is not the global one. */
749
1.98M
    newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
750
1.98M
    if (newobj == NULL) {
751
0
        Py_DECREF(tmp);
752
0
        return NULL;
753
0
    }
754
7.93M
    for (i = 0; i < n; i++) {
755
5.95M
        item = PyTuple_GET_ITEM(tmp, i);
756
5.95M
        PyTuple_SET_ITEM(newobj, i, Py_NewRef(item));
757
5.95M
    }
758
1.98M
    Py_DECREF(tmp);
759
760
1.98M
    _PyTuple_RESET_HASH_CACHE(newobj);
761
762
    // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
763
1.98M
    if (!_PyObject_GC_IS_TRACKED(newobj)) {
764
0
        _PyObject_GC_TRACK(newobj);
765
0
    }
766
1.98M
    return newobj;
767
1.98M
}
768
769
static PySequenceMethods tuple_as_sequence = {
770
    tuple_length,                               /* sq_length */
771
    tuple_concat,                               /* sq_concat */
772
    tuple_repeat,                               /* sq_repeat */
773
    tuple_item,                                 /* sq_item */
774
    0,                                          /* sq_slice */
775
    0,                                          /* sq_ass_item */
776
    0,                                          /* sq_ass_slice */
777
    tuple_contains,                             /* sq_contains */
778
};
779
780
static PyObject*
781
tuple_subscript(PyObject *op, PyObject* item)
782
1.73M
{
783
1.73M
    PyTupleObject *self = _PyTuple_CAST(op);
784
1.73M
    if (_PyIndex_Check(item)) {
785
1.73M
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
786
1.73M
        if (i == -1 && PyErr_Occurred())
787
0
            return NULL;
788
1.73M
        if (i < 0)
789
1.73M
            i += PyTuple_GET_SIZE(self);
790
1.73M
        return tuple_item(op, i);
791
1.73M
    }
792
160
    else if (PySlice_Check(item)) {
793
160
        Py_ssize_t start, stop, step, slicelength, i;
794
160
        size_t cur;
795
160
        PyObject* it;
796
160
        PyObject **src, **dest;
797
798
160
        if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
799
0
            return NULL;
800
0
        }
801
160
        slicelength = PySlice_AdjustIndices(PyTuple_GET_SIZE(self), &start,
802
160
                                            &stop, step);
803
804
160
        if (slicelength <= 0) {
805
0
            return tuple_get_empty();
806
0
        }
807
160
        else if (start == 0 && step == 1 &&
808
160
                 slicelength == PyTuple_GET_SIZE(self) &&
809
160
                 PyTuple_CheckExact(self)) {
810
0
            return Py_NewRef(self);
811
0
        }
812
160
        else {
813
160
            PyTupleObject* result = tuple_alloc(slicelength);
814
160
            if (!result) return NULL;
815
816
160
            src = self->ob_item;
817
160
            dest = result->ob_item;
818
1.03k
            for (cur = start, i = 0; i < slicelength;
819
879
                 cur += step, i++) {
820
879
                it = Py_NewRef(src[cur]);
821
879
                dest[i] = it;
822
879
            }
823
824
160
            _PyObject_GC_TRACK(result);
825
160
            return (PyObject *)result;
826
160
        }
827
160
    }
828
0
    else {
829
0
        PyErr_Format(PyExc_TypeError,
830
0
                     "tuple indices must be integers or slices, not %.200s",
831
0
                     Py_TYPE(item)->tp_name);
832
0
        return NULL;
833
0
    }
834
1.73M
}
835
836
/*[clinic input]
837
tuple.__getnewargs__
838
[clinic start generated code]*/
839
840
static PyObject *
841
tuple___getnewargs___impl(PyTupleObject *self)
842
/*[clinic end generated code: output=25e06e3ee56027e2 input=1aeb4b286a21639a]*/
843
0
{
844
0
    return Py_BuildValue("(N)", tuple_slice(self, 0, Py_SIZE(self)));
845
0
}
846
847
static PyMethodDef tuple_methods[] = {
848
    TUPLE___GETNEWARGS___METHODDEF
849
    TUPLE_INDEX_METHODDEF
850
    TUPLE_COUNT_METHODDEF
851
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, PyDoc_STR("See PEP 585")},
852
    {NULL,              NULL}           /* sentinel */
853
};
854
855
static PyMappingMethods tuple_as_mapping = {
856
    tuple_length,
857
    tuple_subscript,
858
    0
859
};
860
861
static PyObject *tuple_iter(PyObject *seq);
862
863
PyTypeObject PyTuple_Type = {
864
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
865
    "tuple",
866
    sizeof(PyTupleObject) - sizeof(PyObject *),
867
    sizeof(PyObject *),
868
    tuple_dealloc,                              /* tp_dealloc */
869
    0,                                          /* tp_vectorcall_offset */
870
    0,                                          /* tp_getattr */
871
    0,                                          /* tp_setattr */
872
    0,                                          /* tp_as_async */
873
    tuple_repr,                                 /* tp_repr */
874
    0,                                          /* tp_as_number */
875
    &tuple_as_sequence,                         /* tp_as_sequence */
876
    &tuple_as_mapping,                          /* tp_as_mapping */
877
    tuple_hash,                                 /* tp_hash */
878
    0,                                          /* tp_call */
879
    0,                                          /* tp_str */
880
    PyObject_GenericGetAttr,                    /* tp_getattro */
881
    0,                                          /* tp_setattro */
882
    0,                                          /* tp_as_buffer */
883
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
884
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS |
885
        _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_SEQUENCE,  /* tp_flags */
886
    tuple_new__doc__,                           /* tp_doc */
887
    tuple_traverse,                             /* tp_traverse */
888
    0,                                          /* tp_clear */
889
    tuple_richcompare,                          /* tp_richcompare */
890
    0,                                          /* tp_weaklistoffset */
891
    tuple_iter,                                 /* tp_iter */
892
    0,                                          /* tp_iternext */
893
    tuple_methods,                              /* tp_methods */
894
    0,                                          /* tp_members */
895
    0,                                          /* tp_getset */
896
    0,                                          /* tp_base */
897
    0,                                          /* tp_dict */
898
    0,                                          /* tp_descr_get */
899
    0,                                          /* tp_descr_set */
900
    0,                                          /* tp_dictoffset */
901
    0,                                          /* tp_init */
902
    0,                                          /* tp_alloc */
903
    tuple_new,                                  /* tp_new */
904
    PyObject_GC_Del,                            /* tp_free */
905
    .tp_vectorcall = tuple_vectorcall,
906
    .tp_version_tag = _Py_TYPE_VERSION_TUPLE,
907
};
908
909
/* The following function breaks the notion that tuples are immutable:
910
   it changes the size of a tuple.  We get away with this only if there
911
   is only one module referencing the object.  You can also think of it
912
   as creating a new tuple object and destroying the old one, only more
913
   efficiently.  In any case, don't use this if the tuple may already be
914
   known to some other part of the code. */
915
916
int
917
_PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
918
288
{
919
288
    PyTupleObject *v;
920
288
    PyTupleObject *sv;
921
288
    Py_ssize_t i;
922
288
    Py_ssize_t oldsize;
923
924
288
    v = (PyTupleObject *) *pv;
925
288
    if (v == NULL || !Py_IS_TYPE(v, &PyTuple_Type) ||
926
288
        (Py_SIZE(v) != 0 && Py_REFCNT(v) != 1)) {
927
0
        *pv = 0;
928
0
        Py_XDECREF(v);
929
0
        PyErr_BadInternalCall();
930
0
        return -1;
931
0
    }
932
933
288
    oldsize = Py_SIZE(v);
934
288
    if (oldsize == newsize) {
935
272
        return 0;
936
272
    }
937
16
    if (newsize == 0) {
938
0
        Py_DECREF(v);
939
0
        *pv = tuple_get_empty();
940
0
        return 0;
941
0
    }
942
16
    if (oldsize == 0) {
943
#ifdef Py_DEBUG
944
        assert(v == &_Py_SINGLETON(tuple_empty));
945
#endif
946
        /* The empty tuple is statically allocated so we never
947
           resize it in-place. */
948
0
        Py_DECREF(v);
949
0
        *pv = PyTuple_New(newsize);
950
0
        return *pv == NULL ? -1 : 0;
951
0
    }
952
953
16
    if (_PyObject_GC_IS_TRACKED(v)) {
954
16
        _PyObject_GC_UNTRACK(v);
955
16
    }
956
#ifdef Py_TRACE_REFS
957
    _Py_ForgetReference((PyObject *) v);
958
#endif
959
    /* DECREF items deleted by shrinkage */
960
64
    for (i = newsize; i < oldsize; i++) {
961
48
        Py_CLEAR(v->ob_item[i]);
962
48
    }
963
16
    _PyReftracerTrack((PyObject *)v, PyRefTracer_DESTROY);
964
16
    sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
965
16
    if (sv == NULL) {
966
0
        *pv = NULL;
967
#ifdef Py_REF_DEBUG
968
        _Py_DecRefTotal(_PyThreadState_GET());
969
#endif
970
0
        PyObject_GC_Del(v);
971
0
        return -1;
972
0
    }
973
16
    _Py_NewReferenceNoTotal((PyObject *) sv);
974
    /* Zero out items added by growing */
975
16
    if (newsize > oldsize)
976
0
        memset(&sv->ob_item[oldsize], 0,
977
0
               sizeof(*sv->ob_item) * (newsize - oldsize));
978
16
    *pv = (PyObject *) sv;
979
16
    _PyObject_GC_TRACK(sv);
980
16
    return 0;
981
16
}
982
983
/*********************** Tuple Iterator **************************/
984
985
13.8M
#define _PyTupleIterObject_CAST(op) ((_PyTupleIterObject *)(op))
986
987
static void
988
tupleiter_dealloc(PyObject *self)
989
2.76M
{
990
2.76M
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
991
2.76M
    _PyObject_GC_UNTRACK(it);
992
2.76M
    Py_XDECREF(it->it_seq);
993
2.76M
    assert(Py_IS_TYPE(self, &PyTupleIter_Type));
994
2.76M
    _Py_FREELIST_FREE(tuple_iters, it, PyObject_GC_Del);
995
2.76M
}
996
997
static int
998
tupleiter_traverse(PyObject *self, visitproc visit, void *arg)
999
0
{
1000
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1001
0
    Py_VISIT(it->it_seq);
1002
0
    return 0;
1003
0
}
1004
1005
static PyObject *
1006
tupleiter_next(PyObject *self)
1007
11.0M
{
1008
11.0M
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1009
11.0M
    PyTupleObject *seq;
1010
11.0M
    PyObject *item;
1011
1012
11.0M
    assert(it != NULL);
1013
11.0M
    seq = it->it_seq;
1014
11.0M
#ifndef Py_GIL_DISABLED
1015
11.0M
    if (seq == NULL)
1016
0
        return NULL;
1017
11.0M
#endif
1018
11.0M
    assert(PyTuple_Check(seq));
1019
1020
11.0M
    Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1021
11.0M
    if (index < PyTuple_GET_SIZE(seq)) {
1022
8.29M
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index + 1);
1023
8.29M
        item = PyTuple_GET_ITEM(seq, index);
1024
8.29M
        return Py_NewRef(item);
1025
8.29M
    }
1026
1027
2.76M
#ifndef Py_GIL_DISABLED
1028
2.76M
    it->it_seq = NULL;
1029
2.76M
    Py_DECREF(seq);
1030
2.76M
#endif
1031
2.76M
    return NULL;
1032
11.0M
}
1033
1034
static PyObject *
1035
tupleiter_len(PyObject *self, PyObject *Py_UNUSED(ignored))
1036
0
{
1037
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1038
0
    Py_ssize_t len = 0;
1039
#ifdef Py_GIL_DISABLED
1040
    Py_ssize_t idx = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1041
    Py_ssize_t seq_len = PyTuple_GET_SIZE(it->it_seq);
1042
    if (idx < seq_len)
1043
        len = seq_len - idx;
1044
#else
1045
0
    if (it->it_seq)
1046
0
        len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;
1047
0
#endif
1048
0
    return PyLong_FromSsize_t(len);
1049
0
}
1050
1051
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
1052
1053
static PyObject *
1054
tupleiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
1055
0
{
1056
0
    PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
1057
1058
    /* _PyEval_GetBuiltin can invoke arbitrary code,
1059
     * call must be before access of iterator pointers.
1060
     * see issue #101765 */
1061
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1062
1063
#ifdef Py_GIL_DISABLED
1064
    Py_ssize_t idx = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1065
    if (idx < PyTuple_GET_SIZE(it->it_seq))
1066
        return Py_BuildValue("N(O)n", iter, it->it_seq, idx);
1067
#else
1068
0
    if (it->it_seq)
1069
0
        return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index);
1070
0
#endif
1071
0
    return Py_BuildValue("N(())", iter);
1072
0
}
1073
1074
static PyObject *
1075
tupleiter_setstate(PyObject *self, PyObject *state)
1076
0
{
1077
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1078
0
    Py_ssize_t index = PyLong_AsSsize_t(state);
1079
0
    if (index == -1 && PyErr_Occurred())
1080
0
        return NULL;
1081
0
    if (it->it_seq != NULL) {
1082
0
        if (index < 0)
1083
0
            index = 0;
1084
0
        else if (index > PyTuple_GET_SIZE(it->it_seq))
1085
0
            index = PyTuple_GET_SIZE(it->it_seq); /* exhausted iterator */
1086
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index);
1087
0
    }
1088
0
    Py_RETURN_NONE;
1089
0
}
1090
1091
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
1092
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
1093
1094
static PyMethodDef tupleiter_methods[] = {
1095
    {"__length_hint__", tupleiter_len, METH_NOARGS, length_hint_doc},
1096
    {"__reduce__", tupleiter_reduce, METH_NOARGS, reduce_doc},
1097
    {"__setstate__", tupleiter_setstate, METH_O, setstate_doc},
1098
    {NULL, NULL, 0, NULL} /* sentinel */
1099
};
1100
1101
PyTypeObject PyTupleIter_Type = {
1102
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1103
    "tuple_iterator",                           /* tp_name */
1104
    sizeof(_PyTupleIterObject),                 /* tp_basicsize */
1105
    0,                                          /* tp_itemsize */
1106
    /* methods */
1107
    tupleiter_dealloc,                          /* tp_dealloc */
1108
    0,                                          /* tp_vectorcall_offset */
1109
    0,                                          /* tp_getattr */
1110
    0,                                          /* tp_setattr */
1111
    0,                                          /* tp_as_async */
1112
    0,                                          /* tp_repr */
1113
    0,                                          /* tp_as_number */
1114
    0,                                          /* tp_as_sequence */
1115
    0,                                          /* tp_as_mapping */
1116
    0,                                          /* tp_hash */
1117
    0,                                          /* tp_call */
1118
    0,                                          /* tp_str */
1119
    PyObject_GenericGetAttr,                    /* tp_getattro */
1120
    0,                                          /* tp_setattro */
1121
    0,                                          /* tp_as_buffer */
1122
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1123
    0,                                          /* tp_doc */
1124
    tupleiter_traverse,                         /* tp_traverse */
1125
    0,                                          /* tp_clear */
1126
    0,                                          /* tp_richcompare */
1127
    0,                                          /* tp_weaklistoffset */
1128
    PyObject_SelfIter,                          /* tp_iter */
1129
    tupleiter_next,                             /* tp_iternext */
1130
    tupleiter_methods,                          /* tp_methods */
1131
    0,
1132
};
1133
1134
static PyObject *
1135
tuple_iter(PyObject *seq)
1136
2.76M
{
1137
2.76M
    if (!PyTuple_Check(seq)) {
1138
0
        PyErr_BadInternalCall();
1139
0
        return NULL;
1140
0
    }
1141
2.76M
    _PyTupleIterObject *it = _Py_FREELIST_POP(_PyTupleIterObject, tuple_iters);
1142
2.76M
    if (it == NULL) {
1143
28
        it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
1144
28
        if (it == NULL)
1145
0
            return NULL;
1146
28
    }
1147
2.76M
    it->it_index = 0;
1148
2.76M
    it->it_seq = (PyTupleObject *)Py_NewRef(seq);
1149
2.76M
    _PyObject_GC_TRACK(it);
1150
2.76M
    return (PyObject *)it;
1151
2.76M
}
1152
1153
1154
/*************
1155
 * freelists *
1156
 *************/
1157
1158
static inline int
1159
maybe_freelist_push(PyTupleObject *op)
1160
425M
{
1161
425M
    if (!Py_IS_TYPE(op, &PyTuple_Type)) {
1162
1.98M
        return 0;
1163
1.98M
    }
1164
423M
    Py_ssize_t index = Py_SIZE(op) - 1;
1165
423M
    if (index < PyTuple_MAXSAVESIZE) {
1166
423M
        return _Py_FREELIST_PUSH(tuples[index], op, Py_tuple_MAXFREELIST);
1167
423M
    }
1168
2.72k
    return 0;
1169
423M
}
1170
1171
/* Print summary info about the state of the optimized allocator */
1172
void
1173
_PyTuple_DebugMallocStats(FILE *out)
1174
0
{
1175
0
    for (int i = 0; i < PyTuple_MAXSAVESIZE; i++) {
1176
0
        int len = i + 1;
1177
0
        char buf[128];
1178
0
        PyOS_snprintf(buf, sizeof(buf),
1179
0
                      "free %d-sized PyTupleObject", len);
1180
0
        _PyDebugAllocatorStats(out, buf, _Py_FREELIST_SIZE(tuples[i]),
1181
0
                               _PyObject_VAR_SIZE(&PyTuple_Type, len));
1182
0
    }
1183
0
}