@@ -2870,6 +2870,48 @@ unsafe_tuple_compare(PyObject *v, PyObject *w, MergeState *ms)
28702870 return PyObject_RichCompareBool (vt -> ob_item [i ], wt -> ob_item [i ], Py_LT );
28712871}
28722872
2873+ #define DISABLE_LIST (self , saved_ob_size , saved_ob_item , saved_allocated ) \
2874+ do { \
2875+ saved_ob_size = Py_SIZE(self); \
2876+ saved_ob_item = self->ob_item; \
2877+ saved_allocated = self->allocated; \
2878+ Py_SET_SIZE(self, 0); \
2879+ FT_ATOMIC_STORE_PTR_RELEASE(self->ob_item, NULL); \
2880+ self->allocated = -1; /* any operation will reset it to >= 0 */ \
2881+ } while (0 )
2882+
2883+ #ifdef Py_GIL_DISABLED
2884+ #define _REENABLE_LIST_GIL_PART (self , use_qsbr ) \
2885+ do { \
2886+ ensure_shared_on_resize(self); \
2887+ use_qsbr = _PyObject_GC_IS_SHARED(self); \
2888+ } while (0)
2889+ #else
2890+ #define _REENABLE_LIST_GIL_PART (self , use_qsbr ) \
2891+ do { \
2892+ use_qsbr = false; \
2893+ } while (0)
2894+ #endif
2895+
2896+ #define REENABLE_LIST (self , saved_ob_size , saved_ob_item , saved_allocated ) \
2897+ do { \
2898+ final_ob_item = self->ob_item; \
2899+ i = Py_SIZE(self); \
2900+ Py_SET_SIZE(self, saved_ob_size); \
2901+ FT_ATOMIC_STORE_PTR_RELEASE(self->ob_item, saved_ob_item); \
2902+ FT_ATOMIC_STORE_SSIZE_RELAXED(self->allocated, saved_allocated); \
2903+ if (final_ob_item != NULL) { \
2904+ /* we cannot use list_clear() for this because it does not */ \
2905+ /* guarantee that the list is really empty when it returns */ \
2906+ while (-- i >= 0 ) { \
2907+ Py_XDECREF (final_ob_item [i ]); \
2908+ } \
2909+ bool use_qsbr ; \
2910+ _REENABLE_LIST_GIL_PART (self , use_qsbr ); \
2911+ free_list_items (final_ob_item , use_qsbr ); \
2912+ } \
2913+ } while (0 )
2914+
28732915/* An adaptive, stable, natural mergesort. See listsort.txt.
28742916 * Returns Py_None on success, NULL on error. Even in case of error, the
28752917 * list will be some permutation of its input state (nothing is lost or
@@ -2943,12 +2985,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, PyObject *keylist,
29432985 * sorting (allowing mutations during sorting is a core-dump
29442986 * factory, since ob_item may change).
29452987 */
2946- saved_ob_size = Py_SIZE (self );
2947- saved_ob_item = self -> ob_item ;
2948- saved_allocated = self -> allocated ;
2949- Py_SET_SIZE (self , 0 );
2950- FT_ATOMIC_STORE_PTR_RELEASE (self -> ob_item , NULL );
2951- self -> allocated = -1 ; /* any operation will reset it to >= 0 */
2988+ DISABLE_LIST (self , saved_ob_size , saved_ob_item , saved_allocated );
29522989
29532990 if (keyfunc == NULL && keylist == NULL ) {
29542991 keys = NULL ;
@@ -2987,14 +3024,7 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, PyObject *keylist,
29873024 goto keyfunc_fail ;
29883025 }
29893026 self_kl = ((PyListObject * ) keylist );
2990- // Disable keylist modifications via same methodology as for main list
2991- keylist_ob_size = Py_SIZE (self_kl );
2992- keylist_ob_item = self_kl -> ob_item ;
2993- keylist_allocated = self_kl -> allocated ;
2994- Py_SET_SIZE (self_kl , 0 );
2995- FT_ATOMIC_STORE_PTR_RELEASE (self_kl -> ob_item , NULL );
2996- self_kl -> allocated = -1 ; /* any operation will reset it to >= 0 */
2997-
3027+ DISABLE_LIST (self_kl , keylist_ob_size , keylist_ob_item , keylist_allocated );
29983028 keylist_frozen = 1 ;
29993029 if (saved_ob_size != keylist_ob_size ) {
30003030 PyErr_SetString (PyExc_ValueError ,
@@ -3196,49 +3226,17 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, PyObject *keylist,
31963226 if (reverse && saved_ob_size > 1 )
31973227 reverse_slice (keylist_ob_item , keylist_ob_item + keylist_ob_size );
31983228
3199- final_ob_item = self_kl -> ob_item ;
3200- i = Py_SIZE (self_kl );
3201- Py_SET_SIZE (self_kl , keylist_ob_size );
3202- FT_ATOMIC_STORE_PTR_RELEASE (self_kl -> ob_item , keylist_ob_item );
3203- FT_ATOMIC_STORE_SSIZE_RELAXED (self_kl -> allocated , keylist_allocated );
3204- if (final_ob_item != NULL ) {
3205- /* we cannot use list_clear() for this because it does not
3206- guarantee that the list is really empty when it returns */
3207- while (-- i >= 0 ) {
3208- Py_XDECREF (final_ob_item [i ]);
3209- }
3210- #ifdef Py_GIL_DISABLED
3211- ensure_shared_on_resize (self_kl );
3212- bool use_qsbr = _PyObject_GC_IS_SHARED (self_kl );
3213- #else
3214- bool use_qsbr = false;
3215- #endif
3216- free_list_items (final_ob_item , use_qsbr );
3217- }
3229+ REENABLE_LIST (self_kl , keylist_ob_size , keylist_ob_item , keylist_allocated );
3230+ final_ob_item = NULL ;
32183231 }
32193232
32203233keyfunc_fail :
3221- final_ob_item = self -> ob_item ;
3222- i = Py_SIZE (self );
3223- Py_SET_SIZE (self , saved_ob_size );
3224- FT_ATOMIC_STORE_PTR_RELEASE (self -> ob_item , saved_ob_item );
3225- FT_ATOMIC_STORE_SSIZE_RELAXED (self -> allocated , saved_allocated );
3226- if (final_ob_item != NULL ) {
3227- /* we cannot use list_clear() for this because it does not
3228- guarantee that the list is really empty when it returns */
3229- while (-- i >= 0 ) {
3230- Py_XDECREF (final_ob_item [i ]);
3231- }
3232- #ifdef Py_GIL_DISABLED
3233- ensure_shared_on_resize (self );
3234- bool use_qsbr = _PyObject_GC_IS_SHARED (self );
3235- #else
3236- bool use_qsbr = false;
3237- #endif
3238- free_list_items (final_ob_item , use_qsbr );
3239- }
3234+ REENABLE_LIST (self , saved_ob_size , saved_ob_item , saved_allocated );
32403235 return Py_XNewRef (result );
32413236}
3237+ #undef DISABLE_LIST
3238+ #undef _REENABLE_LIST_GIL_PART
3239+ #undef REENABLE_LIST
32423240#undef IFLT
32433241#undef ISLT
32443242
0 commit comments