Skip to content

Commit ad1513a

Browse files
authored
GH-150516: Reduce the work done to spill and reload the stack around calls (GH-151587)
1 parent d47c27e commit ad1513a

19 files changed

Lines changed: 3550 additions & 1496 deletions

Include/internal/pycore_interpframe.h

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ static inline void _PyFrame_Copy(_PyInterpreterFrame *src, _PyInterpreterFrame *
152152
// visited is GC bookkeeping for the current stack walk, not frame state.
153153
dest->visited = 0;
154154
#ifdef Py_DEBUG
155+
dest->stackpointer_valid = src->stackpointer_valid;
155156
dest->lltrace = src->lltrace;
156157
#endif
157158
for (int i = 0; i < stacktop; i++) {
@@ -207,6 +208,7 @@ _PyFrame_Initialize(
207208
frame->owner = FRAME_OWNED_BY_THREAD;
208209
frame->visited = 0;
209210
#ifdef Py_DEBUG
211+
frame->stackpointer_valid = 1;
210212
frame->lltrace = 0;
211213
#endif
212214

@@ -230,26 +232,51 @@ _PyFrame_GetLocalsArray(_PyInterpreterFrame *frame)
230232
static inline _PyStackRef*
231233
_PyFrame_GetStackPointer(_PyInterpreterFrame *frame)
232234
{
235+
return frame->stackpointer;
236+
}
237+
238+
static inline void
239+
_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
240+
{
241+
frame->stackpointer = stack_pointer;
242+
}
243+
244+
static inline void
245+
_PyFrame_StackPointerValidate(_PyInterpreterFrame *frame)
246+
{
247+
#ifdef Py_DEBUG
248+
/* Avoid bloating the JIT code */
233249
#ifndef _Py_JIT
234-
assert(frame->stackpointer != NULL);
250+
assert(frame->stackpointer_valid == 0);
235251
#endif
236-
_PyStackRef *sp = frame->stackpointer;
237-
#ifndef NDEBUG
238-
frame->stackpointer = NULL;
252+
frame->stackpointer_valid = 1;
239253
#endif
240-
return sp;
241254
}
242255

243256
static inline void
244-
_PyFrame_SetStackPointer(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer)
257+
_PyFrame_StackPointerInvalidate(_PyInterpreterFrame *frame)
245258
{
259+
#ifdef Py_DEBUG
246260
/* Avoid bloating the JIT code */
247261
#ifndef _Py_JIT
248-
assert(frame->stackpointer == NULL);
262+
assert(frame->stackpointer_valid == 1);
263+
#endif
264+
frame->stackpointer_valid = 0;
249265
#endif
250-
frame->stackpointer = stack_pointer;
251266
}
252267

268+
static inline void
269+
_PyFrame_StackAssertInvalid(_PyInterpreterFrame *frame)
270+
{
271+
#ifdef Py_DEBUG
272+
/* Avoid bloating the JIT code */
273+
#ifndef _Py_JIT
274+
assert(frame->stackpointer_valid == 0);
275+
#endif
276+
#endif
277+
}
278+
279+
253280
/* Determine whether a frame is incomplete.
254281
* A frame is incomplete if it is part way through
255282
* creating cell objects or a generator or coroutine.
@@ -411,6 +438,7 @@ _PyFrame_PushTrampolineUnchecked(PyThreadState *tstate, PyCodeObject *code, int
411438
frame->owner = FRAME_OWNED_BY_THREAD;
412439
frame->visited = 0;
413440
#ifdef Py_DEBUG
441+
frame->stackpointer_valid = 1;
414442
frame->lltrace = 0;
415443
#endif
416444
frame->return_offset = 0;

Include/internal/pycore_interpframe_structs.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ struct _PyInterpreterFrame {
4444
char owner;
4545
#ifdef Py_DEBUG
4646
uint8_t visited:1;
47-
uint8_t lltrace:7;
47+
uint8_t stackpointer_valid:1;
48+
uint8_t lltrace:6;
4849
#else
4950
uint8_t visited;
5051
#endif

Include/internal/pycore_opcode_metadata.h

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_optimizer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,7 +312,7 @@ int _Py_uop_analyze_and_optimize(
312312
_PyUOpInstruction *input, int trace_len, int curr_stackentries,
313313
_PyUOpInstruction *output, _PyBloomFilter *dependencies);
314314

315-
extern PyTypeObject _PyUOpExecutor_Type;
315+
PyAPI_DATA(PyTypeObject) _PyUOpExecutor_Type;
316316

317317

318318
#define UOP_FORMAT_TARGET 0

Include/internal/pycore_uop_metadata.h

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)