ReviewOS

home-lang/home

Standalone --compile --bytecode misses embedded JSC cache

#549
Closed chris opened this 9 days ago ·
9 days ago

Follow-up to #66, discovered while verifying the adjacent bytecode coverage for #491 against Bun pin 4982b91e3702094330f3be3883354c52b8c01323.

Reproduction

cat >/tmp/home-bytecode-entry.ts <<'JS'
console.log("hello");
JS

./zig-out/bin/home-debug build /tmp/home-bytecode-entry.ts \
  --compile --bytecode --format=cjs --outfile=/tmp/home-bytecode-entry
BUN_JSC_verboseDiskCache=1 /tmp/home-bytecode-entry

Home prints:

[Disk Cache] Cache miss for sourceCode
hello
[Disk Cache] Cache miss for sourceCode

The pinned Bun release prints a cache hit for the embedded entry bytecode under the same reproduction. This is not specific to deferred imports: a one-line entry has the same miss. The compiled executable still produces the correct program output.

Likely boundary

Home already generates bytecode with the compile-time virtual module URL, and ResolvedSource exposes bytecode_origin_path, but the native standalone_graph/StandaloneModuleGraph.zig surface remains partial and does not preserve the bytecode origin path through the embedded graph. Pinned Bun stores that exact path beside each bytecode payload and returns it through ResolvedSource so JSC's cache key matches at runtime.

Port the standalone graph field, serialization/deserialization, loader handoff, and cache-hit coverage together. Keep the generic compiled-executable fix separate from #491's deferred phase metadata; #491's native runtime transpiler-cache cold/warm path is independently covered.

9 days ago

Resolved on main by babb9f9e2 (integrated at deccc8155).

What landed:

  • replaced Home's placeholder standalone graph with the full pinned Bun graph serializer/deserializer and executable writer
  • restored real zstd compression, platform executable formats, graph file/blob bridging, and loader metadata
  • persisted and consumed JSC bytecode, its exact origin path, deserialized module info, and CJS/ESM format
  • detected embedded graphs before Home's compiler dispatcher and booted them through the native JSC VM lifecycle
  • ported Bun's option tokenizer so compile-time execArgv and BUN_OPTIONS are parsed without leaking into user process.argv

End-to-end verification used fresh executables produced by Home's own Bun.build({ compile: ... }) implementation:

  • CJS + bytecode: true: [Disk Cache] Cache hit for sourceCode, then cjs-bytecode-42
  • ESM + bytecode: true: [Disk Cache] Cache hit for sourceCode, then esm-bytecode-42 alpha,--version
  • execArgv + BUN_OPTIONS: process.argv contained only the embedded entry and user args; process.execArgv contained both option sources; --title=HomeStandalone set process.title
  • a final rebuilt CJS executable again produced a cache hit and preserved --version as a user argument

Gates:

  • debug build: 18/18 steps
  • scoped home_rt: 1,841 tests, 1,822 passed, 19 skipped, 0 failed
  • scoped Pickier and git diff --check: clean

The separate outer home build CLI routing gap is tracked in #550; it does not affect the now-working standalone graph/runtime path used by Bun.build().

Sign in to comment on this issue.