GH-128682: Spill the stack pointer in labels, as well as instructions (GH-129618)

This commit is contained in:
Mark Shannon 2025-02-04 12:18:31 +00:00 committed by GitHub
parent d3c54f3788
commit 2effea4dab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 277 additions and 102 deletions

View file

@ -2808,7 +2808,7 @@ dummy_func(
start--;
}
_PyExecutorObject *executor;
int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer, &executor, 0);
int optimized = _PyOptimizer_Optimize(frame, start, &executor, 0);
if (optimized <= 0) {
this_instr[1].counter = restart_backoff_counter(counter);
ERROR_IF(optimized < 0, error);
@ -5033,7 +5033,7 @@ dummy_func(
}
else {
int chain_depth = current_executor->vm_data.chain_depth + 1;
int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth);
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(temperature);
if (optimized < 0) {
@ -5134,7 +5134,7 @@ dummy_func(
exit->temperature = advance_backoff_counter(exit->temperature);
GOTO_TIER_ONE(target);
}
int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, 0);
int optimized = _PyOptimizer_Optimize(frame, target, &executor, 0);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(exit->temperature);
if (optimized < 0) {
@ -5242,29 +5242,29 @@ dummy_func(
goto exception_unwind;
}
label(exception_unwind) {
spilled label(exception_unwind) {
/* We can't use frame->instr_ptr here, as RERAISE may have set it */
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
int handled = get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti);
if (handled == 0) {
// No handlers, so exit.
assert(_PyErr_Occurred(tstate));
/* Pop remaining stack entries. */
_PyStackRef *stackbase = _PyFrame_Stackbase(frame);
while (stack_pointer > stackbase) {
PyStackRef_XCLOSE(POP());
while (frame->stackpointer > stackbase) {
_PyStackRef ref = _PyFrame_StackPop(frame);
PyStackRef_XCLOSE(ref);
}
assert(STACK_LEVEL() == 0);
_PyFrame_SetStackPointer(frame, stack_pointer);
monitor_unwind(tstate, frame, next_instr-1);
goto exit_unwind;
}
assert(STACK_LEVEL() >= level);
_PyStackRef *new_top = _PyFrame_Stackbase(frame) + level;
while (stack_pointer > new_top) {
PyStackRef_XCLOSE(POP());
assert(frame->stackpointer >= new_top);
while (frame->stackpointer > new_top) {
_PyStackRef ref = _PyFrame_StackPop(frame);
PyStackRef_XCLOSE(ref);
}
if (lasti) {
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
@ -5272,7 +5272,7 @@ dummy_func(
if (lasti == NULL) {
goto exception_unwind;
}
PUSH(PyStackRef_FromPyObjectSteal(lasti));
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(lasti));
}
/* Make the raw exception data
@ -5280,10 +5280,11 @@ dummy_func(
so a program can emulate the
Python main loop. */
PyObject *exc = _PyErr_GetRaisedException(tstate);
PUSH(PyStackRef_FromPyObjectSteal(exc));
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(exc));
next_instr = _PyFrame_GetBytecode(frame) + handler;
if (monitor_handled(tstate, frame, next_instr, exc) < 0) {
int err = monitor_handled(tstate, frame, next_instr, exc);
if (err < 0) {
goto exception_unwind;
}
/* Resume normal execution */
@ -5292,10 +5293,11 @@ dummy_func(
lltrace_resume_frame(frame);
}
#endif
RELOAD_STACK();
DISPATCH();
}
label(exit_unwind) {
spilled label(exit_unwind) {
assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallPy(tstate);
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
@ -5311,16 +5313,16 @@ dummy_func(
return NULL;
}
next_instr = frame->instr_ptr;
stack_pointer = _PyFrame_GetStackPointer(frame);
RELOAD_STACK();
goto error;
}
label(start_frame) {
if (_Py_EnterRecursivePy(tstate)) {
spilled label(start_frame) {
int too_deep = _Py_EnterRecursivePy(tstate);
if (too_deep) {
goto exit_unwind;
}
next_instr = frame->instr_ptr;
stack_pointer = _PyFrame_GetStackPointer(frame);
#ifdef LLTRACE
{
@ -5339,6 +5341,7 @@ dummy_func(
assert(!_PyErr_Occurred(tstate));
#endif
RELOAD_STACK();
DISPATCH();
}

View file

@ -6331,7 +6331,7 @@
else {
int chain_depth = current_executor->vm_data.chain_depth + 1;
_PyFrame_SetStackPointer(frame, stack_pointer);
int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, chain_depth);
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(temperature);
@ -6498,7 +6498,7 @@
GOTO_TIER_ONE(target);
}
_PyFrame_SetStackPointer(frame, stack_pointer);
int optimized = _PyOptimizer_Optimize(frame, target, stack_pointer, &executor, 0);
int optimized = _PyOptimizer_Optimize(frame, target, &executor, 0);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(exit->temperature);

View file

@ -3420,6 +3420,7 @@
_PyErr_SetRaisedException(tstate, Py_NewRef(exc_value));
monitor_reraise(tstate, frame, this_instr);
stack_pointer = _PyFrame_GetStackPointer(frame);
_PyFrame_SetStackPointer(frame, stack_pointer);
goto exception_unwind;
}
stack_pointer[-3] = none;
@ -4000,6 +4001,7 @@
_PyErr_SetRaisedException(tstate, exc);
monitor_reraise(tstate, frame, this_instr);
stack_pointer = _PyFrame_GetStackPointer(frame);
_PyFrame_SetStackPointer(frame, stack_pointer);
goto exception_unwind;
}
stack_pointer += -2;
@ -5866,7 +5868,7 @@
}
_PyExecutorObject *executor;
_PyFrame_SetStackPointer(frame, stack_pointer);
int optimized = _PyOptimizer_Optimize(frame, start, stack_pointer, &executor, 0);
int optimized = _PyOptimizer_Optimize(frame, start, &executor, 0);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (optimized <= 0) {
this_instr[1].counter = restart_backoff_counter(counter);
@ -7838,6 +7840,7 @@
_PyFrame_SetStackPointer(frame, stack_pointer);
monitor_reraise(tstate, frame, this_instr);
stack_pointer = _PyFrame_GetStackPointer(frame);
_PyFrame_SetStackPointer(frame, stack_pointer);
goto exception_unwind;
}
goto error;
@ -7883,6 +7886,7 @@
_PyErr_SetRaisedException(tstate, exc);
monitor_reraise(tstate, frame, this_instr);
stack_pointer = _PyFrame_GetStackPointer(frame);
_PyFrame_SetStackPointer(frame, stack_pointer);
goto exception_unwind;
}
@ -9337,8 +9341,10 @@
/* Double-check exception status. */
#ifdef NDEBUG
if (!_PyErr_Occurred(tstate)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyErr_SetString(tstate, PyExc_SystemError,
"error return without exception set");
stack_pointer = _PyFrame_GetStackPointer(frame);
}
#else
assert(_PyErr_Occurred(tstate));
@ -9347,37 +9353,47 @@
/* Log traceback info. */
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
if (!_PyFrame_IsIncomplete(frame)) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyFrameObject *f = _PyFrame_GetFrameObject(frame);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (f != NULL) {
_PyFrame_SetStackPointer(frame, stack_pointer);
PyTraceBack_Here(f);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
}
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyEval_MonitorRaise(tstate, frame, next_instr-1);
stack_pointer = _PyFrame_GetStackPointer(frame);
_PyFrame_SetStackPointer(frame, stack_pointer);
goto exception_unwind;
}
exception_unwind:
{
/* STACK SPILLED */
/* We can't use frame->instr_ptr here, as RERAISE may have set it */
int offset = INSTR_OFFSET()-1;
int level, handler, lasti;
if (get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti) == 0) {
int handled = get_exception_handler(_PyFrame_GetCode(frame), offset, &level, &handler, &lasti);
if (handled == 0) {
// No handlers, so exit.
assert(_PyErr_Occurred(tstate));
/* Pop remaining stack entries. */
_PyStackRef *stackbase = _PyFrame_Stackbase(frame);
while (stack_pointer > stackbase) {
PyStackRef_XCLOSE(POP());
while (frame->stackpointer > stackbase) {
_PyStackRef ref = _PyFrame_StackPop(frame);
PyStackRef_XCLOSE(ref);
}
assert(STACK_LEVEL() == 0);
_PyFrame_SetStackPointer(frame, stack_pointer);
monitor_unwind(tstate, frame, next_instr-1);
goto exit_unwind;
}
assert(STACK_LEVEL() >= level);
_PyStackRef *new_top = _PyFrame_Stackbase(frame) + level;
while (stack_pointer > new_top) {
PyStackRef_XCLOSE(POP());
assert(frame->stackpointer >= new_top);
while (frame->stackpointer > new_top) {
_PyStackRef ref = _PyFrame_StackPop(frame);
PyStackRef_XCLOSE(ref);
}
if (lasti) {
int frame_lasti = _PyInterpreterFrame_LASTI(frame);
@ -9385,16 +9401,17 @@
if (lasti == NULL) {
goto exception_unwind;
}
PUSH(PyStackRef_FromPyObjectSteal(lasti));
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(lasti));
}
/* Make the raw exception data
available to the handler,
so a program can emulate the
Python main loop. */
PyObject *exc = _PyErr_GetRaisedException(tstate);
PUSH(PyStackRef_FromPyObjectSteal(exc));
_PyFrame_StackPush(frame, PyStackRef_FromPyObjectSteal(exc));
next_instr = _PyFrame_GetBytecode(frame) + handler;
if (monitor_handled(tstate, frame, next_instr, exc) < 0) {
int err = monitor_handled(tstate, frame, next_instr, exc);
if (err < 0) {
goto exception_unwind;
}
/* Resume normal execution */
@ -9403,11 +9420,13 @@
lltrace_resume_frame(frame);
}
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}
exit_unwind:
{
/* STACK SPILLED */
assert(_PyErr_Occurred(tstate));
_Py_LeaveRecursiveCallPy(tstate);
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
@ -9429,11 +9448,12 @@
start_frame:
{
if (_Py_EnterRecursivePy(tstate)) {
/* STACK SPILLED */
int too_deep = _Py_EnterRecursivePy(tstate);
if (too_deep) {
goto exit_unwind;
}
next_instr = frame->instr_ptr;
stack_pointer = _PyFrame_GetStackPointer(frame);
#ifdef LLTRACE
{
int lltrace = maybe_lltrace_resume_frame(frame, GLOBALS());
@ -9450,7 +9470,7 @@
caller loses its exception */
assert(!_PyErr_Occurred(tstate));
#endif
stack_pointer = _PyFrame_GetStackPointer(frame);
DISPATCH();
}

View file

@ -105,8 +105,9 @@ uop_optimize(_PyInterpreterFrame *frame, _Py_CODEUNIT *instr,
int
_PyOptimizer_Optimize(
_PyInterpreterFrame *frame, _Py_CODEUNIT *start,
_PyStackRef *stack_pointer, _PyExecutorObject **executor_ptr, int chain_depth)
_PyExecutorObject **executor_ptr, int chain_depth)
{
_PyStackRef *stack_pointer = frame->stackpointer;
assert(_PyInterpreterState_GET()->jit);
// The first executor in a chain and the MAX_CHAIN_DEPTH'th executor *must*
// make progress in order to avoid infinite loops or excessively-long