@@ -20,6 +20,14 @@ class list "PyListObject *" "&PyList_Type"
20
20
21
21
_Py_DECLARE_STR (list_err , "list index out of range" );
22
22
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
+
23
31
#ifdef WITH_FREELISTS
24
32
static struct _Py_list_freelist *
25
33
get_list_freelist (void )
@@ -2971,7 +2979,8 @@ list___sizeof___impl(PyListObject *self)
2971
2979
/*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/
2972
2980
{
2973
2981
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 * );
2975
2984
return PyLong_FromSize_t (res );
2976
2985
}
2977
2986
@@ -3373,33 +3382,34 @@ static PyObject *
3373
3382
listiter_next (PyObject * self )
3374
3383
{
3375
3384
_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 ) {
3382
3387
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 );
3389
3388
}
3390
3389
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 ;
3394
3403
}
3395
3404
3396
3405
static PyObject *
3397
3406
listiter_len (PyObject * self , PyObject * Py_UNUSED (ignored ))
3398
3407
{
3408
+ assert (self != NULL );
3399
3409
_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 ;
3403
3413
if (len >= 0 )
3404
3414
return PyLong_FromSsize_t (len );
3405
3415
}
@@ -3420,8 +3430,8 @@ listiter_setstate(PyObject *self, PyObject *state)
3420
3430
if (index == -1 && PyErr_Occurred ())
3421
3431
return NULL ;
3422
3432
if (it -> it_seq != NULL ) {
3423
- if (index < 0 )
3424
- index = 0 ;
3433
+ if (index < -1 )
3434
+ index = -1 ;
3425
3435
else if (index > PyList_GET_SIZE (it -> it_seq ))
3426
3436
index = PyList_GET_SIZE (it -> it_seq ); /* iterator exhausted */
3427
3437
it -> it_index = index ;
@@ -3526,34 +3536,33 @@ static PyObject *
3526
3536
listreviter_next (PyObject * self )
3527
3537
{
3528
3538
listreviterobject * it = (listreviterobject * )self ;
3529
- PyObject * item ;
3530
- Py_ssize_t index ;
3531
- PyListObject * seq ;
3532
-
3533
3539
assert (it != NULL );
3534
- seq = it -> it_seq ;
3535
- if (seq == NULL ) {
3536
- return NULL ;
3537
- }
3540
+ PyListObject * seq = it -> it_seq ;
3538
3541
assert (PyList_Check (seq ));
3539
3542
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 ;
3545
3551
}
3546
- it -> it_index = -1 ;
3552
+ STORE_SSIZE (it -> it_index , -1 );
3553
+ #ifndef Py_GIL_DISABLED
3547
3554
it -> it_seq = NULL ;
3548
3555
Py_DECREF (seq );
3556
+ #endif
3549
3557
return NULL ;
3550
3558
}
3551
3559
3552
3560
static PyObject *
3553
3561
listreviter_len (PyObject * self , PyObject * Py_UNUSED (ignored ))
3554
3562
{
3555
3563
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 ;
3557
3566
if (it -> it_seq == NULL || PyList_GET_SIZE (it -> it_seq ) < len )
3558
3567
len = 0 ;
3559
3568
return PyLong_FromSsize_t (len );
@@ -3588,36 +3597,29 @@ static PyObject *
3588
3597
listiter_reduce_general (void * _it , int forward )
3589
3598
{
3590
3599
PyObject * list ;
3600
+ PyObject * iter ;
3591
3601
3592
3602
/* _PyEval_GetBuiltin can invoke arbitrary code,
3593
3603
* call must be before access of iterator pointers.
3594
3604
* see issue #101765 */
3595
3605
3596
3606
/* the objects are not the same, index is of different types! */
3597
3607
if (forward ) {
3598
- PyObject * iter = _PyEval_GetBuiltin (& _Py_ID (iter ));
3599
- if (!iter ) {
3600
- return NULL ;
3601
- }
3608
+ iter = _PyEval_GetBuiltin (& _Py_ID (iter ));
3602
3609
_PyListIterObject * it = (_PyListIterObject * )_it ;
3603
- if (it -> it_seq ) {
3610
+ if (it -> it_index >= 0 ) {
3604
3611
return Py_BuildValue ("N(O)n" , iter , it -> it_seq , it -> it_index );
3605
3612
}
3606
- Py_DECREF (iter );
3607
3613
} else {
3608
- PyObject * reversed = _PyEval_GetBuiltin (& _Py_ID (reversed ));
3609
- if (!reversed ) {
3610
- return NULL ;
3611
- }
3614
+ iter = _PyEval_GetBuiltin (& _Py_ID (reversed ));
3612
3615
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 );
3615
3618
}
3616
- Py_DECREF (reversed );
3617
3619
}
3618
3620
/* empty iterator, create an empty list */
3619
3621
list = PyList_New (0 );
3620
3622
if (list == NULL )
3621
3623
return NULL ;
3622
- return Py_BuildValue ("N(N)" , _PyEval_GetBuiltin ( & _Py_ID ( iter )) , list );
3624
+ return Py_BuildValue ("N(N)" , iter , list );
3623
3625
}
0 commit comments