@@ -31,6 +31,91 @@ get_list_freelist(void)
31
31
}
32
32
#endif
33
33
34
+ #ifdef Py_GIL_DISABLED
35
+ static size_t
36
+ list_good_size (Py_ssize_t size )
37
+ {
38
+ // 4, 8, 16, 24, 32, 40, 48, 64, 80, ...
39
+ // NOTE: we add one here so that the rounding accounts for the "allocated"
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
+ #endif
71
+
72
+ static PyListObject *
73
+ list_new (Py_ssize_t size )
74
+ {
75
+ PyListObject * op ;
76
+ assert (size >= 0 );
77
+ #ifdef WITH_FREELISTS
78
+ struct _Py_list_freelist * list_freelist = get_list_freelist ();
79
+ if (PyList_MAXFREELIST && list_freelist -> numfree > 0 ) {
80
+ list_freelist -> numfree -- ;
81
+ op = list_freelist -> items [list_freelist -> numfree ];
82
+ OBJECT_STAT_INC (from_freelist );
83
+ _Py_NewReference ((PyObject * )op );
84
+ }
85
+ else
86
+ #endif
87
+ {
88
+ op = PyObject_GC_New (PyListObject , & PyList_Type );
89
+ if (op == NULL ) {
90
+ return NULL ;
91
+ }
92
+ }
93
+ if (size <= 0 ) {
94
+ op -> ob_item = NULL ;
95
+ op -> allocated = 0 ;
96
+ }
97
+ else {
98
+ #ifdef Py_GIL_DISABLED
99
+ size_t capacity = list_good_size (size );
100
+ PyObject * * items = list_allocate_items (capacity );
101
+ #else
102
+ size_t capacity = size ;
103
+ PyObject * * items = (PyObject * * ) PyMem_Calloc (size , sizeof (PyObject * ));
104
+ #endif
105
+ if (items == NULL ) {
106
+ op -> ob_item = NULL ;
107
+ Py_DECREF (op );
108
+ PyErr_NoMemory ();
109
+ return NULL ;
110
+ }
111
+ op -> ob_item = items ;
112
+ op -> allocated = capacity ;
113
+ }
114
+ Py_SET_SIZE (op , size );
115
+ _PyObject_GC_TRACK (op );
116
+ return op ;
117
+ }
118
+
34
119
/* Ensure ob_item has room for at least newsize elements, and set
35
120
* ob_size to newsize. If newsize > ob_size on entry, the content
36
121
* of the new slots at exit is undefined heap trash; it's the caller's
@@ -151,61 +236,18 @@ _PyList_DebugMallocStats(FILE *out)
151
236
PyObject *
152
237
PyList_New (Py_ssize_t size )
153
238
{
154
- PyListObject * op ;
155
-
156
239
if (size < 0 ) {
157
240
PyErr_BadInternalCall ();
158
241
return NULL ;
159
242
}
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 ();
243
+ PyListObject * op = list_new (size );
244
+ if (op && op -> ob_item ) {
245
+ PyObject * * items = op -> ob_item ;
246
+ for (Py_ssize_t i = 0 , n = op -> allocated ; i < n ; i ++ ) {
247
+ FT_ATOMIC_STORE_PTR_RELEASE (items [i ], NULL );
185
248
}
186
249
}
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 ;
250
+ return (PyObject * )op ;
209
251
}
210
252
211
253
Py_ssize_t
@@ -515,7 +557,7 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
515
557
if (len <= 0 ) {
516
558
return PyList_New (0 );
517
559
}
518
- np = (PyListObject * ) list_new_prealloc (len );
560
+ np = (PyListObject * ) list_new (len );
519
561
if (np == NULL )
520
562
return NULL ;
521
563
@@ -567,7 +609,7 @@ list_concat_lock_held(PyListObject *a, PyListObject *b)
567
609
if (size == 0 ) {
568
610
return PyList_New (0 );
569
611
}
570
- np = (PyListObject * ) list_new_prealloc (size );
612
+ np = (PyListObject * ) list_new (size );
571
613
if (np == NULL ) {
572
614
return NULL ;
573
615
}
@@ -617,7 +659,7 @@ list_repeat_lock_held(PyListObject *a, Py_ssize_t n)
617
659
return PyErr_NoMemory ();
618
660
Py_ssize_t output_size = input_size * n ;
619
661
620
- PyListObject * np = (PyListObject * ) list_new_prealloc (output_size );
662
+ PyListObject * np = (PyListObject * ) list_new (output_size );
621
663
if (np == NULL )
622
664
return NULL ;
623
665
@@ -658,7 +700,7 @@ list_repeat(PyObject *aa, Py_ssize_t n)
658
700
}
659
701
660
702
static void
661
- list_clear (PyListObject * a )
703
+ list_clear_impl (PyListObject * a , bool is_resize )
662
704
{
663
705
PyObject * * items = a -> ob_item ;
664
706
if (items == NULL ) {
@@ -675,16 +717,31 @@ list_clear(PyListObject *a)
675
717
Py_XDECREF (items [i ]);
676
718
}
677
719
// TODO: Use QSBR technique, if the list is shared between threads,
678
- PyMem_Free (items );
679
-
720
+ #ifdef Py_GIL_DISABLED
721
+ bool use_qsbr = is_resize && _PyObject_GC_IS_SHARED (a );
722
+ #else
723
+ bool use_qsbr = false;
724
+ #endif
725
+ if (use_qsbr ) {
726
+ _PyMem_FreeDelayed (items );
727
+ }
728
+ else {
729
+ PyMem_Free (items );
730
+ }
680
731
// Note that there is no guarantee that the list is actually empty
681
732
// at this point, because XDECREF may have populated it indirectly again!
682
733
}
683
734
735
+ static void
736
+ list_clear (PyListObject * a )
737
+ {
738
+ list_clear_impl (a , true);
739
+ }
740
+
684
741
static int
685
742
list_clear_slot (PyObject * self )
686
743
{
687
- list_clear ((PyListObject * )self );
744
+ list_clear_impl ((PyListObject * )self , false );
688
745
return 0 ;
689
746
}
690
747
@@ -3095,7 +3152,7 @@ list_subscript(PyObject* _self, PyObject* item)
3095
3152
return list_slice (self , start , stop );
3096
3153
}
3097
3154
else {
3098
- result = list_new_prealloc (slicelength );
3155
+ result = ( PyObject * ) list_new (slicelength );
3099
3156
if (!result ) return NULL ;
3100
3157
3101
3158
src = self -> ob_item ;
0 commit comments