@@ -31,6 +31,49 @@ get_list_freelist(void)
31
31
}
32
32
#endif
33
33
34
+ #ifdef Py_GIL_DISABLED
35
+ static _PyListArray *
36
+ list_allocate_array (size_t capacity )
37
+ {
38
+ if (capacity > PY_SSIZE_T_MAX /sizeof (PyObject * ) - 1 ) {
39
+ return NULL ;
40
+ }
41
+ _PyListArray * array = PyMem_Malloc (sizeof (_PyListArray ) + (capacity - 1 ) * sizeof (PyObject * ));
42
+ if (array == NULL ) {
43
+ return NULL ;
44
+ }
45
+ array -> allocated = capacity ;
46
+ return array ;
47
+ }
48
+
49
+ static Py_ssize_t
50
+ list_capacity (PyObject * * items )
51
+ {
52
+ char * mem = (char * )items ;
53
+ mem -= offsetof(_PyListArray , ob_item );
54
+ _PyListArray * array = (_PyListArray * )mem ;
55
+ return _Py_atomic_load_ssize_relaxed (& array -> allocated );
56
+ }
57
+ #endif
58
+
59
+ static void
60
+ free_list_items (PyObject * * items , bool use_qsbr )
61
+ {
62
+ #ifdef Py_GIL_DISABLED
63
+ char * mem = (char * )items ;
64
+ mem -= offsetof(_PyListArray , ob_item );
65
+ _PyListArray * array = (_PyListArray * )mem ;
66
+ if (use_qsbr ) {
67
+ _PyMem_FreeDelayed (array );
68
+ }
69
+ else {
70
+ PyMem_Free (array );
71
+ }
72
+ #else
73
+ PyMem_Free (items );
74
+ #endif
75
+ }
76
+
34
77
/* Ensure ob_item has room for at least newsize elements, and set
35
78
* ob_size to newsize. If newsize > ob_size on entry, the content
36
79
* of the new slots at exit is undefined heap trash; it's the caller's
@@ -47,8 +90,7 @@ get_list_freelist(void)
47
90
static int
48
91
list_resize (PyListObject * self , Py_ssize_t newsize )
49
92
{
50
- PyObject * * items ;
51
- size_t new_allocated , num_allocated_bytes ;
93
+ size_t new_allocated ;
52
94
Py_ssize_t allocated = self -> allocated ;
53
95
54
96
/* Bypass realloc() when a previous overallocation is large enough
@@ -80,9 +122,39 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
80
122
81
123
if (newsize == 0 )
82
124
new_allocated = 0 ;
125
+
126
+ #ifdef Py_GIL_DISABLED
127
+ _PyListArray * array = NULL ;
128
+ if (new_allocated <= (size_t )PY_SSIZE_T_MAX / sizeof (PyObject * )) {
129
+ array = list_allocate_array (new_allocated );
130
+ }
131
+ else {
132
+ // integer overflow
133
+ array = NULL ;
134
+ }
135
+ if (array == NULL ) {
136
+ PyErr_NoMemory ();
137
+ return -1 ;
138
+ }
139
+ PyObject * * old_items = self -> ob_item ;
140
+ if (self -> ob_item ) {
141
+ if (allocated < new_allocated ) {
142
+ memcpy (& array -> ob_item , self -> ob_item , allocated * sizeof (PyObject * ));
143
+ }
144
+ else {
145
+ memcpy (& array -> ob_item , self -> ob_item , new_allocated * sizeof (PyObject * ));
146
+ }
147
+ }
148
+ _Py_atomic_store_ptr_release (& self -> ob_item , & array -> ob_item );
149
+ self -> allocated = new_allocated ;
150
+ Py_SET_SIZE (self , newsize );
151
+ if (old_items != NULL ) {
152
+ free_list_items (old_items , _PyObject_GC_IS_SHARED (self ));
153
+ }
154
+ #else
155
+ PyObject * * items ;
83
156
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 );
157
+ items = PyMem_Realloc (self -> ob_item , new_allocated * sizeof (PyObject * ));
86
158
}
87
159
else {
88
160
// integer overflow
@@ -95,6 +167,7 @@ list_resize(PyListObject *self, Py_ssize_t newsize)
95
167
self -> ob_item = items ;
96
168
Py_SET_SIZE (self , newsize );
97
169
self -> allocated = new_allocated ;
170
+ #endif
98
171
return 0 ;
99
172
}
100
173
@@ -110,12 +183,21 @@ list_preallocate_exact(PyListObject *self, Py_ssize_t size)
110
183
* allocated size up to the nearest even number.
111
184
*/
112
185
size = (size + 1 ) & ~(size_t )1 ;
186
+ #ifdef Py_GIL_DISABLED
187
+ _PyListArray * array = list_allocate_array (size );
188
+ if (array == NULL ) {
189
+ PyErr_NoMemory ();
190
+ return -1 ;
191
+ }
192
+ self -> ob_item = array -> ob_item ;
193
+ #else
113
194
PyObject * * items = PyMem_New (PyObject * , size );
114
195
if (items == NULL ) {
115
196
PyErr_NoMemory ();
116
197
return -1 ;
117
198
}
118
199
self -> ob_item = items ;
200
+ #endif
119
201
self -> allocated = size ;
120
202
return 0 ;
121
203
}
@@ -178,7 +260,17 @@ PyList_New(Py_ssize_t size)
178
260
op -> ob_item = NULL ;
179
261
}
180
262
else {
263
+ #ifdef Py_GIL_DISABLED
264
+ _PyListArray * array = list_allocate_array (size );
265
+ if (array == NULL ) {
266
+ Py_DECREF (op );
267
+ return PyErr_NoMemory ();
268
+ }
269
+ op -> ob_item = array -> ob_item ;
270
+ memset (op -> ob_item , 0 , size * sizeof (PyObject * ));
271
+ #else
181
272
op -> ob_item = (PyObject * * ) PyMem_Calloc (size , sizeof (PyObject * ));
273
+ #endif
182
274
if (op -> ob_item == NULL ) {
183
275
Py_DECREF (op );
184
276
return PyErr_NoMemory ();
@@ -199,11 +291,20 @@ list_new_prealloc(Py_ssize_t size)
199
291
return NULL ;
200
292
}
201
293
assert (op -> ob_item == NULL );
294
+ #ifdef Py_GIL_DISABLED
295
+ _PyListArray * array = list_allocate_array (size );
296
+ if (array == NULL ) {
297
+ Py_DECREF (op );
298
+ return PyErr_NoMemory ();
299
+ }
300
+ op -> ob_item = array -> ob_item ;
301
+ #else
202
302
op -> ob_item = PyMem_New (PyObject * , size );
203
303
if (op -> ob_item == NULL ) {
204
304
Py_DECREF (op );
205
305
return PyErr_NoMemory ();
206
306
}
307
+ #endif
207
308
op -> allocated = size ;
208
309
return (PyObject * ) op ;
209
310
}
@@ -268,7 +369,7 @@ list_get_item_ref(PyListObject *op, Py_ssize_t i)
268
369
if (ob_item == NULL ) {
269
370
return NULL ;
270
371
}
271
- Py_ssize_t cap = _Py_atomic_load_ssize_relaxed ( & op -> allocated );
372
+ Py_ssize_t cap = list_capacity ( ob_item );
272
373
assert (cap != -1 && cap >= size );
273
374
if (!valid_index (i , cap )) {
274
375
return NULL ;
@@ -438,7 +539,7 @@ list_dealloc(PyObject *self)
438
539
while (-- i >= 0 ) {
439
540
Py_XDECREF (op -> ob_item [i ]);
440
541
}
441
- PyMem_Free (op -> ob_item );
542
+ free_list_items (op -> ob_item , false );
442
543
}
443
544
#ifdef WITH_FREELISTS
444
545
struct _Py_list_freelist * list_freelist = get_list_freelist ();
@@ -737,12 +838,7 @@ list_clear_impl(PyListObject *a, bool is_resize)
737
838
#else
738
839
bool use_qsbr = false;
739
840
#endif
740
- if (use_qsbr ) {
741
- _PyMem_FreeDelayed (items );
742
- }
743
- else {
744
- PyMem_Free (items );
745
- }
841
+ free_list_items (items , use_qsbr );
746
842
// Note that there is no guarantee that the list is actually empty
747
843
// at this point, because XDECREF may have populated it indirectly again!
748
844
}
@@ -2758,7 +2854,12 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
2758
2854
while (-- i >= 0 ) {
2759
2855
Py_XDECREF (final_ob_item [i ]);
2760
2856
}
2761
- PyMem_Free (final_ob_item );
2857
+ #ifdef Py_GIL_DISABLED
2858
+ bool use_qsbr = _PyObject_GC_IS_SHARED (self );
2859
+ #else
2860
+ bool use_qsbr = false;
2861
+ #endif
2862
+ free_list_items (final_ob_item , use_qsbr );
2762
2863
}
2763
2864
return Py_XNewRef (result );
2764
2865
}
0 commit comments