Coverage Report

Created: 2026-05-16 06:46

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