[Fix] Break JIT cache-key dependency-traversal recursion cycles#803
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a recursion bug in JIT cache-key dependency traversal: _collect_dependency_sources() could re-enter cache-key computation via JitFunction._ensure_cache_manager() using a fresh visited set, causing unbounded recursion (e.g., self-reference, mutual jit references, or .launch name collisions with a top-level @flyc.jit named launch).
Changes:
- Add a reentrancy guard (
_computing_manager_key) toJitFunctionand emit a stablejit-recursive:<name>:<label>placeholder when a cycle is detected during dependency collection. - Wrap manager-key computation in
try/finallyto ensure the guard is cleared even on errors. - Add regression tests covering
.launchattribute collision, jit self-reference, and mutual jit references; improve_load_mod()to dedent module bodies for readability.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
python/flydsl/compiler/jit_function.py |
Adds cycle-breaking logic for dependency-source collection and a per-instance “computing manager key” guard. |
tests/unit/test_jit_cache_key_completeness.py |
Adds regression tests for recursion-cycle scenarios and updates module loader to dedent test module sources. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
sjfeng1999
force-pushed
the
pr/fix-jit-cache-key-recursion
branch
from
July 6, 2026 04:59
f26b7d4 to
9e7558a
Compare
`_collect_dependency_sources` used a `visited` set to guard against cycles, but the JitFunction branch went through `val._ensure_cache_manager()` -> `_jit_function_cache_key` -> `_collect_dependency_sources(<fresh visited>)`, bypassing the caller's `visited`. During that computation `manager_key` is still `None`, so there was no reentrancy guard: any jit self-reference, jit<->jit mutual reference, or a `.launch` attribute name colliding with a same-named top-level `@flyc.jit` would recurse until `RecursionError`. Guard reentrancy with a thread-local set of the `id(func)` whose keys are currently being computed on this thread: `_jit_function_cache_key` adds its func on entry and discards it in `finally`, and the dependency traversal, when it meets a JitFunction already being keyed (a cycle), emits a stable `jit-recursive:<name>:<label>` placeholder instead of reentering. Each cycle member's own source still enters the key via its own `_get_func_source`, so the placeholder only breaks the cycle. The stack is thread-local (not a per-instance flag) so that a JitFunction being keyed on one thread is not mistaken for a cycle by a concurrent compilation on another thread — that would otherwise substitute the placeholder for a real dependency and make keys timing-dependent. Acyclic code never hits the placeholder branch, so existing cache keys (and on-disk cache) are unchanged. Add regression tests for top-level `launch` attribute collision, jit self-reference, jit<->jit mutual reference, thread-local isolation of the guard, and no-leak cleanup of the in-progress stack. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
sjfeng1999
force-pushed
the
pr/fix-jit-cache-key-recursion
branch
from
July 6, 2026 05:01
9e7558a to
7880701
Compare
coderfeli
approved these changes
Jul 7, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
_collect_dependency_sourcesused avisitedset to guard against cycles, but the JitFunction branch went throughval._ensure_cache_manager()->_jit_function_cache_key->_collect_dependency_sources(<fresh visited>), bypassing the caller'svisited. During that computationmanager_keyis stillNone, so there was no reentrancy guard: any jit self-reference, jit<->jit mutual reference, or a.launchattribute name colliding with a same-named top-level@flyc.jitwould recurse untilRecursionError.Add a per-instance
_computing_manager_keyflag, set while a JitFunction computes its own key. When the dependency traversal meets a JitFunction already computing its key (a cycle), emit a stablejit-recursive:<name>:<label>placeholder instead of reentering. Each cycle member's own source still enters the key via its own_get_func_source, so the placeholder only breaks the cycle.Acyclic code never hits the placeholder branch, so existing cache keys (and on-disk cache) are unchanged.
Add regression tests for top-level
launchattribute collision, jit self-reference, and jit<->jit mutual reference.Motivation
Technical Details
Test Plan
Test Result
Submission Checklist