logicaffeine_compile/vm/
tier_trace.rs1use std::sync::atomic::{AtomicU8, Ordering};
11
12static ENABLED: AtomicU8 = AtomicU8::new(0);
15
16pub fn trace_enabled() -> bool {
18 match ENABLED.load(Ordering::Relaxed) {
19 1 => true,
20 2 => false,
21 _ => {
22 let on = std::env::var("LOGOS_TIER_TRACE")
23 .map(|v| !v.is_empty() && v != "0")
24 .unwrap_or(false);
25 ENABLED.store(if on { 1 } else { 2 }, Ordering::Relaxed);
26 on
27 }
28 }
29}
30
31#[derive(Clone, Copy, Debug, PartialEq, Eq)]
33pub enum ExecTier {
34 Bytecode,
36 Warm,
38 NativeForge,
40 NativeAot,
42}
43
44impl ExecTier {
45 pub fn label(self) -> &'static str {
46 match self {
47 ExecTier::Bytecode => "bytecode",
48 ExecTier::Warm => "warm",
49 ExecTier::NativeForge => "native(forge)",
50 ExecTier::NativeAot => "native(aot)",
51 }
52 }
53}
54
55pub fn format_transition(fi: usize, name: &str, to: ExecTier) -> String {
57 if name.is_empty() {
58 format!("[tier] fn#{fi} -> {}", to.label())
59 } else {
60 format!("[tier] fn#{fi} '{name}' -> {}", to.label())
61 }
62}
63
64pub fn trace_transition(fi: usize, name: &str, to: ExecTier) {
66 if trace_enabled() {
67 eprintln!("{}", format_transition(fi, name, to));
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn transition_lines_format_with_and_without_a_name() {
77 assert_eq!(
78 format_transition(3, "fib", ExecTier::Warm),
79 "[tier] fn#3 'fib' -> warm"
80 );
81 assert_eq!(
82 format_transition(7, "quicksort", ExecTier::NativeForge),
83 "[tier] fn#7 'quicksort' -> native(forge)"
84 );
85 assert_eq!(
86 format_transition(0, "", ExecTier::NativeAot),
87 "[tier] fn#0 -> native(aot)"
88 );
89 assert_eq!(
90 format_transition(1, "main", ExecTier::Bytecode),
91 "[tier] fn#1 'main' -> bytecode"
92 );
93 }
94}