Coverage Report

Created: 2025-07-18 06:09

/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
429M
{
39
429M
    if (size < 0) {
40
0
        PyErr_BadInternalCall();
41
0
        return NULL;
42
0
    }
43
429M
    assert(size != 0);    // The empty tuple is statically allocated.
44
429M
    Py_ssize_t index = size - 1;
45
429M
    if (index < PyTuple_MAXSAVESIZE) {
46
429M
        PyTupleObject *op = _Py_FREELIST_POP(PyTupleObject, tuples[index]);
47
429M
        if (op != NULL) {
48
352M
            _PyTuple_RESET_HASH_CACHE(op);
49
352M
            return op;
50
352M
        }
51
429M
    }
52
    /* Check for overflow */
53
77.2M
    if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) -
54
77.2M
                sizeof(PyObject *))) / sizeof(PyObject *)) {
55
0
        return (PyTupleObject *)PyErr_NoMemory();
56
0
    }
57
77.2M
    PyTupleObject *result = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
58
77.2M
    if (result != NULL) {
59
77.2M
        _PyTuple_RESET_HASH_CACHE(result);
60
77.2M
    }
61
77.2M
    return result;
62
77.2M
}
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
68.4M
{
71
68.4M
    return (PyObject *)&_Py_SINGLETON(tuple_empty);
72
68.4M
}
73
74
PyObject *
75
PyTuple_New(Py_ssize_t size)
76
79.6M
{
77
79.6M
    PyTupleObject *op;
78
79.6M
    if (size == 0) {
79
12.8k
        return tuple_get_empty();
80
12.8k
    }
81
79.6M
    op = tuple_alloc(size);
82
79.6M
    if (op == NULL) {
83
0
        return NULL;
84
0
    }
85
295M
    for (Py_ssize_t i = 0; i < size; i++) {
86
216M
        op->ob_item[i] = NULL;
87
216M
    }
88
79.6M
    _PyObject_GC_TRACK(op);
89
79.6M
    return (PyObject *) op;
90
79.6M
}
91
92
Py_ssize_t
93
PyTuple_Size(PyObject *op)
94
6.55M
{
95
6.55M
    if (!PyTuple_Check(op)) {
96
0
        PyErr_BadInternalCall();
97
0
        return -1;
98
0
    }
99
6.55M
    else
100
6.55M
        return Py_SIZE(op);
101
6.55M
}
102
103
PyObject *
104
PyTuple_GetItem(PyObject *op, Py_ssize_t i)
105
31.5M
{
106
31.5M
    if (!PyTuple_Check(op)) {
107
0
        PyErr_BadInternalCall();
108
0
        return NULL;
109
0
    }
110
31.5M
    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
31.5M
    return ((PyTupleObject *)op) -> ob_item[i];
115
31.5M
}
116
117
int
118
PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
119
70.4k
{
120
70.4k
    PyObject **p;
121
70.4k
    if (!PyTuple_Check(op) || Py_REFCNT(op) != 1) {
122
0
        Py_XDECREF(newitem);
123
0
        PyErr_BadInternalCall();
124
0
        return -1;
125
0
    }
126
70.4k
    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
70.4k
    p = ((PyTupleObject *)op) -> ob_item + i;
133
70.4k
    Py_XSETREF(*p, newitem);
134
70.4k
    return 0;
135
70.4k
}
136
137
void
138
_PyTuple_MaybeUntrack(PyObject *op)
139
84.2M
{
140
84.2M
    PyTupleObject *t;
141
84.2M
    Py_ssize_t i, n;
142
143
84.2M
    if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
144
0
        return;
145
84.2M
    t = (PyTupleObject *) op;
146
84.2M
    n = Py_SIZE(t);
147
248M
    for (i = 0; i < n; i++) {
148
166M
        PyObject *elt = PyTuple_GET_ITEM(t, i);
149
        /* Tuple with NULL elements aren't
150
           fully constructed, don't untrack
151
           them yet. */
152
166M
        if (!elt ||
153
166M
            _PyObject_GC_MAY_BE_TRACKED(elt))
154
2.19M
            return;
155
166M
    }
156
82.0M
    _PyObject_GC_UNTRACK(op);
157
82.0M
}
158
159
PyObject *
160
PyTuple_Pack(Py_ssize_t n, ...)
161
7.12M
{
162
7.12M
    Py_ssize_t i;
163
7.12M
    PyObject *o;
164
7.12M
    PyObject **items;
165
7.12M
    va_list vargs;
166
167
7.12M
    if (n == 0) {
168
0
        return tuple_get_empty();
169
0
    }
170
171
7.12M
    va_start(vargs, n);
172
7.12M
    PyTupleObject *result = tuple_alloc(n);
173
7.12M
    if (result == NULL) {
174
0
        va_end(vargs);
175
0
        return NULL;
176
0
    }
177
7.12M
    items = result->ob_item;
178
21.3M
    for (i = 0; i < n; i++) {
179
14.2M
        o = va_arg(vargs, PyObject *);
180
14.2M
        items[i] = Py_NewRef(o);
181
14.2M
    }
182
7.12M
    va_end(vargs);
183
7.12M
    _PyObject_GC_TRACK(result);
184
7.12M
    return (PyObject *)result;
185
7.12M
}
186
187
188
/* Methods */
189
190
static void
191
tuple_dealloc(PyObject *self)
192
431M
{
193
431M
    PyTupleObject *op = _PyTuple_CAST(self);
194
431M
    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
431M
    PyObject_GC_UnTrack(op);
210
211
431M
    Py_ssize_t i = Py_SIZE(op);
212
1.40G
    while (--i >= 0) {
213
975M
        Py_XDECREF(op->ob_item[i]);
214
975M
    }
215
    // This will abort on the empty singleton (if there is one).
216
431M
    if (!maybe_freelist_push(op)) {
217
78.7M
        Py_TYPE(op)->tp_free((PyObject *)op);
218
78.7M
    }
219
431M
}
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
657k
{
307
657k
    PyTupleObject *v = _PyTuple_CAST(op);
308
309
657k
    Py_uhash_t acc = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->ob_hash);
310
657k
    if (acc != (Py_uhash_t)-1) {
311
100k
        return acc;
312
100k
    }
313
314
556k
    Py_ssize_t len = Py_SIZE(v);
315
556k
    PyObject **item = v->ob_item;
316
556k
    acc = _PyTuple_HASH_XXPRIME_5;
317
2.24M
    for (Py_ssize_t i = 0; i < len; i++) {
318
1.69M
        Py_uhash_t lane = PyObject_Hash(item[i]);
319
1.69M
        if (lane == (Py_uhash_t)-1) {
320
0
            return -1;
321
0
        }
322
1.69M
        acc += lane * _PyTuple_HASH_XXPRIME_2;
323
1.69M
        acc = _PyTuple_HASH_XXROTATE(acc);
324
1.69M
        acc *= _PyTuple_HASH_XXPRIME_1;
325
1.69M
    }
326
327
    /* Add input length, mangled to keep the historical value of hash(()). */
328
556k
    acc += len ^ (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL);
329
330
556k
    if (acc == (Py_uhash_t)-1) {
331
0
        acc = 1546275796;
332
0
    }
333
334
556k
    FT_ATOMIC_STORE_SSIZE_RELAXED(v->ob_hash, acc);
335
336
556k
    return acc;
337
556k
}
338
339
static Py_ssize_t
340
tuple_length(PyObject *self)
341
715k
{
342
715k
    PyTupleObject *a = _PyTuple_CAST(self);
343
715k
    return Py_SIZE(a);
344
715k
}
345
346
static int
347
tuple_contains(PyObject *self, PyObject *el)
348
3.74M
{
349
3.74M
    PyTupleObject *a = _PyTuple_CAST(self);
350
3.74M
    int cmp = 0;
351
9.92M
    for (Py_ssize_t i = 0; cmp == 0 && i < Py_SIZE(a); ++i) {
352
6.18M
        cmp = PyObject_RichCompareBool(PyTuple_GET_ITEM(a, i), el, Py_EQ);
353
6.18M
    }
354
3.74M
    return cmp;
355
3.74M
}
356
357
static PyObject *
358
tuple_item(PyObject *op, Py_ssize_t i)
359
18.8M
{
360
18.8M
    PyTupleObject *a = _PyTuple_CAST(op);
361
18.8M
    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.8M
    return Py_NewRef(a->ob_item[i]);
366
18.8M
}
367
368
PyObject *
369
_PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
370
248M
{
371
248M
    if (n == 0) {
372
68.4M
        return tuple_get_empty();
373
68.4M
    }
374
375
180M
    PyTupleObject *tuple = tuple_alloc(n);
376
180M
    if (tuple == NULL) {
377
0
        return NULL;
378
0
    }
379
180M
    PyObject **dst = tuple->ob_item;
380
558M
    for (Py_ssize_t i = 0; i < n; i++) {
381
378M
        PyObject *item = src[i];
382
378M
        dst[i] = Py_NewRef(item);
383
378M
    }
384
180M
    _PyObject_GC_TRACK(tuple);
385
180M
    return (PyObject *)tuple;
386
180M
}
387
388
PyObject *
389
_PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
390
162M
{
391
162M
    if (n == 0) {
392
0
        return tuple_get_empty();
393
0
    }
394
162M
    PyTupleObject *tuple = tuple_alloc(n);
395
162M
    if (tuple == NULL) {
396
0
        return NULL;
397
0
    }
398
162M
    PyObject **dst = tuple->ob_item;
399
524M
    for (Py_ssize_t i = 0; i < n; i++) {
400
361M
        dst[i] = PyStackRef_AsPyObjectSteal(src[i]);
401
361M
    }
402
162M
    _PyObject_GC_TRACK(tuple);
403
162M
    return (PyObject *)tuple;
404
162M
}
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
27.4M
{
432
27.4M
    if (ilow < 0)
433
0
        ilow = 0;
434
27.4M
    if (ihigh > Py_SIZE(a))
435
0
        ihigh = Py_SIZE(a);
436
27.4M
    if (ihigh < ilow)
437
0
        ihigh = ilow;
438
27.4M
    if (ilow == 0 && ihigh == Py_SIZE(a) && PyTuple_CheckExact(a)) {
439
0
        return Py_NewRef(a);
440
0
    }
441
27.4M
    return _PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow);
442
27.4M
}
443
444
PyObject *
445
PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)
446
27.4M
{
447
27.4M
    if (op == NULL || !PyTuple_Check(op)) {
448
0
        PyErr_BadInternalCall();
449
0
        return NULL;
450
0
    }
451
27.4M
    return tuple_slice((PyTupleObject *)op, i, j);
452
27.4M
}
453
454
static PyObject *
455
tuple_concat(PyObject *aa, PyObject *bb)
456
22
{
457
22
    PyTupleObject *a = _PyTuple_CAST(aa);
458
22
    if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) {
459
0
        return Py_NewRef(bb);
460
0
    }
461
22
    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
22
    PyTupleObject *b = (PyTupleObject *)bb;
468
469
22
    if (Py_SIZE(b) == 0 && PyTuple_CheckExact(a)) {
470
0
        return Py_NewRef(a);
471
0
    }
472
22
    assert((size_t)Py_SIZE(a) + (size_t)Py_SIZE(b) < PY_SSIZE_T_MAX);
473
22
    Py_ssize_t size = Py_SIZE(a) + Py_SIZE(b);
474
22
    if (size == 0) {
475
0
        return tuple_get_empty();
476
0
    }
477
478
22
    PyTupleObject *np = tuple_alloc(size);
479
22
    if (np == NULL) {
480
0
        return NULL;
481
0
    }
482
483
22
    PyObject **src = a->ob_item;
484
22
    PyObject **dest = np->ob_item;
485
204
    for (Py_ssize_t i = 0; i < Py_SIZE(a); i++) {
486
182
        PyObject *v = src[i];
487
182
        dest[i] = Py_NewRef(v);
488
182
    }
489
490
22
    src = b->ob_item;
491
22
    dest = np->ob_item + Py_SIZE(a);
492
50
    for (Py_ssize_t i = 0; i < Py_SIZE(b); i++) {
493
28
        PyObject *v = src[i];
494
28
        dest[i] = Py_NewRef(v);
495
28
    }
496
497
22
    _PyObject_GC_TRACK(np);
498
22
    return (PyObject *)np;
499
22
}
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
10.5M
{
621
10.5M
    PyTupleObject *o = _PyTuple_CAST(self);
622
48.6M
    for (Py_ssize_t i = Py_SIZE(o); --i >= 0; ) {
623
38.1M
        Py_VISIT(o->ob_item[i]);
624
38.1M
    }
625
10.5M
    return 0;
626
10.5M
}
627
628
static PyObject *
629
tuple_richcompare(PyObject *v, PyObject *w, int op)
630
2.98M
{
631
2.98M
    PyTupleObject *vt, *wt;
632
2.98M
    Py_ssize_t i;
633
2.98M
    Py_ssize_t vlen, wlen;
634
635
2.98M
    if (!PyTuple_Check(v) || !PyTuple_Check(w))
636
0
        Py_RETURN_NOTIMPLEMENTED;
637
638
2.98M
    vt = (PyTupleObject *)v;
639
2.98M
    wt = (PyTupleObject *)w;
640
641
2.98M
    vlen = Py_SIZE(vt);
642
2.98M
    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.42M
    for (i = 0; i < vlen && i < wlen; i++) {
656
3.93M
        int k = PyObject_RichCompareBool(vt->ob_item[i],
657
3.93M
                                         wt->ob_item[i], Py_EQ);
658
3.93M
        if (k < 0)
659
0
            return NULL;
660
3.93M
        if (!k)
661
2.49M
            break;
662
3.93M
    }
663
664
2.98M
    if (i >= vlen || i >= wlen) {
665
        /* No more items to compare -- compare sizes */
666
488k
        Py_RETURN_RICHCOMPARE(vlen, wlen, op);
667
488k
    }
668
669
    /* We have an item that differs -- shortcuts for EQ/NE */
670
2.49M
    if (op == Py_EQ) {
671
234
        Py_RETURN_FALSE;
672
234
    }
673
2.49M
    if (op == Py_NE) {
674
63
        Py_RETURN_TRUE;
675
63
    }
676
677
    /* Compare the final item again using the proper operator */
678
2.49M
    return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
679
2.49M
}
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.27M
{
702
3.27M
    if (type != &PyTuple_Type)
703
1.63M
        return tuple_subtype_new(type, iterable);
704
705
1.63M
    if (iterable == NULL) {
706
0
        return tuple_get_empty();
707
0
    }
708
1.63M
    else {
709
1.63M
        return PySequence_Tuple(iterable);
710
1.63M
    }
711
1.63M
}
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.63M
{
737
1.63M
    PyObject *tmp, *newobj, *item;
738
1.63M
    Py_ssize_t i, n;
739
740
1.63M
    assert(PyType_IsSubtype(type, &PyTuple_Type));
741
    // tuple subclasses must implement the GC protocol
742
1.63M
    assert(_PyType_IS_GC(type));
743
744
1.63M
    tmp = tuple_new_impl(&PyTuple_Type, iterable);
745
1.63M
    if (tmp == NULL)
746
0
        return NULL;
747
1.63M
    assert(PyTuple_Check(tmp));
748
    /* This may allocate an empty tuple that is not the global one. */
749
1.63M
    newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
750
1.63M
    if (newobj == NULL) {
751
0
        Py_DECREF(tmp);
752
0
        return NULL;
753
0
    }
754
6.54M
    for (i = 0; i < n; i++) {
755
4.90M
        item = PyTuple_GET_ITEM(tmp, i);
756
4.90M
        PyTuple_SET_ITEM(newobj, i, Py_NewRef(item));
757
4.90M
    }
758
1.63M
    Py_DECREF(tmp);
759
760
1.63M
    _PyTuple_RESET_HASH_CACHE(newobj);
761
762
    // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
763
1.63M
    if (!_PyObject_GC_IS_TRACKED(newobj)) {
764
0
        _PyObject_GC_TRACK(newobj);
765
0
    }
766
1.63M
    return newobj;
767
1.63M
}
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.28M
{
783
1.28M
    PyTupleObject *self = _PyTuple_CAST(op);
784
1.28M
    if (_PyIndex_Check(item)) {
785
1.28M
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
786
1.28M
        if (i == -1 && PyErr_Occurred())
787
0
            return NULL;
788
1.28M
        if (i < 0)
789
1.28M
            i += PyTuple_GET_SIZE(self);
790
1.28M
        return tuple_item(op, i);
791
1.28M
    }
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.28M
}
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
11.4M
#define _PyTupleIterObject_CAST(op) ((_PyTupleIterObject *)(op))
986
987
static void
988
tupleiter_dealloc(PyObject *self)
989
2.29M
{
990
2.29M
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
991
2.29M
    _PyObject_GC_UNTRACK(it);
992
2.29M
    Py_XDECREF(it->it_seq);
993
2.29M
    assert(Py_IS_TYPE(self, &PyTupleIter_Type));
994
2.29M
    _Py_FREELIST_FREE(tuple_iters, it, PyObject_GC_Del);
995
2.29M
}
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
9.18M
{
1008
9.18M
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1009
9.18M
    PyTupleObject *seq;
1010
9.18M
    PyObject *item;
1011
1012
9.18M
    assert(it != NULL);
1013
9.18M
    seq = it->it_seq;
1014
9.18M
#ifndef Py_GIL_DISABLED
1015
9.18M
    if (seq == NULL)
1016
0
        return NULL;
1017
9.18M
#endif
1018
9.18M
    assert(PyTuple_Check(seq));
1019
1020
9.18M
    Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1021
9.18M
    if (index < PyTuple_GET_SIZE(seq)) {
1022
6.88M
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index + 1);
1023
6.88M
        item = PyTuple_GET_ITEM(seq, index);
1024
6.88M
        return Py_NewRef(item);
1025
6.88M
    }
1026
1027
2.29M
#ifndef Py_GIL_DISABLED
1028
2.29M
    it->it_seq = NULL;
1029
2.29M
    Py_DECREF(seq);
1030
2.29M
#endif
1031
2.29M
    return NULL;
1032
9.18M
}
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.29M
{
1137
2.29M
    if (!PyTuple_Check(seq)) {
1138
0
        PyErr_BadInternalCall();
1139
0
        return NULL;
1140
0
    }
1141
2.29M
    _PyTupleIterObject *it = _Py_FREELIST_POP(_PyTupleIterObject, tuple_iters);
1142
2.29M
    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.29M
    it->it_index = 0;
1148
2.29M
    it->it_seq = (PyTupleObject *)Py_NewRef(seq);
1149
2.29M
    _PyObject_GC_TRACK(it);
1150
2.29M
    return (PyObject *)it;
1151
2.29M
}
1152
1153
1154
/*************
1155
 * freelists *
1156
 *************/
1157
1158
static inline int
1159
maybe_freelist_push(PyTupleObject *op)
1160
431M
{
1161
431M
    if (!Py_IS_TYPE(op, &PyTuple_Type)) {
1162
1.63M
        return 0;
1163
1.63M
    }
1164
429M
    Py_ssize_t index = Py_SIZE(op) - 1;
1165
429M
    if (index < PyTuple_MAXSAVESIZE) {
1166
429M
        return _Py_FREELIST_PUSH(tuples[index], op, Py_tuple_MAXFREELIST);
1167
429M
    }
1168
2.48k
    return 0;
1169
429M
}
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
}