runmat_core/session/
snapshot.rs1use super::*;
2
3impl RunMatSession {
4 pub fn new() -> Result<Self> {
6 Self::with_options(true, false) }
8
9 pub fn with_options(enable_jit: bool, verbose: bool) -> Result<Self> {
11 Self::from_snapshot(enable_jit, verbose, None)
12 }
13
14 #[cfg(not(target_arch = "wasm32"))]
16 pub fn with_snapshot<P: AsRef<Path>>(
17 enable_jit: bool,
18 verbose: bool,
19 snapshot_path: Option<P>,
20 ) -> Result<Self> {
21 let snapshot = snapshot_path.and_then(|path| match Self::load_snapshot(path.as_ref()) {
22 Ok(snapshot) => {
23 info!(
24 "Snapshot loaded successfully from {}",
25 path.as_ref().display()
26 );
27 Some(Arc::new(snapshot))
28 }
29 Err(e) => {
30 warn!(
31 "Failed to load snapshot from {}: {}, continuing without snapshot",
32 path.as_ref().display(),
33 e
34 );
35 None
36 }
37 });
38 Self::from_snapshot(enable_jit, verbose, snapshot)
39 }
40
41 pub fn with_snapshot_bytes(
43 enable_jit: bool,
44 verbose: bool,
45 snapshot_bytes: Option<&[u8]>,
46 ) -> Result<Self> {
47 let snapshot =
48 snapshot_bytes.and_then(|bytes| match Self::load_snapshot_from_bytes(bytes) {
49 Ok(snapshot) => {
50 info!("Snapshot loaded successfully from in-memory bytes");
51 Some(Arc::new(snapshot))
52 }
53 Err(e) => {
54 warn!("Failed to load snapshot from bytes: {e}, continuing without snapshot");
55 None
56 }
57 });
58 Self::from_snapshot(enable_jit, verbose, snapshot)
59 }
60
61 fn from_snapshot(
62 enable_jit: bool,
63 verbose: bool,
64 snapshot: Option<Arc<Snapshot>>,
65 ) -> Result<Self> {
66 #[cfg(target_arch = "wasm32")]
67 let snapshot = {
68 match snapshot {
69 some @ Some(_) => some,
70 None => Self::build_wasm_snapshot(),
71 }
72 };
73
74 #[cfg(feature = "jit")]
75 let jit_engine = if enable_jit {
76 match TurbineEngine::new() {
77 Ok(engine) => {
78 info!("JIT compiler initialized successfully");
79 Some(engine)
80 }
81 Err(e) => {
82 warn!("JIT compiler initialization failed: {e}, falling back to interpreter");
83 None
84 }
85 }
86 } else {
87 info!("JIT compiler disabled, using interpreter only");
88 None
89 };
90
91 #[cfg(not(feature = "jit"))]
92 if enable_jit {
93 info!("JIT support was requested but the 'jit' feature is disabled; running interpreter-only.");
94 }
95
96 let session = Self {
97 #[cfg(feature = "jit")]
98 jit_engine,
99 verbose,
100 stats: ExecutionStats::default(),
101 variables: HashMap::new(),
102 variable_array: Vec::new(),
103 variable_names: HashMap::new(),
104 workspace_values: HashMap::new(),
105 function_definitions: HashMap::new(),
106 source_pool: SourcePool::default(),
107 function_source_ids: HashMap::new(),
108 snapshot,
109 interrupt_flag: Arc::new(AtomicBool::new(false)),
110 is_executing: false,
111 async_input_handler: None,
112 callstack_limit: runmat_vm::DEFAULT_CALLSTACK_LIMIT,
113 error_namespace: runmat_vm::DEFAULT_ERROR_NAMESPACE.to_string(),
114 default_source_name: "<repl>".to_string(),
115 source_name_override: None,
116 telemetry_consent: true,
117 telemetry_client_id: None,
118 telemetry_platform: TelemetryPlatformInfo::default(),
119 telemetry_sink: None,
120 workspace_preview_tokens: HashMap::new(),
121 workspace_version: 0,
122 emit_fusion_plan: false,
123 compat_mode: CompatMode::Matlab,
124 };
125
126 runmat_vm::set_call_stack_limit(session.callstack_limit);
127
128 #[cfg(any(target_arch = "wasm32", not(target_arch = "wasm32")))]
132 {
133 if let Err(err) =
134 runmat_runtime::builtins::plotting::context::ensure_context_from_provider()
135 {
136 debug!("Plotting context unavailable during session init: {err}");
137 }
138 }
139
140 Ok(session)
141 }
142
143 pub(crate) fn current_source_name(&self) -> &str {
144 self.source_name_override
145 .as_deref()
146 .unwrap_or(&self.default_source_name)
147 }
148
149 #[cfg(target_arch = "wasm32")]
150 fn build_wasm_snapshot() -> Option<Arc<Snapshot>> {
151 use log::{info, warn};
152
153 info!("No snapshot provided; building stdlib snapshot inside wasm runtime");
154 let config = SnapshotConfig {
155 compression_enabled: false,
156 validation_enabled: false,
157 memory_mapping_enabled: false,
158 parallel_loading: false,
159 progress_reporting: false,
160 ..Default::default()
161 };
162
163 match SnapshotBuilder::new(config).build() {
164 Ok(snapshot) => {
165 info!("WASM snapshot build completed successfully");
166 Some(Arc::new(snapshot))
167 }
168 Err(err) => {
169 warn!("Failed to build stdlib snapshot in wasm runtime: {err}");
170 None
171 }
172 }
173 }
174
175 #[cfg(not(target_arch = "wasm32"))]
177 fn load_snapshot(path: &Path) -> Result<Snapshot> {
178 let mut loader = SnapshotLoader::new(SnapshotConfig::default());
179 let (snapshot, _stats) = loader
180 .load(path)
181 .map_err(|e| anyhow::anyhow!("Failed to load snapshot: {}", e))?;
182 Ok(snapshot)
183 }
184
185 fn load_snapshot_from_bytes(bytes: &[u8]) -> Result<Snapshot> {
187 let mut loader = SnapshotLoader::new(SnapshotConfig::default());
188 let (snapshot, _stats) = loader
189 .load_from_bytes(bytes)
190 .map_err(|e| anyhow::anyhow!("Failed to load snapshot: {}", e))?;
191 Ok(snapshot)
192 }
193
194 pub fn snapshot_info(&self) -> Option<String> {
196 self.snapshot.as_ref().map(|snapshot| {
197 format!(
198 "Snapshot loaded: {} builtins, {} HIR functions, {} bytecode entries",
199 snapshot.builtins.functions.len(),
200 snapshot.hir_cache.functions.len(),
201 snapshot.bytecode_cache.stdlib_bytecode.len()
202 )
203 })
204 }
205
206 pub fn has_snapshot(&self) -> bool {
208 self.snapshot.is_some()
209 }
210}