Skip to content

Commit f9e5975

Browse files
[3.15] gh-149459: Fix segfault when _LOAD_SPECIAL guard deoptimizes (GH-149478) (#149552)
gh-149459: Fix segfault when `_LOAD_SPECIAL` guard deoptimizes (GH-149478) (cherry picked from commit c341e34) Co-authored-by: Hai Zhu <haiizhu@outlook.com>
1 parent b922b42 commit f9e5975

4 files changed

Lines changed: 30 additions & 2 deletions

File tree

Lib/test/test_capi/test_opt.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6138,6 +6138,20 @@ def __init__(self, x):
61386138
C(0) if i else str(0)
61396139
"""))
61406140

6141+
def test_load_special_type_guard_deopt(self):
6142+
script_helper.assert_python_ok("-s", "-c", textwrap.dedent(f"""
6143+
def f1():
6144+
class Context:
6145+
def __enter__(self): ...
6146+
def __exit__(self, e, v, t): ...
6147+
6148+
with Context():
6149+
pass
6150+
6151+
for _ in range({TIER2_THRESHOLD + 5}):
6152+
f1()
6153+
"""), PYTHON_JIT="1")
6154+
61416155
def global_identity(x):
61426156
return x
61436157

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a crash in the JIT optimizer when a specialized ``LOAD_SPECIAL`` guard deoptimized after inserting the synthetic ``NULL`` stack entry.

Python/optimizer_bytecodes.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2043,7 +2043,16 @@ dummy_func(void) {
20432043
PyObject *name = _Py_SpecialMethods[oparg].name;
20442044
PyObject *descr = _PyType_Lookup(type, name);
20452045
if (descr != NULL && (Py_TYPE(descr)->tp_flags & Py_TPFLAGS_METHOD_DESCRIPTOR)) {
2046-
ADD_OP(_GUARD_TYPE_VERSION, 0, type->tp_version_tag);
2046+
/* LOAD_SPECIAL expands to _RECORD_TOS_TYPE + _INSERT_NULL +
2047+
* _LOAD_SPECIAL. Insert _GUARD_TYPE_VERSION before the
2048+
* already-emitted _INSERT_NULL so deopt sees the original
2049+
* stack shape.*/
2050+
_PyUOpInstruction *insert_null = uop_buffer_last(&ctx->out_buffer);
2051+
assert(insert_null->opcode == _INSERT_NULL);
2052+
assert(insert_null->target == this_instr->target);
2053+
REPLACE_OP(insert_null, _GUARD_TYPE_VERSION, 0, type->tp_version_tag);
2054+
ADD_OP(_INSERT_NULL, 0, 0);
2055+
20472056
bool immortal = _Py_IsImmortal(descr) || (type->tp_flags & Py_TPFLAGS_IMMUTABLETYPE);
20482057
ADD_OP(immortal ? _LOAD_CONST_INLINE_BORROW : _LOAD_CONST_INLINE,
20492058
0, (uintptr_t)descr);

Python/optimizer_cases.c.h

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)