lust/vm/
mod.rs

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