Coverage Report

Created: 2026-10-17 06:15

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