@@ -1993,9 +1993,6 @@ PyObject *
19931993PySequence_Tuple (PyObject * v )
19941994{
19951995 PyObject * it ; /* iter(v) */
1996- Py_ssize_t n ; /* guess for result tuple size */
1997- PyObject * result = NULL ;
1998- Py_ssize_t j ;
19991996
20001997 if (v == NULL ) {
20011998 return null_error ();
@@ -2017,58 +2014,54 @@ PySequence_Tuple(PyObject *v)
20172014 if (it == NULL )
20182015 return NULL ;
20192016
2020- /* Guess result size and allocate space. */
2021- n = PyObject_LengthHint (v , 10 );
2022- if (n == -1 )
2023- goto Fail ;
2024- result = PyTuple_New (n );
2025- if (result == NULL )
2026- goto Fail ;
2027-
2028- /* Fill the tuple. */
2029- for (j = 0 ; ; ++ j ) {
2017+ Py_ssize_t n ;
2018+ PyObject * buffer [8 ];
2019+ for (n = 0 ; n < 8 ; n ++ ) {
20302020 PyObject * item = PyIter_Next (it );
20312021 if (item == NULL ) {
2032- if (PyErr_Occurred ())
2033- goto Fail ;
2034- break ;
2035- }
2036- if (j >= n ) {
2037- size_t newn = (size_t )n ;
2038- /* The over-allocation strategy can grow a bit faster
2039- than for lists because unlike lists the
2040- over-allocation isn't permanent -- we reclaim
2041- the excess before the end of this routine.
2042- So, grow by ten and then add 25%.
2043- */
2044- newn += 10u ;
2045- newn += newn >> 2 ;
2046- if (newn > PY_SSIZE_T_MAX ) {
2047- /* Check for overflow */
2048- PyErr_NoMemory ();
2049- Py_DECREF (item );
2050- goto Fail ;
2022+ if (PyErr_Occurred ()) {
2023+ goto fail ;
20512024 }
2052- n = (Py_ssize_t )newn ;
2053- if (_PyTuple_Resize (& result , n ) != 0 ) {
2054- Py_DECREF (item );
2055- goto Fail ;
2025+ Py_DECREF (it );
2026+ return _PyTuple_FromArraySteal (buffer , n );
2027+ }
2028+ buffer [n ] = item ;
2029+ }
2030+ PyListObject * list = (PyListObject * )PyList_New (16 );
2031+ if (list == NULL ) {
2032+ goto fail ;
2033+ }
2034+ assert (n == 8 );
2035+ Py_SET_SIZE (list , n );
2036+ for (Py_ssize_t j = 0 ; j < n ; j ++ ) {
2037+ PyList_SET_ITEM (list , j , buffer [j ]);
2038+ }
2039+ for (;;) {
2040+ PyObject * item = PyIter_Next (it );
2041+ if (item == NULL ) {
2042+ if (PyErr_Occurred ()) {
2043+ Py_DECREF (list );
2044+ Py_DECREF (it );
2045+ return NULL ;
20562046 }
2047+ break ;
2048+ }
2049+ if (_PyList_AppendTakeRef (list , item ) < 0 ) {
2050+ Py_DECREF (list );
2051+ Py_DECREF (it );
2052+ return NULL ;
20572053 }
2058- PyTuple_SET_ITEM (result , j , item );
20592054 }
2060-
2061- /* Cut tuple back if guess was too large. */
2062- if (j < n &&
2063- _PyTuple_Resize (& result , j ) != 0 )
2064- goto Fail ;
2065-
20662055 Py_DECREF (it );
2067- return result ;
2068-
2069- Fail :
2070- Py_XDECREF ( result );
2056+ PyObject * res = _PyList_AsTupleAndClear ( list ) ;
2057+ Py_DECREF ( list );
2058+ return res ;
2059+ fail :
20712060 Py_DECREF (it );
2061+ while (n > 0 ) {
2062+ n -- ;
2063+ Py_DECREF (buffer [n ]);
2064+ }
20722065 return NULL ;
20732066}
20742067
0 commit comments