--- name: jit-overview description: Orientation to facet-format JIT deserialization (tiering, fallbacks, key types/entry points) and where to look when changing or debugging JIT code --- # JIT deserialization overview (facet-format) Facet’s JIT lives in `facet-format` and is used by format crates like `facet-json`. ## When to read this - You’re touching anything under `facet-format/src/jit/` or enabling the `jit` feature. - You’re investigating performance changes in deserialization (especially “tier2”/JIT benchmarks). - You’re debugging a JIT crash (SIGSEGV/UB-ish symptoms). ## Mental model `facet-format` defines a **format-neutral** deserialization pipeline: - A `FormatParser` (implemented by each format crate) produces a stream of `ParseEvent`s. - A shape-driven layer consumes those events and writes to an output value (often via `facet-reflect`). The JIT accelerates this by compiling deserialization code specialized for: 1. the **target type** (`T` / its `Shape`), and sometimes 2. the **format parser** (`P`). ## Two-tier architecture (high level) ### Tier 1 (shape JIT) - Compiles code that consumes `ParseEvent`s and writes directly into the output’s memory at known offsets. - Works with any format that implements `FormatParser` (JSON/YAML/TOML/…). ### Tier 2 (format JIT) - For the “entire input slice is available” case, a format crate can provide a `FormatJitParser` + `JitFormat` implementation. - Tier 2 emits Cranelift IR to parse bytes directly, bypassing the `ParseEvent` stream for maximum throughput. ### Fallbacks are part of the design - Tier 2 may return “unsupported” for shapes/input it can’t handle, and must be side-effect-free in that case. - Callers typically try tier 2, then tier 1, then reflection. ## Entry points & where to look - Main docs and contracts: `facet-format/src/jit/mod.rs` - JIT-enabled parser trait: `facet-format/src/parser.rs` (`FormatJitParser`) - JIT usage in a format crate: - `facet-json/Cargo.toml` feature `jit = ["facet-format/jit"]` - Example: `facet-json/examples/profile_jit_vec` (requires `jit`) - Windows crash debugging notes: `.claude/skills/windbg-jit.md` - Memory debugging: `.claude/skills/debug-with-valgrind/SKILL.md` (uses nextest profiles) ## Debugging checklist (practical) 1. Reproduce with a minimal type + input (see `.claude/skills/reproduce-reduce-regress/SKILL.md`). 2. Run the failing test under: - valgrind: `cargo nextest run --profile valgrind …` (configured in `.config/nextest.toml`) - or Miri when applicable (`just miri`) for UB/provenance issues outside the JIT itself. 3. If the crash is in JIT codegen/execution: - Prefer isolating the smallest shape that triggers tier selection and failure. - Look for tier selection diagnostics and caching behavior in `facet-format/src/jit/mod.rs`. ## Common pitfalls - Assuming tier 2 supports “all shapes”: it intentionally supports a performance-focused subset. - Forgetting that “unsupported” must not advance the parser cursor or partially initialize output. - Introducing new unsafe paths without tests that exercise drop/cleanup on error paths.