You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
compile: a multi-MB JSON object literal supplied via --define (OpenCode's models.dev snapshot) never finishes codegen — lower large JSON defines through JSON.parse like #8418 #10151
Parent: #10107 (OpenCode v1.18.30). Related: #10101 / PR #10129 (defines), #8418 (JSON imports lowered via JSON.parse of a serialized constant to avoid exactly this).
Problem
scripts/build_opencode.ts injects OpenCode's models.dev snapshot as a build-time define: OPENCODE_MODELS_DEV = <4,623,748-byte JSON object literal> (the same value Bun's define receives). Perry substitutes the literal at its single use site (packages/core/src/models-dev.ts:199) and then lowers a 4.6 MB object literal into IR. The resulting codegen unit never finishes: on perrymaster (16 cores, 61 GB) the full 7,897-module OpenCode compile stalled with one perry-llvm-unit thread at 100 % for 25+ minutes (the progress log went silent at 3,355 staged objects, RSS flat at 22.5 GB) under PERRY_LL_SIZE_OPT=1 PERRY_LL_PREOPT_OPTNONE_INSTRS=8192, so the per-function optnone escape hatch does not cover it (the literal is one expression, not many functions).
Killing the compile and restarting on the same object cache with --define OPENCODE_MODELS_DEV=undefined (everything else identical) went straight past that point (6,444 objects after 20 minutes) — the fallback path fetches models.dev at runtime, which is not what the shipped binary does.
Repro
cd opencode-v1.18.30 && bun install --frozen-lockfile --ignore-scripts
cd /path/to/perry && bun scripts/build_opencode.ts /path/to/opencode-v1.18.30 --prepare-only --os linux --libc glibc
cd /path/to/opencode-v1.18.30/packages/opencode
perry compile src/index.ts --platform bun --output /tmp/oc --asset-module 'opencode-web-ui.gen.ts=../app/dist'# after `bun run --cwd ../app build`# stalls in codegen; PERRY_CODEGEN_PROGRESS=1 log stops; one perry-llvm-unit thread stays at 100 %
perry compile ... --define OPENCODE_MODELS_DEV=undefined # completes
A standalone reproduction: any module reading a defined identifier whose value is a multi-MB JSON object literal (--define 'BIG=<contents of models.dev api.json>', then export const x = typeof BIG === "undefined" ? undefined : BIG).
Expected
A define whose value is a large JSON literal should lower the way #8418 lowers JSON imports: embed the serialized text as a string constant and materialize it with JSON.parse at first use (or lazily), instead of IR-expanding the literal. Thresholds should be by literal size, independent of the function's instruction count, and the object cache key must still include the define value.
Acceptance
The repro compiles in seconds; the produced object for models-dev.ts is small (the string constant plus a parse call).
opencode --version from a build with the real snapshot define prints 1.18.30, and the models list matches the embedded snapshot without a network fetch.
A regression test with a >1 MiB JSON define under crates/perry/tests.
Fixed by #10161, landed via merge train #10172 (main 9b911855f8). JSON-compatible literals at or above 24,576 value nodes or 1 MiB of key/string content, and flat primitive arrays at 1,024 nodes or 64 KiB, now lower to a serialized string plus the JSON-parse intrinsic at their evaluation site. A record probe of this shape (6,400 records, 44,801 nodes) compiles --no-link in under a second on macOS. Mid-size record literals keep ordinary lowering and their static shapes.
Activity
proggeramlug commentedon Sep 13, 2026
Fixed by #10161, landed via merge train #10172 (main
9b911855f8). JSON-compatible literals at or above 24,576 value nodes or 1 MiB of key/string content, and flat primitive arrays at 1,024 nodes or 64 KiB, now lower to a serialized string plus the JSON-parse intrinsic at their evaluation site. A record probe of this shape (6,400 records, 44,801 nodes) compiles--no-linkin under a second on macOS. Mid-size record literals keep ordinary lowering and their static shapes.