@@ -2182,9 +2182,6 @@ _Py_GetConfig(void)
2182
2182
static PyObject * *
2183
2183
push_chunk (PyThreadState * tstate , int size )
2184
2184
{
2185
- assert (tstate -> datastack_chunk == NULL ||
2186
- tstate -> datastack_top + size >= tstate -> datastack_limit );
2187
-
2188
2185
int allocate_size = DATA_STACK_CHUNK_SIZE ;
2189
2186
while (allocate_size < (int )sizeof (PyObject * )* (size + MINIMUM_OVERHEAD )) {
2190
2187
allocate_size *= 2 ;
@@ -2199,6 +2196,9 @@ push_chunk(PyThreadState *tstate, int size)
2199
2196
}
2200
2197
tstate -> datastack_chunk = new ;
2201
2198
tstate -> datastack_limit = (PyObject * * )(((char * )new ) + allocate_size );
2199
+ // When new is the "root" chunk (new->previous == NULL), we keep
2200
+ // _PyThreadState_PopFrame from freeing it later by "skipping" over the
2201
+ // first element.
2202
2202
PyObject * * res = & new -> data [new -> previous == NULL ];
2203
2203
tstate -> datastack_top = res + size ;
2204
2204
return res ;
@@ -2225,7 +2225,8 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject
2225
2225
{
2226
2226
PyCodeObject * code = (PyCodeObject * )func -> func_code ;
2227
2227
int nlocalsplus = code -> co_nlocalsplus ;
2228
- size_t size = nlocalsplus + code -> co_stacksize + FRAME_SPECIALS_SIZE ;
2228
+ size_t size = nlocalsplus + code -> co_stacksize +
2229
+ FRAME_SPECIALS_SIZE ;
2229
2230
InterpreterFrame * frame = _PyThreadState_BumpFramePointer (tstate , size );
2230
2231
if (frame == NULL ) {
2231
2232
return NULL ;
@@ -2240,25 +2241,20 @@ _PyThreadState_PushFrame(PyThreadState *tstate, PyFunctionObject *func, PyObject
2240
2241
void
2241
2242
_PyThreadState_PopFrame (PyThreadState * tstate , InterpreterFrame * frame )
2242
2243
{
2243
- assert (tstate -> datastack_top );
2244
- assert (tstate -> datastack_limit );
2245
2244
assert (tstate -> datastack_chunk );
2246
2245
PyObject * * base = (PyObject * * )frame ;
2247
2246
if (base == & tstate -> datastack_chunk -> data [0 ]) {
2248
2247
_PyStackChunk * chunk = tstate -> datastack_chunk ;
2249
2248
_PyStackChunk * previous = chunk -> previous ;
2250
- if (previous ) {
2251
- tstate -> datastack_top = & previous -> data [previous -> top ];
2252
- tstate -> datastack_limit = (PyObject * * )(((char * )previous ) + previous -> size );
2253
- }
2254
- else {
2255
- tstate -> datastack_top = NULL ;
2256
- tstate -> datastack_limit = NULL ;
2257
- }
2249
+ // push_chunk ensures that the root chunk is never popped:
2250
+ assert (previous );
2251
+ tstate -> datastack_top = & previous -> data [previous -> top ];
2258
2252
tstate -> datastack_chunk = previous ;
2259
2253
_PyObject_VirtualFree (chunk , chunk -> size );
2254
+ tstate -> datastack_limit = (PyObject * * )(((char * )previous ) + previous -> size );
2260
2255
}
2261
2256
else {
2257
+ assert (tstate -> datastack_top );
2262
2258
assert (tstate -> datastack_top >= base );
2263
2259
tstate -> datastack_top = base ;
2264
2260
}
0 commit comments