@@ -1726,10 +1726,12 @@ clear_datastack(PyThreadState *tstate)
17261726 _PyObject_VirtualFree (chunk , chunk -> size );
17271727 chunk = prev ;
17281728 }
1729- if (tstate -> datastack_cached_chunk != NULL ) {
1730- _PyObject_VirtualFree (tstate -> datastack_cached_chunk ,
1731- tstate -> datastack_cached_chunk -> size );
1732- tstate -> datastack_cached_chunk = NULL ;
1729+ chunk = tstate -> datastack_cached_chunk ;
1730+ tstate -> datastack_cached_chunk = NULL ;
1731+ while (chunk != NULL ) {
1732+ _PyStackChunk * prev = chunk -> previous ;
1733+ _PyObject_VirtualFree (chunk , chunk -> size );
1734+ chunk = prev ;
17331735 }
17341736}
17351737
@@ -3077,6 +3079,56 @@ _PyInterpreterState_HasFeature(PyInterpreterState *interp, unsigned long feature
30773079
30783080
30793081#define MINIMUM_OVERHEAD 1000
3082+ #define DATA_STACK_CACHE_MAX_SIZE (8 * _PY_DATA_STACK_CHUNK_SIZE)
3083+
3084+ static _PyStackChunk *
3085+ pop_cached_datastack_chunk (PyThreadState * tstate , int allocate_size )
3086+ {
3087+ _PyStackChunk * * best_link = NULL ;
3088+ size_t best_size = (size_t )-1 ;
3089+
3090+ for (_PyStackChunk * * link = & tstate -> datastack_cached_chunk ;
3091+ * link != NULL ;
3092+ link = & (* link )-> previous )
3093+ {
3094+ _PyStackChunk * chunk = * link ;
3095+ if ((size_t )allocate_size <= chunk -> size && chunk -> size < best_size ) {
3096+ best_link = link ;
3097+ best_size = chunk -> size ;
3098+ }
3099+ }
3100+ if (best_link == NULL ) {
3101+ return NULL ;
3102+ }
3103+
3104+ _PyStackChunk * chunk = * best_link ;
3105+ * best_link = chunk -> previous ;
3106+ chunk -> previous = NULL ;
3107+ chunk -> top = 0 ;
3108+ return chunk ;
3109+ }
3110+
3111+ static void
3112+ cache_or_free_datastack_chunk (PyThreadState * tstate , _PyStackChunk * chunk )
3113+ {
3114+ assert (chunk -> previous == NULL );
3115+
3116+ size_t cached_size = chunk -> size ;
3117+ for (_PyStackChunk * cached = tstate -> datastack_cached_chunk ;
3118+ cached != NULL ;
3119+ cached = cached -> previous )
3120+ {
3121+ cached_size += cached -> size ;
3122+ if (cached_size > DATA_STACK_CACHE_MAX_SIZE ) {
3123+ _PyObject_VirtualFree (chunk , chunk -> size );
3124+ return ;
3125+ }
3126+ }
3127+
3128+ chunk -> top = 0 ;
3129+ chunk -> previous = tstate -> datastack_cached_chunk ;
3130+ tstate -> datastack_cached_chunk = chunk ;
3131+ }
30803132
30813133static PyObject * *
30823134push_chunk (PyThreadState * tstate , int size )
@@ -3086,13 +3138,9 @@ push_chunk(PyThreadState *tstate, int size)
30863138 allocate_size *= 2 ;
30873139 }
30883140 _PyStackChunk * new ;
3089- if (tstate -> datastack_cached_chunk != NULL
3090- && (size_t )allocate_size <= tstate -> datastack_cached_chunk -> size )
3091- {
3092- new = tstate -> datastack_cached_chunk ;
3093- tstate -> datastack_cached_chunk = NULL ;
3141+ new = pop_cached_datastack_chunk (tstate , allocate_size );
3142+ if (new != NULL ) {
30943143 new -> previous = tstate -> datastack_chunk ;
3095- new -> top = 0 ;
30963144 }
30973145 else {
30983146 new = allocate_chunk (allocate_size , tstate -> datastack_chunk );
@@ -3134,17 +3182,13 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame)
31343182 if (base == & tstate -> datastack_chunk -> data [0 ]) {
31353183 _PyStackChunk * chunk = tstate -> datastack_chunk ;
31363184 _PyStackChunk * previous = chunk -> previous ;
3137- _PyStackChunk * cached = tstate -> datastack_cached_chunk ;
31383185 // push_chunk ensures that the root chunk is never popped:
31393186 assert (previous );
31403187 tstate -> datastack_top = & previous -> data [previous -> top ];
31413188 tstate -> datastack_chunk = previous ;
31423189 tstate -> datastack_limit = (PyObject * * )(((char * )previous ) + previous -> size );
31433190 chunk -> previous = NULL ;
3144- if (cached != NULL ) {
3145- _PyObject_VirtualFree (cached , cached -> size );
3146- }
3147- tstate -> datastack_cached_chunk = chunk ;
3191+ cache_or_free_datastack_chunk (tstate , chunk );
31483192 }
31493193 else {
31503194 assert (tstate -> datastack_top );
0 commit comments