Problem
The target model is AOT compilation for statically typed code and the JIT for everything else, in the same process. #800 covers compiling typed TS to a standalone native binary, and its extern "js" escape hatch lets native code call into the engine — but nothing lets JIT'd JS call AOT-compiled functions. The bridge already exists: bun:ffi builds JIT'd call stubs between JSC and native code, and upstream js/bun/ffi/cc.test.ts passes natively (8 pass, 0 fail). (New direction.)
Evidence (origin/main @ d4b219507)
packages/runtime/src/jsc/FFI.zigpackages/runtime/src/runtime/ffi/ffi.zigdocs/docs/NATIVE_RUNTIME_BINDINGS.md:91docs/docs/TS_PARITY_PLAN.md:3251-3268
Scope
home runcompiles each sound-typed module that fits the AOT subset to native code and registers its exports as native functions via the FFI stub machinery; everything else stays on the JIT.- Argument and return conversion generated from the sound types (numbers, strings, structs, arrays, callbacks).
- A rule for objects crossing between AOT code and JSC's garbage-collected heap: allocate in the JSC heap, or wrap with handles plus stack maps — decided in a short design note.
- An
HMdiagnostic /--explain-aotreport saying which functions were AOT-compiled and, for the rest, why not. - Cache compiled modules by content hash.
Acceptance criteria
- A mixed program (untyped JS calling a sound-typed hot loop) runs under
home runwith output identical to pure-JIT execution. - The hot loop runs from AOT code (verified by the report) and is not slower than the JIT on the compute benchmarks.
- A GC stress test with objects crossing the boundary in both directions passes.