@@ -1564,6 +1564,7 @@ init_threadstate(_PyThreadStateImpl *_tstate,
15641564 tstate -> datastack_chunk = NULL ;
15651565 tstate -> datastack_top = NULL ;
15661566 tstate -> datastack_limit = NULL ;
1567+ tstate -> datastack_cached_chunk = NULL ;
15671568 tstate -> what_event = -1 ;
15681569 tstate -> current_executor = NULL ;
15691570 tstate -> jit_exit = NULL ;
@@ -1714,6 +1715,11 @@ clear_datastack(PyThreadState *tstate)
17141715 _PyObject_VirtualFree (chunk , chunk -> size );
17151716 chunk = prev ;
17161717 }
1718+ if (tstate -> datastack_cached_chunk != NULL ) {
1719+ _PyObject_VirtualFree (tstate -> datastack_cached_chunk ,
1720+ tstate -> datastack_cached_chunk -> size );
1721+ tstate -> datastack_cached_chunk = NULL ;
1722+ }
17171723}
17181724
17191725void
@@ -3045,9 +3051,20 @@ push_chunk(PyThreadState *tstate, int size)
30453051 while (allocate_size < (int )sizeof (PyObject * )* (size + MINIMUM_OVERHEAD )) {
30463052 allocate_size *= 2 ;
30473053 }
3048- _PyStackChunk * new = allocate_chunk (allocate_size , tstate -> datastack_chunk );
3049- if (new == NULL ) {
3050- return NULL ;
3054+ _PyStackChunk * new ;
3055+ if (tstate -> datastack_cached_chunk != NULL
3056+ && (size_t )allocate_size <= tstate -> datastack_cached_chunk -> size )
3057+ {
3058+ new = tstate -> datastack_cached_chunk ;
3059+ tstate -> datastack_cached_chunk = NULL ;
3060+ new -> previous = tstate -> datastack_chunk ;
3061+ new -> top = 0 ;
3062+ }
3063+ else {
3064+ new = allocate_chunk (allocate_size , tstate -> datastack_chunk );
3065+ if (new == NULL ) {
3066+ return NULL ;
3067+ }
30513068 }
30523069 if (tstate -> datastack_chunk ) {
30533070 tstate -> datastack_chunk -> top = tstate -> datastack_top -
@@ -3083,12 +3100,17 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame)
30833100 if (base == & tstate -> datastack_chunk -> data [0 ]) {
30843101 _PyStackChunk * chunk = tstate -> datastack_chunk ;
30853102 _PyStackChunk * previous = chunk -> previous ;
3103+ _PyStackChunk * cached = tstate -> datastack_cached_chunk ;
30863104 // push_chunk ensures that the root chunk is never popped:
30873105 assert (previous );
30883106 tstate -> datastack_top = & previous -> data [previous -> top ];
30893107 tstate -> datastack_chunk = previous ;
3090- _PyObject_VirtualFree (chunk , chunk -> size );
30913108 tstate -> datastack_limit = (PyObject * * )(((char * )previous ) + previous -> size );
3109+ chunk -> previous = NULL ;
3110+ if (cached != NULL ) {
3111+ _PyObject_VirtualFree (cached , cached -> size );
3112+ }
3113+ tstate -> datastack_cached_chunk = chunk ;
30923114 }
30933115 else {
30943116 assert (tstate -> datastack_top );
0 commit comments