Skip to content
This repository was archived by the owner on Oct 3, 2025. It is now read-only.

Commit 37e0152

Browse files
chore: improve simd
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
1 parent 275b13f commit 37e0152

File tree

6 files changed

+98
-33
lines changed

6 files changed

+98
-33
lines changed

crates/tinywasm/src/runtime/interpreter/mod.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
295295
// custom instructions
296296
LocalGet2(a, b) => self.exec_local_get2(*a, *b),
297297
LocalGet3(a, b, c) => self.exec_local_get3(*a, *b, *c),
298-
LocalTeeGet(a, b) => self.exec_local_tee_get(*a, *b),
298+
LocalTeeGet(a, b) => self.exec_local_tee_get(*a, *b)?,
299299
LocalGetSet(a, b) => self.exec_local_get_set(*a, *b),
300300
I64XorConstRotl(rotate_by) => self.exec_i64_xor_const_rotl(*rotate_by)?,
301301
I32LocalGetConstAdd(local, val) => self.exec_i32_local_get_const_add(*local, *val),
@@ -317,13 +317,21 @@ impl<'store, 'stack> Executor<'store, 'stack> {
317317
fn exec_end_block(&mut self) -> Result<()> {
318318
let block = self.stack.blocks.pop()?;
319319
self.stack.values.truncate_keep(block.stack_ptr, block.results as u32);
320+
321+
#[cfg(feature = "simd")]
322+
self.stack.values.truncate_keep_simd(block.simd_stack_ptr, block.simd_results as u32);
320323
Ok(())
321324
}
322325

323326
#[inline(always)]
324327
fn exec_else(&mut self, end_offset: u32) -> Result<()> {
325328
let block = self.stack.blocks.pop()?;
329+
326330
self.stack.values.truncate_keep(block.stack_ptr, block.results as u32);
331+
332+
#[cfg(feature = "simd")]
333+
self.stack.values.truncate_keep_simd(block.simd_stack_ptr, block.simd_results as u32);
334+
327335
self.cf.instr_ptr += end_offset as usize;
328336
Ok(())
329337
}
@@ -448,14 +456,14 @@ impl<'store, 'stack> Executor<'store, 'stack> {
448456
}
449457

450458
#[inline(always)]
451-
fn exec_local_tee_get(&mut self, a: u32, b: u32) {
452-
let last =
453-
self.stack.values.last().expect("localtee: stack is empty. this should have been validated by the parser");
459+
fn exec_local_tee_get(&mut self, a: u32, b: u32) -> Result<()> {
460+
let last = self.stack.values.last()?;
454461
self.cf.set_local(a, *last);
455462
self.stack.values.push(match a == b {
456463
true => *last,
457464
false => self.cf.get_local(b),
458465
});
466+
Ok(())
459467
}
460468

461469
#[inline(always)]

crates/tinywasm/src/runtime/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ mod stack;
33

44
mod raw;
55

6-
#[cfg(all(nightly, feature = "simd"))]
6+
#[cfg(all(not(nightly), feature = "simd"))]
7+
compile_error!("`simd` feature requires nightly");
8+
9+
#[cfg(feature = "simd")]
710
mod raw_simd;
811

912
use crate::Result;

crates/tinywasm/src/runtime/stack/block_stack.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,16 @@ pub(crate) struct BlockFrame {
5656
pub(crate) end_instr_offset: u32, // position of the end instruction of the block
5757

5858
pub(crate) stack_ptr: u32, // position of the stack pointer when the block was entered
59+
pub(crate) results: u8,
60+
pub(crate) params: u8,
5961

60-
#[cfg(all(nightly, feature = "simd"))]
62+
#[cfg(feature = "simd")]
6163
pub(crate) simd_stack_ptr: u32, // position of the large stack pointer when the block was entered
64+
#[cfg(feature = "simd")]
65+
pub(crate) simd_results: u8,
66+
#[cfg(feature = "simd")]
67+
pub(crate) simd_params: u8,
6268

63-
pub(crate) results: u8,
64-
pub(crate) params: u8,
6569
pub(crate) ty: BlockType,
6670
}
6771

crates/tinywasm/src/runtime/stack/call_stack.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,7 @@ impl CallFrame {
6262
pub(crate) fn fetch_instr(&self) -> &Instruction {
6363
match self.func_instance.instructions.get(self.instr_ptr) {
6464
Some(instr) => instr,
65-
None => {
66-
cold();
67-
panic!("Instruction pointer out of bounds");
68-
}
65+
None => unreachable!("Instruction pointer out of bounds"),
6966
}
7067
}
7168

@@ -87,7 +84,7 @@ impl CallFrame {
8784
self.instr_ptr = break_to.instr_ptr;
8885

8986
// We also want to push the params to the stack
90-
values.break_to(break_to.stack_ptr, break_to.params);
87+
values.break_to_params(&break_to);
9188

9289
// check if we're breaking to the loop
9390
if break_to_relative != 0 {
@@ -100,7 +97,7 @@ impl CallFrame {
10097
BlockType::Block | BlockType::If | BlockType::Else => {
10198
// this is a block, so we want to jump to the next instruction after the block ends
10299
// We also want to push the block's results to the stack
103-
values.break_to(break_to.stack_ptr, break_to.results);
100+
values.break_to_results(&break_to);
104101

105102
// (the inst_ptr will be incremented by 1 before the next instruction is executed)
106103
self.instr_ptr = break_to.instr_ptr + break_to.end_instr_offset as usize;

crates/tinywasm/src/runtime/stack/value_stack.rs

Lines changed: 71 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,18 @@ use crate::{cold, runtime::RawWasmValue, unlikely, Error, Result};
22
use alloc::vec::Vec;
33
use tinywasm_types::{ValType, WasmValue};
44

5+
use super::BlockFrame;
6+
57
pub(crate) const MIN_VALUE_STACK_SIZE: usize = 1024 * 128;
68

7-
#[cfg(all(nightly, feature = "simd"))]
9+
#[cfg(feature = "simd")]
810
pub(crate) const MIN_SIMD_VALUE_STACK_SIZE: usize = 1024 * 32;
911

1012
#[derive(Debug)]
1113
pub(crate) struct ValueStack {
1214
stack: Vec<RawWasmValue>,
1315

14-
#[cfg(all(nightly, feature = "simd"))]
16+
#[cfg(feature = "simd")]
1517
simd_stack: Vec<RawSimdWasmValue>,
1618
}
1719

@@ -20,7 +22,7 @@ impl Default for ValueStack {
2022
Self {
2123
stack: Vec::with_capacity(MIN_VALUE_STACK_SIZE),
2224

23-
#[cfg(all(nightly, feature = "simd"))]
25+
#[cfg(feature = "simd")]
2426
simd_stack: Vec::with_capacity(MIN_SIMD_VALUE_STACK_SIZE),
2527
}
2628
}
@@ -29,7 +31,16 @@ impl Default for ValueStack {
2931
impl ValueStack {
3032
#[inline]
3133
pub(crate) fn extend_from_typed(&mut self, values: &[WasmValue]) {
34+
#[cfg(not(feature = "simd"))]
3235
self.stack.extend(values.iter().map(|v| RawWasmValue::from(*v)));
36+
37+
#[cfg(feature = "simd")]
38+
{
39+
values.iter().for_each(|v| match v {
40+
WasmValue::V128(v) => self.simd_stack.push(*v),
41+
v => self.stack.push(RawWasmValue::from(*v)),
42+
});
43+
}
3344
}
3445

3546
#[inline(always)]
@@ -65,18 +76,13 @@ impl ValueStack {
6576

6677
#[inline]
6778
pub(crate) fn truncate_keep(&mut self, n: u32, end_keep: u32) {
68-
let total_to_keep = n + end_keep;
69-
let len = self.stack.len() as u32;
70-
assert!(len >= total_to_keep, "RawWasmValueotal to keep should be less than or equal to self.top");
71-
72-
if len <= total_to_keep {
73-
return; // No need to truncate if the current size is already less than or equal to total_to_keep
74-
}
79+
truncate_keep(&mut self.stack, n, end_keep);
80+
}
7581

76-
let items_to_remove = len - total_to_keep;
77-
let remove_start_index = (len - items_to_remove - end_keep) as usize;
78-
let remove_end_index = (len - end_keep) as usize;
79-
self.stack.drain(remove_start_index..remove_end_index);
82+
#[cfg(feature = "simd")]
83+
#[inline]
84+
pub(crate) fn truncate_keep_simd(&mut self, n: u32, end_keep: u32) {
85+
truncate_keep(&mut self.simd_stack, n, end_keep);
8086
}
8187

8288
#[inline(always)]
@@ -124,14 +130,44 @@ impl ValueStack {
124130

125131
#[inline]
126132
pub(crate) fn pop_params(&mut self, types: &[ValType]) -> Result<Vec<WasmValue>> {
127-
Ok(self.pop_n_rev(types.len())?.zip(types.iter()).map(|(v, ty)| v.attach_type(*ty)).collect())
133+
#[cfg(not(feature = "simd"))]
134+
return Ok(self.pop_n_rev(types.len())?.zip(types.iter()).map(|(v, ty)| v.attach_type(*ty)).collect());
135+
136+
#[cfg(feature = "simd")]
137+
{
138+
let mut values = Vec::with_capacity(types.len());
139+
for ty in types {
140+
match ty {
141+
ValType::V128 => values.push(WasmValue::V128(self.simd_stack.pop().unwrap())),
142+
ty => values.push(self.pop()?.attach_type(*ty)),
143+
}
144+
}
145+
Ok(values)
146+
}
128147
}
129148

130149
#[inline]
131-
pub(crate) fn break_to(&mut self, new_stack_size: u32, result_count: u8) {
132-
let start = new_stack_size as usize;
133-
let end = self.stack.len() - result_count as usize;
134-
self.stack.drain(start..end);
150+
pub(crate) fn break_to_results(&mut self, bf: &BlockFrame) {
151+
let end = self.stack.len() - bf.results as usize;
152+
self.stack.drain(bf.stack_ptr as usize..end);
153+
154+
#[cfg(feature = "simd")]
155+
{
156+
let end = self.simd_stack.len() - bf.simd_results as usize;
157+
self.simd_stack.drain(bf.simd_stack_ptr as usize..end);
158+
}
159+
}
160+
161+
#[inline]
162+
pub(crate) fn break_to_params(&mut self, bf: &BlockFrame) {
163+
let end = self.stack.len() - bf.params as usize;
164+
self.stack.drain(bf.stack_ptr as usize..end);
165+
166+
#[cfg(feature = "simd")]
167+
{
168+
let end = self.simd_stack.len() - bf.simd_params as usize;
169+
self.simd_stack.drain(bf.simd_stack_ptr as usize..end);
170+
}
135171
}
136172

137173
#[inline]
@@ -152,6 +188,22 @@ impl ValueStack {
152188
}
153189
}
154190

191+
#[inline(always)]
192+
fn truncate_keep<T>(data: &mut Vec<T>, n: u32, end_keep: u32) {
193+
let total_to_keep = n + end_keep;
194+
let len = data.len() as u32;
195+
assert!(len >= total_to_keep, "RawWasmValueotal to keep should be less than or equal to self.top");
196+
197+
if len <= total_to_keep {
198+
return; // No need to truncate if the current size is already less than or equal to total_to_keep
199+
}
200+
201+
let items_to_remove = len - total_to_keep;
202+
let remove_start_index = (len - items_to_remove - end_keep) as usize;
203+
let remove_end_index = (len - end_keep) as usize;
204+
data.drain(remove_start_index..remove_end_index);
205+
}
206+
155207
#[cfg(test)]
156208
mod tests {
157209
use super::*;

crates/types/src/value.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub enum WasmValue {
1818
F64(f64),
1919
// /// A 128-bit vector
2020
V128(u128),
21+
2122
RefExtern(ExternAddr),
2223
RefFunc(FuncAddr),
2324
RefNull(ValType),

0 commit comments

Comments
 (0)