Repository navigation
C builds a segment of any width: continuations take wide frames, joins and closures pack the words past WIDE (#1069) - #1958
Open
Lorenzobattistela wants to merge 6 commits into
Open
Lorenzobattistela wants to merge 6 commits into
Lorenzobattistela wants to merge 6 commits into
Conversation
Contributor
|
Verified against current main ( The regression tests are meaningful: on current main, Blocker: repo-gate fails. Merged with current main, Please:
Happy to help with a token-diet patch if useful. |
…; a continuation's frame takes any width Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…past WIDE wide_capture_calls and wide_capture_closure come from #1788. Co-authored-by: Sebastian Griego <177274079+sebastian-griego@users.noreply.github.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… loop A pack rounded to 2^cls_fit(len+1) and filled the rest with zeros. Only a node past WIDE needs a power-of-two arity (lay_node), so a pack now takes its own size up to WIDE and pads only past it. seg_pack no longer mutates its parameter inside findIndex, seg_open unpacks in a plain loop, and the join splits its held words from its results with two filters. The 207 reg/run programs without a pack emit the same C; the wide tests pass on C (1 and 4 threads) and JS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
nicolas-abril
force-pushed
the
wide-spill
branch
from
November 3, 2026 14:54
bb166fa to
8c53670
Compare
The 212 reg/run programs emit the same C. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… its limit - term_drop kept a node's live-field count in 8 bits of its cursor; a task can now pass 255 fields, so one with 256+ live fields keeps the count in its last word, as an array or a wide constructor does. - WL_ARGS checks WL_ROOM: a continuation's frame is no longer capped at 247 words, and FID_ENTER and FID_EXIT pushed it unchecked on the device. - seg_open hands a ~pack node to the segment's spares, so the body's first alloc of its class reuses it. - "an arity over" names the limit passed: 247 for a register segment, 65535 for a frame, 32768 for a constructor. Programs without a pack differ only in those runtime lines (212 reg/run programs); the wide tests pass on C (1 and 4 threads) and JS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only a def's own parameters and one parallel let's results keep the 247 limit now. 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.
Fixes #1069.
A program the interpreter and JS run could fail
bend -owithan arity over 247whenever a segment kept more than 247 words live: a record built field by field with calls, a list literal of calls, values live across a fork, a closure's captures. Since 2.0.39 a real program hits it too (hapsland, reported on #1069): #1806 letscommand_selectedborrowcommandinstead of moving it, soNativeRun.command_selected$k1063keeps it live and goes from 243 to 254 words. #1806 is right; the limit is the problem, and that program has 27 segments between 200 and 247 words.The 247 limit is the register bank's, but only some segments enter through it:
seg_take,WL_ARGS); only its results ride registers, and the bank is already sized without it. It only needed a wider arity:Fidtakes u16 fields when some arity passes 255, u8 otherwise, so other builds keep their table. On Metal all four fields must share one width: a u16arbeside u8 fields leaves the device lane with "frontier drained" even in small programs.FID_ENTER'sWL_LOAD,Clo~apply).seg_packmoves their live words past WIDE into one~packnode of 2^c words, a constructor with its own CID, so a dropped closure'sterm_dropfrees it and its fields.seg_openreads it back into locals at the segment's entry and frees it. Both join paths, parallel and sequential, pack the same tail. Words of any width pack, which covers the multiword captures fix(compiler): box wide continuation and closure captures #1788 boxed.term_dropreads64 | (n - 240)only for constructors: a wide task or closure now exists.Programs under the limit emit the same C as before, apart from the
Fidtypedef's position and thatterm_dropline (checked on 73 tests in tests/run and tests/reg).Tests (tests/reg), each failing to build on main and passing on interpreter, JS and C at 1 and 4 threads:
!.What stays:
preserve_nonefunction's frame passes 4 KB (ARM64 native emission triggers clang backend crashes; isolated LLVM14 IR reproducer and Apple clang21 report #1233). A segment with about 500 live words reaches it;-fno-stack-checkbuilds it, and 600 live words then run correctly.!, very large programs (10+ MB of C) are slow or crash in Metal's compiler on main too.Related: #1788 (multiword captures, superseded by this), #1494 (an earlier spill through the evaluator stack, closed).
Gates on 9d514f3: test 1789 / 1789, perf 124 / 124, ping 81 / 81, safe 1144 agree and 0 false reject.
🤖 Generated with Claude Code