Coverage Report

Created: 2026-07-14 06:16

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
488M
{
39
488M
    if (size < 0) {
40
0
        PyErr_BadInternalCall();
41
0
        return NULL;
42
0
    }
43
488M
    assert(size != 0);    // The empty tuple is statically allocated.
44
488M
    Py_ssize_t index = size - 1;
45
488M
    if (index < PyTuple_MAXSAVESIZE) {
46
485M
        PyTupleObject *op = _Py_FREELIST_POP(PyTupleObject, tuples[index]);
47
485M
        if (op != NULL) {
48
382M
            _PyTuple_RESET_HASH_CACHE(op);
49
382M
            return op;
50
382M
        }
51
485M
    }
52
    /* Check for overflow */
53
105M
    if ((size_t)size > ((size_t)PY_SSIZE_T_MAX - (sizeof(PyTupleObject) -
54
105M
                sizeof(PyObject *))) / sizeof(PyObject *)) {
55
0
        return (PyTupleObject *)PyErr_NoMemory();
56
0
    }
57
105M
    PyTupleObject *result = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);
58
105M
    if (result != NULL) {
59
105M
        _PyTuple_RESET_HASH_CACHE(result);
60
105M
    }
61
105M
    return result;
62
105M
}
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.5M
{
71
83.5M
    return (PyObject *)&_Py_SINGLETON(tuple_empty);
72
83.5M
}
73
74
PyObject *
75
PyTuple_New(Py_ssize_t size)
76
61.6M
{
77
61.6M
    PyTupleObject *op;
78
61.6M
    if (size == 0) {
79
3.32M
        return tuple_get_empty();
80
3.32M
    }
81
58.3M
    op = tuple_alloc(size);
82
58.3M
    if (op == NULL) {
83
0
        return NULL;
84
0
    }
85
1.57G
    for (Py_ssize_t i = 0; i < size; i++) {
86
1.51G
        op->ob_item[i] = NULL;
87
1.51G
    }
88
58.3M
    _PyObject_GC_TRACK(op);
89
58.3M
    return (PyObject *) op;
90
58.3M
}
91
92
Py_ssize_t
93
PyTuple_Size(PyObject *op)
94
6.80M
{
95
6.80M
    if (!PyTuple_Check(op)) {
96
0
        PyErr_BadInternalCall();
97
0
        return -1;
98
0
    }
99
6.80M
    else
100
6.80M
        return Py_SIZE(op);
101
6.80M
}
102
103
PyObject *
104
PyTuple_GetItem(PyObject *op, Py_ssize_t i)
105
16.8M
{
106
16.8M
    if (!PyTuple_Check(op)) {
107
0
        PyErr_BadInternalCall();
108
0
        return NULL;
109
0
    }
110
16.8M
    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
16.8M
    return ((PyTupleObject *)op) -> ob_item[i];
115
16.8M
}
116
117
int
118
PyTuple_SetItem(PyObject *op, Py_ssize_t i, PyObject *newitem)
119
128k
{
120
128k
    PyObject **p;
121
128k
    if (!PyTuple_Check(op) || !_PyObject_IsUniquelyReferenced(op)) {
122
0
        Py_XDECREF(newitem);
123
0
        PyErr_BadInternalCall();
124
0
        return -1;
125
0
    }
126
128k
    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
128k
    p = ((PyTupleObject *)op) -> ob_item + i;
133
128k
    Py_XSETREF(*p, newitem);
134
128k
    return 0;
135
128k
}
136
137
void
138
_PyTuple_MaybeUntrack(PyObject *op)
139
214M
{
140
214M
    PyTupleObject *t;
141
214M
    Py_ssize_t i, n;
142
143
214M
    if (!PyTuple_CheckExact(op) || !_PyObject_GC_IS_TRACKED(op))
144
0
        return;
145
214M
    t = (PyTupleObject *) op;
146
214M
    n = Py_SIZE(t);
147
250M
    for (i = 0; i < n; i++) {
148
243M
        PyObject *elt = PyTuple_GET_ITEM(t, i);
149
        /* Tuple with NULL elements aren't
150
           fully constructed, don't untrack
151
           them yet. */
152
243M
        if (!elt ||
153
243M
            _PyObject_GC_MAY_BE_TRACKED(elt))
154
208M
            return;
155
243M
    }
156
6.61M
    _PyObject_GC_UNTRACK(op);
157
6.61M
}
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
558M
{
168
558M
    return _PyType_IS_GC(Py_TYPE(ob));
169
558M
}
170
171
PyObject *
172
PyTuple_Pack(Py_ssize_t n, ...)
173
444k
{
174
444k
    Py_ssize_t i;
175
444k
    PyObject *o;
176
444k
    PyObject **items;
177
444k
    va_list vargs;
178
444k
    bool track = false;
179
180
444k
    if (n == 0) {
181
0
        return tuple_get_empty();
182
0
    }
183
184
444k
    va_start(vargs, n);
185
444k
    PyTupleObject *result = tuple_alloc(n);
186
444k
    if (result == NULL) {
187
0
        va_end(vargs);
188
0
        return NULL;
189
0
    }
190
444k
    items = result->ob_item;
191
1.57M
    for (i = 0; i < n; i++) {
192
1.12M
        o = va_arg(vargs, PyObject *);
193
1.12M
        if (!track && maybe_tracked(o)) {
194
213k
            track = true;
195
213k
        }
196
1.12M
        items[i] = Py_NewRef(o);
197
1.12M
    }
198
444k
    va_end(vargs);
199
444k
    if (track) {
200
213k
        _PyObject_GC_TRACK(result);
201
213k
    }
202
444k
    return (PyObject *)result;
203
444k
}
204
205
PyObject *
206
_PyTuple_FromPair(PyObject *first, PyObject *second)
207
131k
{
208
131k
    assert(first != NULL);
209
131k
    assert(second != NULL);
210
211
131k
    return _PyTuple_FromPairSteal(Py_NewRef(first), Py_NewRef(second));
212
131k
}
213
214
PyObject *
215
_PyTuple_FromPairSteal(PyObject *first, PyObject *second)
216
16.4M
{
217
16.4M
    assert(first != NULL);
218
16.4M
    assert(second != NULL);
219
220
16.4M
    PyTupleObject *op = tuple_alloc(2);
221
16.4M
    if (op == NULL) {
222
0
        Py_DECREF(first);
223
0
        Py_DECREF(second);
224
0
        return NULL;
225
0
    }
226
16.4M
    PyObject **items = op->ob_item;
227
16.4M
    items[0] = first;
228
16.4M
    items[1] = second;
229
16.4M
    if (maybe_tracked(first) || maybe_tracked(second)) {
230
153k
        _PyObject_GC_TRACK(op);
231
153k
    }
232
16.4M
    return (PyObject *)op;
233
16.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
488M
{
257
488M
    PyTupleObject *op = _PyTuple_CAST(self);
258
488M
    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
488M
    PyObject_GC_UnTrack(op);
274
275
488M
    Py_ssize_t i = Py_SIZE(op);
276
2.82G
    while (--i >= 0) {
277
2.33G
        Py_XDECREF(op->ob_item[i]);
278
2.33G
    }
279
    // This will abort on the empty singleton (if there is one).
280
488M
    if (!maybe_freelist_push(op)) {
281
104M
        Py_TYPE(op)->tp_free((PyObject *)op);
282
104M
    }
283
488M
}
284
285
static PyObject *
286
tuple_repr(PyObject *self)
287
80.5k
{
288
80.5k
    PyTupleObject *v = _PyTuple_CAST(self);
289
80.5k
    Py_ssize_t n = PyTuple_GET_SIZE(v);
290
80.5k
    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
80.5k
    int res = Py_ReprEnter((PyObject *)v);
299
80.5k
    if (res != 0) {
300
0
        return res > 0 ? PyUnicode_FromString("(...)") : NULL;
301
0
    }
302
303
80.5k
    Py_ssize_t prealloc;
304
80.5k
    if (n > 1) {
305
        // "(" + "1" + ", 2" * (len - 1) + ")"
306
40.2k
        prealloc = 1 + 1 + (2 + 1) * (n - 1) + 1;
307
40.2k
    }
308
40.2k
    else {
309
        // "(1,)"
310
40.2k
        prealloc = 4;
311
40.2k
    }
312
80.5k
    PyUnicodeWriter *writer = PyUnicodeWriter_Create(prealloc);
313
80.5k
    if (writer == NULL) {
314
0
        goto error;
315
0
    }
316
317
80.5k
    if (PyUnicodeWriter_WriteChar(writer, '(') < 0) {
318
0
        goto error;
319
0
    }
320
321
    /* Do repr() on each element. */
322
201k
    for (Py_ssize_t i = 0; i < n; ++i) {
323
120k
        if (i > 0) {
324
40.3k
            if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
325
0
                goto error;
326
0
            }
327
40.3k
            if (PyUnicodeWriter_WriteChar(writer, ' ') < 0) {
328
0
                goto error;
329
0
            }
330
40.3k
        }
331
332
120k
        if (PyUnicodeWriter_WriteRepr(writer, v->ob_item[i]) < 0) {
333
0
            goto error;
334
0
        }
335
120k
    }
336
337
80.5k
    if (n == 1) {
338
40.2k
        if (PyUnicodeWriter_WriteChar(writer, ',') < 0) {
339
0
            goto error;
340
0
        }
341
40.2k
    }
342
80.5k
    if (PyUnicodeWriter_WriteChar(writer, ')') < 0) {
343
0
        goto error;
344
0
    }
345
346
80.5k
    Py_ReprLeave((PyObject *)v);
347
80.5k
    return PyUnicodeWriter_Finish(writer);
348
349
0
error:
350
0
    PyUnicodeWriter_Discard(writer);
351
0
    Py_ReprLeave((PyObject *)v);
352
0
    return NULL;
353
80.5k
}
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
26.8M
{
374
26.8M
    PyTupleObject *v = _PyTuple_CAST(op);
375
376
26.8M
    Py_uhash_t acc = FT_ATOMIC_LOAD_SSIZE_RELAXED(v->ob_hash);
377
26.8M
    if (acc != (Py_uhash_t)-1) {
378
9.61M
        return acc;
379
9.61M
    }
380
381
17.1M
    Py_ssize_t len = Py_SIZE(v);
382
17.1M
    PyObject **item = v->ob_item;
383
17.1M
    acc = _PyTuple_HASH_XXPRIME_5;
384
62.3M
    for (Py_ssize_t i = 0; i < len; i++) {
385
45.1M
        Py_uhash_t lane = PyObject_Hash(item[i]);
386
45.1M
        if (lane == (Py_uhash_t)-1) {
387
0
            return -1;
388
0
        }
389
45.1M
        acc += lane * _PyTuple_HASH_XXPRIME_2;
390
45.1M
        acc = _PyTuple_HASH_XXROTATE(acc);
391
45.1M
        acc *= _PyTuple_HASH_XXPRIME_1;
392
45.1M
    }
393
394
    /* Add input length, mangled to keep the historical value of hash(()). */
395
17.1M
    acc += len ^ (_PyTuple_HASH_XXPRIME_5 ^ 3527539UL);
396
397
17.1M
    if (acc == (Py_uhash_t)-1) {
398
0
        acc = 1546275796;
399
0
    }
400
401
17.1M
    FT_ATOMIC_STORE_SSIZE_RELAXED(v->ob_hash, acc);
402
403
17.1M
    return acc;
404
17.1M
}
405
406
static Py_ssize_t
407
tuple_length(PyObject *self)
408
11.8M
{
409
11.8M
    PyTupleObject *a = _PyTuple_CAST(self);
410
11.8M
    return Py_SIZE(a);
411
11.8M
}
412
413
static int
414
tuple_contains(PyObject *self, PyObject *el)
415
62.0M
{
416
62.0M
    PyTupleObject *a = _PyTuple_CAST(self);
417
62.0M
    int cmp = 0;
418
209M
    for (Py_ssize_t i = 0; cmp == 0 && i < Py_SIZE(a); ++i) {
419
147M
        cmp = PyObject_RichCompareBool(PyTuple_GET_ITEM(a, i), el, Py_EQ);
420
147M
    }
421
62.0M
    return cmp;
422
62.0M
}
423
424
static PyObject *
425
tuple_item(PyObject *op, Py_ssize_t i)
426
18.8M
{
427
18.8M
    PyTupleObject *a = _PyTuple_CAST(op);
428
18.8M
    if (i < 0 || i >= Py_SIZE(a)) {
429
36
        PyErr_SetString(PyExc_IndexError, "tuple index out of range");
430
36
        return NULL;
431
36
    }
432
18.8M
    return Py_NewRef(a->ob_item[i]);
433
18.8M
}
434
435
PyObject *
436
PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
437
245M
{
438
245M
    if (n == 0) {
439
80.2M
        return tuple_get_empty();
440
80.2M
    }
441
442
164M
    PyTupleObject *tuple = tuple_alloc(n);
443
164M
    if (tuple == NULL) {
444
0
        return NULL;
445
0
    }
446
164M
    PyObject **dst = tuple->ob_item;
447
164M
    bool track = false;
448
391M
    for (Py_ssize_t i = 0; i < n; i++) {
449
226M
        PyObject *item = src[i];
450
226M
        if (!track && maybe_tracked(item)) {
451
27.8M
            track = true;
452
27.8M
        }
453
226M
        dst[i] = Py_NewRef(item);
454
226M
    }
455
164M
    if (track) {
456
27.8M
        _PyObject_GC_TRACK(tuple);
457
27.8M
    }
458
164M
    return (PyObject *)tuple;
459
164M
}
460
461
PyObject *
462
_PyTuple_FromStackRefStealOnSuccess(const _PyStackRef *src, Py_ssize_t n)
463
231M
{
464
231M
    if (n == 0) {
465
0
        return tuple_get_empty();
466
0
    }
467
231M
    PyTupleObject *tuple = tuple_alloc(n);
468
231M
    if (tuple == NULL) {
469
0
        return NULL;
470
0
    }
471
231M
    PyObject **dst = tuple->ob_item;
472
231M
    bool track = false;
473
727M
    for (Py_ssize_t i = 0; i < n; i++) {
474
495M
        PyObject *item = PyStackRef_AsPyObjectSteal(src[i]);
475
495M
        if (!track && maybe_tracked(item)) {
476
172M
            track = true;
477
172M
        }
478
495M
        dst[i] = item;
479
495M
    }
480
231M
    if (track) {
481
172M
        _PyObject_GC_TRACK(tuple);
482
172M
    }
483
231M
    return (PyObject *)tuple;
484
231M
}
485
486
PyObject *
487
_PyTuple_FromArraySteal(PyObject *const *src, Py_ssize_t n)
488
11.2M
{
489
11.2M
    if (n == 0) {
490
52
        return tuple_get_empty();
491
52
    }
492
11.2M
    PyTupleObject *tuple = tuple_alloc(n);
493
11.2M
    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
11.2M
    PyObject **dst = tuple->ob_item;
500
36.5M
    for (Py_ssize_t i = 0; i < n; i++) {
501
25.3M
        PyObject *item = src[i];
502
25.3M
        dst[i] = item;
503
25.3M
    }
504
11.2M
    _PyObject_GC_TRACK(tuple);
505
11.2M
    return (PyObject *)tuple;
506
11.2M
}
507
508
static PyObject *
509
tuple_slice(PyTupleObject *a, Py_ssize_t ilow,
510
           Py_ssize_t ihigh)
511
15.6M
{
512
15.6M
    if (ilow < 0)
513
0
        ilow = 0;
514
15.6M
    if (ihigh > Py_SIZE(a))
515
192
        ihigh = Py_SIZE(a);
516
15.6M
    if (ihigh < ilow)
517
0
        ihigh = ilow;
518
15.6M
    if (ilow == 0 && ihigh == Py_SIZE(a) && PyTuple_CheckExact(a)) {
519
0
        return Py_NewRef(a);
520
0
    }
521
15.6M
    return PyTuple_FromArray(a->ob_item + ilow, ihigh - ilow);
522
15.6M
}
523
524
PyObject *
525
_PyTuple_BinarySlice(PyObject *container, PyObject *start, PyObject *stop)
526
58.1k
{
527
58.1k
    assert(PyTuple_CheckExact(container));
528
58.1k
    Py_ssize_t len = Py_SIZE(container);
529
58.1k
    Py_ssize_t istart, istop;
530
58.1k
    if (!_PyEval_UnpackIndices(start, stop, len, &istart, &istop)) {
531
0
        return NULL;
532
0
    }
533
58.1k
    if (istart == 0 && istop == len) {
534
21.9k
        return Py_NewRef(container);
535
21.9k
    }
536
36.1k
    if (istop < istart) {
537
0
        istop = istart;
538
0
    }
539
36.1k
    return PyTuple_FromArray(((PyTupleObject *)container)->ob_item + istart,
540
36.1k
                             istop - istart);
541
58.1k
}
542
543
PyObject *
544
PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j)
545
15.6M
{
546
15.6M
    if (op == NULL || !PyTuple_Check(op)) {
547
0
        PyErr_BadInternalCall();
548
0
        return NULL;
549
0
    }
550
15.6M
    return tuple_slice((PyTupleObject *)op, i, j);
551
15.6M
}
552
553
PyObject *
554
_PyTuple_Concat(PyObject *aa, PyObject *bb)
555
3.54M
{
556
3.54M
    PyTupleObject *a = _PyTuple_CAST(aa);
557
3.54M
    if (Py_SIZE(a) == 0 && PyTuple_CheckExact(bb)) {
558
6.99k
        return Py_NewRef(bb);
559
6.99k
    }
560
3.53M
    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
3.53M
    PyTupleObject *b = (PyTupleObject *)bb;
567
568
3.53M
    if (Py_SIZE(b) == 0 && PyTuple_CheckExact(a)) {
569
40
        return Py_NewRef(a);
570
40
    }
571
3.53M
    assert((size_t)Py_SIZE(a) + (size_t)Py_SIZE(b) < PY_SSIZE_T_MAX);
572
3.53M
    Py_ssize_t size = Py_SIZE(a) + Py_SIZE(b);
573
3.53M
    if (size == 0) {
574
0
        return tuple_get_empty();
575
0
    }
576
577
3.53M
    PyTupleObject *np = tuple_alloc(size);
578
3.53M
    if (np == NULL) {
579
0
        return NULL;
580
0
    }
581
582
3.53M
    PyObject **src = a->ob_item;
583
3.53M
    PyObject **dest = np->ob_item;
584
25.6M
    for (Py_ssize_t i = 0; i < Py_SIZE(a); i++) {
585
22.1M
        PyObject *v = src[i];
586
22.1M
        dest[i] = Py_NewRef(v);
587
22.1M
    }
588
589
3.53M
    src = b->ob_item;
590
3.53M
    dest = np->ob_item + Py_SIZE(a);
591
8.24M
    for (Py_ssize_t i = 0; i < Py_SIZE(b); i++) {
592
4.70M
        PyObject *v = src[i];
593
4.70M
        dest[i] = Py_NewRef(v);
594
4.70M
    }
595
596
3.53M
    _PyObject_GC_TRACK(np);
597
3.53M
    return (PyObject *)np;
598
3.53M
}
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
692
{
667
692
    Py_ssize_t i;
668
669
692
    if (start < 0) {
670
0
        start += Py_SIZE(self);
671
0
        if (start < 0)
672
0
            start = 0;
673
0
    }
674
692
    if (stop < 0) {
675
0
        stop += Py_SIZE(self);
676
0
    }
677
692
    else if (stop > Py_SIZE(self)) {
678
692
        stop = Py_SIZE(self);
679
692
    }
680
888
    for (i = start; i < stop; i++) {
681
352
        int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ);
682
352
        if (cmp > 0)
683
156
            return PyLong_FromSsize_t(i);
684
196
        else if (cmp < 0)
685
0
            return NULL;
686
352
    }
687
536
    PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in tuple");
688
536
    return NULL;
689
692
}
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
432M
{
720
432M
    PyTupleObject *o = _PyTuple_CAST(self);
721
1.34G
    for (Py_ssize_t i = Py_SIZE(o); --i >= 0; ) {
722
911M
        Py_VISIT(o->ob_item[i]);
723
911M
    }
724
432M
    return 0;
725
432M
}
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
62.7M
    for (i = 0; i < vlen && i < wlen; i++) {
755
43.7M
        int k = PyObject_RichCompareBool(vt->ob_item[i],
756
43.7M
                                         wt->ob_item[i], Py_EQ);
757
43.7M
        if (k < 0)
758
0
            return NULL;
759
43.7M
        if (!k)
760
1.79M
            break;
761
43.7M
    }
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.79M
    if (op == Py_EQ) {
770
446k
        Py_RETURN_FALSE;
771
446k
    }
772
1.34M
    if (op == Py_NE) {
773
233k
        Py_RETURN_TRUE;
774
233k
    }
775
776
    /* Compare the final item again using the proper operator */
777
1.11M
    return PyObject_RichCompare(vt->ob_item[i], wt->ob_item[i], op);
778
1.34M
}
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.30M
{
801
1.30M
    if (type != &PyTuple_Type)
802
654k
        return tuple_subtype_new(type, iterable);
803
804
654k
    if (iterable == NULL) {
805
0
        return tuple_get_empty();
806
0
    }
807
654k
    else {
808
654k
        return PySequence_Tuple(iterable);
809
654k
    }
810
654k
}
811
812
static PyObject *
813
tuple_vectorcall(PyObject *type, PyObject * const*args,
814
                 size_t nargsf, PyObject *kwnames)
815
200
{
816
200
    if (!_PyArg_NoKwnames("tuple", kwnames)) {
817
0
        return NULL;
818
0
    }
819
820
200
    Py_ssize_t nargs = PyVectorcall_NARGS(nargsf);
821
200
    if (!_PyArg_CheckPositional("tuple", nargs, 0, 1)) {
822
0
        return NULL;
823
0
    }
824
825
200
    if (nargs) {
826
200
        return tuple_new_impl(_PyType_CAST(type), args[0]);
827
200
    }
828
0
    else {
829
0
        return tuple_get_empty();
830
0
    }
831
200
}
832
833
static PyObject *
834
tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
835
654k
{
836
654k
    PyObject *tmp, *newobj, *item;
837
654k
    Py_ssize_t i, n;
838
839
654k
    assert(PyType_IsSubtype(type, &PyTuple_Type));
840
    // tuple subclasses must implement the GC protocol
841
654k
    assert(_PyType_IS_GC(type));
842
843
654k
    tmp = tuple_new_impl(&PyTuple_Type, iterable);
844
654k
    if (tmp == NULL)
845
0
        return NULL;
846
654k
    assert(PyTuple_Check(tmp));
847
    /* This may allocate an empty tuple that is not the global one. */
848
654k
    newobj = type->tp_alloc(type, n = PyTuple_GET_SIZE(tmp));
849
654k
    if (newobj == NULL) {
850
0
        Py_DECREF(tmp);
851
0
        return NULL;
852
0
    }
853
2.46M
    for (i = 0; i < n; i++) {
854
1.80M
        item = PyTuple_GET_ITEM(tmp, i);
855
1.80M
        PyTuple_SET_ITEM(newobj, i, Py_NewRef(item));
856
1.80M
    }
857
654k
    Py_DECREF(tmp);
858
859
654k
    _PyTuple_RESET_HASH_CACHE(newobj);
860
861
    // Don't track if a subclass tp_alloc is PyType_GenericAlloc()
862
654k
    if (!_PyObject_GC_IS_TRACKED(newobj)) {
863
0
        _PyObject_GC_TRACK(newobj);
864
0
    }
865
654k
    return newobj;
866
654k
}
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.36k
{
882
6.36k
    if (index >= PyTuple_GET_SIZE(obj)) {
883
456
        return (_PyObjectIndexPair) { .object = NULL, .index = index };
884
456
    }
885
5.91k
    PyObject *result = PyTuple_GET_ITEM(obj, index);
886
5.91k
    Py_INCREF(result);
887
5.91k
    return (_PyObjectIndexPair) { .object = result, .index = index + 1 };
888
6.36k
}
889
890
static PyObject*
891
tuple_subscript(PyObject *op, PyObject* item)
892
1.81M
{
893
1.81M
    PyTupleObject *self = _PyTuple_CAST(op);
894
1.81M
    if (_PyIndex_Check(item)) {
895
633k
        Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
896
633k
        if (i == -1 && PyErr_Occurred())
897
0
            return NULL;
898
633k
        if (i < 0)
899
632k
            i += PyTuple_GET_SIZE(self);
900
633k
        return tuple_item(op, i);
901
633k
    }
902
1.18M
    else if (PySlice_Check(item)) {
903
1.18M
        Py_ssize_t start, stop, step, slicelength, i;
904
1.18M
        size_t cur;
905
1.18M
        PyObject* it;
906
1.18M
        PyObject **src, **dest;
907
908
1.18M
        if (PySlice_Unpack(item, &start, &stop, &step) < 0) {
909
0
            return NULL;
910
0
        }
911
1.18M
        slicelength = PySlice_AdjustIndices(PyTuple_GET_SIZE(self), &start,
912
1.18M
                                            &stop, step);
913
914
1.18M
        if (slicelength <= 0) {
915
21.0k
            return tuple_get_empty();
916
21.0k
        }
917
1.16M
        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.16M
        else {
923
1.16M
            PyTupleObject* result = tuple_alloc(slicelength);
924
1.16M
            if (!result) return NULL;
925
926
1.16M
            src = self->ob_item;
927
1.16M
            dest = result->ob_item;
928
9.29M
            for (cur = start, i = 0; i < slicelength;
929
8.12M
                 cur += step, i++) {
930
8.12M
                it = Py_NewRef(src[cur]);
931
8.12M
                dest[i] = it;
932
8.12M
            }
933
934
1.16M
            _PyObject_GC_TRACK(result);
935
1.16M
            return (PyObject *)result;
936
1.16M
        }
937
1.18M
    }
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
1.81M
}
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
958
PyDoc_STRVAR(tuple_class_getitem_doc,
959
"Tuples are generic over the types of their contents.\n\n\
960
For example, use ``tuple[int, str]`` for a pair whose first element\n\
961
is an int and second element is a string.\n\n\
962
Tuples also support the form ``tuple[T, ...]`` to indicate\n\
963
an arbitrary length tuple of elements of type T.");
964
965
static PyMethodDef tuple_methods[] = {
966
    TUPLE___GETNEWARGS___METHODDEF
967
    TUPLE_INDEX_METHODDEF
968
    TUPLE_COUNT_METHODDEF
969
    {"__class_getitem__", Py_GenericAlias, METH_O|METH_CLASS, tuple_class_getitem_doc},
970
    {NULL,              NULL}           /* sentinel */
971
};
972
973
static PyMappingMethods tuple_as_mapping = {
974
    tuple_length,
975
    tuple_subscript,
976
    0
977
};
978
979
static PyObject *tuple_iter(PyObject *seq);
980
981
PyTypeObject PyTuple_Type = {
982
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
983
    "tuple",
984
    sizeof(PyTupleObject) - sizeof(PyObject *),
985
    sizeof(PyObject *),
986
    tuple_dealloc,                              /* tp_dealloc */
987
    0,                                          /* tp_vectorcall_offset */
988
    0,                                          /* tp_getattr */
989
    0,                                          /* tp_setattr */
990
    0,                                          /* tp_as_async */
991
    tuple_repr,                                 /* tp_repr */
992
    0,                                          /* tp_as_number */
993
    &tuple_as_sequence,                         /* tp_as_sequence */
994
    &tuple_as_mapping,                          /* tp_as_mapping */
995
    tuple_hash,                                 /* tp_hash */
996
    0,                                          /* tp_call */
997
    0,                                          /* tp_str */
998
    PyObject_GenericGetAttr,                    /* tp_getattro */
999
    0,                                          /* tp_setattro */
1000
    0,                                          /* tp_as_buffer */
1001
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
1002
        Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS |
1003
        _Py_TPFLAGS_MATCH_SELF | Py_TPFLAGS_SEQUENCE,  /* tp_flags */
1004
    tuple_new__doc__,                           /* tp_doc */
1005
    tuple_traverse,                             /* tp_traverse */
1006
    0,                                          /* tp_clear */
1007
    tuple_richcompare,                          /* tp_richcompare */
1008
    0,                                          /* tp_weaklistoffset */
1009
    tuple_iter,                                 /* tp_iter */
1010
    0,                                          /* tp_iternext */
1011
    tuple_methods,                              /* tp_methods */
1012
    0,                                          /* tp_members */
1013
    0,                                          /* tp_getset */
1014
    0,                                          /* tp_base */
1015
    0,                                          /* tp_dict */
1016
    0,                                          /* tp_descr_get */
1017
    0,                                          /* tp_descr_set */
1018
    0,                                          /* tp_dictoffset */
1019
    0,                                          /* tp_init */
1020
    0,                                          /* tp_alloc */
1021
    tuple_new,                                  /* tp_new */
1022
    PyObject_GC_Del,                            /* tp_free */
1023
    .tp_vectorcall = tuple_vectorcall,
1024
    .tp_version_tag = _Py_TYPE_VERSION_TUPLE,
1025
    ._tp_iteritem = tuple_iteritem,
1026
};
1027
1028
/* The following function breaks the notion that tuples are immutable:
1029
   it changes the size of a tuple.  We get away with this only if there
1030
   is only one module referencing the object.  You can also think of it
1031
   as creating a new tuple object and destroying the old one, only more
1032
   efficiently.  In any case, don't use this if the tuple may already be
1033
   known to some other part of the code. */
1034
1035
int
1036
_PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)
1037
744
{
1038
744
    PyTupleObject *v;
1039
744
    PyTupleObject *sv;
1040
744
    Py_ssize_t i;
1041
744
    Py_ssize_t oldsize;
1042
1043
744
    v = (PyTupleObject *) *pv;
1044
744
    if (v == NULL || !Py_IS_TYPE(v, &PyTuple_Type) ||
1045
744
        (Py_SIZE(v) != 0 && !_PyObject_IsUniquelyReferenced(*pv))) {
1046
0
        *pv = 0;
1047
0
        Py_XDECREF(v);
1048
0
        PyErr_BadInternalCall();
1049
0
        return -1;
1050
0
    }
1051
1052
744
    oldsize = Py_SIZE(v);
1053
744
    if (oldsize == newsize) {
1054
628
        return 0;
1055
628
    }
1056
116
    if (newsize == 0) {
1057
76
        Py_DECREF(v);
1058
76
        *pv = tuple_get_empty();
1059
76
        return 0;
1060
76
    }
1061
40
    if (oldsize == 0) {
1062
#ifdef Py_DEBUG
1063
        assert(v == &_Py_SINGLETON(tuple_empty));
1064
#endif
1065
        /* The empty tuple is statically allocated so we never
1066
           resize it in-place. */
1067
0
        Py_DECREF(v);
1068
0
        *pv = PyTuple_New(newsize);
1069
0
        return *pv == NULL ? -1 : 0;
1070
0
    }
1071
1072
40
    if (_PyObject_GC_IS_TRACKED(v)) {
1073
40
        _PyObject_GC_UNTRACK(v);
1074
40
    }
1075
#ifdef Py_TRACE_REFS
1076
    _Py_ForgetReference((PyObject *) v);
1077
#endif
1078
    /* DECREF items deleted by shrinkage */
1079
152
    for (i = newsize; i < oldsize; i++) {
1080
112
        Py_CLEAR(v->ob_item[i]);
1081
112
    }
1082
40
    _PyReftracerTrack((PyObject *)v, PyRefTracer_DESTROY);
1083
40
    sv = PyObject_GC_Resize(PyTupleObject, v, newsize);
1084
40
    if (sv == NULL) {
1085
0
        *pv = NULL;
1086
#ifdef Py_REF_DEBUG
1087
        _Py_DecRefTotal(_PyThreadState_GET());
1088
#endif
1089
0
        PyObject_GC_Del(v);
1090
0
        return -1;
1091
0
    }
1092
40
    _Py_NewReferenceNoTotal((PyObject *) sv);
1093
    /* Zero out items added by growing */
1094
40
    if (newsize > oldsize)
1095
0
        memset(&sv->ob_item[oldsize], 0,
1096
0
               sizeof(*sv->ob_item) * (newsize - oldsize));
1097
40
    *pv = (PyObject *) sv;
1098
40
    _PyObject_GC_TRACK(sv);
1099
40
    return 0;
1100
40
}
1101
1102
/*********************** Tuple Iterator **************************/
1103
1104
1.39G
#define _PyTupleIterObject_CAST(op) ((_PyTupleIterObject *)(op))
1105
1106
static void
1107
tupleiter_dealloc(PyObject *self)
1108
4.04M
{
1109
4.04M
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1110
4.04M
    _PyObject_GC_UNTRACK(it);
1111
4.04M
    Py_XDECREF(it->it_seq);
1112
4.04M
    assert(Py_IS_TYPE(self, &PyTupleIter_Type));
1113
4.04M
    _Py_FREELIST_FREE(tuple_iters, it, PyObject_GC_Del);
1114
4.04M
}
1115
1116
static int
1117
tupleiter_traverse(PyObject *self, visitproc visit, void *arg)
1118
816k
{
1119
816k
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1120
816k
    Py_VISIT(it->it_seq);
1121
816k
    return 0;
1122
816k
}
1123
1124
static PyObject *
1125
tupleiter_next(PyObject *self)
1126
1.38G
{
1127
1.38G
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1128
1.38G
    PyTupleObject *seq;
1129
1.38G
    PyObject *item;
1130
1131
1.38G
    assert(it != NULL);
1132
1.38G
    seq = it->it_seq;
1133
1.38G
#ifndef Py_GIL_DISABLED
1134
1.38G
    if (seq == NULL)
1135
0
        return NULL;
1136
1.38G
#endif
1137
1.38G
    assert(PyTuple_Check(seq));
1138
1139
1.38G
    Py_ssize_t index = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1140
1.38G
    if (index < PyTuple_GET_SIZE(seq)) {
1141
1.38G
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index + 1);
1142
1.38G
        item = PyTuple_GET_ITEM(seq, index);
1143
1.38G
        return Py_NewRef(item);
1144
1.38G
    }
1145
1146
3.55M
#ifndef Py_GIL_DISABLED
1147
3.55M
    it->it_seq = NULL;
1148
3.55M
    Py_DECREF(seq);
1149
3.55M
#endif
1150
3.55M
    return NULL;
1151
1.38G
}
1152
1153
static PyObject *
1154
tupleiter_len(PyObject *self, PyObject *Py_UNUSED(ignored))
1155
0
{
1156
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1157
0
    Py_ssize_t len = 0;
1158
#ifdef Py_GIL_DISABLED
1159
    Py_ssize_t idx = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1160
    Py_ssize_t seq_len = PyTuple_GET_SIZE(it->it_seq);
1161
    if (idx < seq_len)
1162
        len = seq_len - idx;
1163
#else
1164
0
    if (it->it_seq)
1165
0
        len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;
1166
0
#endif
1167
0
    return PyLong_FromSsize_t(len);
1168
0
}
1169
1170
PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");
1171
1172
static PyObject *
1173
tupleiter_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
1174
0
{
1175
0
    PyObject *iter = _PyEval_GetBuiltin(&_Py_ID(iter));
1176
1177
    /* _PyEval_GetBuiltin can invoke arbitrary code,
1178
     * call must be before access of iterator pointers.
1179
     * see issue #101765 */
1180
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1181
1182
#ifdef Py_GIL_DISABLED
1183
    Py_ssize_t idx = FT_ATOMIC_LOAD_SSIZE_RELAXED(it->it_index);
1184
    if (idx < PyTuple_GET_SIZE(it->it_seq))
1185
        return Py_BuildValue("N(O)n", iter, it->it_seq, idx);
1186
#else
1187
0
    if (it->it_seq)
1188
0
        return Py_BuildValue("N(O)n", iter, it->it_seq, it->it_index);
1189
0
#endif
1190
0
    return Py_BuildValue("N(())", iter);
1191
0
}
1192
1193
static PyObject *
1194
tupleiter_setstate(PyObject *self, PyObject *state)
1195
0
{
1196
0
    _PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
1197
0
    Py_ssize_t index = PyLong_AsSsize_t(state);
1198
0
    if (index == -1 && PyErr_Occurred())
1199
0
        return NULL;
1200
0
    if (it->it_seq != NULL) {
1201
0
        if (index < 0)
1202
0
            index = 0;
1203
0
        else if (index > PyTuple_GET_SIZE(it->it_seq))
1204
0
            index = PyTuple_GET_SIZE(it->it_seq); /* exhausted iterator */
1205
0
        FT_ATOMIC_STORE_SSIZE_RELAXED(it->it_index, index);
1206
0
    }
1207
0
    Py_RETURN_NONE;
1208
0
}
1209
1210
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
1211
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
1212
1213
static PyMethodDef tupleiter_methods[] = {
1214
    {"__length_hint__", tupleiter_len, METH_NOARGS, length_hint_doc},
1215
    {"__reduce__", tupleiter_reduce, METH_NOARGS, reduce_doc},
1216
    {"__setstate__", tupleiter_setstate, METH_O, setstate_doc},
1217
    {NULL, NULL, 0, NULL} /* sentinel */
1218
};
1219
1220
PyTypeObject PyTupleIter_Type = {
1221
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
1222
    "tuple_iterator",                           /* tp_name */
1223
    sizeof(_PyTupleIterObject),                 /* tp_basicsize */
1224
    0,                                          /* tp_itemsize */
1225
    /* methods */
1226
    tupleiter_dealloc,                          /* tp_dealloc */
1227
    0,                                          /* tp_vectorcall_offset */
1228
    0,                                          /* tp_getattr */
1229
    0,                                          /* tp_setattr */
1230
    0,                                          /* tp_as_async */
1231
    0,                                          /* tp_repr */
1232
    0,                                          /* tp_as_number */
1233
    0,                                          /* tp_as_sequence */
1234
    0,                                          /* tp_as_mapping */
1235
    0,                                          /* tp_hash */
1236
    0,                                          /* tp_call */
1237
    0,                                          /* tp_str */
1238
    PyObject_GenericGetAttr,                    /* tp_getattro */
1239
    0,                                          /* tp_setattro */
1240
    0,                                          /* tp_as_buffer */
1241
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
1242
    0,                                          /* tp_doc */
1243
    tupleiter_traverse,                         /* tp_traverse */
1244
    0,                                          /* tp_clear */
1245
    0,                                          /* tp_richcompare */
1246
    0,                                          /* tp_weaklistoffset */
1247
    PyObject_SelfIter,                          /* tp_iter */
1248
    tupleiter_next,                             /* tp_iternext */
1249
    tupleiter_methods,                          /* tp_methods */
1250
    0,
1251
};
1252
1253
static PyObject *
1254
tuple_iter(PyObject *seq)
1255
4.04M
{
1256
4.04M
    if (!PyTuple_Check(seq)) {
1257
0
        PyErr_BadInternalCall();
1258
0
        return NULL;
1259
0
    }
1260
4.04M
    _PyTupleIterObject *it = _Py_FREELIST_POP(_PyTupleIterObject, tuple_iters);
1261
4.04M
    if (it == NULL) {
1262
481k
        it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
1263
481k
        if (it == NULL)
1264
0
            return NULL;
1265
481k
    }
1266
4.04M
    it->it_index = 0;
1267
4.04M
    it->it_seq = (PyTupleObject *)Py_NewRef(seq);
1268
4.04M
    _PyObject_GC_TRACK(it);
1269
4.04M
    return (PyObject *)it;
1270
4.04M
}
1271
1272
1273
/*************
1274
 * freelists *
1275
 *************/
1276
1277
static inline int
1278
maybe_freelist_push(PyTupleObject *op)
1279
488M
{
1280
488M
    if (!Py_IS_TYPE(op, &PyTuple_Type)) {
1281
652k
        return 0;
1282
652k
    }
1283
487M
    Py_ssize_t index = Py_SIZE(op) - 1;
1284
487M
    if (index < PyTuple_MAXSAVESIZE) {
1285
484M
        return _Py_FREELIST_PUSH(tuples[index], op, Py_tuple_MAXFREELIST);
1286
484M
    }
1287
2.94M
    return 0;
1288
487M
}
1289
1290
/* Print summary info about the state of the optimized allocator */
1291
void
1292
_PyTuple_DebugMallocStats(FILE *out)
1293
0
{
1294
0
    for (int i = 0; i < PyTuple_MAXSAVESIZE; i++) {
1295
0
        int len = i + 1;
1296
0
        char buf[128];
1297
0
        PyOS_snprintf(buf, sizeof(buf),
1298
0
                      "free %d-sized PyTupleObject", len);
1299
0
        _PyDebugAllocatorStats(out, buf, _Py_FREELIST_SIZE(tuples[i]),
1300
0
                               _PyType_PreHeaderSize(&PyTuple_Type) + _PyObject_VAR_SIZE(&PyTuple_Type, len));
1301
0
    }
1302
0
}