shape_vm/executor/vm_impl/
init.rs1use super::super::*;
2use shape_value::NativeKind;
3
4impl VirtualMachine {
5 pub fn new(config: VMConfig) -> Self {
6 let debugger = if config.debug_mode {
7 Some(VMDebugger::new())
8 } else {
9 None
10 };
11
12 let gc = GarbageCollector::new(config.gc_config.clone());
13
14 let (registry, builtin_schemas) =
17 shape_runtime::type_schema::TypeSchemaRegistry::with_stdlib_types_and_builtin_ids();
18
19 let mut program = BytecodeProgram::new();
20 program.type_schema_registry = registry;
21
22 let mut vm = Self {
23 config,
24 program,
25 ip: 0,
26 stack: vec![0u64; crate::constants::DEFAULT_STACK_CAPACITY],
31 kinds: vec![NativeKind::Bool; crate::constants::DEFAULT_STACK_CAPACITY],
32 sp: 0,
33 module_bindings: Vec::new(),
38 module_binding_kinds: Vec::new(),
39 shared_module_bindings: std::collections::HashSet::new(),
40 call_stack: Vec::with_capacity(crate::constants::DEFAULT_CALL_STACK_CAPACITY),
41 loop_stack: Vec::new(),
42 timeframe_stack: Vec::new(),
43 debugger,
44 gc,
45 instruction_count: 0,
46 exception_handlers: Vec::new(),
47 builtin_schemas,
48 last_error_line: None,
49 last_error_file: None,
50 last_uncaught_exception: None,
51 module_init_done: false,
52 output_buffer: None,
53 module_registry: shape_runtime::module_exports::ModuleExportRegistry::new(),
54 module_fn_table: Vec::new(),
55 function_name_index: HashMap::new(),
56 extension_methods: HashMap::new(),
57 merged_schema_cache: HashMap::new(),
58 interrupt: Arc::new(AtomicU8::new(0)),
59 future_id_counter: 0,
60 async_scope_stack: Vec::new(),
61 task_scheduler: task_scheduler::TaskScheduler::new(),
62 foreign_fn_handles: Vec::new(),
63 function_hashes: Vec::new(),
64 function_hash_raw: Vec::new(),
65 function_id_by_hash: HashMap::new(),
66 function_entry_points: Vec::new(),
67 program_entry_ip: 0,
68 resource_usage: None,
69 time_travel: None,
70 #[cfg(feature = "gc")]
71 gc_heap: None,
72 #[cfg(feature = "jit")]
73 jit_compiled: false,
74 #[cfg(feature = "jit")]
75 jit_dispatch_table: std::collections::HashMap::new(),
76 tier_manager: None,
77 pending_resume: None,
78 pending_frame_resume: None,
79 metrics: None,
80 feedback_vectors: Vec::new(),
81 megamorphic_cache: crate::megamorphic_cache::MegamorphicCache::new(),
82 shape_table: shape_value::ShapeTableHandle::new(),
83 };
84
85 vm.register_stdlib_module(state_builtins::create_state_module());
89 vm.register_stdlib_module(create_transport_module_exports());
90 vm.register_stdlib_module(create_remote_module_exports());
91 for module in shape_runtime::stdlib::all_stdlib_modules() {
93 vm.register_stdlib_module(module);
94 }
95
96 if vm.config.metrics_enabled {
98 vm.metrics = Some(crate::metrics::VmMetrics::new());
99 }
100
101 #[cfg(feature = "gc")]
103 if vm.config.use_tracing_gc {
104 vm.init_gc_heap();
105 }
106
107 vm
108 }
109
110 pub fn with_resource_limits(mut self, limits: crate::resource_limits::ResourceLimits) -> Self {
112 let mut usage = crate::resource_limits::ResourceUsage::new(limits);
113 usage.start();
114 self.resource_usage = Some(usage);
115 self
116 }
117
118 #[cfg(feature = "gc")]
124 pub fn init_gc_heap(&mut self) {
125 let heap = shape_gc::GcHeap::new();
126 self.gc_heap = Some(heap);
127 if let Some(ref mut heap) = self.gc_heap {
130 unsafe { shape_gc::set_thread_gc_heap(heap as *mut _) };
131 }
132 }
133
134 pub fn set_interrupt(&mut self, flag: Arc<AtomicU8>) {
136 self.interrupt = flag;
137 }
138
139 pub fn enable_time_travel(&mut self, mode: time_travel::CaptureMode, max_entries: usize) {
141 self.time_travel = Some(time_travel::TimeTravel::new(mode, max_entries));
142 }
143
144 pub fn disable_time_travel(&mut self) {
146 self.time_travel = None;
147 }
148
149 #[cfg(feature = "jit")]
164 pub fn set_jit_compiled(&mut self) {
165 self.jit_compiled = true;
166 }
167
168 #[cfg(feature = "jit")]
170 pub fn is_jit_compiled(&self) -> bool {
171 self.jit_compiled
172 }
173
174 #[cfg(feature = "jit")]
179 pub fn register_jit_function(&mut self, function_id: u16, ptr: JitFnPtr) {
180 self.jit_dispatch_table.insert(function_id, ptr);
181 self.jit_compiled = true;
182 }
183
184 #[cfg(feature = "jit")]
186 pub fn jit_dispatch_table(&self) -> &std::collections::HashMap<u16, JitFnPtr> {
187 &self.jit_dispatch_table
188 }
189
190 pub fn enable_tiered_compilation(
198 &mut self,
199 ) -> (
200 std::sync::mpsc::Receiver<crate::tier::CompilationRequest>,
201 std::sync::mpsc::Sender<crate::tier::CompilationResult>,
202 ) {
203 let function_count = self.program.functions.len();
204 let mut mgr = crate::tier::TierManager::new(function_count, true);
205
206 let (req_tx, req_rx) = std::sync::mpsc::channel();
207 let (res_tx, res_rx) = std::sync::mpsc::channel();
208 mgr.set_channels(req_tx, res_rx);
209
210 self.tier_manager = Some(mgr);
211 (req_rx, res_tx)
212 }
213
214 pub fn tier_manager(&self) -> Option<&crate::tier::TierManager> {
216 self.tier_manager.as_ref()
217 }
218
219 pub(crate) fn poll_tier_completions(&mut self) {
228 if let Some(ref mut tier_mgr) = self.tier_manager {
229 let completions = tier_mgr.poll_completions();
232
233 if let Some(ref mut metrics) = self.metrics {
235 for result in &completions {
236 if result.native_code.is_some() {
237 let from_tier = match result.compiled_tier {
238 crate::tier::Tier::BaselineJit => 0, crate::tier::Tier::OptimizingJit => 1, crate::tier::Tier::Interpreted => continue,
241 };
242 let to_tier = match result.compiled_tier {
243 crate::tier::Tier::BaselineJit => 1,
244 crate::tier::Tier::OptimizingJit => 2,
245 crate::tier::Tier::Interpreted => continue,
246 };
247 metrics.record_tier_event(crate::metrics::TierEvent {
248 function_id: result.function_id,
249 from_tier,
250 to_tier,
251 call_count: tier_mgr.get_call_count(result.function_id),
252 timestamp_us: metrics.elapsed_us(),
253 });
254 }
255 }
256 }
257 }
258 }
259
260 #[inline]
263 pub(crate) fn current_feedback_vector(
264 &mut self,
265 ) -> Option<&mut crate::feedback::FeedbackVector> {
266 let func_id = self.call_stack.last()?.function_id? as usize;
267 if func_id >= self.feedback_vectors.len() {
268 return None;
269 }
270 if self.feedback_vectors[func_id].is_none() {
271 if self.tier_manager.is_none() {
272 return None;
273 }
274 self.feedback_vectors[func_id] =
275 Some(crate::feedback::FeedbackVector::new(func_id as u16));
276 }
277 self.feedback_vectors[func_id].as_mut()
278 }
279
280 pub fn feedback_vectors(&self) -> &[Option<crate::feedback::FeedbackVector>] {
282 &self.feedback_vectors
283 }
284
285 pub fn program(&self) -> &BytecodeProgram {
287 &self.program
288 }
289
290 pub fn time_travel(&self) -> Option<&time_travel::TimeTravel> {
292 self.time_travel.as_ref()
293 }
294
295 pub fn time_travel_mut(&mut self) -> Option<&mut time_travel::TimeTravel> {
297 self.time_travel.as_mut()
298 }
299
300 pub fn module_registry(&self) -> &shape_runtime::module_exports::ModuleExportRegistry {
302 &self.module_registry
303 }
304
305 pub(crate) fn next_future_id(&mut self) -> u64 {
307 self.future_id_counter += 1;
308 self.future_id_counter
309 }
310
311 pub fn get_function_id(&self, name: &str) -> Option<u16> {
313 self.program
314 .functions
315 .iter()
316 .position(|f| f.name == name)
317 .map(|id| id as u16)
318 }
319}