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

@ -2964,6 +2964,8 @@ dummy_func(
else {
this_instr[1].counter = initial_jump_backoff_counter();
assert(tstate->current_executor == NULL);
assert(executor != tstate->interp->cold_executor);
tstate->jit_exit = NULL;
GOTO_TIER_TWO(executor);
}
}
@ -3028,6 +3030,8 @@ dummy_func(
}
DISPATCH_GOTO();
}
assert(executor != tstate->interp->cold_executor);
tstate->jit_exit = NULL;
GOTO_TIER_TWO(executor);
#else
Py_FatalError("ENTER_EXECUTOR is not supported in this build");
@ -5238,9 +5242,8 @@ dummy_func(
tier2 op(_EXIT_TRACE, (exit_p/4 --)) {
_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) {
printf("SIDE EXIT: [UOp ");
@ -5251,32 +5254,7 @@ dummy_func(
_PyOpcode_OpName[target->op.code]);
}
#endif
if (exit->executor && !exit->executor->vm_data.valid) {
exit->temperature = initial_temperature_backoff_counter();
Py_CLEAR(exit->executor);
}
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;
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
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);
}
@ -5375,7 +5353,14 @@ dummy_func(
#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);
_PyExecutor_ClearExit(tstate->jit_exit);
DEOPT_IF(true);
}
}
tier2 op(_MAKE_WARM, (--)) {
@ -5414,6 +5399,37 @@ dummy_func(
assert(tstate->tracing || eval_breaker == FT_ATOMIC_LOAD_UINTPTR_ACQUIRE(_PyFrame_GetCode(frame)->_co_instrumentation_version));
}
tier2 op(_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 {
_PyExecutorObject *previous_executor = _PyExecutor_FromExit(exit);
assert(tstate->current_executor == (PyObject *)previous_executor);
int chain_depth = previous_executor->vm_data.chain_depth + 1;
int optimized = _PyOptimizer_Optimize(frame, target, &executor, chain_depth);
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);
}
label(pop_2_error) {
stack_pointer -= 2;
assert(WITHIN_STACK_BOUNDS());