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 , arg ) 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 , arg_loc) 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 , ret_value_loc ) 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) 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 in frame.frame_start..frame.frame_end {
204 if let Some(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 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 , arg ) 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 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 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}