Skip to content

Commit 3eacfc1

Browse files
authored
GH-121784: Generate an error during code gen if a variable is marked unused, but is used and thus cached in a prior uop. (#121788)
* Reject uop definitions that declare values as 'unused' that are already cached by prior uops * Track which variables are defined and only load from memory when needed * Support explicit `flush` in macro definitions. * Make sure stack is flushed in where needed.
1 parent 169324c commit 3eacfc1

9 files changed

+443
-255
lines changed

Lib/test/test_generated_cases.py

Lines changed: 194 additions & 52 deletions
Large diffs are not rendered by default.

Python/bytecodes.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3448,7 +3448,7 @@ dummy_func(
34483448
}
34493449
}
34503450

3451-
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
3451+
op(_CHECK_FUNCTION_VERSION, (func_version/2, callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
34523452
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
34533453
EXIT_IF(!PyFunction_Check(callable_o));
34543454
PyFunctionObject *func = (PyFunctionObject *)callable_o;
@@ -3479,7 +3479,6 @@ dummy_func(
34793479
assert(PyStackRef_IsNull(null));
34803480
assert(Py_TYPE(callable_o) == &PyMethod_Type);
34813481
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
3482-
stack_pointer[-1 - oparg] = self; // Patch stack as it is used by _PY_FRAME_GENERAL
34833482
method = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
34843483
assert(PyFunction_Check(PyStackRef_AsPyObjectBorrow(method)));
34853484
PyStackRef_CLOSE(callable);
@@ -3490,6 +3489,7 @@ dummy_func(
34903489
_CHECK_PEP_523 +
34913490
_CHECK_METHOD_VERSION +
34923491
_EXPAND_METHOD +
3492+
flush + // so that self is in the argument array
34933493
_PY_FRAME_GENERAL +
34943494
_SAVE_RETURN_OFFSET +
34953495
_PUSH_FRAME;
@@ -3544,16 +3544,12 @@ dummy_func(
35443544
EXIT_IF(Py_TYPE(PyStackRef_AsPyObjectBorrow(callable)) != &PyMethod_Type);
35453545
}
35463546

3547-
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, unused, unused[oparg] -- func, self, unused[oparg])) {
3547+
op(_INIT_CALL_BOUND_METHOD_EXACT_ARGS, (callable, null, unused[oparg] -- func, self, unused[oparg])) {
35483548
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
35493549
STAT_INC(CALL, hit);
3550-
stack_pointer[-1 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self); // Patch stack as it is used by _INIT_CALL_PY_EXACT_ARGS
3551-
stack_pointer[-2 - oparg] = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func); // This is used by CALL, upon deoptimization
3552-
self = stack_pointer[-1 - oparg];
3553-
func = stack_pointer[-2 - oparg];
3550+
self = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_self);
3551+
func = PyStackRef_FromPyObjectNew(((PyMethodObject *)callable_o)->im_func);
35543552
PyStackRef_CLOSE(callable);
3555-
// self may be unused in tier 1, so silence warnings.
3556-
(void)self;
35573553
}
35583554

35593555
op(_CHECK_PEP_523, (--)) {
@@ -3568,7 +3564,7 @@ dummy_func(
35683564
EXIT_IF(code->co_argcount != oparg + (!PyStackRef_IsNull(self_or_null)));
35693565
}
35703566

3571-
op(_CHECK_STACK_SPACE, (callable, unused, unused[oparg] -- callable, unused, unused[oparg])) {
3567+
op(_CHECK_STACK_SPACE, (callable, self_or_null, unused[oparg] -- callable, self_or_null, unused[oparg])) {
35723568
PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
35733569
PyFunctionObject *func = (PyFunctionObject *)callable_o;
35743570
PyCodeObject *code = (PyCodeObject *)func->func_code;
@@ -3609,6 +3605,7 @@ dummy_func(
36093605
_CHECK_PEP_523 +
36103606
_CHECK_CALL_BOUND_METHOD_EXACT_ARGS +
36113607
_INIT_CALL_BOUND_METHOD_EXACT_ARGS +
3608+
flush + // In case the following deopt
36123609
_CHECK_FUNCTION_VERSION +
36133610
_CHECK_FUNCTION_EXACT_ARGS +
36143611
_CHECK_STACK_SPACE +

Python/executor_cases.c.h

Lines changed: 2 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)