GH-136410: Faster side exits by using a cold exit stub (GH-136411)

This commit is contained in:
Mark Shannon 2025-08-01 16:26:07 +01:00 committed by GitHub
parent 718e0c89ba
commit e7b55f564d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 387 additions and 267 deletions

View file

@ -7113,9 +7113,8 @@
case _EXIT_TRACE: {
PyObject *exit_p = (PyObject *)CURRENT_OPERAND0();
_PyExitData *exit = (_PyExitData *)exit_p;
PyCodeObject *code = _PyFrame_GetCode(frame);
_Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target;
#if defined(Py_DEBUG) && !defined(_Py_JIT)
_Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target;
OPT_HIST(trace_uop_execution_counter, trace_run_length_hist);
if (frame->lltrace >= 2) {
_PyFrame_SetStackPointer(frame, stack_pointer);
@ -7128,36 +7127,7 @@
stack_pointer = _PyFrame_GetStackPointer(frame);
}
#endif
if (exit->executor && !exit->executor->vm_data.valid) {
exit->temperature = initial_temperature_backoff_counter();
_PyFrame_SetStackPointer(frame, stack_pointer);
Py_CLEAR(exit->executor);
stack_pointer = _PyFrame_GetStackPointer(frame);
}
if (exit->executor == NULL) {
_Py_BackoffCounter temperature = exit->temperature;
if (!backoff_counter_triggers(temperature)) {
exit->temperature = advance_backoff_counter(temperature);
GOTO_TIER_ONE(target);
}
_PyExecutorObject *executor;
if (target->op.code == ENTER_EXECUTOR) {
executor = code->co_executors->executors[target->op.arg];
Py_INCREF(executor);
}
else {
int chain_depth = current_executor->vm_data.chain_depth + 1;
_PyFrame_SetStackPointer(frame, stack_pointer);
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(temperature);
GOTO_TIER_ONE(optimized < 0 ? NULL : target);
}
exit->temperature = initial_temperature_backoff_counter();
}
exit->executor = executor;
}
tstate->jit_exit = exit;
GOTO_TIER_TWO(exit->executor);
break;
}
@ -7438,7 +7408,19 @@
#ifndef _Py_JIT
current_executor = (_PyExecutorObject*)executor;
#endif
assert(((_PyExecutorObject *)executor)->vm_data.valid);
assert(tstate->jit_exit == NULL || tstate->jit_exit->executor == current_executor);
tstate->current_executor = (PyObject *)executor;
if (!current_executor->vm_data.valid) {
assert(tstate->jit_exit->executor == current_executor);
assert(tstate->current_executor == executor);
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyExecutor_ClearExit(tstate->jit_exit);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (true) {
UOP_STAT_INC(uopcode, miss);
JUMP_TO_JUMP_TARGET();
}
}
break;
}
@ -7487,4 +7469,40 @@
break;
}
case _COLD_EXIT: {
_PyExitData *exit = tstate->jit_exit;
assert(exit != NULL);
_Py_CODEUNIT *target = _PyFrame_GetBytecode(frame) + exit->target;
_Py_BackoffCounter temperature = exit->temperature;
if (!backoff_counter_triggers(temperature)) {
exit->temperature = advance_backoff_counter(temperature);
GOTO_TIER_ONE(target);
}
_PyExecutorObject *executor;
if (target->op.code == ENTER_EXECUTOR) {
PyCodeObject *code = _PyFrame_GetCode(frame);
executor = code->co_executors->executors[target->op.arg];
Py_INCREF(executor);
}
else {
_PyFrame_SetStackPointer(frame, stack_pointer);
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
stack_pointer = _PyFrame_GetStackPointer(frame);
assert(tstate->current_executor == (PyObject *)previous_executor);
int chain_depth = previous_executor->vm_data.chain_depth + 1;
_PyFrame_SetStackPointer(frame, stack_pointer);
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
stack_pointer = _PyFrame_GetStackPointer(frame);
if (optimized <= 0) {
exit->temperature = restart_backoff_counter(temperature);
GOTO_TIER_ONE(optimized < 0 ? NULL : target);
}
exit->temperature = initial_temperature_backoff_counter();
}
assert(tstate->jit_exit == exit);
exit->executor = executor;
GOTO_TIER_TWO(exit->executor);
break;
}
#undef TIER_TWO