Skip to main content

lust/vm/
mod.rs

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}