cljrs_runtime/mode.rs
1//! Execution mode and tier state.
2//!
3//! [`ExecutionMode`] is chosen once, when a runtime is built, and never
4//! changes: it selects which function-call path a runtime uses. Before the
5//! merge each mode was expressed by storing a different `fn` pointer in
6//! `GlobalEnv`; the pointers existed only to let `cljrs-interp` reach
7//! `cljrs-eval` without a dependency cycle. Now that both live in this
8//! package the mode is data and the dispatch is a direct call.
9//!
10//! [`TierState`] is the *current* state of that mode, and it does change: a
11//! tiered runtime tree-walks its own bootstrap (nothing can be lowered before
12//! `clojure.core` exists) and is promoted to [`TierState::Ir`] or
13//! [`TierState::Jit`] once the bootstrap finishes. It replaces the old
14//! `GlobalEnv::compiler_ready` flag, which said only "not tree-walk" and could
15//! not distinguish the IR interpreter from native JIT dispatch.
16
17/// How a runtime executes Clojure function calls.
18///
19/// Selected with [`crate::RuntimeBuilder::execution_mode`] and fixed for the
20/// life of the runtime.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
22pub enum ExecutionMode {
23 /// Tree-walking interpreter only. No IR is lowered, cached, or executed.
24 ///
25 /// The cheapest mode to construct and the one to use for short-lived
26 /// environments (tests, one-shot evaluation, the AOT test harness) where
27 /// populating the IR cache would be pure overhead.
28 TreeWalk,
29
30 /// Tree walk, tier-1 IR interpreter, and native JIT promotion.
31 ///
32 /// The default, and what the `cljrs` CLI uses. Native dispatch is only
33 /// reached once a JIT backend has installed its hooks (`cljrs_jit::init`);
34 /// without one this behaves like [`ExecutionMode::TieredNoJit`].
35 #[default]
36 Tiered,
37
38 /// Tree walk and tier-1 IR interpreter, with native JIT promotion
39 /// suppressed even when a JIT backend is linked in.
40 TieredNoJit,
41
42 /// Tree walk inside a no-GC transaction arena, with a call-depth cap.
43 ///
44 /// Used by `cljrs-tx`, where interpreted recursion runs on the host's
45 /// Rust stack and must be bounded. Install the cap for the dynamic
46 /// extent of one transaction with [`crate::env::depth::DepthGuard`].
47 NoGcTransaction,
48}
49
50impl ExecutionMode {
51 /// The tier this mode is promoted to once bootstrap finishes.
52 pub fn target_tier(self) -> TierState {
53 match self {
54 ExecutionMode::TreeWalk | ExecutionMode::NoGcTransaction => TierState::TreeWalk,
55 ExecutionMode::Tiered => TierState::Jit,
56 ExecutionMode::TieredNoJit => TierState::Ir,
57 }
58 }
59
60 /// True when function calls go through the IR-aware dispatch path
61 /// (`crate::tiered::apply::call_cljrs_fn`) rather than straight to the
62 /// tree walker.
63 pub fn is_tiered(self) -> bool {
64 matches!(self, ExecutionMode::Tiered | ExecutionMode::TieredNoJit)
65 }
66}
67
68/// Which execution tiers are live right now.
69///
70/// Monotonic within a runtime's life: it starts at [`TierState::TreeWalk`]
71/// while `clojure.core` bootstraps and is raised once to
72/// [`ExecutionMode::target_tier`] when the runtime is ready.
73#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
74#[repr(u8)]
75pub enum TierState {
76 /// Only the tree walker runs. No lowering is attempted.
77 TreeWalk = 0,
78 /// Tree walk plus IR lowering and the tier-1 IR interpreter.
79 Ir = 1,
80 /// Tree walk, IR, and native code published by a JIT backend.
81 Jit = 2,
82}
83
84impl TierState {
85 /// Decode from the `AtomicU8` representation held by `GlobalEnv`.
86 /// Unknown values decode as [`TierState::TreeWalk`].
87 pub(crate) fn from_u8(raw: u8) -> Self {
88 match raw {
89 1 => TierState::Ir,
90 2 => TierState::Jit,
91 _ => TierState::TreeWalk,
92 }
93 }
94
95 /// True when IR may be lowered, cached, and interpreted.
96 pub fn ir_enabled(self) -> bool {
97 self >= TierState::Ir
98 }
99
100 /// True when dispatch may jump to native code published by a JIT backend.
101 pub fn jit_enabled(self) -> bool {
102 self == TierState::Jit
103 }
104}