@@ -31,6 +31,50 @@ get_list_freelist(void)
3131}
3232#endif
3333
34+ #ifdef Py_GIL_DISABLED
35+ typedef struct {
36+ Py_ssize_t allocated ;
37+ PyObject * ob_item [];
38+ } _PyListArray ;
39+
40+ static _PyListArray *
41+ list_allocate_array (size_t capacity )
42+ {
43+ if (capacity > PY_SSIZE_T_MAX /sizeof (PyObject * ) - 1 ) {
44+ return NULL ;
45+ }
46+ _PyListArray * array = PyMem_Malloc (sizeof (_PyListArray ) + capacity * sizeof (PyObject * ));
47+ if (array == NULL ) {
48+ return NULL ;
49+ }
50+ array -> allocated = capacity ;
51+ return array ;
52+ }
53+
54+ static Py_ssize_t
55+ list_capacity (PyObject * * items )
56+ {
57+ _PyListArray * array = _Py_CONTAINER_OF (items , _PyListArray , ob_item );
58+ return array -> allocated ;
59+ }
60+ #endif
61+
62+ static void
63+ free_list_items (PyObject * * items , bool use_qsbr )
64+ {
65+ #ifdef Py_GIL_DISABLED
66+ _PyListArray * array = _Py_CONTAINER_OF (items , _PyListArray , ob_item );
67+ if (use_qsbr ) {
68+ _PyMem_FreeDelayed (array );
69+ }
70+ else {
71+ PyMem_Free (array );
72+ }
73+ #else
74+ PyMem_Free (items );
75+ #endif
76+ }
77+
3478/* Ensure ob_item has room for at least newsize elements, and set
3579 * ob_size to newsize. If newsize > ob_size on entry, the content
3680 * of the new slots at exit is undefined heap trash; it's the caller's
@@ -47,8 +91,7 @@ get_list_freelist(void)
4791static int
4892list_resize (PyListObject * self , Py_ssize_t newsize )
4993{
50- PyObject * * items ;
51- size_t new_allocated , num_allocated_bytes ;
94+ size_t new_allocated , target_bytes ;
5295 Py_ssize_t allocated = self -> allocated ;
5396
5497 /* Bypass realloc() when a previous overallocation is large enough
@@ -80,9 +123,34 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
80123
81124 if (newsize == 0 )
82125 new_allocated = 0 ;
126+
127+ #ifdef Py_GIL_DISABLED
128+ _PyListArray * array = list_allocate_array (new_allocated );
129+ if (array == NULL ) {
130+ PyErr_NoMemory ();
131+ return -1 ;
132+ }
133+ PyObject * * old_items = self -> ob_item ;
134+ if (self -> ob_item ) {
135+ if (new_allocated < (size_t )allocated ) {
136+ target_bytes = new_allocated * sizeof (PyObject * );
137+ }
138+ else {
139+ target_bytes = allocated * sizeof (PyObject * );
140+ }
141+ memcpy (array -> ob_item , self -> ob_item , target_bytes );
142+ }
143+ _Py_atomic_store_ptr_release (& self -> ob_item , & array -> ob_item );
144+ self -> allocated = new_allocated ;
145+ Py_SET_SIZE (self , newsize );
146+ if (old_items != NULL ) {
147+ free_list_items (old_items , _PyObject_GC_IS_SHARED (self ));
148+ }
149+ #else
150+ PyObject * * items ;
83151 if (new_allocated <= (size_t )PY_SSIZE_T_MAX / sizeof (PyObject * )) {
84- num_allocated_bytes = new_allocated * sizeof (PyObject * );
85- items = (PyObject * * )PyMem_Realloc (self -> ob_item , num_allocated_bytes );
152+ target_bytes = new_allocated * sizeof (PyObject * );
153+ items = (PyObject * * )PyMem_Realloc (self -> ob_item , target_bytes );
86154 }
87155 else {
88156 // integer overflow
@@ -95,12 +163,14 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
95163 self -> ob_item = items ;
96164 Py_SET_SIZE (self , newsize );
97165 self -> allocated = new_allocated ;
166+ #endif
98167 return 0 ;
99168}
100169
101170static int
102171list_preallocate_exact (PyListObject * self , Py_ssize_t size )
103172{
173+ PyObject * * items ;
104174 assert (self -> ob_item == NULL );
105175 assert (size > 0 );
106176
@@ -110,11 +180,20 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size)
110180 * allocated size up to the nearest even number.
111181 */
112182 size = (size + 1 ) & ~(size_t )1 ;
113- PyObject * * items = PyMem_New (PyObject * , size );
183+ #ifdef Py_GIL_DISABLED
184+ _PyListArray * array = list_allocate_array (size );
185+ if (array == NULL ) {
186+ PyErr_NoMemory ();
187+ return -1 ;
188+ }
189+ items = array -> ob_item ;
190+ #else
191+ items = PyMem_New (PyObject * , size );
114192 if (items == NULL ) {
115193 PyErr_NoMemory ();
116194 return -1 ;
117195 }
196+ #endif
118197 self -> ob_item = items ;
119198 self -> allocated = size ;
120199 return 0 ;
@@ -178,7 +257,17 @@ PyList_New(Py_ssize_t size)
178257 op -> ob_item = NULL ;
179258 }
180259 else {
260+ #ifdef Py_GIL_DISABLED
261+ _PyListArray * array = list_allocate_array (size );
262+ if (array == NULL ) {
263+ Py_DECREF (op );
264+ return PyErr_NoMemory ();
265+ }
266+ memset (& array -> ob_item , 0 , size * sizeof (PyObject * ));
267+ op -> ob_item = array -> ob_item ;
268+ #else
181269 op -> ob_item = (PyObject * * ) PyMem_Calloc (size , sizeof (PyObject * ));
270+ #endif
182271 if (op -> ob_item == NULL ) {
183272 Py_DECREF (op );
184273 return PyErr_NoMemory ();
@@ -199,11 +288,20 @@ list_new_prealloc(Py_ssize_t size)
199288 return NULL ;
200289 }
201290 assert (op -> ob_item == NULL );
291+ #ifdef Py_GIL_DISABLED
292+ _PyListArray * array = list_allocate_array (size );
293+ if (array == NULL ) {
294+ Py_DECREF (op );
295+ return PyErr_NoMemory ();
296+ }
297+ op -> ob_item = array -> ob_item ;
298+ #else
202299 op -> ob_item = PyMem_New (PyObject * , size );
203300 if (op -> ob_item == NULL ) {
204301 Py_DECREF (op );
205302 return PyErr_NoMemory ();
206303 }
304+ #endif
207305 op -> allocated = size ;
208306 return (PyObject * ) op ;
209307}
@@ -268,7 +366,7 @@ list_get_item_ref(PyListObject *op, Py_ssize_t i)
268366 if (ob_item == NULL ) {
269367 return NULL ;
270368 }
271- Py_ssize_t cap = _Py_atomic_load_ssize_relaxed ( & op -> allocated );
369+ Py_ssize_t cap = list_capacity ( ob_item );
272370 assert (cap != -1 && cap >= size );
273371 if (!valid_index (i , cap )) {
274372 return NULL ;
@@ -438,7 +536,7 @@ list_dealloc(PyObject *self)
438536 while (-- i >= 0 ) {
439537 Py_XDECREF (op -> ob_item [i ]);
440538 }
441- PyMem_Free (op -> ob_item );
539+ free_list_items (op -> ob_item , false );
442540 }
443541#ifdef WITH_FREELISTS
444542 struct _Py_list_freelist * list_freelist = get_list_freelist ();
@@ -737,12 +835,7 @@ list_clear_impl(PyListObject *a, bool is_resize)
737835#else
738836 bool use_qsbr = false;
739837#endif
740- if (use_qsbr ) {
741- _PyMem_FreeDelayed (items );
742- }
743- else {
744- PyMem_Free (items );
745- }
838+ free_list_items (items , use_qsbr );
746839 // Note that there is no guarantee that the list is actually empty
747840 // at this point, because XDECREF may have populated it indirectly again!
748841}
@@ -2758,7 +2851,12 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
27582851 while (-- i >= 0 ) {
27592852 Py_XDECREF (final_ob_item [i ]);
27602853 }
2761- PyMem_Free (final_ob_item );
2854+ #ifdef Py_GIL_DISABLED
2855+ bool use_qsbr = _PyObject_GC_IS_SHARED (self );
2856+ #else
2857+ bool use_qsbr = false;
2858+ #endif
2859+ free_list_items (final_ob_item , use_qsbr );
27622860 }
27632861 return Py_XNewRef (result );
27642862}
0 commit comments