@@ -233,6 +233,63 @@ valid_index(Py_ssize_t i, Py_ssize_t limit)
233
233
return (size_t ) i < (size_t ) limit ;
234
234
}
235
235
236
+ #ifdef Py_GIL_DISABLED
237
+
238
+ static PyObject *
239
+ list_item_impl (PyListObject * self , Py_ssize_t idx )
240
+ {
241
+ PyObject * item = NULL ;
242
+ Py_BEGIN_CRITICAL_SECTION (self );
243
+ if (!_PyObject_GC_IS_SHARED (self )) {
244
+ _PyObject_GC_SET_SHARED (self );
245
+ }
246
+ Py_ssize_t size = Py_SIZE (self );
247
+ if (!valid_index (idx , size )) {
248
+ goto exit ;
249
+ }
250
+ item = Py_NewRef (self -> ob_item [idx ]);
251
+ exit :
252
+ Py_END_CRITICAL_SECTION ();
253
+ return item ;
254
+ }
255
+
256
+ static inline PyObject *
257
+ list_get_item_ref (PyListObject * op , Py_ssize_t i )
258
+ {
259
+ if (!_Py_IsOwnedByCurrentThread ((PyObject * )op ) && !_PyObject_GC_IS_SHARED (op )) {
260
+ return list_item_impl (op , i );
261
+ }
262
+ // Need atomic operation for the getting size.
263
+ Py_ssize_t size = PyList_GET_SIZE (op );
264
+ if (!valid_index (i , size )) {
265
+ return NULL ;
266
+ }
267
+ PyObject * * ob_item = _Py_atomic_load_ptr (& op -> ob_item );
268
+ if (ob_item == NULL ) {
269
+ return NULL ;
270
+ }
271
+ Py_ssize_t cap = _Py_atomic_load_ssize_relaxed (& op -> allocated );
272
+ assert (cap != -1 && cap >= size );
273
+ if (!valid_index (i , cap )) {
274
+ return NULL ;
275
+ }
276
+ PyObject * item = _Py_TryXGetRef (& ob_item [i ]);
277
+ if (item == NULL ) {
278
+ return list_item_impl (op , i );
279
+ }
280
+ return item ;
281
+ }
282
+ #else
283
+ static inline PyObject *
284
+ list_get_item_ref (PyListObject * op , Py_ssize_t i )
285
+ {
286
+ if (!valid_index (i , Py_SIZE (op ))) {
287
+ return NULL ;
288
+ }
289
+ return Py_NewRef (PyList_GET_ITEM (op , i ));
290
+ }
291
+ #endif
292
+
236
293
PyObject *
237
294
PyList_GetItem (PyObject * op , Py_ssize_t i )
238
295
{
@@ -255,21 +312,13 @@ PyList_GetItemRef(PyObject *op, Py_ssize_t i)
255
312
PyErr_SetString (PyExc_TypeError , "expected a list" );
256
313
return NULL ;
257
314
}
258
- if (!valid_index (i , Py_SIZE (op ))) {
315
+ PyObject * item = list_get_item_ref ((PyListObject * )op , i );
316
+ if (item == NULL ) {
259
317
_Py_DECLARE_STR (list_err , "list index out of range" );
260
318
PyErr_SetObject (PyExc_IndexError , & _Py_STR (list_err ));
261
319
return NULL ;
262
320
}
263
- return Py_NewRef (PyList_GET_ITEM (op , i ));
264
- }
265
-
266
- static inline PyObject *
267
- list_get_item_ref (PyListObject * op , Py_ssize_t i )
268
- {
269
- if (!valid_index (i , Py_SIZE (op ))) {
270
- return NULL ;
271
- }
272
- return Py_NewRef (PyList_GET_ITEM (op , i ));
321
+ return item ;
273
322
}
274
323
275
324
int
0 commit comments