@@ -59,6 +59,15 @@ show_track(void)
59
59
}
60
60
#endif
61
61
62
+ static inline void
63
+ tuple_gc_track (PyTupleObject * op )
64
+ {
65
+ #ifdef SHOW_TRACK_COUNT
66
+ count_tracked ++ ;
67
+ #endif
68
+ _PyObject_GC_TRACK (op );
69
+ }
70
+
62
71
/* Print summary info about the state of the optimized allocator */
63
72
void
64
73
_PyTuple_DebugMallocStats (FILE * out )
@@ -76,25 +85,25 @@ _PyTuple_DebugMallocStats(FILE *out)
76
85
#endif
77
86
}
78
87
79
- PyObject *
80
- PyTuple_New (Py_ssize_t size )
88
+ /* Allocate an uninitialized tuple object. Before making it public following
89
+ steps must be done:
90
+ - initialize its items
91
+ - call tuple_gc_track() on it
92
+ Because the empty tuple is always reused and it's already tracked by GC,
93
+ this function must not be called with size == 0 (unless from PyTuple_New()
94
+ which wraps this function).
95
+ */
96
+ static PyTupleObject *
97
+ tuple_alloc (Py_ssize_t size )
81
98
{
82
99
PyTupleObject * op ;
83
- Py_ssize_t i ;
84
100
if (size < 0 ) {
85
101
PyErr_BadInternalCall ();
86
102
return NULL ;
87
103
}
88
104
#if PyTuple_MAXSAVESIZE > 0
89
- if (size == 0 && free_list [0 ]) {
90
- op = free_list [0 ];
91
- Py_INCREF (op );
92
- #ifdef COUNT_ALLOCS
93
- _Py_tuple_zero_allocs ++ ;
94
- #endif
95
- return (PyObject * ) op ;
96
- }
97
105
if (size < PyTuple_MAXSAVESIZE && (op = free_list [size ]) != NULL ) {
106
+ assert (size != 0 );
98
107
free_list [size ] = (PyTupleObject * ) op -> ob_item [0 ];
99
108
numfree [size ]-- ;
100
109
#ifdef COUNT_ALLOCS
@@ -113,25 +122,41 @@ PyTuple_New(Py_ssize_t size)
113
122
/* Check for overflow */
114
123
if ((size_t )size > ((size_t )PY_SSIZE_T_MAX - sizeof (PyTupleObject ) -
115
124
sizeof (PyObject * )) / sizeof (PyObject * )) {
116
- return PyErr_NoMemory ();
125
+ return ( PyTupleObject * ) PyErr_NoMemory ();
117
126
}
118
127
op = PyObject_GC_NewVar (PyTupleObject , & PyTuple_Type , size );
119
128
if (op == NULL )
120
129
return NULL ;
121
130
}
122
- for (i = 0 ; i < size ; i ++ )
131
+ return op ;
132
+ }
133
+
134
+ PyObject *
135
+ PyTuple_New (Py_ssize_t size )
136
+ {
137
+ PyTupleObject * op ;
138
+ #if PyTuple_MAXSAVESIZE > 0
139
+ if (size == 0 && free_list [0 ]) {
140
+ op = free_list [0 ];
141
+ Py_INCREF (op );
142
+ #ifdef COUNT_ALLOCS
143
+ _Py_tuple_zero_allocs ++ ;
144
+ #endif
145
+ return (PyObject * ) op ;
146
+ }
147
+ #endif
148
+ op = tuple_alloc (size );
149
+ for (Py_ssize_t i = 0 ; i < size ; i ++ ) {
123
150
op -> ob_item [i ] = NULL ;
151
+ }
124
152
#if PyTuple_MAXSAVESIZE > 0
125
153
if (size == 0 ) {
126
154
free_list [0 ] = op ;
127
155
++ numfree [0 ];
128
156
Py_INCREF (op ); /* extra INCREF so that this is never freed */
129
157
}
130
158
#endif
131
- #ifdef SHOW_TRACK_COUNT
132
- count_tracked ++ ;
133
- #endif
134
- _PyObject_GC_TRACK (op );
159
+ tuple_gc_track (op );
135
160
return (PyObject * ) op ;
136
161
}
137
162
@@ -211,24 +236,28 @@ PyTuple_Pack(Py_ssize_t n, ...)
211
236
{
212
237
Py_ssize_t i ;
213
238
PyObject * o ;
214
- PyObject * result ;
215
239
PyObject * * items ;
216
240
va_list vargs ;
217
241
242
+ if (n == 0 ) {
243
+ return PyTuple_New (0 );
244
+ }
245
+
218
246
va_start (vargs , n );
219
- result = PyTuple_New (n );
247
+ PyTupleObject * result = tuple_alloc (n );
220
248
if (result == NULL ) {
221
249
va_end (vargs );
222
250
return NULL ;
223
251
}
224
- items = (( PyTupleObject * ) result ) -> ob_item ;
252
+ items = result -> ob_item ;
225
253
for (i = 0 ; i < n ; i ++ ) {
226
254
o = va_arg (vargs , PyObject * );
227
255
Py_INCREF (o );
228
256
items [i ] = o ;
229
257
}
230
258
va_end (vargs );
231
- return result ;
259
+ tuple_gc_track (result );
260
+ return (PyObject * )result ;
232
261
}
233
262
234
263
@@ -421,7 +450,11 @@ tupleitem(PyTupleObject *a, Py_ssize_t i)
421
450
PyObject *
422
451
_PyTuple_FromArray (PyObject * const * src , Py_ssize_t n )
423
452
{
424
- PyTupleObject * tuple = (PyTupleObject * )PyTuple_New (n );
453
+ if (n == 0 ) {
454
+ return PyTuple_New (0 );
455
+ }
456
+
457
+ PyTupleObject * tuple = tuple_alloc (n );
425
458
if (tuple == NULL ) {
426
459
return NULL ;
427
460
}
@@ -431,6 +464,7 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
431
464
Py_INCREF (item );
432
465
dst [i ] = item ;
433
466
}
467
+ tuple_gc_track (tuple );
434
468
return (PyObject * )tuple ;
435
469
}
436
470
@@ -486,7 +520,11 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
486
520
if (Py_SIZE (a ) > PY_SSIZE_T_MAX - Py_SIZE (b ))
487
521
return PyErr_NoMemory ();
488
522
size = Py_SIZE (a ) + Py_SIZE (b );
489
- np = (PyTupleObject * ) PyTuple_New (size );
523
+ if (size == 0 ) {
524
+ return PyTuple_New (0 );
525
+ }
526
+
527
+ np = tuple_alloc (size );
490
528
if (np == NULL ) {
491
529
return NULL ;
492
530
}
@@ -504,6 +542,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
504
542
Py_INCREF (v );
505
543
dest [i ] = v ;
506
544
}
545
+ tuple_gc_track (np );
507
546
return (PyObject * )np ;
508
547
#undef b
509
548
}
@@ -515,22 +554,21 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
515
554
Py_ssize_t size ;
516
555
PyTupleObject * np ;
517
556
PyObject * * p , * * items ;
518
- if (n < 0 )
519
- n = 0 ;
520
557
if (Py_SIZE (a ) == 0 || n == 1 ) {
521
558
if (PyTuple_CheckExact (a )) {
522
559
/* Since tuples are immutable, we can return a shared
523
560
copy in this case */
524
561
Py_INCREF (a );
525
562
return (PyObject * )a ;
526
563
}
527
- if (Py_SIZE (a ) == 0 )
528
- return PyTuple_New (0 );
564
+ }
565
+ if (Py_SIZE (a ) == 0 || n <= 0 ) {
566
+ return PyTuple_New (0 );
529
567
}
530
568
if (n > PY_SSIZE_T_MAX / Py_SIZE (a ))
531
569
return PyErr_NoMemory ();
532
570
size = Py_SIZE (a ) * n ;
533
- np = ( PyTupleObject * ) PyTuple_New (size );
571
+ np = tuple_alloc (size );
534
572
if (np == NULL )
535
573
return NULL ;
536
574
p = np -> ob_item ;
@@ -542,6 +580,7 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
542
580
p ++ ;
543
581
}
544
582
}
583
+ tuple_gc_track (np );
545
584
return (PyObject * ) np ;
546
585
}
547
586
@@ -754,7 +793,6 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
754
793
else if (PySlice_Check (item )) {
755
794
Py_ssize_t start , stop , step , slicelength , i ;
756
795
size_t cur ;
757
- PyObject * result ;
758
796
PyObject * it ;
759
797
PyObject * * src , * * dest ;
760
798
@@ -774,19 +812,20 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
774
812
return (PyObject * )self ;
775
813
}
776
814
else {
777
- result = PyTuple_New (slicelength );
815
+ PyTupleObject * result = tuple_alloc (slicelength );
778
816
if (!result ) return NULL ;
779
817
780
818
src = self -> ob_item ;
781
- dest = (( PyTupleObject * ) result ) -> ob_item ;
819
+ dest = result -> ob_item ;
782
820
for (cur = start , i = 0 ; i < slicelength ;
783
821
cur += step , i ++ ) {
784
822
it = src [cur ];
785
823
Py_INCREF (it );
786
824
dest [i ] = it ;
787
825
}
788
826
789
- return result ;
827
+ tuple_gc_track (result );
828
+ return (PyObject * )result ;
790
829
}
791
830
}
792
831
else {
0 commit comments