@@ -233,6 +233,63 @@ valid_index(Py_ssize_t i, Py_ssize_t limit)
233233 return (size_t ) i < (size_t ) limit ;
234234}
235235
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+
236293PyObject *
237294PyList_GetItem (PyObject * op , Py_ssize_t i )
238295{
@@ -255,21 +312,13 @@ PyList_GetItemRef(PyObject *op, Py_ssize_t i)
255312 PyErr_SetString (PyExc_TypeError , "expected a list" );
256313 return NULL ;
257314 }
258- if (!valid_index (i , Py_SIZE (op ))) {
315+ PyObject * item = list_get_item_ref ((PyListObject * )op , i );
316+ if (item == NULL ) {
259317 _Py_DECLARE_STR (list_err , "list index out of range" );
260318 PyErr_SetObject (PyExc_IndexError , & _Py_STR (list_err ));
261319 return NULL ;
262320 }
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 ;
273322}
274323
275324int
0 commit comments