Skip to content

Commit 92a4d35

Browse files
cocolatoblurb-it[bot]
authored andcommitted
gh-154701: prevent executor self-links in JIT cold exits (GH-155323)
* prevent executor self-links in JIT cold exits * πŸ“œπŸ€– Added by blurb_it. * fix windows ci --------- (cherry picked from commit 716cbae) Co-authored-by: Hai Zhu <haiizhu@outlook.com> Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
1 parent 39a0217 commit 92a4d35

6 files changed

Lines changed: 38 additions & 3 deletions

File tree

β€ŽInclude/internal/pycore_optimizer.hβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ typedef struct _PyExecutorObject {
206206
PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset);
207207

208208
int _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *);
209-
void _Py_ExecutorDetach(_PyExecutorObject *);
209+
PyAPI_FUNC(void) _Py_ExecutorDetach(_PyExecutorObject *);
210210
PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);
211211

212212
/* We use a bloomfilter with k = 6, m = 256

β€ŽInclude/internal/pycore_uop_metadata.hβ€Ž

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

β€ŽLib/test/test_capi/test_opt.pyβ€Ž

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
from test.support import (script_helper, requires_specialization,
1313
import_helper, Py_GIL_DISABLED, requires_jit_enabled,
14-
reset_code)
14+
reset_code, SHORT_TIMEOUT, isolation)
1515

1616
_testinternalcapi = import_helper.import_module("_testinternalcapi")
1717

@@ -6200,6 +6200,28 @@ def __exit__(self, e, v, t): ...
62006200
f1()
62016201
"""), PYTHON_JIT="1")
62026202

6203+
@isolation.runInSubprocess(timeout=SHORT_TIMEOUT)
6204+
def test_for_iter_side_exit_does_not_self_link(self):
6205+
def exhaust(iterator):
6206+
for _ in iterator:
6207+
pass
6208+
6209+
values = range(TIER2_THRESHOLD)
6210+
# After the initial trace, MAX_CHAIN_DEPTH side exits cause the final
6211+
# executor to be installed at FOR_ITER.
6212+
warmup_iterators = (
6213+
iter(set(values)),
6214+
iter(dict.fromkeys(values)),
6215+
iter(values),
6216+
enumerate(values),
6217+
zip(values, values),
6218+
)
6219+
for iterator in warmup_iterators:
6220+
exhaust(iterator)
6221+
6222+
# A different iterator type must not link that executor to itself.
6223+
exhaust(map(bool, values))
6224+
62036225
def global_identity(x):
62046226
return x
62056227

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix an infinite loop in JIT when a ``FOR_ITER`` side exit links an executor back to itself.

β€ŽPython/bytecodes.cβ€Ž

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6308,6 +6308,10 @@ dummy_func(
63086308
if (target->op.code == ENTER_EXECUTOR) {
63096309
PyCodeObject *code = _PyFrame_GetCode(frame);
63106310
executor = code->co_executors->executors[target->op.arg];
6311+
if (executor == _PyExecutor_FromExit(exit)) {
6312+
_Py_ExecutorDetach(executor);
6313+
GOTO_TIER_ONE(target);
6314+
}
63116315
Py_INCREF(executor);
63126316
assert(tstate->jit_exit == exit);
63136317
exit->executor = executor;

β€ŽPython/executor_cases.c.hβ€Ž

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

0 commit comments

Comments
Β (0)