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