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

Commit 2bcf333

Browse files
chore: improve breaking
Signed-off-by: Henry Gressmann <[email protected]>
1 parent 6c2c6b2 commit 2bcf333

File tree

2 files changed

+85
-87
lines changed

2 files changed

+85
-87
lines changed

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

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,7 @@
1212
macro_rules! break_to {
1313
($break_to_relative:expr, $self:expr) => {{
1414
if $self.cf.break_to($break_to_relative, &mut $self.stack.values, &mut $self.stack.blocks).is_none() {
15-
if $self.stack.call_stack.is_empty() {
16-
return Ok(ExecResult::Return);
17-
}
18-
19-
return $self.process_call();
15+
return $self.exec_return();
2016
}
2117
}};
2218
}
@@ -199,15 +195,6 @@ macro_rules! checked_int_arithmetic {
199195
};
200196
}
201197

202-
macro_rules! skip {
203-
($code:expr) => {
204-
match $code {
205-
Ok(_) => return Ok(ExecResult::Continue),
206-
Err(e) => return Err(e),
207-
}
208-
};
209-
}
210-
211198
pub(super) use arithmetic;
212199
pub(super) use arithmetic_single;
213200
pub(super) use break_to;
@@ -219,4 +206,3 @@ pub(super) use conv;
219206
pub(super) use float_min_max;
220207
pub(super) use mem_load;
221208
pub(super) use mem_store;
222-
pub(super) use skip;

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

Lines changed: 84 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use alloc::format;
22
use alloc::string::ToString;
33
use core::ops::{BitAnd, BitOr, BitXor, Neg};
4-
use tinywasm_types::{BlockArgs, ElementKind, ValType};
4+
use tinywasm_types::{BlockArgs, ElementKind, Instruction, ValType};
55

66
use super::{InterpreterRuntime, RawWasmValue, Stack};
77
use crate::runtime::{BlockFrame, BlockType, CallFrame};
@@ -48,84 +48,43 @@ impl<'store, 'stack> Executor<'store, 'stack> {
4848

4949
pub(crate) fn run_to_completion(&mut self) -> Result<()> {
5050
loop {
51-
match self.exec_one()? {
52-
ExecResult::Return => return Ok(()),
53-
ExecResult::Continue => continue,
51+
match self.next() {
52+
Ok(ExecResult::Return) => return Ok(()),
53+
Ok(ExecResult::Continue) => continue,
54+
Err(e) => {
55+
cold();
56+
return Err(e);
57+
}
5458
};
5559
}
5660
}
5761

58-
pub(crate) fn process_call(&mut self) -> Result<ExecResult> {
59-
let old = self.cf.block_ptr;
60-
self.cf = self.stack.call_stack.pop()?;
61-
62-
if old > self.cf.block_ptr {
63-
self.stack.blocks.truncate(old);
64-
}
65-
66-
if self.cf.module_addr != self.module.id() {
67-
self.module.swap_with(self.cf.module_addr, self.store);
68-
}
69-
70-
Ok(ExecResult::Continue)
71-
}
72-
73-
pub(crate) fn exec_one(&mut self) -> Result<ExecResult> {
62+
#[inline(always)]
63+
pub(crate) fn next(&mut self) -> Result<ExecResult> {
7464
use tinywasm_types::Instruction::*;
7565
match self.cf.fetch_instr() {
7666
Nop => cold(),
7767
Unreachable => self.exec_unreachable()?,
68+
7869
Drop => self.stack.values.pop().map(|_| ())?,
7970
Select(_valtype) => self.exec_select()?,
8071

81-
Call(v) => skip!(self.exec_call(*v)),
82-
CallIndirect(ty, table) => {
83-
skip!(self.exec_call_indirect(*ty, *table))
84-
}
85-
If(args, el, end) => skip!(self.exec_if((*args).into(), *el, *end)),
72+
Call(v) => return self.exec_call(*v),
73+
CallIndirect(ty, table) => return self.exec_call_indirect(*ty, *table),
74+
75+
If(args, el, end) => return self.exec_if((*args).into(), *el, *end),
76+
Else(end_offset) => self.exec_else(*end_offset)?,
8677
Loop(args, end) => self.enter_block(self.cf.instr_ptr, *end, BlockType::Loop, *args),
8778
Block(args, end) => self.enter_block(self.cf.instr_ptr, *end, BlockType::Block, *args),
88-
8979
Br(v) => break_to!(*v, self),
90-
BrIf(v) => {
91-
if i32::from(self.stack.values.pop()?) != 0 {
92-
break_to!(*v, self);
93-
}
94-
}
95-
BrTable(default, len) => {
96-
let start = self.cf.instr_ptr + 1;
97-
let end = start + *len as usize;
98-
if end > self.cf.instructions().len() {
99-
return Err(Error::Other(format!(
100-
"br_table out of bounds: {} >= {}",
101-
end,
102-
self.cf.instructions().len()
103-
)));
104-
}
105-
106-
let idx: i32 = self.stack.values.pop()?.into();
107-
match self.cf.instructions()[start..end].get(idx as usize) {
108-
None => break_to!(*default, self),
109-
Some(BrLabel(to)) => break_to!(*to, self),
110-
_ => return Err(Error::Other("br_table with invalid label".to_string())),
111-
}
112-
}
113-
114-
Return => match self.stack.call_stack.is_empty() {
115-
true => return Ok(ExecResult::Return),
116-
false => return self.process_call(),
117-
},
118-
119-
// We're essentially using else as a EndBlockFrame instruction for if blocks
120-
Else(end_offset) => self.exec_else(*end_offset)?,
121-
122-
// remove the label from the label stack
80+
BrIf(v) => return self.exec_br_if(*v),
81+
BrTable(default, len) => return self.exec_brtable(*default, *len),
82+
Return => return self.exec_return(),
12383
EndBlockFrame => self.exec_end_block()?,
12484

12585
LocalGet(local_index) => self.exec_local_get(*local_index),
12686
LocalSet(local_index) => self.exec_local_set(*local_index)?,
12787
LocalTee(local_index) => self.exec_local_tee(*local_index)?,
128-
12988
GlobalGet(global_index) => self.exec_global_get(*global_index)?,
13089
GlobalSet(global_index) => self.exec_global_set(*global_index)?,
13190

@@ -337,9 +296,10 @@ impl<'store, 'stack> Executor<'store, 'stack> {
337296
LocalGetSet(a, b) => self.exec_local_get_set(*a, *b),
338297
I64XorConstRotl(rotate_by) => self.exec_i64_xor_const_rotl(*rotate_by)?,
339298
I32LocalGetConstAdd(local, val) => self.exec_i32_local_get_const_add(*local, *val),
340-
I32StoreLocal { local, const_i32: consti32, offset, mem_addr } => {
341-
self.exec_i32_store_local(*local, *consti32, *offset, *mem_addr)?
299+
I32StoreLocal { local, const_i32, offset, mem_addr } => {
300+
self.exec_i32_store_local(*local, *const_i32, *offset, *mem_addr)?
342301
}
302+
343303
i => {
344304
cold();
345305
return Err(Error::UnsupportedFeature(format!("unimplemented instruction: {:?}", i)));
@@ -365,6 +325,57 @@ impl<'store, 'stack> Executor<'store, 'stack> {
365325
Ok(())
366326
}
367327

328+
#[inline(always)]
329+
fn exec_br_if(&mut self, to: u32) -> Result<ExecResult> {
330+
let val: i32 = self.stack.values.pop()?.into();
331+
if val != 0 {
332+
break_to!(to, self);
333+
}
334+
335+
self.cf.instr_ptr += 1;
336+
Ok(ExecResult::Continue)
337+
}
338+
339+
#[inline(always)]
340+
fn exec_brtable(&mut self, default: u32, len: u32) -> Result<ExecResult> {
341+
let start = self.cf.instr_ptr + 1;
342+
let end = start + len as usize;
343+
if end > self.cf.instructions().len() {
344+
return Err(Error::Other(format!("br_table out of bounds: {} >= {}", end, self.cf.instructions().len())));
345+
}
346+
347+
let idx: i32 = self.stack.values.pop()?.into();
348+
349+
match self.cf.instructions()[start..end].get(idx as usize) {
350+
None => break_to!(default, self),
351+
Some(Instruction::BrLabel(to)) => break_to!(*to, self),
352+
_ => return Err(Error::Other("br_table with invalid label".to_string())),
353+
}
354+
355+
self.cf.instr_ptr += 1;
356+
Ok(ExecResult::Continue)
357+
}
358+
359+
#[inline(always)]
360+
fn exec_return(&mut self) -> Result<ExecResult> {
361+
if self.stack.call_stack.is_empty() {
362+
return Ok(ExecResult::Return);
363+
}
364+
365+
let old = self.cf.block_ptr;
366+
self.cf = self.stack.call_stack.pop()?;
367+
368+
if old > self.cf.block_ptr {
369+
self.stack.blocks.truncate(old);
370+
}
371+
372+
if self.cf.module_addr != self.module.id() {
373+
self.module.swap_with(self.cf.module_addr, self.store);
374+
}
375+
376+
Ok(ExecResult::Continue)
377+
}
378+
368379
#[inline(always)]
369380
#[cold]
370381
fn exec_unreachable(&self) -> Result<()> {
@@ -598,7 +609,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
598609
}
599610

600611
#[inline(always)]
601-
fn exec_call(&mut self, v: u32) -> Result<()> {
612+
fn exec_call(&mut self, v: u32) -> Result<ExecResult> {
602613
let func_inst = self.store.get_func(self.module.resolve_func_addr(v))?;
603614
let wasm_func = match &func_inst.func {
604615
crate::Function::Wasm(wasm_func) => wasm_func,
@@ -608,7 +619,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
608619
let res = (func.func)(FuncContext { store: self.store, module_addr: self.module.id() }, &params)?;
609620
self.stack.values.extend_from_typed(&res);
610621
self.cf.instr_ptr += 1;
611-
return Ok(());
622+
return Ok(ExecResult::Continue);
612623
}
613624
};
614625

@@ -620,11 +631,11 @@ impl<'store, 'stack> Executor<'store, 'stack> {
620631
if self.cf.module_addr != self.module.id() {
621632
self.module.swap_with(self.cf.module_addr, self.store);
622633
}
623-
Ok(())
634+
Ok(ExecResult::Continue)
624635
}
625636

626637
#[inline(always)]
627-
fn exec_call_indirect(&mut self, type_addr: u32, table_addr: u32) -> Result<()> {
638+
fn exec_call_indirect(&mut self, type_addr: u32, table_addr: u32) -> Result<ExecResult> {
628639
let table = self.store.get_table(self.module.resolve_table_addr(table_addr))?;
629640
let table_idx: u32 = self.stack.values.pop()?.into();
630641

@@ -654,7 +665,7 @@ impl<'store, 'stack> Executor<'store, 'stack> {
654665
let res = (host_func.func)(FuncContext { store: self.store, module_addr: self.module.id() }, &params)?;
655666
self.stack.values.extend_from_typed(&res);
656667
self.cf.instr_ptr += 1;
657-
return Ok(());
668+
return Ok(ExecResult::Continue);
658669
}
659670
};
660671

@@ -672,29 +683,30 @@ impl<'store, 'stack> Executor<'store, 'stack> {
672683
if self.cf.module_addr != self.module.id() {
673684
self.module.swap_with(self.cf.module_addr, self.store);
674685
}
675-
Ok(())
686+
687+
Ok(ExecResult::Continue)
676688
}
677689

678690
#[inline(always)]
679-
fn exec_if(&mut self, args: BlockArgs, else_offset: u32, end_offset: u32) -> Result<()> {
691+
fn exec_if(&mut self, args: BlockArgs, else_offset: u32, end_offset: u32) -> Result<ExecResult> {
680692
// truthy value is on the top of the stack, so enter the then block
681693
if i32::from(self.stack.values.pop()?) != 0 {
682694
self.enter_block(self.cf.instr_ptr, end_offset, BlockType::If, args);
683695
self.cf.instr_ptr += 1;
684-
return Ok(());
696+
return Ok(ExecResult::Continue);
685697
}
686698

687699
// falsy value is on the top of the stack
688700
if else_offset == 0 {
689701
self.cf.instr_ptr += end_offset as usize + 1;
690-
return Ok(());
702+
return Ok(ExecResult::Continue);
691703
}
692704

693705
let old = self.cf.instr_ptr;
694706
self.cf.instr_ptr += else_offset as usize;
695707
self.enter_block(old + else_offset as usize, end_offset - else_offset, BlockType::Else, args);
696708
self.cf.instr_ptr += 1;
697-
Ok(())
709+
Ok(ExecResult::Continue)
698710
}
699711

700712
#[inline(always)]

0 commit comments

Comments
 (0)