Coverage Report

Created: 2026-05-30 06:18

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