Skip to content

Commit 209cd64

Browse files
committed
gh-158072: Fix JIT crash with omitted default arguments
1 parent a5b03fa commit 209cd64

3 files changed

Lines changed: 29 additions & 5 deletions

File tree

‎Lib/test/test_capi/test_opt.py‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1812,6 +1812,20 @@ def testfunc(n):
18121812
# __init__ resolution allows promotion of range to constant
18131813
self.assertNotIn("_LOAD_GLOBAL_BUILTINS", uops)
18141814

1815+
# See https://github.com/python/cpython/issues/158072
1816+
def test_init_with_default_argument(self):
1817+
script_helper.assert_python_ok("-c", textwrap.dedent(f"""\
1818+
sentinel = object()
1819+
1820+
class WithDefault:
1821+
def __init__(self, value=sentinel):
1822+
if value is not sentinel:
1823+
pass
1824+
1825+
for _ in range({TIER2_THRESHOLD * 3}):
1826+
WithDefault()
1827+
"""), PYTHON_JIT="1")
1828+
18151829
def test_init_guards_removed(self):
18161830
class MyPoint:
18171831
def __init__(self, x, y):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix a JIT crash when a class is instantiated with their default arguments

‎Python/optimizer_symbols.c‎

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1392,13 +1392,22 @@ _Py_uop_frame_new(
13921392
frame->locals[i] = PyJitRef_RemoveUnique(args[i]);
13931393
}
13941394

1395-
// If the args are known, then it's safe to just initialize
1396-
// every other non-set local to null symbol.
1397-
bool default_null = args != NULL;
1395+
// When args is available, missing parameters get defaults or *args/**kwargs.
1396+
// Other locals start as NULL. When args is NULL, treat all locals as unknown.
1397+
int parameter_count = co->co_argcount + co->co_kwonlyargcount;
1398+
parameter_count += (co->co_flags & CO_VARARGS) != 0;
1399+
parameter_count += (co->co_flags & CO_VARKEYWORDS) != 0;
13981400

13991401
for (int i = arg_len; i < co->co_nlocalsplus; i++) {
1400-
JitOptRef local = default_null ? _Py_uop_sym_new_null(ctx) : _Py_uop_sym_new_unknown(ctx);
1401-
frame->locals[i] = local;
1402+
if (args == NULL) {
1403+
frame->locals[i] = _Py_uop_sym_new_unknown(ctx);
1404+
}
1405+
else if (i < parameter_count) {
1406+
frame->locals[i] = _Py_uop_sym_new_not_null(ctx);
1407+
}
1408+
else {
1409+
frame->locals[i] = _Py_uop_sym_new_null(ctx);
1410+
}
14021411
}
14031412

14041413
frame->callable = _Py_uop_sym_new_not_null(ctx);

0 commit comments

Comments
 (0)