diff options
| author | Henry Gressmann <mail@henrygressmann.de> | 2024-05-26 00:29:33 +0200 |
|---|---|---|
| committer | Henry Gressmann <mail@henrygressmann.de> | 2024-05-26 00:29:33 +0200 |
| commit | 6853862b4c08e55d2d82498eb3cdbcfa151b5e71 (patch) | |
| tree | 12e7222f84fc007007bfe909ecdf8de7b908e6f3 | |
| parent | e2ae76cdc5f23c54da84a65ffddec566d6650a95 (diff) | |
chore: simplify interpreter
Signed-off-by: Henry Gressmann <mail@henrygressmann.de>
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/mod.rs | 46 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/mod.rs | 11 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/call_stack.rs | 21 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/mod.rs | 2 |
4 files changed, 31 insertions, 49 deletions
diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs index 1b57c17..9ba9388 100644 --- a/crates/tinywasm/src/runtime/interpreter/mod.rs +++ b/crates/tinywasm/src/runtime/interpreter/mod.rs @@ -23,8 +23,7 @@ use no_std_floats::NoStdFloatExt; impl InterpreterRuntime { pub(crate) fn exec(&self, store: &mut Store, stack: &mut Stack) -> Result<()> { - let mut executor = Executor::new(store, stack)?; - executor.run_to_completion() + Executor::new(store, stack)?.run_to_completion() } } @@ -36,16 +35,28 @@ struct Executor<'store, 'stack> { module: ModuleInstance, } +impl Iterator for Executor<'_, '_> { + type Item = Result<()>; + + fn next(&mut self) -> Option<Self::Item> { + match self.exec_next() { + Ok(ControlFlow::Continue(())) => Some(Ok(())), + Ok(ControlFlow::Break(())) => None, + Err(e) => Some(Err(e)), + } + } +} + impl<'store, 'stack> Executor<'store, 'stack> { pub(crate) fn new(store: &'store mut Store, stack: &'stack mut Stack) -> Result<Self> { - let current_frame = stack.call_stack.pop()?; + let current_frame = stack.call_stack.pop().ok_or_else(|| Error::CallStackUnderflow)?; let current_module = store.get_module_instance_raw(current_frame.module_addr); Ok(Self { cf: current_frame, module: current_module, stack, store }) } pub(crate) fn run_to_completion(&mut self) -> Result<()> { loop { - match self.next()? { + match self.exec_next()? { ControlFlow::Break(..) => return Ok(()), ControlFlow::Continue(..) => continue, }; @@ -53,7 +64,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { } #[inline(always)] - pub(crate) fn next(&mut self) -> Result<ControlFlow<()>> { + pub(crate) fn exec_next(&mut self) -> Result<ControlFlow<()>> { use tinywasm_types::Instruction::*; match self.cf.fetch_instr() { Nop => cold(), @@ -360,22 +371,17 @@ impl<'store, 'stack> Executor<'store, 'stack> { #[inline(always)] fn exec_return(&mut self) -> Result<ControlFlow<()>> { - // returning from the main function is a break - if self.stack.call_stack.is_empty() { - return Ok(ControlFlow::Break(())); - } - let old = self.cf.block_ptr; - self.cf = self.stack.call_stack.pop()?; + match self.stack.call_stack.pop() { + None => return Ok(ControlFlow::Break(())), + Some(cf) => self.cf = cf, + } if old > self.cf.block_ptr { self.stack.blocks.truncate(old); } - if self.cf.module_addr != self.module.id() { - self.module.swap_with(self.cf.module_addr, self.store); - } - + self.module.swap_with(self.cf.module_addr, self.store); Ok(ControlFlow::Continue(())) } @@ -390,7 +396,6 @@ impl<'store, 'stack> Executor<'store, 'stack> { self.stack.values.push(val.into()); } - #[allow(clippy::too_many_arguments)] #[inline(always)] fn exec_i32_store_local(&mut self, local: u32, const_i32: i32, offset: u32, mem_addr: u8) -> Result<()> { let mem = self.store.get_mem(self.module.resolve_mem_addr(mem_addr as u32))?; @@ -660,7 +665,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { return Ok(ControlFlow::Continue(())); } }; - return self.exec_call(wasm_func.clone(), func_inst.owner); + self.exec_call(wasm_func.clone(), func_inst.owner) } #[inline(always)] @@ -680,11 +685,10 @@ impl<'store, 'stack> Executor<'store, 'stack> { crate::Function::Wasm(f) => f, crate::Function::Host(host_func) => { if unlikely(host_func.ty != *call_ty) { - return Err(Trap::IndirectCallTypeMismatch { + return Err(Error::Trap(Trap::IndirectCallTypeMismatch { actual: host_func.ty.clone(), expected: call_ty.clone(), - } - .into()); + })); } let host_func = host_func.clone(); @@ -701,7 +705,7 @@ impl<'store, 'stack> Executor<'store, 'stack> { } cold(); - return Err(Trap::IndirectCallTypeMismatch { actual: wasm_func.ty.clone(), expected: call_ty.clone() }.into()); + Err(Trap::IndirectCallTypeMismatch { actual: wasm_func.ty.clone(), expected: call_ty.clone() }.into()) } #[inline(always)] diff --git a/crates/tinywasm/src/runtime/mod.rs b/crates/tinywasm/src/runtime/mod.rs index 6c8a553..dc4816b 100644 --- a/crates/tinywasm/src/runtime/mod.rs +++ b/crates/tinywasm/src/runtime/mod.rs @@ -9,21 +9,10 @@ compile_error!("`simd` feature requires nightly"); #[cfg(feature = "simd")] mod raw_simd; -use crate::Result; - pub use raw::RawWasmValue; pub(crate) use stack::CallFrame; pub(crate) use stack::Stack; -#[allow(rustdoc::private_intra_doc_links)] -/// A WebAssembly runtime. -/// -/// See <https://webassembly.github.io/spec/core/exec/runtime.html> -pub trait Runtime { - /// Execute all call-frames on the stack until the stack is empty. - fn exec(&self, store: &mut crate::Store, stack: &mut Stack) -> Result<()>; -} - /// The main TinyWasm runtime. /// /// This is the default runtime used by TinyWasm. diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index b7360a0..93f2c03 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -1,6 +1,6 @@ use crate::runtime::RawWasmValue; -use crate::{cold, unlikely}; -use crate::{Error, Result, Trap}; +use crate::unlikely; +use crate::{Result, Trap}; use alloc::{boxed::Box, rc::Rc, vec::Vec}; use tinywasm_types::{Instruction, LocalAddr, ModuleInstanceAddr, WasmFunction}; @@ -22,25 +22,14 @@ impl CallStack { Self { stack } } - #[inline] - pub(crate) fn is_empty(&self) -> bool { - self.stack.is_empty() - } - #[inline(always)] - pub(crate) fn pop(&mut self) -> Result<CallFrame> { - match self.stack.pop() { - Some(frame) => Ok(frame), - None => { - cold(); - Err(Error::CallStackUnderflow) - } - } + pub(crate) fn pop(&mut self) -> Option<CallFrame> { + self.stack.pop() } #[inline(always)] pub(crate) fn push(&mut self, call_frame: CallFrame) -> Result<()> { - if unlikely(self.stack.len() >= self.stack.capacity()) { + if unlikely((self.stack.len() + 1) >= CALL_STACK_SIZE) { return Err(Trap::CallStackOverflow.into()); } self.stack.push(call_frame); diff --git a/crates/tinywasm/src/runtime/stack/mod.rs b/crates/tinywasm/src/runtime/stack/mod.rs index 052a67c..c9cc048 100644 --- a/crates/tinywasm/src/runtime/stack/mod.rs +++ b/crates/tinywasm/src/runtime/stack/mod.rs @@ -8,7 +8,7 @@ pub(crate) use value_stack::ValueStack; /// A WebAssembly Stack #[derive(Debug)] -pub struct Stack { +pub(crate) struct Stack { pub(crate) values: ValueStack, pub(crate) blocks: BlockStack, pub(crate) call_stack: CallStack, |
