@@ -59,6 +59,15 @@ show_track(void)
5959}
6060#endif
6161
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+
6271/* Print summary info about the state of the optimized allocator */
6372void
6473_PyTuple_DebugMallocStats (FILE * out )
@@ -76,25 +85,25 @@ _PyTuple_DebugMallocStats(FILE *out)
7685#endif
7786}
7887
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 )
8198{
8299 PyTupleObject * op ;
83- Py_ssize_t i ;
84100 if (size < 0 ) {
85101 PyErr_BadInternalCall ();
86102 return NULL ;
87103 }
88104#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- }
97105 if (size < PyTuple_MAXSAVESIZE && (op = free_list [size ]) != NULL ) {
106+ assert (size != 0 );
98107 free_list [size ] = (PyTupleObject * ) op -> ob_item [0 ];
99108 numfree [size ]-- ;
100109#ifdef COUNT_ALLOCS
@@ -113,25 +122,41 @@ PyTuple_New(Py_ssize_t size)
113122 /* Check for overflow */
114123 if ((size_t )size > ((size_t )PY_SSIZE_T_MAX - sizeof (PyTupleObject ) -
115124 sizeof (PyObject * )) / sizeof (PyObject * )) {
116- return PyErr_NoMemory ();
125+ return ( PyTupleObject * ) PyErr_NoMemory ();
117126 }
118127 op = PyObject_GC_NewVar (PyTupleObject , & PyTuple_Type , size );
119128 if (op == NULL )
120129 return NULL ;
121130 }
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 ++ ) {
123150 op -> ob_item [i ] = NULL ;
151+ }
124152#if PyTuple_MAXSAVESIZE > 0
125153 if (size == 0 ) {
126154 free_list [0 ] = op ;
127155 ++ numfree [0 ];
128156 Py_INCREF (op ); /* extra INCREF so that this is never freed */
129157 }
130158#endif
131- #ifdef SHOW_TRACK_COUNT
132- count_tracked ++ ;
133- #endif
134- _PyObject_GC_TRACK (op );
159+ tuple_gc_track (op );
135160 return (PyObject * ) op ;
136161}
137162
@@ -211,24 +236,28 @@ PyTuple_Pack(Py_ssize_t n, ...)
211236{
212237 Py_ssize_t i ;
213238 PyObject * o ;
214- PyObject * result ;
215239 PyObject * * items ;
216240 va_list vargs ;
217241
242+ if (n == 0 ) {
243+ return PyTuple_New (0 );
244+ }
245+
218246 va_start (vargs , n );
219- result = PyTuple_New (n );
247+ PyTupleObject * result = tuple_alloc (n );
220248 if (result == NULL ) {
221249 va_end (vargs );
222250 return NULL ;
223251 }
224- items = (( PyTupleObject * ) result ) -> ob_item ;
252+ items = result -> ob_item ;
225253 for (i = 0 ; i < n ; i ++ ) {
226254 o = va_arg (vargs , PyObject * );
227255 Py_INCREF (o );
228256 items [i ] = o ;
229257 }
230258 va_end (vargs );
231- return result ;
259+ tuple_gc_track (result );
260+ return (PyObject * )result ;
232261}
233262
234263
@@ -421,7 +450,11 @@ tupleitem(PyTupleObject *a, Py_ssize_t i)
421450PyObject *
422451_PyTuple_FromArray (PyObject * const * src , Py_ssize_t n )
423452{
424- PyTupleObject * tuple = (PyTupleObject * )PyTuple_New (n );
453+ if (n == 0 ) {
454+ return PyTuple_New (0 );
455+ }
456+
457+ PyTupleObject * tuple = tuple_alloc (n );
425458 if (tuple == NULL ) {
426459 return NULL ;
427460 }
@@ -431,6 +464,7 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)
431464 Py_INCREF (item );
432465 dst [i ] = item ;
433466 }
467+ tuple_gc_track (tuple );
434468 return (PyObject * )tuple ;
435469}
436470
@@ -486,7 +520,11 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
486520 if (Py_SIZE (a ) > PY_SSIZE_T_MAX - Py_SIZE (b ))
487521 return PyErr_NoMemory ();
488522 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 );
490528 if (np == NULL ) {
491529 return NULL ;
492530 }
@@ -504,6 +542,7 @@ tupleconcat(PyTupleObject *a, PyObject *bb)
504542 Py_INCREF (v );
505543 dest [i ] = v ;
506544 }
545+ tuple_gc_track (np );
507546 return (PyObject * )np ;
508547#undef b
509548}
@@ -515,22 +554,21 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
515554 Py_ssize_t size ;
516555 PyTupleObject * np ;
517556 PyObject * * p , * * items ;
518- if (n < 0 )
519- n = 0 ;
520557 if (Py_SIZE (a ) == 0 || n == 1 ) {
521558 if (PyTuple_CheckExact (a )) {
522559 /* Since tuples are immutable, we can return a shared
523560 copy in this case */
524561 Py_INCREF (a );
525562 return (PyObject * )a ;
526563 }
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 );
529567 }
530568 if (n > PY_SSIZE_T_MAX / Py_SIZE (a ))
531569 return PyErr_NoMemory ();
532570 size = Py_SIZE (a ) * n ;
533- np = ( PyTupleObject * ) PyTuple_New (size );
571+ np = tuple_alloc (size );
534572 if (np == NULL )
535573 return NULL ;
536574 p = np -> ob_item ;
@@ -542,6 +580,7 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
542580 p ++ ;
543581 }
544582 }
583+ tuple_gc_track (np );
545584 return (PyObject * ) np ;
546585}
547586
@@ -754,7 +793,6 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
754793 else if (PySlice_Check (item )) {
755794 Py_ssize_t start , stop , step , slicelength , i ;
756795 size_t cur ;
757- PyObject * result ;
758796 PyObject * it ;
759797 PyObject * * src , * * dest ;
760798
@@ -774,19 +812,20 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
774812 return (PyObject * )self ;
775813 }
776814 else {
777- result = PyTuple_New (slicelength );
815+ PyTupleObject * result = tuple_alloc (slicelength );
778816 if (!result ) return NULL ;
779817
780818 src = self -> ob_item ;
781- dest = (( PyTupleObject * ) result ) -> ob_item ;
819+ dest = result -> ob_item ;
782820 for (cur = start , i = 0 ; i < slicelength ;
783821 cur += step , i ++ ) {
784822 it = src [cur ];
785823 Py_INCREF (it );
786824 dest [i ] = it ;
787825 }
788826
789- return result ;
827+ tuple_gc_track (result );
828+ return (PyObject * )result ;
790829 }
791830 }
792831 else {
0 commit comments