Skip to main content

Module conversion

Module conversion 

Source
Expand description

JIT-FFI bits ↔ runtime-tier carrier conversions (ADR-006 §2.7.5).

Pre-strict-typing this module bridged the JIT’s NaN-boxed u64 representation and the VM’s ValueWord (the v1 dynamic tagged word). The Phase-2 bulldozer deleted both the ValueWord type and the tag_bits::* discriminator family.

§Carrier shape (§2.7.5 stamp-at-compile-time)

Per ADR-006 §2.7.5 the JIT-FFI surface is (u64, NativeKind) — raw bits plus a parallel kind companion. The kind is stamped at JIT compile time from the call signature; it is never decoded from the bits. Consumers that need a runtime-tier carrier wrap the pair as KindedSlot::new(ValueSlot::from_raw(bits), kind) per §2.7.6/Q7 when crossing into runtime-tier dispatch.

§What this module does (W11-jit-carrier-conversion close)

These functions are the bookkeeping layer between the JIT call signature’s separate bits: u64 and kind: NativeKind parameters (the §2.7.5 stable-FFI raw-pair shape) and the in-Rust JitFfiCarrier tuple alias (u64, NativeKind). The body is intentionally trivial — per §2.7.5 the conversion is identity: raw bits stay raw bits, and the kind companion is whatever the caller’s static stamp passed in. No decode, no probe, no is_heap() classification — the kind is authoritative because the caller proved it at JIT compile time.

§What is forbidden

  • Decoding kind from bits (CLAUDE.md “Forbidden Patterns” #4, ADR-006 §2.7.7 #4 — the deleted tag_bits dispatch).
  • is_heap() / is_tagged() probe to classify (§2.7.7 #7).
  • Bool-default fallback when the caller didn’t supply a kind (forbidden #9 — surface-and-stop instead).
  • ValueWord resurrection under any name — the body’s pre-bulldozer shape decoded Arc<HeapValue> from raw bits via ValueWord::clone_from_bits and re-encoded per-arm via ValueWord::as_heap_ref / tag_bits::TAG_HEAP; all deleted.

§Historical context (pre-bulldozer body, what’s gone)

The deleted pipeline ran:

  1. nanboxed_to_jit_bits(&ValueWord) decoded ValueWord per arm (each arm a tag_bits::TAG_* discriminator), produced JIT bits.
  2. jit_bits_to_nanboxed(bits) re-decoded raw bits via the same tag_bits machinery, constructed a ValueWord via ValueWord::from_* constructors, returned it.
  3. The UNIFIED_HEAP_REFS thread-local accumulator captured retained Arc<HeapValue> shares for drain_unified_heap_refs() to release at the end of each JIT call.

All three steps are gone. The retain/release path now flows through clone_with_kind / drop_with_kind at the producing call site (ADR-006 §2.7.7), driven by the parallel-kind track — no global drain accumulator.

Functions§

drain_unified_heap_refs
Per-JIT-call ref-drain hook. Retained as a named export for the JIT executor’s per-call epilogue (executor.rs). The pre-bulldozer body drained the deleted UNIFIED_HEAP_REFS thread-local that the deleted nanboxed_to_jit_bits pushed Arc<HeapValue> retain-shares into.
jit_bits_to_nanboxed
Pack raw JIT-FFI bits + their static NativeKind stamp into a JitFfiCarrier per ADR-006 §2.7.5.
jit_bits_to_nanboxed_with_ctx
Variant of jit_bits_to_nanboxed with JITContext access, retained for downstream call sites (async_ops, control, generic_builtin, data_access, etc.) that need function-name resolution from the JIT context. The ctx pointer is plumbing for caller-side lookups (function table, function names) — the carrier itself is the same (bits, kind) pair.
jit_bits_to_typed_scalar
Convert JIT NaN-boxed bits to a TypedScalar with an optional type hint.
nanboxed_to_jit_bits
Unpack a JitFfiCarrier back to raw JIT-FFI bits per ADR-006 §2.7.5.
typed_scalar_to_jit_bits
Convert a TypedScalar to JIT NaN-boxed bits. Integer kinds box as box_number(value as f64) since the JIT’s Cranelift IR uses f64 for all numeric operations internally — this is JIT-internal scalar encoding, not tag_bits dispatch.