1use core::cell::Cell;
2use core::ops::Deref;
3use crate::runtime::{Variant, HashMap};
4use crate::runtime::gc::{Gc, GcWeak, GcTrace, gc_collect};
5use crate::runtime::function::{Call, Function, Upvalue, UpvalueIndex, Closure};
6use crate::runtime::module::Module;
7use crate::runtime::errors::ExecResult;
8use crate::debug::traceback::TraceSite;
9use crate::debug::snapshot::{VMSnapshot, VMFrameSnapshot};
10
11mod callframe;
12mod instruction;
13
14use callframe::VMCallFrame;
15
16
17struct CallInfo {
21 stack_frame: usize,
22 local_frame: usize,
23 call: Call,
24 site: TraceSite,
25}
26
27enum Control {
28 Next, Call(CallInfo), Return(Variant), Exit(Variant), }
33
34
35#[derive(Debug, Clone, Copy)]
36struct UpvalueRef {
37 fun: Gc<Function>,
38 index: UpvalueIndex,
39}
40
41impl UpvalueRef {
42 fn mark_trace(&self) {
43 self.fun.mark_trace()
44 }
45
46 fn weakref(&self) -> UpvalueWeakRef {
47 UpvalueWeakRef {
48 fun: self.fun.weakref(),
49 index: self.index,
50 }
51 }
52}
53
54impl Deref for UpvalueRef {
55 type Target = Upvalue;
56
57 #[inline(always)]
58 fn deref(&self) -> &Self::Target {
59 &self.fun.upvalues()[usize::from(self.index)]
60 }
61}
62
63impl Gc<Function> {
64 #[inline(always)]
65 fn upvalue(self, index: UpvalueIndex) -> UpvalueRef {
66 UpvalueRef {
67 fun: self,
68 index
69 }
70 }
71}
72
73
74#[derive(Debug, Clone, Copy)]
75struct UpvalueWeakRef {
76 fun: GcWeak<Function>,
77 index: UpvalueIndex,
78}
79
80impl UpvalueWeakRef {
81 #[inline(always)]
82 fn try_deref(&self) -> Option<&Upvalue> {
83 self.fun.try_deref()
84 .map(|fun| &fun.upvalues()[usize::from(self.index)])
85 }
86
87 fn is_valid(&self) -> bool {
88 self.fun.is_valid()
89 }
90
91 fn mark_trace(&self) {
92 self.fun.mark_trace()
93 }
94}
95
96
97
98
99#[derive(Debug)]
104pub struct VirtualMachine<'c> {
105 traceback: Vec<TraceSite>,
106
107 frame: VMCallFrame<'c>, calls: Vec<VMCallFrame<'c>>,
109 locals: ValueStack,
110 stack: ValueStack,
111 upvalues: OpenUpvalues,
112}
113
114impl<'c> VirtualMachine<'c> {
115 pub fn new(main_module: Gc<Module>, main_chunk: &'c [u8]) -> Self {
117 Self {
118 traceback: Vec::new(),
119 calls: Vec::new(),
120 locals: ValueStack::new(),
121 stack: ValueStack::new(),
122 frame: VMCallFrame::main_chunk(main_module, main_chunk),
123 upvalues: OpenUpvalues::new(),
124 }
125 }
126
127 pub fn frame(&self) -> &VMCallFrame<'_> { &self.frame }
128
129 pub fn run(mut self) -> ExecResult<Variant> {
131 loop {
132 if let Control::Exit(value) = self.exec_next()? {
133 return Ok(value)
134 }
135 }
136 }
137
138 pub fn run_steps(self) -> impl Iterator<Item=ExecResult<VMSnapshot>> + 'c {
139 VMStepper::from(self)
140 }
141
142 #[inline]
143 fn exec_next(&mut self) -> ExecResult<Control> {
144 let control = self.frame.exec_next(&mut self.stack, &mut self.locals, &mut self.upvalues)
145 .map_err(|error| error.extend_trace(self.traceback.iter().rev().cloned()))?;
146
147 match &control {
148 Control::Exit(..) => return Ok(control),
149
150 Control::Return(value) if self.calls.is_empty() =>
151 return Ok(Control::Exit(*value)),
152
153 Control::Return(value) => self.return_call(*value),
154 Control::Call(info) => self.setup_call(info)?,
155
156 Control::Next => { }
157 }
158
159 self.upvalues.prune_invalid();
160 gc_collect(self);
161
162 Ok(control)
163 }
164
165 fn setup_call(&mut self, callinfo: &CallInfo) -> ExecResult<()> {
166 self.traceback.push(callinfo.site.clone());
167
168 match callinfo.call {
169 Call::Native { func, nargs } => {
170 let args = self.stack.peek_many(nargs)
171 .iter().copied().collect::<Vec<Variant>>();
172
173 let retval = func.exec_fun(self, &args)?;
174 self.stack.truncate(callinfo.stack_frame);
175 self.locals.truncate(callinfo.local_frame);
176 self.stack.push(retval);
177 self.traceback.pop();
178 },
179
180 Call::Chunk { module, chunk_id } => {
181 let mut frame = VMCallFrame::call_frame(
182 module, chunk_id, callinfo.stack_frame, callinfo.local_frame
183 );
184 core::mem::swap(&mut self.frame, &mut frame);
185 self.calls.push(frame);
186
187 log::debug!(
188 "Setup call: {{ stack: {}, locals: {} }}",
189 self.frame.stack_frame(), self.frame.local_frame()
190 );
191 },
192 }
193
194 Ok(())
195 }
196
197 fn return_call(&mut self, retval: Variant) {
198 let stack_idx = self.frame.stack_frame();
199 let local_idx = self.frame.local_frame();
200
201 let mut frame = self.calls.pop().expect("empty call stack");
202 core::mem::swap(&mut self.frame, &mut frame);
203
204 self.stack.truncate(stack_idx);
205 self.locals.truncate(local_idx);
206 self.stack.push(retval);
207 self.traceback.pop();
208
209 log::debug!(
210 "Return call: {{ stack: {}, locals: {} }}",
211 self.frame.stack_frame(), self.frame.local_frame()
212 );
213 }
214}
215
216unsafe impl GcTrace for VirtualMachine<'_> {
218 fn trace(&self) {
219 self.stack.trace();
221 self.locals.trace();
222
223 self.frame.trace();
225 for frame in self.calls.iter() {
226 frame.trace();
227 }
228
229 for site in self.traceback.iter() {
231 site.trace();
232 }
233
234 for upval_ref in self.upvalues.iter_refs() {
236 upval_ref.mark_trace();
237 }
238 }
239}
240
241
242#[derive(Debug)]
244struct ValueStack {
245 stack: Vec<Variant>,
246}
247
248impl ValueStack {
249 fn new() -> Self {
250 Self { stack: Vec::new() }
251 }
252
253 fn take(self) -> Vec<Variant> {
254 self.stack
255 }
256
257 #[inline(always)]
258 fn trace(&self) {
259 self.stack.iter().for_each(Variant::trace)
260 }
261
262 #[inline(always)]
263 fn len(&self) -> usize {
264 self.stack.len()
265 }
266
267 #[inline(always)]
268 fn is_empty(&self) -> bool {
269 self.stack.len() == 0
270 }
271
272 #[inline(always)]
273 fn clear(&mut self) {
274 self.stack.clear()
275 }
276
277 #[inline(always)]
278 fn pop(&mut self) -> Variant {
279 self.stack.pop().expect("empty stack")
280 }
281
282 #[inline(always)]
283 fn pop_many(&mut self, count: usize) -> Vec<Variant> {
284 self.stack.split_off(self.stack.len() - count)
285 }
286
287 #[inline(always)]
288 fn truncate(&mut self, index: usize) {
289 self.stack.truncate(index)
290 }
291
292 #[inline(always)]
293 fn discard(&mut self, count: usize) {
294 self.stack.truncate(self.stack.len() - count)
295 }
296
297 #[inline(always)]
298 fn discard_at(&mut self, index: usize, count: usize) {
299 let discard_range = index..(index + count);
300 self.stack.splice(discard_range, core::iter::empty());
301 }
302
303 #[inline(always)]
304 fn push(&mut self, value: Variant) {
305 self.stack.push(value)
306 }
307
308 #[inline(always)]
309 fn insert(&mut self, index: usize, value: Variant) {
310 self.stack.insert(index, value);
311 }
312
313 #[inline(always)]
314 fn extend(&mut self, values: &[Variant]) {
315 self.stack.extend(values)
316 }
317
318 #[inline(always)]
319 fn replace(&mut self, value: Variant) {
320 *self.stack.last_mut().expect("empty stack") = value;
321 }
322
323 #[inline(always)]
324 fn replace_many(&mut self, count: usize, value: Variant) {
325 let replace_range = (self.stack.len()-count).. ;
326 self.stack.splice(replace_range, core::iter::once(value));
327 }
328
329 #[inline(always)]
330 fn replace_at(&mut self, index: usize, value: Variant) {
331 let item = self.stack.get_mut(index)
332 .expect("index out of bounds");
333 *item = value;
334 }
335
336 #[inline(always)]
337 fn swap_last(&mut self, index: usize) {
338 let len = self.stack.len();
339 self.stack.swap(index, len - 1)
340 }
341
342 #[inline(always)]
343 fn peek(&self) -> &Variant {
344 self.stack.last().expect("empty stack")
345 }
346
347 #[inline(always)]
348 fn peek_at(&self, index: usize) -> &Variant {
349 self.stack.get(index)
350 .expect("index out of bounds")
351 }
352
353 #[inline(always)]
354 fn peek_many(&self, count: usize) -> &[Variant] {
355 let (_, peek) = self.stack.as_slice().split_at(self.stack.len() - count);
356 peek
357 }
358
359 #[inline]
360 fn get_closure(&self, closure: &Closure) -> Variant {
361 match closure {
362 Closure::Open(index) => *self.peek_at(*index),
363 Closure::Closed(cell) => cell.get(),
364 }
365 }
366
367 #[inline]
368 fn set_closure(&mut self, closure: &Closure, value: Variant) {
369 match closure {
370 Closure::Open(index) => self.replace_at(*index, value),
371 Closure::Closed(cell) => cell.set(value),
372 }
373 }
374}
375
376#[derive(Debug)]
379struct OpenUpvalues {
380 upvalues: HashMap<usize, Vec<UpvalueWeakRef>>,
381}
382
383impl OpenUpvalues {
384 fn new() -> Self {
385 Self {
386 upvalues: HashMap::with_hasher(Default::default())
387 }
388 }
389
390 fn iter_refs(&self) -> impl Iterator<Item=&UpvalueWeakRef> {
391 self.upvalues.values().flat_map(|refs| refs.iter())
392 }
393
394 fn prune_invalid(&mut self) {
395 self.upvalues.retain(|_, upvals| {
396 upvals.retain(UpvalueWeakRef::is_valid);
397 !upvals.is_empty()
398 })
399 }
400
401 fn register(&mut self, function: Gc<Function>) {
403 for (index, upval) in function.upvalues().iter().enumerate() {
404 if upval.closure().is_open() {
405 let upval_ref = function.upvalue(index.try_into().unwrap());
406 self.insert_ref(upval_ref);
407 }
408 }
409 }
410
411 fn insert_ref(&mut self, upval_ref: UpvalueRef) {
412 let index = match upval_ref.closure() {
413 Closure::Open(index) => index,
414 _ => panic!("insert non-open upvalue"),
415 };
416
417 let weak_ref = upval_ref.weakref();
418 self.upvalues.entry(index)
419 .and_modify(|refs| refs.push(weak_ref))
420 .or_insert_with(|| vec![ weak_ref ]);
421 }
422
423 fn close_upvalues(&mut self, index: usize, value: Variant) {
424 if let Some(upvalues) = self.upvalues.remove(&index) {
425 let gc_cell = Gc::new(Cell::new(value));
426 for weak_ref in upvalues.iter() {
427 if let Some(upvalue) = weak_ref.try_deref() {
428 upvalue.close(gc_cell)
429 }
430 }
431 }
432 }
433}
434
435
436impl From<&VirtualMachine<'_>> for VMSnapshot {
440 fn from (vm: &VirtualMachine) -> Self {
441 Self {
442 calls: vm.calls.iter().map(VMFrameSnapshot::from).collect(),
443 stack: vm.stack.stack.clone(),
444 locals: vm.locals.stack.clone(),
445 frame: (&vm.frame).into(),
446 }
447 }
448}
449
450
451struct VMStepper<'m> {
452 vm: VirtualMachine<'m>,
453 start: bool,
454 stop: bool,
455}
456
457impl<'m> From<VirtualMachine<'m>> for VMStepper<'m> {
458 fn from(vm: VirtualMachine<'m>) -> Self {
459 Self {
460 vm,
461 start: false,
462 stop: false,
463 }
464 }
465}
466
467impl<'m> Iterator for VMStepper<'m> {
468 type Item = ExecResult<VMSnapshot>;
469
470 fn next(&mut self) -> Option<Self::Item> {
471 if !self.start {
472 self.start = true;
473 return Some(Ok(VMSnapshot::from(&self.vm)))
474 }
475
476 if !self.stop {
477 let status = self.vm.exec_next();
478 if let Err(error) = status {
479 self.stop = true;
480 return Some(Err(error));
481 }
482 if let Ok(Control::Exit(..)) = status {
483 self.stop = true;
484 }
485 return Some(Ok(VMSnapshot::from(&self.vm)))
486 }
487
488 None
489 }
490}