-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathcall_stack.rs
More file actions
92 lines (78 loc) · 2.6 KB
/
call_stack.rs
File metadata and controls
92 lines (78 loc) · 2.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::{Result, Trap};
use core::hint::cold_path;
use alloc::vec::Vec;
use tinywasm_types::{FuncAddr, ValueCounts};
#[cfg_attr(feature = "debug", derive(Debug))]
pub(crate) struct CallStack {
stack: Vec<CallFrame>,
max_size: usize,
dynamic: bool,
}
impl CallStack {
pub(crate) fn new(config: &crate::engine::Config) -> Self {
let stack = config.call_stack;
Self { stack: Vec::with_capacity(stack.initial_size), max_size: stack.max_size, dynamic: stack.dynamic }
}
pub(crate) fn clear(&mut self) {
self.stack.clear();
}
#[inline(always)]
pub(crate) fn pop(&mut self) -> Option<CallFrame> {
self.stack.pop()
}
#[inline(always)]
pub(crate) fn push(&mut self, mut call_frame: CallFrame) -> Result<(), Trap> {
self.ensure_capacity_for(self.stack.len() + 1)?;
call_frame.incr_instr_ptr();
self.stack.push(call_frame);
Ok(())
}
#[inline(always)]
fn ensure_capacity_for(&mut self, required_len: usize) -> Result<(), Trap> {
if required_len <= self.stack.capacity() {
return Ok(());
}
if required_len > self.max_size || !self.dynamic {
cold_path();
return Err(Trap::CallStackOverflow);
}
let target_capacity = required_len.max(self.stack.capacity().max(1).saturating_mul(2)).min(self.max_size);
let Ok(()) = self.stack.try_reserve(target_capacity.saturating_sub(self.stack.len())) else {
cold_path();
return Err(Trap::CallStackOverflow);
};
Ok(())
}
}
#[derive(Clone, Copy)]
#[cfg_attr(feature = "debug", derive(Debug))]
pub(crate) struct CallFrame {
pub(crate) instr_ptr: u32,
pub(crate) func_addr: FuncAddr,
pub(crate) locals_base: StackBase,
pub(crate) stack_offset: ValueCounts,
}
#[derive(Clone, Copy, Default)]
#[cfg_attr(feature = "debug", derive(Debug))]
pub(crate) struct StackBase {
pub(crate) s32: u32,
pub(crate) s64: u32,
pub(crate) s128: u32,
}
impl CallFrame {
pub(crate) fn new(func_addr: FuncAddr, locals_base: StackBase, stack_offset: ValueCounts) -> Self {
Self { instr_ptr: 0, func_addr, locals_base, stack_offset }
}
#[inline]
pub(crate) fn stack_base(&self) -> StackBase {
StackBase {
s32: self.locals_base.s32 + self.stack_offset.c32 as u32,
s64: self.locals_base.s64 + self.stack_offset.c64 as u32,
s128: self.locals_base.s128 + self.stack_offset.c128 as u32,
}
}
#[inline(always)]
pub(crate) fn incr_instr_ptr(&mut self) {
self.instr_ptr += 1;
}
}