@@ -20,6 +20,14 @@ class list "PyListObject *" "&PyList_Type"
2020
2121_Py_DECLARE_STR (list_err , "list index out of range" );
2222
23+ #ifdef Py_GIL_DISABLED
24+ # define LOAD_SSIZE (value ) _Py_atomic_load_ssize_relaxed(&value)
25+ # define STORE_SSIZE (value , new_value ) _Py_atomic_store_ssize_relaxed(&value, new_value)
26+ #else
27+ # define LOAD_SSIZE (value ) value
28+ # define STORE_SSIZE (value , new_value ) value = new_value
29+ #endif
30+
2331#ifdef WITH_FREELISTS
2432static struct _Py_list_freelist *
2533get_list_freelist (void )
@@ -2971,7 +2979,8 @@ list___sizeof___impl(PyListObject *self)
29712979/*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/
29722980{
29732981 size_t res = _PyObject_SIZE (Py_TYPE (self ));
2974- res += (size_t )self -> allocated * sizeof (void * );
2982+ Py_ssize_t allocated = LOAD_SSIZE (self -> allocated );
2983+ res += (size_t )allocated * sizeof (void * );
29752984 return PyLong_FromSize_t (res );
29762985}
29772986
@@ -3373,33 +3382,34 @@ static PyObject *
33733382listiter_next (PyObject * self )
33743383{
33753384 _PyListIterObject * it = (_PyListIterObject * )self ;
3376- PyListObject * seq ;
3377- PyObject * item ;
3378-
3379- assert (it != NULL );
3380- seq = it -> it_seq ;
3381- if (seq == NULL )
3385+ Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3386+ if (index < 0 ) {
33823387 return NULL ;
3383- assert (PyList_Check (seq ));
3384-
3385- if (it -> it_index < PyList_GET_SIZE (seq )) {
3386- item = PyList_GET_ITEM (seq , it -> it_index );
3387- ++ it -> it_index ;
3388- return Py_NewRef (item );
33893388 }
33903389
3391- it -> it_seq = NULL ;
3392- Py_DECREF (seq );
3393- return NULL ;
3390+ PyObject * item = list_get_item_ref (it -> it_seq , index );
3391+ if (item == NULL ) {
3392+ // out-of-bounds
3393+ STORE_SSIZE (it -> it_index , -1 );
3394+ #ifndef Py_GIL_DISABLED
3395+ PyListObject * seq = it -> it_seq ;
3396+ it -> it_seq = NULL ;
3397+ Py_DECREF (seq );
3398+ #endif
3399+ return NULL ;
3400+ }
3401+ STORE_SSIZE (it -> it_index , index + 1 );
3402+ return item ;
33943403}
33953404
33963405static PyObject *
33973406listiter_len (PyObject * self , PyObject * Py_UNUSED (ignored ))
33983407{
3408+ assert (self != NULL );
33993409 _PyListIterObject * it = (_PyListIterObject * )self ;
3400- Py_ssize_t len ;
3401- if (it -> it_seq ) {
3402- len = PyList_GET_SIZE (it -> it_seq ) - it -> it_index ;
3410+ Py_ssize_t index = LOAD_SSIZE ( it -> it_index ) ;
3411+ if (index >= 0 ) {
3412+ Py_ssize_t len = PyList_GET_SIZE (it -> it_seq ) - index ;
34033413 if (len >= 0 )
34043414 return PyLong_FromSsize_t (len );
34053415 }
@@ -3420,8 +3430,8 @@ listiter_setstate(PyObject *self, PyObject *state)
34203430 if (index == -1 && PyErr_Occurred ())
34213431 return NULL ;
34223432 if (it -> it_seq != NULL ) {
3423- if (index < 0 )
3424- index = 0 ;
3433+ if (index < -1 )
3434+ index = -1 ;
34253435 else if (index > PyList_GET_SIZE (it -> it_seq ))
34263436 index = PyList_GET_SIZE (it -> it_seq ); /* iterator exhausted */
34273437 it -> it_index = index ;
@@ -3526,34 +3536,33 @@ static PyObject *
35263536listreviter_next (PyObject * self )
35273537{
35283538 listreviterobject * it = (listreviterobject * )self ;
3529- PyObject * item ;
3530- Py_ssize_t index ;
3531- PyListObject * seq ;
3532-
35333539 assert (it != NULL );
3534- seq = it -> it_seq ;
3535- if (seq == NULL ) {
3536- return NULL ;
3537- }
3540+ PyListObject * seq = it -> it_seq ;
35383541 assert (PyList_Check (seq ));
35393542
3540- index = it -> it_index ;
3541- if (index >=0 && index < PyList_GET_SIZE (seq )) {
3542- item = PyList_GET_ITEM (seq , index );
3543- it -> it_index -- ;
3544- return Py_NewRef (item );
3543+ Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3544+ if (index < 0 ) {
3545+ return NULL ;
3546+ }
3547+ PyObject * item = list_get_item_ref (seq , index );
3548+ if (item != NULL ) {
3549+ STORE_SSIZE (it -> it_index , index - 1 );
3550+ return item ;
35453551 }
3546- it -> it_index = -1 ;
3552+ STORE_SSIZE (it -> it_index , -1 );
3553+ #ifndef Py_GIL_DISABLED
35473554 it -> it_seq = NULL ;
35483555 Py_DECREF (seq );
3556+ #endif
35493557 return NULL ;
35503558}
35513559
35523560static PyObject *
35533561listreviter_len (PyObject * self , PyObject * Py_UNUSED (ignored ))
35543562{
35553563 listreviterobject * it = (listreviterobject * )self ;
3556- Py_ssize_t len = it -> it_index + 1 ;
3564+ Py_ssize_t index = LOAD_SSIZE (it -> it_index );
3565+ Py_ssize_t len = index + 1 ;
35573566 if (it -> it_seq == NULL || PyList_GET_SIZE (it -> it_seq ) < len )
35583567 len = 0 ;
35593568 return PyLong_FromSsize_t (len );
@@ -3588,36 +3597,29 @@ static PyObject *
35883597listiter_reduce_general (void * _it , int forward )
35893598{
35903599 PyObject * list ;
3600+ PyObject * iter ;
35913601
35923602 /* _PyEval_GetBuiltin can invoke arbitrary code,
35933603 * call must be before access of iterator pointers.
35943604 * see issue #101765 */
35953605
35963606 /* the objects are not the same, index is of different types! */
35973607 if (forward ) {
3598- PyObject * iter = _PyEval_GetBuiltin (& _Py_ID (iter ));
3599- if (!iter ) {
3600- return NULL ;
3601- }
3608+ iter = _PyEval_GetBuiltin (& _Py_ID (iter ));
36023609 _PyListIterObject * it = (_PyListIterObject * )_it ;
3603- if (it -> it_seq ) {
3610+ if (it -> it_index >= 0 ) {
36043611 return Py_BuildValue ("N(O)n" , iter , it -> it_seq , it -> it_index );
36053612 }
3606- Py_DECREF (iter );
36073613 } else {
3608- PyObject * reversed = _PyEval_GetBuiltin (& _Py_ID (reversed ));
3609- if (!reversed ) {
3610- return NULL ;
3611- }
3614+ iter = _PyEval_GetBuiltin (& _Py_ID (reversed ));
36123615 listreviterobject * it = (listreviterobject * )_it ;
3613- if (it -> it_seq ) {
3614- return Py_BuildValue ("N(O)n" , reversed , it -> it_seq , it -> it_index );
3616+ if (it -> it_index >= 0 ) {
3617+ return Py_BuildValue ("N(O)n" , iter , it -> it_seq , it -> it_index );
36153618 }
3616- Py_DECREF (reversed );
36173619 }
36183620 /* empty iterator, create an empty list */
36193621 list = PyList_New (0 );
36203622 if (list == NULL )
36213623 return NULL ;
3622- return Py_BuildValue ("N(N)" , _PyEval_GetBuiltin ( & _Py_ID ( iter )) , list );
3624+ return Py_BuildValue ("N(N)" , iter , list );
36233625}
0 commit comments