gh-127958: Trace from RESUME in the JIT (GH-145905)

This commit is contained in:
Ken Jin 2026-03-17 00:18:59 +08:00 committed by GitHub
parent 81ef1b7317
commit 3d0824aef2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 915 additions and 597 deletions

View file

@ -148,8 +148,9 @@ dummy_func(
pure inst(NOP, (--)) {
}
family(RESUME, 0) = {
family(RESUME, 1) = {
RESUME_CHECK,
RESUME_CHECK_JIT,
};
macro(NOT_TAKEN) = NOP;
@ -171,12 +172,8 @@ dummy_func(
}
}
op(_QUICKEN_RESUME, (--)) {
#if ENABLE_SPECIALIZATION
if (tstate->tracing == 0 && this_instr->op.code == RESUME) {
FT_ATOMIC_STORE_UINT8_RELAXED(this_instr->op.code, RESUME_CHECK);
}
#endif /* ENABLE_SPECIALIZATION */
tier1 op(_QUICKEN_RESUME, (counter/1 --)) {
_Py_Specialize_Resume(this_instr, tstate, frame);
}
tier1 op(_MAYBE_INSTRUMENT, (--)) {
@ -226,7 +223,11 @@ dummy_func(
_QUICKEN_RESUME +
_CHECK_PERIODIC_IF_NOT_YIELD_FROM;
inst(RESUME_CHECK, (--)) {
macro(RESUME_CHECK) =
unused/1 +
_RESUME_CHECK;
op(_RESUME_CHECK, (--)) {
#if defined(__EMSCRIPTEN__)
DEOPT_IF(_Py_emscripten_signal_clock == 0);
_Py_emscripten_signal_clock -= Py_EMSCRIPTEN_SIGNAL_HANDLING;
@ -241,6 +242,11 @@ dummy_func(
#endif
}
macro(RESUME_CHECK_JIT) =
unused/1 +
_RESUME_CHECK +
_JIT;
op(_MONITOR_RESUME, (--)) {
int err = _Py_call_instrumentation(
tstate, oparg == 0 ? PY_MONITORING_EVENT_PY_START : PY_MONITORING_EVENT_PY_RESUME, frame, this_instr);
@ -252,6 +258,7 @@ dummy_func(
}
macro(INSTRUMENTED_RESUME) =
unused/1 +
_LOAD_BYTECODE +
_MAYBE_INSTRUMENT +
_CHECK_PERIODIC_IF_NOT_YIELD_FROM +
@ -3114,9 +3121,11 @@ dummy_func(
tier1 op(_JIT, (--)) {
#ifdef _Py_TIER2
bool is_resume = this_instr->op.code == RESUME_CHECK_JIT;
_Py_BackoffCounter counter = this_instr[1].counter;
if (!IS_JIT_TRACING() && backoff_counter_triggers(counter) &&
this_instr->op.code == JUMP_BACKWARD_JIT &&
if ((backoff_counter_triggers(counter) &&
!IS_JIT_TRACING() &&
(this_instr->op.code == JUMP_BACKWARD_JIT || is_resume)) &&
next_instr->op.code != ENTER_EXECUTOR) {
/* Back up over EXTENDED_ARGs so executor is inserted at the correct place */
_Py_CODEUNIT *insert_exec_at = this_instr;
@ -3124,7 +3133,8 @@ dummy_func(
oparg >>= 8;
insert_exec_at--;
}
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at, next_instr, stack_pointer, 0, NULL, oparg, NULL);
int succ = _PyJit_TryInitializeTracing(tstate, frame, this_instr, insert_exec_at,
is_resume ? insert_exec_at : next_instr, stack_pointer, 0, NULL, oparg, NULL);
if (succ) {
ENTER_TRACING();
}
@ -3175,12 +3185,22 @@ dummy_func(
tier1 inst(ENTER_EXECUTOR, (--)) {
#ifdef _Py_TIER2
if (IS_JIT_TRACING()) {
next_instr = this_instr;
goto stop_tracing;
}
PyCodeObject *code = _PyFrame_GetCode(frame);
_PyExecutorObject *executor = code->co_executors->executors[oparg & 255];
if (IS_JIT_TRACING()) {
int og_opcode = executor->vm_data.opcode;
int og_oparg = (oparg & ~255) | executor->vm_data.oparg;
next_instr = this_instr;
if (_PyJit_EnterExecutorShouldStopTracing(og_opcode)) {
if (_PyOpcode_Caches[_PyOpcode_Deopt[opcode]]) {
PAUSE_ADAPTIVE_COUNTER(this_instr[1].counter);
}
opcode = og_opcode;
oparg = og_oparg;
DISPATCH_GOTO_NON_TRACING();
}
goto stop_tracing;
}
assert(executor->vm_data.index == INSTR_OFFSET() - 1);
assert(executor->vm_data.code == code);
assert(executor->vm_data.valid);