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 format_mode: runmat_builtins::FormatMode::default(),
125 };
126
127 runmat_vm::set_call_stack_limit(session.callstack_limit);
128
129 #[cfg(any(target_arch = "wasm32", not(target_arch = "wasm32")))]
133 {
134 if let Err(err) =
135 runmat_runtime::builtins::plotting::context::ensure_context_from_provider()
136 {
137 debug!("Plotting context unavailable during session init: {err}");
138 }
139 }
140
141 Ok(session)
142 }
143
144 pub(crate) fn current_source_name(&self) -> &str {
145 self.source_name_override
146 .as_deref()
147 .unwrap_or(&self.default_source_name)
148 }
149
150 #[cfg(target_arch = "wasm32")]
151 fn build_wasm_snapshot() -> Option<Arc<Snapshot>> {
152 use log::{info, warn};
153
154 info!("No snapshot provided; building stdlib snapshot inside wasm runtime");
155 let config = SnapshotConfig {
156 compression_enabled: false,
157 validation_enabled: false,
158 memory_mapping_enabled: false,
159 parallel_loading: false,
160 progress_reporting: false,
161 ..Default::default()
162 };
163
164 match SnapshotBuilder::new(config).build() {
165 Ok(snapshot) => {
166 info!("WASM snapshot build completed successfully");
167 Some(Arc::new(snapshot))
168 }
169 Err(err) => {
170 warn!("Failed to build stdlib snapshot in wasm runtime: {err}");
171 None
172 }
173 }
174 }
175
176 #[cfg(not(target_arch = "wasm32"))]
178 fn load_snapshot(path: &Path) -> Result<Snapshot> {
179 let mut loader = SnapshotLoader::new(SnapshotConfig::default());
180 let (snapshot, _stats) = loader
181 .load(path)
182 .map_err(|e| anyhow::anyhow!("Failed to load snapshot: {}", e))?;
183 Ok(snapshot)
184 }
185
186 fn load_snapshot_from_bytes(bytes: &[u8]) -> Result<Snapshot> {
188 let mut loader = SnapshotLoader::new(SnapshotConfig::default());
189 let (snapshot, _stats) = loader
190 .load_from_bytes(bytes)
191 .map_err(|e| anyhow::anyhow!("Failed to load snapshot: {}", e))?;
192 Ok(snapshot)
193 }
194
195 pub fn snapshot_info(&self) -> Option<String> {
197 self.snapshot.as_ref().map(|snapshot| {
198 format!(
199 "Snapshot loaded: {} builtins, {} HIR functions, {} bytecode entries",
200 snapshot.builtins.functions.len(),
201 snapshot.hir_cache.functions.len(),
202 snapshot.bytecode_cache.stdlib_bytecode.len()
203 )
204 })
205 }
206
207 pub fn has_snapshot(&self) -> bool {
209 self.snapshot.is_some()
210 }
211}