Coverage Report

Created: 2026-03-08 06:40

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