1mod corelib;
2mod budget;
3mod cycle;
4#[cfg(feature = "std")]
5pub mod stdlib;
6mod task;
7pub(super) use self::task::{TaskId, TaskInstance, TaskManager, TaskState};
8use self::budget::BudgetState;
9pub(super) use crate::ast::{FieldOwnership, StructDef};
10pub(super) use crate::bytecode::{
11 FieldStorage, Function, Instruction, NativeCallResult, Register, StructLayout, TaskHandle,
12 Value,
13};
14#[cfg(feature = "std")]
15pub(super) use crate::embed::native_types::ModuleStub;
16pub(super) use crate::error::StackFrame;
17pub(super) use crate::jit::{
18 JitCompiler, JitState, TraceOptimizer, TraceRecorder, MAX_TRACE_LENGTH,
19};
20pub(super) use crate::number::{
21 float_abs, float_acos, float_asin, float_atan, float_atan2, float_ceil, float_clamp,
22 float_cos, float_floor, float_from_int, float_round, float_sin, float_sqrt, float_tan,
23 int_from_float, int_from_usize, LustFloat,
24};
25pub(super) use crate::{LustError, Result};
26pub(super) use alloc::{
27 format,
28 rc::Rc,
29 string::{String, ToString},
30 vec,
31 vec::Vec,
32};
33use core::cell::RefCell;
34use hashbrown::{DefaultHashBuilder, HashMap};
35mod api;
36mod execution;
37mod tasks;
38mod tracing;
39pub use self::api::{NativeExport, NativeExportParam};
40#[cfg(feature = "std")]
41thread_local! {
42 static CURRENT_VM_STACK: RefCell<Vec<*mut VM>> = RefCell::new(Vec::new());
43}
44
45#[cfg(not(feature = "std"))]
46struct VmStack {
47 inner: core::cell::UnsafeCell<Option<Vec<*mut VM>>>,
48}
49
50#[cfg(not(feature = "std"))]
51impl VmStack {
52 const fn new() -> Self {
53 Self {
54 inner: core::cell::UnsafeCell::new(None),
55 }
56 }
57
58 fn with_mut<F, R>(&self, f: F) -> R
59 where
60 F: FnOnce(&mut Vec<*mut VM>) -> R,
61 {
62 let vec = self.ensure_vec();
63 f(vec)
64 }
65
66 fn with_ref<F, R>(&self, f: F) -> R
67 where
68 F: FnOnce(&Vec<*mut VM>) -> R,
69 {
70 let vec = self.ensure_vec();
71 f(vec)
72 }
73
74 fn ensure_vec(&self) -> &mut Vec<*mut VM> {
75 unsafe {
76 let slot = &mut *self.inner.get();
77 if slot.is_none() {
78 *slot = Some(Vec::new());
79 }
80 slot.as_mut().unwrap()
81 }
82 }
83}
84
85#[cfg(not(feature = "std"))]
86unsafe impl Sync for VmStack {}
87
88#[cfg(not(feature = "std"))]
89static VM_STACK: VmStack = VmStack::new();
90
91#[cfg(feature = "std")]
92fn with_vm_stack_ref<F, R>(f: F) -> R
93where
94 F: FnOnce(&Vec<*mut VM>) -> R,
95{
96 CURRENT_VM_STACK.with(|stack| {
97 let stack = stack.borrow();
98 f(&stack)
99 })
100}
101
102#[cfg(feature = "std")]
103fn with_vm_stack_mut<F, R>(f: F) -> R
104where
105 F: FnOnce(&mut Vec<*mut VM>) -> R,
106{
107 CURRENT_VM_STACK.with(|stack| {
108 let mut stack = stack.borrow_mut();
109 f(&mut stack)
110 })
111}
112
113#[cfg(not(feature = "std"))]
114fn with_vm_stack_ref<F, R>(f: F) -> R
115where
116 F: FnOnce(&Vec<*mut VM>) -> R,
117{
118 VM_STACK.with_ref(f)
119}
120
121#[cfg(not(feature = "std"))]
122fn with_vm_stack_mut<F, R>(f: F) -> R
123where
124 F: FnOnce(&mut Vec<*mut VM>) -> R,
125{
126 VM_STACK.with_mut(f)
127}
128
129pub(crate) fn push_vm_ptr(vm: *mut VM) {
130 with_vm_stack_mut(|stack| stack.push(vm));
131}
132
133pub(crate) fn pop_vm_ptr() {
134 with_vm_stack_mut(|stack| {
135 stack.pop();
136 });
137}
138
139#[cfg(feature = "std")]
140pub(super) fn with_vm_stack<F, R>(f: F) -> R
141where
142 F: FnOnce(&Vec<*mut VM>) -> R,
143{
144 with_vm_stack_ref(f)
145}
146
147#[cfg(not(feature = "std"))]
148pub(super) fn with_vm_stack<F, R>(f: F) -> R
149where
150 F: FnOnce(&Vec<*mut VM>) -> R,
151{
152 with_vm_stack_ref(f)
153}
154
155pub(super) const TO_STRING_TRAIT: &str = "ToString";
156pub(super) const TO_STRING_METHOD: &str = "to_string";
157pub(super) const HASH_KEY_TRAIT: &str = "HashKey";
158pub(super) const HASH_KEY_METHOD: &str = "to_hashkey";
159pub struct VM {
160 pub(super) jit: JitState,
161 pub(super) budgets: BudgetState,
162 pub(super) functions: Vec<Function>,
163 pub(super) natives: HashMap<String, Value>,
164 pub(super) globals: HashMap<String, Value>,
165 pub(super) map_hasher: DefaultHashBuilder,
166 pub(super) call_stack: Vec<CallFrame>,
167 pub(super) max_stack_depth: usize,
168 pub(super) pending_return_value: Option<Value>,
169 pub(super) pending_return_dest: Option<Register>,
170 pub(super) trace_recorder: Option<TraceRecorder>,
171 pub(super) side_trace_context: Option<(crate::jit::TraceId, usize)>,
172 pub(super) skip_next_trace_record: bool,
173 pub(super) trait_impls: HashMap<(String, String), bool>,
174 pub(super) struct_tostring_cache: HashMap<usize, Rc<String>>,
175 pub(super) struct_metadata: HashMap<String, RuntimeStructInfo>,
176 pub(super) call_until_depth: Option<usize>,
177 pub(super) task_manager: TaskManager,
178 pub(super) current_task: Option<TaskId>,
179 pub(super) pending_task_signal: Option<TaskSignal>,
180 pub(super) last_task_signal: Option<TaskSignal>,
181 pub(super) cycle_collector: cycle::CycleCollector,
182 pub(super) exported_natives: Vec<NativeExport>,
183 pub(super) export_prefix_stack: Vec<String>,
184 #[cfg(feature = "std")]
185 pub(super) exported_type_stubs: Vec<ModuleStub>,
186}
187
188#[derive(Debug, Clone)]
189pub(super) struct CallFrame {
190 pub(super) function_idx: usize,
191 pub(super) ip: usize,
192 #[cfg(feature = "std")]
196 pub(super) registers: [Value; 256],
197 #[cfg(not(feature = "std"))]
198 pub(super) registers: Vec<Value>,
199 #[allow(dead_code)]
200 pub(super) base_register: usize,
201 pub(super) return_dest: Option<Register>,
202 pub(super) upvalues: Vec<Value>,
203}
204
205impl CallFrame {
206 #[allow(unused_variables)]
207 pub(super) fn new(function_idx: usize, return_dest: Option<Register>, register_count: u8) -> Self {
208 Self {
209 function_idx,
210 ip: 0,
211 #[cfg(feature = "std")]
212 registers: core::array::from_fn(|_| Value::Nil),
213 #[cfg(not(feature = "std"))]
214 registers: alloc::vec![Value::Nil; register_count as usize],
215 base_register: 0,
216 return_dest,
217 upvalues: Vec::new(),
218 }
219 }
220}
221
222#[derive(Debug, Clone)]
223pub(super) struct RuntimeStructInfo {
224 pub layout: Rc<StructLayout>,
225}
226
227#[derive(Debug, Clone)]
228pub(super) enum TaskSignal {
229 Yield { dest: Register, value: Value },
230 Stop { value: Value },
231}
232
233impl Default for VM {
234 fn default() -> Self {
235 Self::new()
236 }
237}