gh-146058: Fix _GUARD_CODE_VERSION_* (GH-146060)

This commit is contained in:
Ken Jin 2026-03-18 01:19:44 +08:00 committed by GitHub
parent ff287a72de
commit 966fc81531
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 1557 additions and 1154 deletions

View file

@ -5755,10 +5755,39 @@ dummy_func(
Py_UNREACHABLE();
}
tier2 op(_GUARD_CODE_VERSION, (version/2 -- )) {
tier2 op(_GUARD_CODE_VERSION__PUSH_FRAME, (version/2 -- )) {
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
EXIT_IF(((PyCodeObject *)code)->co_version != version);
if (((PyCodeObject *)code)->co_version != version) {
EXIT_IF(true);
}
}
tier2 op(_GUARD_CODE_VERSION_YIELD_VALUE, (version/2 -- )) {
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND;
EXIT_IF(true);
}
}
tier2 op(_GUARD_CODE_VERSION_RETURN_VALUE, (version/2 -- )) {
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
EXIT_IF(true);
}
}
tier2 op(_GUARD_CODE_VERSION_RETURN_GENERATOR, (version/2 -- )) {
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
EXIT_IF(true);
}
}
tier2 op(_GUARD_IP__PUSH_FRAME, (ip/4 --)) {

View file

@ -20753,23 +20753,25 @@
GOTO_TIER_ONE(target);
}
case _GUARD_CODE_VERSION_r00: {
case _GUARD_CODE_VERSION__PUSH_FRAME_r00: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
if (true) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
}
}
SET_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_r11: {
case _GUARD_CODE_VERSION__PUSH_FRAME_r11: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
@ -20777,10 +20779,12 @@
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
UOP_STAT_INC(uopcode, miss);
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
JUMP_TO_JUMP_TARGET();
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
@ -20788,7 +20792,7 @@
break;
}
case _GUARD_CODE_VERSION_r22: {
case _GUARD_CODE_VERSION__PUSH_FRAME_r22: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
@ -20797,11 +20801,13 @@
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
@ -20810,7 +20816,7 @@
break;
}
case _GUARD_CODE_VERSION_r33: {
case _GUARD_CODE_VERSION__PUSH_FRAME_r33: {
CHECK_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
@ -20820,12 +20826,296 @@
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
UOP_STAT_INC(uopcode, miss);
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
JUMP_TO_JUMP_TARGET();
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_YIELD_VALUE_r00: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND;
if (true) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
}
}
SET_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_YIELD_VALUE_r11: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_YIELD_VALUE_r22: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_YIELD_VALUE_r33: {
CHECK_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
_PyStackRef _stack_item_2 = _tos_cache2;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += 1 + INLINE_CACHE_ENTRIES_SEND;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_VALUE_r00: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
}
}
SET_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_VALUE_r11: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_VALUE_r22: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_VALUE_r33: {
CHECK_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
_PyStackRef _stack_item_2 = _tos_cache2;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_GENERATOR_r00: {
CHECK_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
SET_CURRENT_CACHED_VALUES(0);
JUMP_TO_JUMP_TARGET();
}
}
SET_CURRENT_CACHED_VALUES(0);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_GENERATOR_r11: {
CHECK_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(1);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_GENERATOR_r22: {
CHECK_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(2);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
break;
}
case _GUARD_CODE_VERSION_RETURN_GENERATOR_r33: {
CHECK_CURRENT_CACHED_VALUES(3);
assert(WITHIN_STACK_BOUNDS_IGNORING_CACHE());
_PyStackRef _stack_item_0 = _tos_cache0;
_PyStackRef _stack_item_1 = _tos_cache1;
_PyStackRef _stack_item_2 = _tos_cache2;
uint32_t version = (uint32_t)CURRENT_OPERAND0_32();
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
assert(PyCode_Check(code));
if (((PyCodeObject *)code)->co_version != version) {
frame->instr_ptr += frame->return_offset;
if (true) {
UOP_STAT_INC(uopcode, miss);
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;
_tos_cache0 = _stack_item_0;
SET_CURRENT_CACHED_VALUES(3);
JUMP_TO_JUMP_TARGET();
}
}
_tos_cache2 = _stack_item_2;
_tos_cache1 = _stack_item_1;

View file

@ -528,6 +528,26 @@ guard_ip_uop[MAX_UOP_ID + 1] = {
[_YIELD_VALUE] = _GUARD_IP_YIELD_VALUE,
};
static const uint16_t
guard_code_version_uop[MAX_UOP_ID + 1] = {
[_PUSH_FRAME] = _GUARD_CODE_VERSION__PUSH_FRAME,
[_RETURN_GENERATOR] = _GUARD_CODE_VERSION_RETURN_GENERATOR,
[_RETURN_VALUE] = _GUARD_CODE_VERSION_RETURN_VALUE,
[_YIELD_VALUE] = _GUARD_CODE_VERSION_YIELD_VALUE,
};
static const uint16_t
dynamic_exit_uop[MAX_UOP_ID + 1] = {
[_GUARD_IP__PUSH_FRAME] = 1,
[_GUARD_IP_RETURN_GENERATOR] = 1,
[_GUARD_IP_RETURN_VALUE] = 1,
[_GUARD_IP_YIELD_VALUE] = 1,
[_GUARD_CODE_VERSION__PUSH_FRAME] = 1,
[_GUARD_CODE_VERSION_RETURN_GENERATOR] = 1,
[_GUARD_CODE_VERSION_RETURN_VALUE] = 1,
[_GUARD_CODE_VERSION_YIELD_VALUE] = 1,
};
#define CONFIDENCE_RANGE 1000
#define CONFIDENCE_CUTOFF 333
@ -939,9 +959,10 @@ _PyJit_translate_single_bytecode_to_trace(
} // End switch (opcode)
if (needs_guard_ip) {
uint16_t guard_ip = guard_ip_uop[uop_buffer_last(trace)->opcode];
int last_opcode = uop_buffer_last(trace)->opcode;
uint16_t guard_ip = guard_ip_uop[last_opcode];
if (guard_ip == 0) {
DPRINTF(1, "Unknown uop needing guard ip %s\n", _PyOpcode_uop_name[uop_buffer_last(trace)->opcode]);
DPRINTF(1, "Unknown uop needing guard ip %s\n", _PyOpcode_uop_name[last_opcode]);
Py_UNREACHABLE();
}
PyObject *code = PyStackRef_AsPyObjectBorrow(frame->f_executable);
@ -952,7 +973,7 @@ _PyJit_translate_single_bytecode_to_trace(
/* Record stack depth, in operand1 */
int stack_depth = (int)(frame->stackpointer - _PyFrame_Stackbase(frame));
uop_buffer_last(trace)->operand1 = stack_depth;
ADD_TO_TRACE(_GUARD_CODE_VERSION, 0, ((PyCodeObject *)code)->co_version, 0);
ADD_TO_TRACE(guard_code_version_uop[last_opcode], 0, ((PyCodeObject *)code)->co_version, 0);
}
}
// Loop back to the start
@ -1219,13 +1240,7 @@ prepare_for_execution(_PyUOpInstruction *buffer, int length)
base_exit_op = _HANDLE_PENDING_AND_DEOPT;
}
int32_t jump_target = target;
if (
base_opcode == _GUARD_IP__PUSH_FRAME ||
base_opcode == _GUARD_IP_RETURN_VALUE ||
base_opcode == _GUARD_IP_YIELD_VALUE ||
base_opcode == _GUARD_IP_RETURN_GENERATOR ||
base_opcode == _GUARD_CODE_VERSION
) {
if (dynamic_exit_uop[base_opcode]) {
base_exit_op = _DYNAMIC_EXIT;
}
int exit_depth = get_cached_entries_for_side_exit(inst);

View file

@ -1775,19 +1775,6 @@ dummy_func(void) {
// do not need an IP guard.
}
op(_GUARD_CODE_VERSION, (version/2 -- )) {
PyCodeObject *co = get_current_code_object(ctx);
if (co->co_version == version) {
_Py_BloomFilter_Add(dependencies, co);
// TODO gh-144651:
// If we've previously guarded on this code version in a trace, we
// can avoid guarding it again.
}
else {
ctx->done = true;
}
}
op(_GUARD_IP_YIELD_VALUE, (ip/4 --)) {
(void)ip;
if (ctx->frame->caller) {

View file

@ -4299,15 +4299,19 @@
break;
}
case _GUARD_CODE_VERSION: {
uint32_t version = (uint32_t)this_instr->operand0;
PyCodeObject *co = get_current_code_object(ctx);
if (co->co_version == version) {
_Py_BloomFilter_Add(dependencies, co);
}
else {
ctx->done = true;
}
case _GUARD_CODE_VERSION__PUSH_FRAME: {
break;
}
case _GUARD_CODE_VERSION_YIELD_VALUE: {
break;
}
case _GUARD_CODE_VERSION_RETURN_VALUE: {
break;
}
case _GUARD_CODE_VERSION_RETURN_GENERATOR: {
break;
}