Skip to content

[JSC] Make the bytecode cache format independent of the encoding platform - #389

Draft
dylan-conway wants to merge 2 commits into
mainfrom
claude/portable-bytecode-cache
Draft

[JSC] Make the bytecode cache format independent of the encoding platform#389
dylan-conway wants to merge 2 commits into
mainfrom
claude/portable-bytecode-cache

Conversation

@dylan-conway

@dylan-conway dylan-conway commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

Bun cross-compiles bun build --compile --bytecode executables, so the JSC bytecode cache is decoded on a different OS/CPU than encoded it. The cache is the in-memory image of the Cached* objects, and two parts of it depended on the encoder's C++ ABI: CachedMetadataTable stored byte offsets computed from sizeof(Op::Metadata) (every opcode embedding CallLinkInfo is 16 bytes larger under MSVC, so a POSIX-built table linked on Windows had LLInt indexing past each entry — a crash in llint_entry), and the Bun-only CachedStringSourceProvider::m_sourceLength landed at a different offset under MSVC. The table is now serialized as per-opcode entry counts and laid out again by the decoder through the normal finalize() path; m_sourceLength is gone (the key already compares the source hash and length).

The encoder's output is also made a pure function of its input — fixed allocation alignment/page size, zeroed pages, string switch tables in index order instead of StringImpl* hash order, UnlinkedHandlerInfo encoded field-wise instead of with bit-field slack — so Bun can assert byte-identical output on every platform in CI. The two allocation entry points static_assert what the compiler can check about a serialized type's portability. All behavior changes are under USE(BUN_JSC_ADDITIONS).

Test plan

In progress — will fill in before marking ready: Release and Debug builds on macOS arm64 are done and Bun built against this decodes its own --bytecode output (new cross-platform snapshot test stable across runs); currently running JSTests/stress in disk-cache mode (JSC_diskCachePath then JSC_forceDiskCache) with the Debug shell against a baseline shell, Linux/Windows builds, cross-OS decode of one executable, and startup/size A/B against the current pin.

…form

The cache is decoded by Bun executables cross-compiled for a different OS/CPU
than the one that produced it, but two things in it depended on the encoder's
C++ ABI:

- CachedMetadataTable serialized the finalized metadata offset table, whose
  entries are byte offsets computed from sizeof(Op::Metadata). Those sizes
  differ between ABIs (everything embedding CallLinkInfo is 16 bytes larger
  under MSVC), so a table encoded on Linux/macOS and linked on Windows had
  LLInt indexing past each entry. Serialize per-opcode entry counts instead
  and lay the table out again on decode via the normal finalize() path.
- CachedStringSourceProvider's Bun-only m_sourceLength sat in the base
  class's tail padding under Itanium but not under MSVC. It didn't validate
  anything SourceCodeKey doesn't already (the key compares the source hash),
  so drop it and hand back the provider being decoded against.

Also make the encoder's output a pure function of its input so it can be
compared across platforms: fixed allocation alignment and page size instead
of alignof(max_align_t)/pageSize(), zeroed pages so struct padding is not
heap garbage, string switch tables encoded in index order rather than
StringImpl-pointer hash order, and UnlinkedHandlerInfo encoded field-wise
rather than copied with 30 bits of bit-field slack.

The two allocation entry points now static_assert what the compiler can
check about a type's portability (alignment, no destructor/array cookie,
and for verbatim-copied types: no padding or bit-field slack, no
long/wchar_t/long double).
The verbatim-copy check rejected `long` by name to catch the LP64/LLP64
size difference, but int64_t (EncodedJSValue) is `long` under glibc. Only
reject `long` where it is the 32-bit outlier.
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Preview Builds

Commit Release Date
08a83d53 autobuild-preview-pr-389-08a83d53 2026-08-05 22:01:57 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant