Skip to content

Commit 2e40140

Browse files
chore: move locals to stack
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 99f5168 commit 2e40140

File tree

17 files changed

+339
-232
lines changed

17 files changed

+339
-232
lines changed

crates/tinywasm/src/func.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,14 @@ impl FuncHandle {
5656
};
5757

5858
// 6. Let f be the dummy frame
59-
let callframe = CallFrame::new_with_params(wasm_func.locals, self.addr, func_inst.owner, params);
60-
6159
// 7. Push the frame f to the call stack
6260
// & 8. Push the values to the stack
6361
store.stack.clear();
62+
store.stack.values.extend_from_wasmvalues(params)?;
63+
let (locals_base, _stack_base, stack_offset) =
64+
store.stack.values.enter_locals(wasm_func.params, wasm_func.locals)?;
65+
let callframe = CallFrame::new(self.addr, func_inst.owner, locals_base, stack_offset);
66+
6467
// 9. Invoke the function instance
6568
InterpreterRuntime::exec(store, callframe)?;
6669

crates/tinywasm/src/imports.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,17 +122,17 @@ pub enum Extern {
122122

123123
impl Extern {
124124
/// Create a new global import
125-
pub fn global(val: WasmValue, mutable: bool) -> Self {
125+
pub const fn global(val: WasmValue, mutable: bool) -> Self {
126126
Self::Global { ty: GlobalType { ty: val.val_type(), mutable }, val }
127127
}
128128

129129
/// Create a new table import
130-
pub fn table(ty: TableType, init: WasmValue) -> Self {
130+
pub const fn table(ty: TableType, init: WasmValue) -> Self {
131131
Self::Table { ty, init }
132132
}
133133

134134
/// Create a new memory import
135-
pub fn memory(ty: MemoryType) -> Self {
135+
pub const fn memory(ty: MemoryType) -> Self {
136136
Self::Memory { ty }
137137
}
138138

@@ -180,7 +180,7 @@ impl Extern {
180180
}
181181

182182
/// Get the kind of the external value
183-
pub fn kind(&self) -> ExternalKind {
183+
pub const fn kind(&self) -> ExternalKind {
184184
match self {
185185
Self::Global { .. } => ExternalKind::Global,
186186
Self::Table { .. } => ExternalKind::Table,
@@ -257,14 +257,14 @@ pub(crate) struct ResolvedImports {
257257
}
258258

259259
impl ResolvedImports {
260-
pub(crate) fn new() -> Self {
260+
pub(crate) const fn new() -> Self {
261261
Self { globals: Vec::new(), tables: Vec::new(), memories: Vec::new(), funcs: Vec::new() }
262262
}
263263
}
264264

265265
impl Imports {
266266
/// Create a new empty import set
267-
pub fn new() -> Self {
267+
pub const fn new() -> Self {
268268
Self { values: BTreeMap::new(), modules: BTreeMap::new() }
269269
}
270270

crates/tinywasm/src/instance.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,21 @@ pub(crate) struct ModuleInstanceInner {
3636
}
3737

3838
impl ModuleInstanceInner {
39+
#[inline]
3940
pub(crate) fn func_ty(&self, addr: FuncAddr) -> &FuncType {
4041
match self.types.get(addr as usize) {
4142
Some(ty) => ty,
4243
None => unreachable!("invalid function address: {addr}"),
4344
}
4445
}
4546

47+
#[inline]
4648
pub(crate) fn func_addrs(&self) -> &[FuncAddr] {
4749
&self.func_addrs
4850
}
4951

5052
// resolve a function address to the global store address
53+
#[inline]
5154
pub(crate) fn resolve_func_addr(&self, addr: FuncAddr) -> FuncAddr {
5255
match self.func_addrs.get(addr as usize) {
5356
Some(addr) => *addr,
@@ -56,6 +59,7 @@ impl ModuleInstanceInner {
5659
}
5760

5861
// resolve a table address to the global store address
62+
#[inline]
5963
pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> TableAddr {
6064
match self.table_addrs.get(addr as usize) {
6165
Some(addr) => *addr,
@@ -64,6 +68,7 @@ impl ModuleInstanceInner {
6468
}
6569

6670
// resolve a memory address to the global store address
71+
#[inline]
6772
pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> MemAddr {
6873
match self.mem_addrs.get(addr as usize) {
6974
Some(addr) => *addr,
@@ -72,6 +77,7 @@ impl ModuleInstanceInner {
7277
}
7378

7479
// resolve a data address to the global store address
80+
#[inline]
7581
pub(crate) fn resolve_data_addr(&self, addr: DataAddr) -> DataAddr {
7682
match self.data_addrs.get(addr as usize) {
7783
Some(addr) => *addr,
@@ -80,6 +86,7 @@ impl ModuleInstanceInner {
8086
}
8187

8288
// resolve a memory address to the global store address
89+
#[inline]
8390
pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr {
8491
match self.elem_addrs.get(addr as usize) {
8592
Some(addr) => *addr,
@@ -88,6 +95,7 @@ impl ModuleInstanceInner {
8895
}
8996

9097
// resolve a global address to the global store address
98+
#[inline]
9199
pub(crate) fn resolve_global_addr(&self, addr: GlobalAddr) -> GlobalAddr {
92100
match self.global_addrs.get(addr as usize) {
93101
Some(addr) => *addr,

crates/tinywasm/src/interpreter/executor.rs

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -114,36 +114,36 @@ impl<'store> Executor<'store> {
114114
return ControlFlow::Continue(());
115115
}
116116
DropKeepSmall { base32, keep32, base64, keep64, base128, keep128, base_ref, keep_ref } => {
117-
let b32 = self.cf.stack_base.s32 + *base32 as usize;
117+
let b32 = self.cf.stack_base().s32 + *base32 as usize;
118118
let k32 = *keep32 as usize;
119119
self.store.stack.values.stack_32.truncate_keep(b32, k32);
120-
let b64 = self.cf.stack_base.s64 + *base64 as usize;
120+
let b64 = self.cf.stack_base().s64 + *base64 as usize;
121121
let k64 = *keep64 as usize;
122122
self.store.stack.values.stack_64.truncate_keep(b64, k64);
123-
let b128 = self.cf.stack_base.s128 + *base128 as usize;
123+
let b128 = self.cf.stack_base().s128 + *base128 as usize;
124124
let k128 = *keep128 as usize;
125125
self.store.stack.values.stack_128.truncate_keep(b128, k128);
126-
let bref = self.cf.stack_base.sref + *base_ref as usize;
126+
let bref = self.cf.stack_base().sref + *base_ref as usize;
127127
let kref = *keep_ref as usize;
128128
self.store.stack.values.stack_ref.truncate_keep(bref, kref);
129129
}
130130
DropKeep32(base, keep) => {
131-
let b = self.cf.stack_base.s32 + *base as usize;
131+
let b = self.cf.stack_base().s32 + *base as usize;
132132
let k = *keep as usize;
133133
self.store.stack.values.stack_32.truncate_keep(b, k);
134134
}
135135
DropKeep64(base, keep) => {
136-
let b = self.cf.stack_base.s64 + *base as usize;
136+
let b = self.cf.stack_base().s64 + *base as usize;
137137
let k = *keep as usize;
138138
self.store.stack.values.stack_64.truncate_keep(b, k);
139139
}
140140
DropKeep128(base, keep) => {
141-
let b = self.cf.stack_base.s128 + *base as usize;
141+
let b = self.cf.stack_base().s128 + *base as usize;
142142
let k = *keep as usize;
143143
self.store.stack.values.stack_128.truncate_keep(b, k);
144144
}
145145
DropKeepRef(base, keep) => {
146-
let b = self.cf.stack_base.sref + *base as usize;
146+
let b = self.cf.stack_base().sref + *base as usize;
147147
let k = *keep as usize;
148148
self.store.stack.values.stack_ref.truncate_keep(b, k);
149149
}
@@ -163,22 +163,58 @@ impl<'store> Executor<'store> {
163163
return ControlFlow::Continue(());
164164
}
165165
Return => return self.exec_return(),
166-
LocalGet32(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value32>(*local_index)).to_cf()?,
167-
LocalGet64(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value64>(*local_index)).to_cf()?,
168-
LocalGet128(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value128>(*local_index)).to_cf()?,
169-
LocalGetRef(local_index) => self.store.stack.values.push(self.cf.locals.get::<ValueRef>(*local_index)).to_cf()?,
170-
LocalSet32(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value32>()),
171-
LocalSet64(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value64>()),
172-
LocalSet128(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value128>()),
173-
LocalSetRef(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<ValueRef>()),
174-
LocalCopy32(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value32>(*from)),
175-
LocalCopy64(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value64>(*from)),
176-
LocalCopy128(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value128>(*from)),
177-
LocalCopyRef(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<ValueRef>(*from)),
178-
LocalTee32(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value32>()),
179-
LocalTee64(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value64>()),
180-
LocalTee128(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value128>()),
181-
LocalTeeRef(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<ValueRef>()),
166+
LocalGet32(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_32(&self.cf, *local_index)).to_cf()?,
167+
LocalGet64(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_64(&self.cf, *local_index)).to_cf()?,
168+
LocalGet128(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_128(&self.cf, *local_index)).to_cf()?,
169+
LocalGetRef(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_ref(&self.cf, *local_index)).to_cf()?,
170+
LocalSet32(local_index) => {
171+
let val = self.store.stack.values.pop::<Value32>();
172+
self.store.stack.values.local_set_32(&self.cf, *local_index, val);
173+
}
174+
LocalSet64(local_index) => {
175+
let val = self.store.stack.values.pop::<Value64>();
176+
self.store.stack.values.local_set_64(&self.cf, *local_index, val);
177+
}
178+
LocalSet128(local_index) => {
179+
let val = self.store.stack.values.pop::<Value128>();
180+
self.store.stack.values.local_set_128(&self.cf, *local_index, val);
181+
}
182+
LocalSetRef(local_index) => {
183+
let val = self.store.stack.values.pop::<ValueRef>();
184+
self.store.stack.values.local_set_ref(&self.cf, *local_index, val);
185+
}
186+
LocalCopy32(from, to) => {
187+
let val = self.store.stack.values.local_get_32(&self.cf, *from);
188+
self.store.stack.values.local_set_32(&self.cf, *to, val);
189+
}
190+
LocalCopy64(from, to) => {
191+
let val = self.store.stack.values.local_get_64(&self.cf, *from);
192+
self.store.stack.values.local_set_64(&self.cf, *to, val);
193+
}
194+
LocalCopy128(from, to) => {
195+
let val = self.store.stack.values.local_get_128(&self.cf, *from);
196+
self.store.stack.values.local_set_128(&self.cf, *to, val);
197+
}
198+
LocalCopyRef(from, to) => {
199+
let val = self.store.stack.values.local_get_ref(&self.cf, *from);
200+
self.store.stack.values.local_set_ref(&self.cf, *to, val);
201+
}
202+
LocalTee32(local_index) => {
203+
let val = self.store.stack.values.peek::<Value32>();
204+
self.store.stack.values.local_set_32(&self.cf, *local_index, val);
205+
}
206+
LocalTee64(local_index) => {
207+
let val = self.store.stack.values.peek::<Value64>();
208+
self.store.stack.values.local_set_64(&self.cf, *local_index, val);
209+
}
210+
LocalTee128(local_index) => {
211+
let val = self.store.stack.values.peek::<Value128>();
212+
self.store.stack.values.local_set_128(&self.cf, *local_index, val);
213+
}
214+
LocalTeeRef(local_index) => {
215+
let val = self.store.stack.values.peek::<ValueRef>();
216+
self.store.stack.values.local_set_ref(&self.cf, *local_index, val);
217+
}
182218
GlobalGet(global_index) => self.exec_global_get(*global_index).to_cf()?,
183219
GlobalSet32(global_index) => self.exec_global_set::<Value32>(*global_index),
184220
GlobalSet64(global_index) => self.exec_global_set::<Value64>(*global_index),
@@ -627,20 +663,35 @@ impl<'store> Executor<'store> {
627663
func_addr: FuncAddr,
628664
owner: ModuleInstanceAddr,
629665
) -> ControlFlow<Option<Error>> {
666+
if !IS_RETURN_CALL && self.store.stack.call_stack.is_full() {
667+
return ControlFlow::Break(Some(Trap::CallStackOverflow.into()));
668+
}
669+
630670
if !Rc::ptr_eq(&self.func, &wasm_func) {
631671
self.func = wasm_func.clone();
632672
}
633673

634674
if IS_RETURN_CALL {
635-
let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals);
636-
let stack_base = self.store.stack.values.height();
637-
self.cf.reuse_for(func_addr, locals, owner, stack_base);
675+
self.store.stack.values.truncate_keep_counts(self.cf.locals_base, wasm_func.params);
676+
}
677+
678+
let (locals_base, _stack_base, stack_offset) =
679+
match self.store.stack.values.enter_locals(wasm_func.params, wasm_func.locals) {
680+
Ok(v) => v,
681+
Err(Error::Trap(Trap::ValueStackOverflow)) if !IS_RETURN_CALL => {
682+
return ControlFlow::Break(Some(Trap::CallStackOverflow.into()));
683+
}
684+
Err(err) => return ControlFlow::Break(Some(err)),
685+
};
686+
687+
let new_call_frame = CallFrame::new(func_addr, owner, locals_base, stack_offset);
688+
689+
if IS_RETURN_CALL {
690+
self.cf = new_call_frame;
638691
} else {
639-
let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals);
640-
let stack_base = self.store.stack.values.height();
641-
let new_call_frame = CallFrame::new(func_addr, owner, locals, stack_base);
642692
self.cf.incr_instr_ptr(); // skip the call instruction
643-
self.store.stack.call_stack.push(core::mem::replace(&mut self.cf, new_call_frame)).to_cf()?;
693+
self.store.stack.call_stack.push(self.cf).to_cf()?;
694+
self.cf = new_call_frame;
644695
}
645696

646697
if self.cf.module_addr != self.module.idx {
@@ -709,6 +760,9 @@ impl<'store> Executor<'store> {
709760
}
710761

711762
fn exec_return(&mut self) -> ControlFlow<Option<Error>> {
763+
let result_counts = ValueCountsSmall::from(self.func.ty.results.iter());
764+
self.store.stack.values.truncate_keep_counts(self.cf.locals_base, result_counts);
765+
712766
let Some(cf) = self.store.stack.call_stack.pop() else { return ControlFlow::Break(None) };
713767

714768
if cf.func_addr != self.cf.func_addr {
@@ -718,7 +772,6 @@ impl<'store> Executor<'store> {
718772
self.module = self.store.get_module_instance_raw(cf.module_addr).clone();
719773
}
720774
}
721-
722775
self.cf = cf;
723776
ControlFlow::Continue(())
724777
}

crates/tinywasm/src/interpreter/no_std_floats.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,18 @@ pub(super) trait NoStdFloatExt {
99

1010
#[rustfmt::skip]
1111
impl NoStdFloatExt for f64 {
12-
fn round(self) -> Self { libm::round(self) }
13-
fn ceil(self) -> Self { libm::ceil(self) }
14-
fn floor(self) -> Self { libm::floor(self) }
15-
fn trunc(self) -> Self { libm::trunc(self) }
16-
fn sqrt(self) -> Self { libm::sqrt(self) }
12+
#[inline] fn round(self) -> Self { libm::round(self) }
13+
#[inline] fn ceil(self) -> Self { libm::ceil(self) }
14+
#[inline] fn floor(self) -> Self { libm::floor(self) }
15+
#[inline] fn trunc(self) -> Self { libm::trunc(self) }
16+
#[inline] fn sqrt(self) -> Self { libm::sqrt(self) }
1717
}
1818

1919
#[rustfmt::skip]
2020
impl NoStdFloatExt for f32 {
21-
fn round(self) -> Self { libm::roundf(self) }
22-
fn ceil(self) -> Self { libm::ceilf(self) }
23-
fn floor(self) -> Self { libm::floorf(self) }
24-
fn trunc(self) -> Self { libm::truncf(self) }
25-
fn sqrt(self) -> Self { libm::sqrtf(self) }
21+
#[inline] fn round(self) -> Self { libm::roundf(self) }
22+
#[inline] fn ceil(self) -> Self { libm::ceilf(self) }
23+
#[inline] fn floor(self) -> Self { libm::floorf(self) }
24+
#[inline] fn trunc(self) -> Self { libm::truncf(self) }
25+
#[inline] fn sqrt(self) -> Self { libm::sqrtf(self) }
2626
}

crates/tinywasm/src/interpreter/num_helpers.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ macro_rules! impl_wasm_float_ops {
7070
($($t:ty)*) => ($(
7171
impl TinywasmFloatExt for $t {
7272
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest
73+
#[inline]
7374
fn tw_nearest(self) -> Self {
7475
match self {
7576
#[cfg(not(feature = "canonicalize_nans"))]
@@ -94,6 +95,7 @@ macro_rules! impl_wasm_float_ops {
9495

9596
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fmin
9697
// Based on f32::minimum (which is not yet stable)
98+
#[inline]
9799
fn tw_minimum(self, other: Self) -> Self {
98100
match self.partial_cmp(&other) {
99101
Some(core::cmp::Ordering::Less) => self,
@@ -108,6 +110,7 @@ macro_rules! impl_wasm_float_ops {
108110

109111
// https://webassembly.github.io/spec/core/exec/numerics.html#op-fmax
110112
// Based on f32::maximum (which is not yet stable)
113+
#[inline]
111114
fn tw_maximum(self, other: Self) -> Self {
112115
match self.partial_cmp(&other) {
113116
Some(core::cmp::Ordering::Greater) => self,
@@ -135,18 +138,22 @@ pub(crate) trait WasmIntOps {
135138
macro_rules! impl_wrapping_self_sh {
136139
($($t:ty)*) => ($(
137140
impl WasmIntOps for $t {
141+
#[inline]
138142
fn wasm_shl(self, rhs: Self) -> Self {
139143
self.wrapping_shl(rhs as u32)
140144
}
141145

146+
#[inline]
142147
fn wasm_shr(self, rhs: Self) -> Self {
143148
self.wrapping_shr(rhs as u32)
144149
}
145150

151+
#[inline]
146152
fn wasm_rotl(self, rhs: Self) -> Self {
147153
self.rotate_left(rhs as u32)
148154
}
149155

156+
#[inline]
150157
fn wasm_rotr(self, rhs: Self) -> Self {
151158
self.rotate_right(rhs as u32)
152159
}

0 commit comments

Comments
 (0)