1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! luna-core JIT surface — **trait + types only, zero Cranelift**.
//!
//! The interpreter dispatcher in [`crate::vm::exec`] routes JIT calls
//! through [`IntChunkCompiler`] / [`TraceCompiler`] trait objects;
//! luna-core ships only the no-op [`NullJitBackend`], which makes the
//! whole crate Cranelift-free (and therefore zero-three-party-dep,
//! per v1.1 F1).
//!
//! The Cranelift-backed implementations (`CraneliftBackend`, the 26
//! `luna_jit_*` extern "C" helpers, the `JIT_CACHE` thread-local,
//! `enter_jit`, `cache_lookup_or_compile`, `try_compile_int_chunk`,
//! `try_compile_trace_with_options`, …) live in the `luna` crate
//! under `luna::jit_backend`. Embedders who want the JIT use
//! `luna::Vm::new_minimal_with_jit(version)` instead of
//! `luna_core::vm::Vm::new_minimal(version)`.
// v1.1 A1 Session B — pure data types + small cranelift-free helpers
// for the trace JIT live here. Session C moves the file under
// luna-core unchanged.
pub use *;
// v1.3 Phase AOT Stage 7 sub-piece 4 — wire format for AOT trace
// metadata (header + index entry + encode/decode). Pure data; both
// `luna-aot` (compile-time encode) and `luna-runtime-helpers`
// (deploy-time decode) depend on this single module so the on-disk
// shape stays in lock-step.
// v1.1 A1 Session A — backend trait surface introduced in-place.
// Session C moves it to luna-core (this file) and extracts the
// Cranelift-bound CraneliftBackend struct out into luna's
// jit_backend module.
pub use ;
// v2.0 Track J sub-step J-B — per-Vm JIT storage trait. Holds the
// (formerly thread-local) JIT cache + handle collections so a Vm
// carries its own JIT state across thread moves (Send-prep for J-D).
pub use ;
// v2.1 Track J-C — cfg-gated Send-friendly aliases & wrappers for
// the trace IR interior-mutability types. Default-feature path is
// 0-cost (`Rc` / `Cell` / `RefCell`); `feature = "send"` flips to
// `Arc` / `AtomicU32` / `AtomicBool` / `AtomicPtr<u8>` / `RwLock` so
// `CompiledTrace` + `Proto::traces` become structurally Send + Sync.
pub use ;
// Compatibility re-export so external `use luna::jit::trace::*` paths
// (and the historical `crate::jit::trace::*` accesses inside this
// crate) keep resolving even after Session C's physical split. In
// luna-core `trace` is just a namespace alias for `trace_types`; in
// luna it's enriched with codegen-bearing items via a different
// re-export.
/// Trace-JIT types namespace. In `luna-core` this is a thin re-export of
/// [`trace_types`]; the `luna` crate enriches it with the Cranelift-backed
/// codegen entry points (`try_compile_trace`, etc.).
/// Construct an inert [`JitVmGuard`] that performs neither TLS install
/// nor TLS clear. Used by [`NullJitBackend::enter`]: since
/// `try_compile` / `try_compile_trace` always skip work, no JIT mcode
/// ever fires and no helper consults the TLS slots, so the guard only
/// has to keep the trait method signature symmetric with luna's
/// `CraneliftBackend::enter`. The inert guard carries no restore
/// callback, so its drop is a no-op.
/// P11-S5c — RAII guard pinning the active `Vm` (and optional closure)
/// pointer for JIT-emitted Rust helper calls.
///
/// # v2.0 Track J sub-step J-D — real RAII rebind
///
/// Prior to J-D, this guard's drop was a deliberate no-op: the
/// dispatcher always re-installed `JIT_VM` / `JIT_CL` on every
/// `enter_jit` call, so the previous-dispatch values would simply be
/// overwritten on the next entry. That trick saved 2 TLS writes per
/// dispatch (~5-10 cycles each on arm64) — measurable on fib_28's
/// 434k dispatches (~1.5 ms aggregate).
///
/// Track J Option B targets cross-thread Vm move under
/// `feature = "send"` (J-E flip). Once a Vm parks on thread A, moves
/// to thread B, and dispatches there, the per-thread `JIT_VM` slot on
/// thread B is null/stale at entry — `enter_jit` installs it fine on
/// the way in, but on the way out the no-op drop left stale Vm
/// pointers behind for any **nested** JIT entry (Lua-from-Rust-from-
/// JIT call chains, e.g. metamethod dispatch under a JIT'd op). With
/// nested entries restoring an outer Vm pointer becomes load-bearing.
///
/// J-D therefore turns the guard into a real RAII: `enter_jit`
/// captures the prior `(JIT_VM, JIT_CL)` values into the guard, and
/// `Drop` restores them. The cost is the 2 TLS writes we previously
/// elided per dispatch. The single-thread-no-nesting case is
/// semantically equivalent: prior values restored on exit are the
/// same null/stale ones the next `enter_jit` would overwrite anyway;
/// no observable behavior change for existing call sites.
///
/// `NullJitBackend::enter` keeps the no-op shape via
/// [`noop_jit_guard`] — its guard has `restore = None`.
///
/// Debug-mode assertions still catch misuse via `current_jit_vm`'s
/// is_null check IF a helper runs outside `enter_jit` (would happen
/// only if some bug calls a helper symbol from interp code, which
/// never happens by design).
/// Capture of the previous `(JIT_VM, JIT_CL)` slot contents at the
/// moment [`JitVmGuard`] takes ownership, plus a function pointer
/// that writes them back. The function pointer lets luna-core hold
/// the drop semantics without referencing Cranelift's TLS storage
/// (the cells themselves live in `luna_jit::jit_backend` because
/// that's where the `thread_local!` block is, but the cells hold
/// luna-core types — `*mut Vm` and `*const LuaClosure`).
///
/// Fields are `pub` rather than `pub(crate)` because luna-jit's
/// `enter_jit` needs to construct an instance, and luna-jit is a
/// separate crate. The whole type is `#[doc(hidden)]` so it stays
/// out of the embedder surface.