C(0) if i else str(0)
"""))
+ def test_load_special_type_guard_deopt(self):
+ script_helper.assert_python_ok("-s", "-c", textwrap.dedent(f"""
+ def f1():
+ class Context:
+ def __enter__(self): ...
+ def __exit__(self, e, v, t): ...
+
+ with Context():
+ pass
+
+ for _ in range({TIER2_THRESHOLD + 5}):
+ f1()
+ """), PYTHON_JIT="1")
+
def global_identity(x):
return x
--- /dev/null
+Fix a crash in the JIT optimizer when a specialized ``LOAD_SPECIAL`` guard deoptimized after inserting the synthetic ``NULL`` stack entry.
PyObject *name = _Py_SpecialMethods[oparg].name;
PyObject *descr = _PyType_Lookup(type, name);
if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) {
- ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag);
+ /* LOAD_SPECIAL expands to _RECORD_TOS_TYPE + _INSERT_NULL +
+ * _LOAD_SPECIAL. Insert _GUARD_TYPE_VERSION before the
+ * already-emitted _INSERT_NULL so deopt sees the original
+ * stack shape.*/
+ _PyUOpInstruction *insert_null = uop_buffer_last(&ctx->out_buffer);
+ assert(insert_null->opcode == _INSERT_NULL);
+ assert(insert_null->target == this_instr->target);
+ REPLACE_OP(insert_null, _GUARD_TYPE_VERSION, 0, type->tp_version_tag);
+ ADD_OP(_INSERT_NULL, 0, 0);
+
bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);
PyObject *name = _Py_SpecialMethods[oparg].name;
PyObject *descr = _PyType_Lookup(type, name);
if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) {
- ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag);
+ _PyUOpInstruction *insert_null = uop_buffer_last(&ctx->out_buffer);
+ assert(insert_null->opcode == _INSERT_NULL);
+ assert(insert_null->target == this_instr->target);
+ REPLACE_OP(insert_null, _GUARD_TYPE_VERSION, 0, type->tp_version_tag);
+ ADD_OP(_INSERT_NULL, 0, 0);
bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
0, (uintptr_t)descr);