ReviewOS

zig-utils/zig-js

JIT: unify backend-neutral codegen and W^X memory contracts

#483
Open chris opened this 8 days ago ·
8 days ago

Parent: #459 Depends on: #466, #469, #470, #462

Goal

Create one backend-neutral native code-generation and executable-memory contract shared by JavaScript baseline/optimizer tiers and future WebAssembly compilers.

Scope

  • Separate target-independent machine IR, calling convention, register classes, stack-frame layout, relocations, patch/link sites, safepoints/stack maps, unwind/debug metadata, and deopt records from instruction encoding.
  • Define owned assemblers/encoders for each declared ISA; no LLVM, external assembler process, DynASM, third-party JIT, or opaque codegen library.
  • Implement platform W^X allocation/write/publish/patch/retire policies for supported OSes, including instruction-cache synchronization and hardened-runtime requirements.
  • Preserve and test platform control-flow/code-integrity mitigations where applicable: AArch64 BTI and pointer-authentication conventions, x86 CET, Windows CFG/unwind registration, and equivalent future policies. Unsupported mitigation combinations fail closed rather than silently disabling protection.
  • Emit deterministic code bytes, relocations, stack maps, unwind/debug records, and artifact identities for identical IR/target/options/dependency inputs; nondeterministic addresses are normalized out of reproducibility evidence.
  • Provide the exact symbol/unwind/source registration contract consumed by #501, including safe retirement after the final artifact reader.
  • Add deterministic disassembly/encoding fixtures, relocation validation, executable mapping accounting, and fail-closed target feature detection.
  • Share runtime-operation ABIs and map/recovery formats where JS and Wasm semantics align without conflating their value models.
  • Keep generated code immutable after publication except through explicitly synchronized patch/link protocols.

No-workaround rules

  • No executable writable pages after publication, RWX mapping, Zig private ABI dependency, shelling out to an assembler, or target advertised when it only falls back.
  • Fallback remains correct but does not satisfy native-backend completion/performance claims.

Acceptance

  • A versioned backend contract and verifier cover encodings, relocations, frames, maps, recovery, W^X, cache flush, patching, and retirement.
  • Existing macOS AArch64 baseline/optimizer behavior migrates with exact differentials and no noise-qualified regression.
  • Malformed machine IR/relocations/maps fail before publication.
  • Code bytes, mapping bytes, compile time, and retirement are reconciled under #480/#461.
  • Hardened-runtime/control-flow mitigation fixtures, deterministic artifact hashes, unwind registration, and #501 symbol/source attribution pass on each backend.
  • x86-64 (#484), Linux (#485), and Wasm (#487) consume this contract without third-party runtime dependencies.

Foundation

#52/#146/#433; current AArch64 files under src/jit/; W^X creation began at 3e69e9c9.

8 days ago

Landed the executable-memory/W^X contract slice in 95948fb3.

Implemented:

  • versioned v1 executable-memory profiles with verified, stable owned encodings;
  • macOS AArch64 MAP_JIT thread-scoped write protection and cache synchronization behind the shared contract;
  • Linux AArch64/x86-64 anonymous RW allocation followed by one RX mprotect publication transition, with compiler-rt AArch64 cache clearing and no libc dependency;
  • fail-closed target selection kept separate from native-tier advertisement;
  • exact used-byte publication, mapping-byte accounting, immutable-after-publish policy, and existing epoch-safe retirement;
  • real child-process W^X probes plus an independent Debug/ReleaseSafe Linux CI leg.

Validation: 1,531 unit tests passed with one expected Linux-only perf-writer skip, zero failures/leaks; 207 focused JIT tests passed with the same platform skip; focused TSan, VM, concurrency, GC relocation and optimizer-release inventories passed; native signal/crash attribution passed; 400 seeded threadfuzz programs completed; Linux AArch64/x86-64 cross-links passed; docs link/build gates passed.

Test262 flips: 0. Generated bytes, entry ABI, and JavaScript semantics are unchanged.

Keeping #483 open: this completes the shared W^X/cache/publish/retire foundation only. The versioned machine IR, relocations/link sites, mitigation-specific codegen contracts, and downstream #484/#485/#487 consumers remain.

Sign in to comment on this issue.