pr47/vm/al31f/
stack.rs

1use std::ptr::NonNull;
2
3use unchecked_unwrap::UncheckedUnwrap;
4
5use crate::data::Value;
6
7#[cfg(debug_assertions)]
8#[derive(Copy, Clone)]
9pub struct StackSlice(*mut [Option<Value>]);
10
11#[cfg(debug_assertions)]
12impl StackSlice {
13    pub unsafe fn set_value(&mut self, idx: usize, value: Value) {
14        (*self.0)[idx].replace(value);
15    }
16
17    pub unsafe fn get_value(&self, idx: usize) -> Value {
18        (*self.0)[idx].unwrap()
19    }
20
21    pub unsafe fn get_value_mut_ref(&self, idx: usize) -> *mut Value {
22        (*self.0)[idx].as_mut().unwrap() as *mut Value
23    }
24}
25
26#[cfg(not(debug_assertions))]
27#[derive(Copy, Clone)]
28pub struct StackSlice(*mut Value);
29
30#[cfg(not(debug_assertions))]
31impl StackSlice {
32    #[inline(always)] pub unsafe fn set_value(&mut self, idx: usize, value: Value) {
33        let dest: &mut Value = &mut *self.0.offset(idx as isize);
34        *dest = value;
35    }
36
37    #[inline(always)] pub unsafe fn get_value(&mut self, idx: usize) -> Value {
38        *self.0.offset(idx as isize)
39    }
40
41    #[inline(always)] pub unsafe fn get_value_mut_ref(&self, idx: usize) -> *mut Value {
42        self.0.offset(idx as isize)
43    }
44}
45
46#[derive(Debug)]
47pub struct FrameInfo {
48    pub frame_start: usize,
49    pub frame_end: usize,
50    pub ret_value_locs: NonNull<[usize]>,
51    pub ret_addr: usize,
52
53    pub func_id: usize
54}
55
56impl FrameInfo {
57    pub fn new(
58        frame_start: usize,
59        frame_end: usize,
60        ret_value_locs: NonNull<[usize]>,
61        ret_addr: usize,
62        func_id: usize
63    ) -> Self {
64        Self {
65            frame_start,
66            frame_end,
67            ret_value_locs,
68            ret_addr,
69            func_id
70        }
71    }
72}
73
74#[cfg(debug_assertions)]
75pub struct Stack {
76    pub values: Vec<Option<Value>>,
77    pub frames: Vec<FrameInfo>
78}
79
80pub const EMPTY_RET_LOCS_SLICE: &'static [usize] = &[];
81
82#[cfg(debug_assertions)]
83impl Stack {
84    pub fn new() -> Self {
85        Self {
86            values: Vec::with_capacity(64),
87            frames: Vec::with_capacity(4)
88        }
89    }
90
91    pub unsafe fn ext_func_call_grow_stack(
92        &mut self,
93        func_id: usize,
94        frame_size: usize,
95        args: &[Value]
96    ) -> StackSlice {
97        assert_eq!(self.values.len(), 0);
98        assert_eq!(self.frames.len(), 0);
99
100        self.values.resize(frame_size, None);
101        for (i /*: usize*/, arg /*: &Value*/) in args.iter().enumerate() {
102            self.values[i].replace(*arg);
103        }
104        self.frames.push(FrameInfo::new(
105            0, frame_size, NonNull::from(EMPTY_RET_LOCS_SLICE), 0, func_id
106        ));
107        StackSlice(&mut self.values[..] as *mut [Option<Value>])
108    }
109
110    pub unsafe fn func_call_grow_stack(
111        &mut self,
112        func_id: usize,
113        frame_size: usize,
114        arg_locs: &[usize],
115        ret_value_locs: NonNull<[usize]>,
116        ret_addr: usize
117    ) -> StackSlice {
118        let this_frame: &FrameInfo = self.frames.last().unwrap();
119        let (this_frame_start, this_frame_end): (usize, usize)
120            = (this_frame.frame_start, this_frame.frame_end);
121
122        assert_eq!(this_frame_end, self.values.len());
123        let new_frame_end: usize = this_frame_end + frame_size;
124        self.values.resize(new_frame_end, None);
125        self.frames.push(
126            FrameInfo::new(this_frame_end, new_frame_end, ret_value_locs, ret_addr, func_id)
127        );
128        let old_slice: StackSlice =
129            StackSlice(&mut self.values[this_frame_start..this_frame_end] as *mut _);
130        let mut new_slice: StackSlice =
131            StackSlice(&mut self.values[this_frame_end..new_frame_end] as *mut _);
132        for (i /*: usize*/, arg_loc/*: &usize*/) in arg_locs.iter().enumerate() {
133            new_slice.set_value(i, old_slice.get_value(*arg_loc));
134        }
135        new_slice
136    }
137
138    pub unsafe fn done_func_call_shrink_stack0(&mut self) -> Option<(StackSlice, usize)> {
139        self.done_func_call_shrink_stack(&[])
140    }
141
142    pub unsafe fn done_func_call_shrink_stack1(
143        &mut self,
144        ret_value_src: usize
145    ) -> Option<(StackSlice, usize)> {
146        self.done_func_call_shrink_stack(&[ret_value_src])
147    }
148
149    pub unsafe fn done_func_call_shrink_stack(
150        &mut self,
151        ret_values: &[usize]
152    ) -> Option<(StackSlice, usize)> {
153        let frame_count: usize = self.frames.len();
154        if frame_count == 1 {
155            return None;
156        }
157
158        let this_frame: &FrameInfo = &self.frames[frame_count - 1];
159        let prev_frame: &FrameInfo = &self.frames[frame_count - 2];
160        assert_eq!(prev_frame.frame_end, this_frame.frame_start);
161        let this_slice =
162            StackSlice(&mut self.values[this_frame.frame_start..this_frame.frame_end] as *mut _);
163        let mut prev_slice =
164            StackSlice(&mut self.values[prev_frame.frame_start..prev_frame.frame_end] as *mut _);
165
166        assert_eq!(ret_values.len(), this_frame.ret_value_locs.as_ref().len());
167        for (ret_value /*: &usize*/, ret_value_loc /*: &usize*/) in
168            ret_values.iter().zip(this_frame.ret_value_locs.as_ref().iter())
169        {
170            prev_slice.set_value(*ret_value_loc, this_slice.get_value(*ret_value))
171        }
172
173        let ret_addr: usize = this_frame.ret_addr;
174        self.values.truncate(prev_frame.frame_end);
175        self.frames.pop().unwrap();
176        Some((prev_slice, ret_addr))
177    }
178
179    pub unsafe fn last_frame_slice(&mut self) -> StackSlice {
180        let frame: &FrameInfo = self.frames.last().unchecked_unwrap();
181        StackSlice(&mut self.values[frame.frame_start..frame.frame_end] as *mut _)
182    }
183
184    pub unsafe fn unwind_shrink_slice(&mut self) {
185        let frame: FrameInfo = self.frames.pop().unchecked_unwrap();
186        self.values.truncate(frame.frame_start);
187    }
188}
189
190#[cfg(any(feature = "bench", test))]
191impl Stack {
192    pub fn trace(&self) {
193        eprintln!("[STACK-TRACE] Begin stack tracing");
194        eprintln!("[STACK-TRACE] {{");
195        for (i, frame) /*: (usize, &FrameInfo)*/ in self.frames.iter().enumerate() {
196            eprintln!("[STACK-TRACE]     <frame {}: size = {}, ret_addr = {}, ret_val_locs = {:?}>",
197                      i,
198                      frame.frame_end - frame.frame_start,
199                      frame.ret_addr,
200                      unsafe { frame.ret_value_locs.as_ref() });
201            eprintln!("[STACK-TRACE]     [");
202            #[cfg(debug_assertions)]
203            for i /*: usize*/ in frame.frame_start..frame.frame_end {
204                if let Some(value /*: &Value*/) = &self.values[i] {
205                    eprintln!("[STACK-TRACE]         [{}] = {:?}", i - frame.frame_start, value);
206                } else {
207                    eprintln!("[STACK-TRACE]         [{}] = UNINIT", i - frame.frame_start);
208                }
209            }
210            #[cfg(not(debug_assertions))]
211            for i /*: usize*/ in frame.frame_start..frame.frame_end {
212                let value: &Value = &self.values[i];
213                eprintln!("[STACK-TRACE]         [{}] = {:?}", i - frame.frame_start, value);
214            }
215            eprintln!("[STACK-TRACE]     ]");
216        }
217        eprintln!("[STACK-TRACE] }}");
218        eprintln!("[STACK-TRACE] End stack tracing");
219    }
220}
221
222#[cfg(not(debug_assertions))]
223pub struct Stack {
224    pub values: Vec<Value>,
225    pub frames: Vec<FrameInfo>
226}
227
228#[cfg(not(debug_assertions))]
229impl Stack {
230    pub fn new() -> Self {
231        Self {
232            values: Vec::with_capacity(64),
233            frames: Vec::with_capacity(4)
234        }
235    }
236
237    pub unsafe fn ext_func_call_grow_stack(
238        &mut self,
239        func_id: usize,
240        frame_size: usize,
241        args: &[Value]
242    ) -> StackSlice {
243        self.values.resize(frame_size, Value::new_null());
244        for (i /*: usize*/, arg /*: &Value*/) in args.iter().enumerate() {
245            let dest: &mut Value = self.values.get_unchecked_mut(i);
246            *dest = *arg;
247        }
248        self.frames.push(FrameInfo::new(
249            0, frame_size, NonNull::from(EMPTY_RET_LOCS_SLICE), 0, func_id)
250        );
251        StackSlice(self.values.as_mut_ptr())
252    }
253
254    pub unsafe fn func_call_grow_stack(
255        &mut self,
256        func_id: usize,
257        frame_size: usize,
258        arg_locs: &[usize],
259        ret_value_locs: NonNull<[usize]>,
260        ret_addr: usize
261    ) -> StackSlice {
262        let this_frame: &FrameInfo = self.frames.last().unchecked_unwrap();
263        let (this_frame_start, this_frame_end): (usize, usize)
264            = (this_frame.frame_start, this_frame.frame_end);
265        let new_frame_end: usize = this_frame_end + frame_size;
266        self.values.resize(new_frame_end, Value::new_null());
267        self.frames.push(
268            FrameInfo::new(this_frame_end, new_frame_end, ret_value_locs, ret_addr, func_id)
269        );
270        let old_slice_ptr: *mut Value = self.values.as_mut_ptr().offset(this_frame_start as isize);
271        let new_slice_ptr: *mut Value = self.values.as_mut_ptr().offset(this_frame_end as isize);
272
273        for i /*: usize*/ in 0..arg_locs.len() {
274            let arg_loc: usize = *arg_locs.get_unchecked(i);
275            *new_slice_ptr.offset(i as isize) = *old_slice_ptr.offset(arg_loc as isize);
276        }
277        StackSlice(new_slice_ptr)
278    }
279
280    #[inline] pub unsafe fn done_func_call_shrink_stack0(&mut self) -> Option<(StackSlice, usize)> {
281        let frame_count = self.frames.len();
282        if frame_count == 1 {
283            return None;
284        }
285
286        let this_frame: &FrameInfo = self.frames.get_unchecked(frame_count - 1);
287        let prev_frame: &FrameInfo = self.frames.get_unchecked(frame_count - 2);
288        let prev_slice_ptr: *mut Value =
289            self.values.as_mut_ptr().offset(prev_frame.frame_start as isize);
290
291        let ret_addr: usize = this_frame.ret_addr;
292        self.values.truncate(prev_frame.frame_end);
293        self.frames.pop().unchecked_unwrap();
294        Some((StackSlice(prev_slice_ptr), ret_addr))
295    }
296
297    #[inline] pub unsafe fn done_func_call_shrink_stack1(
298        &mut self,
299        ret_value_src: usize
300    ) -> Option<(StackSlice, usize)> {
301        let frame_count = self.frames.len();
302        if frame_count == 1 {
303            return None;
304        }
305
306        let this_frame: &FrameInfo = self.frames.get_unchecked(frame_count - 1);
307        let prev_frame: &FrameInfo = self.frames.get_unchecked(frame_count - 2);
308
309        let this_slice_ptr = self.values.as_ptr().offset(this_frame.frame_start as isize);
310        let prev_slice_ptr = self.values.as_mut_ptr().offset(prev_frame.frame_start as isize);
311
312        let ret_value_loc: usize = *this_frame.ret_value_locs.as_ref().get_unchecked(0);
313        *prev_slice_ptr.offset(ret_value_loc as isize)
314            = *this_slice_ptr.offset(ret_value_src as isize);
315
316        let ret_addr: usize = this_frame.ret_addr;
317        self.values.truncate(prev_frame.frame_end);
318        self.frames.pop().unchecked_unwrap();
319        Some((StackSlice(prev_slice_ptr), ret_addr))
320    }
321
322    pub unsafe fn done_func_call_shrink_stack(
323        &mut self,
324        ret_values: &[usize]
325    ) -> Option<(StackSlice, usize)> {
326        let frame_count = self.frames.len();
327        if frame_count == 1 {
328            return None;
329        }
330
331        let this_frame: &FrameInfo = self.frames.get_unchecked(frame_count - 1);
332        let prev_frame: &FrameInfo = self.frames.get_unchecked(frame_count - 2);
333        let this_slice_ptr: *mut Value =
334            self.values.as_mut_ptr().offset(this_frame.frame_start as isize);
335        let prev_slice_ptr: *mut Value =
336            self.values.as_mut_ptr().offset(prev_frame.frame_start as isize);
337
338        let len: usize = ret_values.len();
339        for i /*: usize*/ in 0..len {
340            let ret_value_loc: usize = *this_frame.ret_value_locs.as_ref().get_unchecked(i);
341            let ret_value_src: usize = *ret_values.get_unchecked(i);
342            *prev_slice_ptr.offset(ret_value_loc as isize) =
343                *this_slice_ptr.offset(ret_value_src as isize);
344        }
345
346        let ret_addr: usize = this_frame.ret_addr;
347        self.values.truncate(prev_frame.frame_end);
348        self.frames.pop().unchecked_unwrap();
349        Some((StackSlice(prev_slice_ptr), ret_addr))
350    }
351
352    #[inline] pub unsafe fn last_frame_slice(&mut self) -> StackSlice {
353        let frame: &FrameInfo = self.frames.last().unchecked_unwrap();
354        StackSlice(self.values.as_mut_ptr().offset(frame.frame_start as isize))
355    }
356
357    #[inline] pub unsafe fn unwind_shrink_slice(&mut self) {
358        let frame: FrameInfo = self.frames.pop().unchecked_unwrap();
359        self.values.truncate(frame.frame_start);
360    }
361}