Repository navigation
Stack promotion: loop exits, direct closure calls, try under gc/none - #606
Merged
Merged
Conversation
- Loop rule: a use outside the loop is loop-carried only when the site can run again after it (CFG reachability, unwind edges included), so a `return p.s` or `found = p.s; break` in a search loop promotes. - A closure called by name (ts.SymbolCallInternal with the box as its `this`) is classified through the callee's parameter fact. - The nested-closure invariant is checked: a box field never holds a capture box, and every closure made from the box keeps its `this`. - Functions with a try region promote under gc and none. - ts.ReleaseContents nulls each field it gives back. - Pass caches cleared per run; recursion from one SCC pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
These are the reviewer's deferred findings on stack promotion version 1 (#605).
return p.sor afound = p.s; breakin a search loop now promotes. A slot declared outside the loop (loop_carried.ts) still stays on the heap. Test:loop_exit_use.const g = () => ...; g()lowers tots.SymbolCallInternalwith the box as operand 0.decideBoxnow classifies that use through the callee's parameter fact. Test:closure_direct_call(gc/none → stack).emitReleaseContentsnow nulls each field it releases, so a later release finds nothing. At a return those stores are dead and LLVM drops them. Test:test-stack-release-contents-nulls-{rc,own}, which greps the lowered IR for the null store after the release call.recursive_mutual. It passed before this change too; the change keeps the same answers.decideBox: a box field must not hold a capture box, and every closure made from the box must keep itsthis, checked through the parameter fact. No source program can produce the violating shape, so no test can fail first.closure_nestedcovers the case where the invariant holds.try_region(gc/none → stack, rc/own → heap: try-region), plustry_catch_reads, which reads a stack object in a catch (a funclet on Windows) and continues a loop from it.The decision tests for items 1, 2, 3 and 6 failed on the old binary before the fix. All new files are also run tests under every model, JIT and AOT. The box itself is now also checked by the loop rule, which keeps the decision on the safe side. The user docs (
docs/memory-models.md) and spec section 5.5 are updated.Full ctest: 4652/4652 passed. With
-DTSLANG_TEST_NO_STACK_PROMOTION=ON: 4652/4652 passed.🤖 Generated with Claude Code