@@ -31,6 +31,90 @@ get_list_freelist(void)
31
31
}
32
32
#endif
33
33
34
+ static size_t
35
+ list_good_size (Py_ssize_t size )
36
+ {
37
+ // 4, 8, 16, 24, 32, 40, 48, 64, 80, ...
38
+ // NOTE: we add one here so that the rounding accounts for the "allocated"
39
+ // field in _PyListArray.
40
+ size_t reqsize = (size_t )size + 1 ;
41
+ if (reqsize <= 4 ) {
42
+ reqsize = 4 ;
43
+ }
44
+ else if (reqsize <= 48 ) {
45
+ reqsize = (reqsize + 7 ) & ~7 ;
46
+ }
47
+ else {
48
+ reqsize = (reqsize + 15 ) & ~15 ;
49
+ if (reqsize <= MI_MEDIUM_OBJ_WSIZE_MAX ) {
50
+ reqsize = mi_good_size (reqsize * sizeof (PyObject * ))/sizeof (PyObject * );
51
+ }
52
+ else {
53
+ // ensure geometric spacing for large arrays
54
+ size_t shift = mi_bsr (reqsize ) - 2 ;
55
+ reqsize = ((reqsize >> shift ) + 1 ) << shift ;
56
+ }
57
+ }
58
+ return reqsize - 1 ;
59
+ }
60
+
61
+ static PyObject * *
62
+ list_allocate_items (size_t capacity )
63
+ {
64
+ if (capacity > PY_SSIZE_T_MAX / sizeof (PyObject * ) - 1 ) {
65
+ return NULL ;
66
+ }
67
+ PyObject * * items = PyMem_Malloc (capacity * sizeof (PyObject * ));
68
+ return items ;
69
+ }
70
+
71
+ static PyListObject *
72
+ list_new (Py_ssize_t size )
73
+ {
74
+ PyListObject * op ;
75
+ assert (size >= 0 );
76
+ #ifdef WITH_FREELISTS
77
+ struct _Py_list_freelist * list_freelist = get_list_freelist ();
78
+ if (PyList_MAXFREELIST && list_freelist -> numfree > 0 ) {
79
+ list_freelist -> numfree -- ;
80
+ op = list_freelist -> items [list_freelist -> numfree ];
81
+ OBJECT_STAT_INC (from_freelist );
82
+ _Py_NewReference ((PyObject * )op );
83
+ }
84
+ else
85
+ #endif
86
+ {
87
+ op = PyObject_GC_New (PyListObject , & PyList_Type );
88
+ if (op == NULL ) {
89
+ return NULL ;
90
+ }
91
+ }
92
+ if (size <= 0 ) {
93
+ op -> ob_item = NULL ;
94
+ op -> allocated = 0 ;
95
+ }
96
+ else {
97
+ #ifdef Py_GIL_DISABLED
98
+ size_t capacity = list_good_size (size );
99
+ PyObject * * items = list_allocate_items (capacity );
100
+ #else
101
+ size_t capacity = size ;
102
+ PyObject * * items = (PyObject * * ) PyMem_Calloc (size , sizeof (PyObject * ));
103
+ #endif
104
+ if (items == NULL ) {
105
+ op -> ob_item = NULL ;
106
+ Py_DECREF (op );
107
+ PyErr_NoMemory ();
108
+ return NULL ;
109
+ }
110
+ op -> ob_item = items ;
111
+ op -> allocated = capacity ;
112
+ }
113
+ Py_SET_SIZE (op , size );
114
+ _PyObject_GC_TRACK (op );
115
+ return op ;
116
+ }
117
+
34
118
/* Ensure ob_item has room for at least newsize elements, and set
35
119
* ob_size to newsize. If newsize > ob_size on entry, the content
36
120
* of the new slots at exit is undefined heap trash; it's the caller's
@@ -151,61 +235,18 @@ _PyList_DebugMallocStats(FILE *out)
151
235
PyObject *
152
236
PyList_New (Py_ssize_t size )
153
237
{
154
- PyListObject * op ;
155
-
156
238
if (size < 0 ) {
157
239
PyErr_BadInternalCall ();
158
240
return NULL ;
159
241
}
160
-
161
- #ifdef WITH_FREELISTS
162
- struct _Py_list_freelist * list_freelist = get_list_freelist ();
163
- if (PyList_MAXFREELIST && list_freelist -> numfree > 0 ) {
164
- list_freelist -> numfree -- ;
165
- op = list_freelist -> items [list_freelist -> numfree ];
166
- OBJECT_STAT_INC (from_freelist );
167
- _Py_NewReference ((PyObject * )op );
168
- }
169
- else
170
- #endif
171
- {
172
- op = PyObject_GC_New (PyListObject , & PyList_Type );
173
- if (op == NULL ) {
174
- return NULL ;
175
- }
176
- }
177
- if (size <= 0 ) {
178
- op -> ob_item = NULL ;
179
- }
180
- else {
181
- op -> ob_item = (PyObject * * ) PyMem_Calloc (size , sizeof (PyObject * ));
182
- if (op -> ob_item == NULL ) {
183
- Py_DECREF (op );
184
- return PyErr_NoMemory ();
242
+ PyListObject * op = list_new (size );
243
+ if (op && op -> ob_item ) {
244
+ PyObject * * items = op -> ob_item ;
245
+ for (Py_ssize_t i = 0 , n = op -> allocated ; i < n ; i ++ ) {
246
+ FT_ATOMIC_STORE_PTR_RELEASE (items [i ], NULL );
185
247
}
186
248
}
187
- Py_SET_SIZE (op , size );
188
- op -> allocated = size ;
189
- _PyObject_GC_TRACK (op );
190
- return (PyObject * ) op ;
191
- }
192
-
193
- static PyObject *
194
- list_new_prealloc (Py_ssize_t size )
195
- {
196
- assert (size > 0 );
197
- PyListObject * op = (PyListObject * ) PyList_New (0 );
198
- if (op == NULL ) {
199
- return NULL ;
200
- }
201
- assert (op -> ob_item == NULL );
202
- op -> ob_item = PyMem_New (PyObject * , size );
203
- if (op -> ob_item == NULL ) {
204
- Py_DECREF (op );
205
- return PyErr_NoMemory ();
206
- }
207
- op -> allocated = size ;
208
- return (PyObject * ) op ;
249
+ return (PyObject * )op ;
209
250
}
210
251
211
252
Py_ssize_t
@@ -515,7 +556,7 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
515
556
if (len <= 0 ) {
516
557
return PyList_New (0 );
517
558
}
518
- np = (PyListObject * ) list_new_prealloc (len );
559
+ np = (PyListObject * ) list_new (len );
519
560
if (np == NULL )
520
561
return NULL ;
521
562
@@ -567,7 +608,7 @@ list_concat_lock_held(PyListObject *a, PyListObject *b)
567
608
if (size == 0 ) {
568
609
return PyList_New (0 );
569
610
}
570
- np = (PyListObject * ) list_new_prealloc (size );
611
+ np = (PyListObject * ) list_new (size );
571
612
if (np == NULL ) {
572
613
return NULL ;
573
614
}
@@ -617,7 +658,7 @@ list_repeat_lock_held(PyListObject *a, Py_ssize_t n)
617
658
return PyErr_NoMemory ();
618
659
Py_ssize_t output_size = input_size * n ;
619
660
620
- PyListObject * np = (PyListObject * ) list_new_prealloc (output_size );
661
+ PyListObject * np = (PyListObject * ) list_new (output_size );
621
662
if (np == NULL )
622
663
return NULL ;
623
664
@@ -3095,7 +3136,7 @@ list_subscript(PyObject* _self, PyObject* item)
3095
3136
return list_slice (self , start , stop );
3096
3137
}
3097
3138
else {
3098
- result = list_new_prealloc (slicelength );
3139
+ result = ( PyObject * ) list_new (slicelength );
3099
3140
if (!result ) return NULL ;
3100
3141
3101
3142
src = self -> ob_item ;
0 commit comments