@@ -31,6 +31,91 @@ get_list_freelist(void)
3131}
3232#endif
3333
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+
34119/* Ensure ob_item has room for at least newsize elements, and set
35120 * ob_size to newsize. If newsize > ob_size on entry, the content
36121 * of the new slots at exit is undefined heap trash; it's the caller's
@@ -151,61 +236,18 @@ _PyList_DebugMallocStats(FILE *out)
151236PyObject *
152237PyList_New (Py_ssize_t size )
153238{
154- PyListObject * op ;
155-
156239 if (size < 0 ) {
157240 PyErr_BadInternalCall ();
158241 return NULL ;
159242 }
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 );
185248 }
186249 }
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 ;
209251}
210252
211253Py_ssize_t
@@ -515,7 +557,7 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
515557 if (len <= 0 ) {
516558 return PyList_New (0 );
517559 }
518- np = (PyListObject * ) list_new_prealloc (len );
560+ np = (PyListObject * ) list_new (len );
519561 if (np == NULL )
520562 return NULL ;
521563
@@ -567,7 +609,7 @@ list_concat_lock_held(PyListObject *a, PyListObject *b)
567609 if (size == 0 ) {
568610 return PyList_New (0 );
569611 }
570- np = (PyListObject * ) list_new_prealloc (size );
612+ np = (PyListObject * ) list_new (size );
571613 if (np == NULL ) {
572614 return NULL ;
573615 }
@@ -617,7 +659,7 @@ list_repeat_lock_held(PyListObject *a, Py_ssize_t n)
617659 return PyErr_NoMemory ();
618660 Py_ssize_t output_size = input_size * n ;
619661
620- PyListObject * np = (PyListObject * ) list_new_prealloc (output_size );
662+ PyListObject * np = (PyListObject * ) list_new (output_size );
621663 if (np == NULL )
622664 return NULL ;
623665
@@ -658,7 +700,7 @@ list_repeat(PyObject *aa, Py_ssize_t n)
658700}
659701
660702static void
661- list_clear (PyListObject * a )
703+ list_clear_impl (PyListObject * a , bool is_resize )
662704{
663705 PyObject * * items = a -> ob_item ;
664706 if (items == NULL ) {
@@ -675,16 +717,31 @@ list_clear(PyListObject *a)
675717 Py_XDECREF (items [i ]);
676718 }
677719 // 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+ }
680731 // Note that there is no guarantee that the list is actually empty
681732 // at this point, because XDECREF may have populated it indirectly again!
682733}
683734
735+ static void
736+ list_clear (PyListObject * a )
737+ {
738+ list_clear_impl (a , true);
739+ }
740+
684741static int
685742list_clear_slot (PyObject * self )
686743{
687- list_clear ((PyListObject * )self );
744+ list_clear_impl ((PyListObject * )self , false );
688745 return 0 ;
689746}
690747
@@ -3095,7 +3152,7 @@ list_subscript(PyObject* _self, PyObject* item)
30953152 return list_slice (self , start , stop );
30963153 }
30973154 else {
3098- result = list_new_prealloc (slicelength );
3155+ result = ( PyObject * ) list_new (slicelength );
30993156 if (!result ) return NULL ;
31003157
31013158 src = self -> ob_item ;
0 commit comments