Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Include/internal/pycore_optimizer.h
Original file line numberDiff line numberDiff line change
Expand Up@@ -206,7 +206,7 @@ typedef struct _PyExecutorObject {
PyAPI_FUNC(_PyExecutorObject*) _Py_GetExecutor(PyCodeObject *code, int offset);

int _Py_ExecutorInit(_PyExecutorObject *, const _PyBloomFilter *);
void _Py_ExecutorDetach(_PyExecutorObject *);
PyAPI_FUNC(void) _Py_ExecutorDetach(_PyExecutorObject *);
PyAPI_FUNC(void) _Py_Executor_DependsOn(_PyExecutorObject *executor, void *obj);

/* We use a bloomfilter with k = 6, m = 256
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_uop_metadata.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 23 additions & 1 deletion Lib/test/test_capi/test_opt.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@

from test.support import (script_helper, requires_specialization,
import_helper, Py_GIL_DISABLED, requires_jit_enabled,
reset_code)
reset_code, SHORT_TIMEOUT, isolation)

_testinternalcapi = import_helper.import_module("_testinternalcapi")

Expand DownExpand Up@@ -6225,6 +6225,28 @@ def __exit__(self, e, v, t): ...
f1()
"""), PYTHON_JIT="1")

@isolation.runInSubprocess(timeout=SHORT_TIMEOUT)
def test_for_iter_side_exit_does_not_self_link(self):
def exhaust(iterator):
for _ in iterator:
pass

values = range(TIER2_THRESHOLD)
# After the initial trace, MAX_CHAIN_DEPTH side exits cause the final
# executor to be installed at FOR_ITER.
warmup_iterators = (
iter(set(values)),
iter(dict.fromkeys(values)),
iter(values),
enumerate(values),
zip(values, values),
)
for iterator in warmup_iterators:
exhaust(iterator)

# A different iterator type must not link that executor to itself.
exhaust(map(bool, values))

def global_identity(x):
return x

Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
Fix an infinite loop in JIT when a ``FOR_ITER`` side exit links an executor back to itself.
4 changes: 4 additions & 0 deletions Python/bytecodes.c
Original file line numberDiff line numberDiff line change
Expand Up@@ -6262,6 +6262,10 @@ dummy_func(
if (target->op.code == ENTER_EXECUTOR) {
PyCodeObject *code = _PyFrame_GetCode(frame);
executor = code->co_executors->executors[target->op.arg];
if (executor == _PyExecutor_FromExit(exit)) {
_Py_ExecutorDetach(executor);
GOTO_TIER_ONE(target);
}
Py_INCREF(executor);
assert(tstate->jit_exit == exit);
exit->executor = executor;
Expand Down
8 changes: 8 additions & 0 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading