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!(
94 "JIT support was requested but the 'jit' feature is disabled; running interpreter-only."
95 );
96 }
97
98 let session = Self {
99 #[cfg(feature = "jit")]
100 jit_engine,
101 verbose,
102 stats: ExecutionStats::default(),
103 variable_array: Vec::new(),
104 workspace_bindings: HashMap::new(),
105 workspace_values: HashMap::new(),
106 abi_workspace_handle: crate::abi::WorkspaceHandle(Uuid::new_v4()),
107 active_source_identity: None,
108 function_registry: runmat_vm::FunctionRegistry::default(),
109 next_semantic_function_id: 0,
110 source_pool: SourcePool::default(),
111 snapshot,
112 interrupt_flag: Arc::new(AtomicBool::new(false)),
113 is_executing: false,
114 async_input_handler: None,
115 callstack_limit: runmat_vm::DEFAULT_CALLSTACK_LIMIT,
116 error_namespace: runmat_vm::DEFAULT_ERROR_NAMESPACE.to_string(),
117 active_source_name: "<repl>".to_string(),
118 telemetry_consent: true,
119 telemetry_client_id: None,
120 telemetry_platform: TelemetryPlatformInfo::default(),
121 telemetry_sink: None,
122 workspace_preview_tokens: HashMap::new(),
123 workspace_version: 0,
124 emit_fusion_plan: false,
125 compat_mode: CompatMode::Matlab,
126 top_level_await_enabled: true,
127 dynamic_eval_enabled: true,
128 format_mode: runmat_builtins::FormatMode::default(),
129 pending_companion_source_discovery: None,
130 };
131
132 runmat_vm::set_call_stack_limit(session.callstack_limit);
133
134 #[cfg(any(target_arch = "wasm32", not(target_arch = "wasm32")))]
138 {
139 if let Err(err) =
140 runmat_runtime::builtins::plotting::context::ensure_context_from_provider()
141 {
142 debug!("Plotting context unavailable during session init: {err}");
143 }
144 }
145
146 Ok(session)
147 }
148
149 pub(crate) fn current_source_name(&self) -> &str {
150 &self.active_source_name
151 }
152
153 #[cfg(target_arch = "wasm32")]
154 fn build_wasm_snapshot() -> Option<Arc<Snapshot>> {
155 use log::{info, warn};
156
157 info!("No snapshot provided; building stdlib snapshot inside wasm runtime");
158 let config = SnapshotConfig {
159 compression_enabled: false,
160 validation_enabled: false,
161 memory_mapping_enabled: false,
162 parallel_loading: false,
163 progress_reporting: false,
164 ..Default::default()
165 };
166
167 match SnapshotBuilder::new(config).build() {
168 Ok(snapshot) => {
169 info!("WASM snapshot build completed successfully");
170 Some(Arc::new(snapshot))
171 }
172 Err(err) => {
173 warn!("Failed to build stdlib snapshot in wasm runtime: {err}");
174 None
175 }
176 }
177 }
178
179 #[cfg(not(target_arch = "wasm32"))]
181 fn load_snapshot(path: &Path) -> Result<Snapshot> {
182 let mut loader = SnapshotLoader::new(SnapshotConfig::default());
183 let (snapshot, _stats) = loader
184 .load(path)
185 .map_err(|e| anyhow::anyhow!("Failed to load snapshot: {}", e))?;
186 Ok(snapshot)
187 }
188
189 fn load_snapshot_from_bytes(bytes: &[u8]) -> Result<Snapshot> {
191 let mut loader = SnapshotLoader::new(SnapshotConfig::default());
192 let (snapshot, _stats) = loader
193 .load_from_bytes(bytes)
194 .map_err(|e| anyhow::anyhow!("Failed to load snapshot: {}", e))?;
195 Ok(snapshot)
196 }
197
198 pub fn snapshot_info(&self) -> Option<String> {
200 self.snapshot.as_ref().map(|snapshot| {
201 format!(
202 "Snapshot loaded: {} builtins, {} HIR functions, {} bytecode entries",
203 snapshot.builtins.functions.len(),
204 snapshot.hir_cache.functions.len(),
205 snapshot.bytecode_cache.stdlib_bytecode.len()
206 )
207 })
208 }
209
210 pub fn has_snapshot(&self) -> bool {
212 self.snapshot.is_some()
213 }
214}