diff options
| -rw-r--r-- | crates/tinywasm/src/func.rs | 7 | ||||
| -rw-r--r-- | crates/tinywasm/src/imports.rs | 12 | ||||
| -rw-r--r-- | crates/tinywasm/src/instance.rs | 8 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/executor.rs | 117 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/no_std_floats.rs | 20 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/num_helpers.rs | 7 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/stack/call_stack.rs | 114 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/stack/mod.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/stack/value_stack.rs | 126 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/value128.rs | 5 | ||||
| -rw-r--r-- | crates/tinywasm/src/interpreter/values.rs | 44 | ||||
| -rw-r--r-- | crates/tinywasm/src/store/memory.rs | 8 | ||||
| -rw-r--r-- | crates/tinywasm/src/store/mod.rs | 6 | ||||
| -rw-r--r-- | crates/types/src/instructions.rs | 24 | ||||
| -rw-r--r-- | crates/types/src/lib.rs | 37 | ||||
| -rw-r--r-- | crates/types/src/value.rs | 30 | ||||
| -rwxr-xr-x | examples/rust/build.sh | 4 |
17 files changed, 339 insertions, 232 deletions
diff --git a/crates/tinywasm/src/func.rs b/crates/tinywasm/src/func.rs index a741e0f..0e42dd7 100644 --- a/crates/tinywasm/src/func.rs +++ b/crates/tinywasm/src/func.rs @@ -56,11 +56,14 @@ impl FuncHandle { }; // 6. Let f be the dummy frame - let callframe = CallFrame::new_with_params(wasm_func.locals, self.addr, func_inst.owner, params); - // 7. Push the frame f to the call stack // & 8. Push the values to the stack store.stack.clear(); + store.stack.values.extend_from_wasmvalues(params)?; + let (locals_base, _stack_base, stack_offset) = + store.stack.values.enter_locals(wasm_func.params, wasm_func.locals)?; + let callframe = CallFrame::new(self.addr, func_inst.owner, locals_base, stack_offset); + // 9. Invoke the function instance InterpreterRuntime::exec(store, callframe)?; diff --git a/crates/tinywasm/src/imports.rs b/crates/tinywasm/src/imports.rs index 099396b..ea8b965 100644 --- a/crates/tinywasm/src/imports.rs +++ b/crates/tinywasm/src/imports.rs @@ -122,17 +122,17 @@ pub enum Extern { impl Extern { /// Create a new global import - pub fn global(val: WasmValue, mutable: bool) -> Self { + pub const fn global(val: WasmValue, mutable: bool) -> Self { Self::Global { ty: GlobalType { ty: val.val_type(), mutable }, val } } /// Create a new table import - pub fn table(ty: TableType, init: WasmValue) -> Self { + pub const fn table(ty: TableType, init: WasmValue) -> Self { Self::Table { ty, init } } /// Create a new memory import - pub fn memory(ty: MemoryType) -> Self { + pub const fn memory(ty: MemoryType) -> Self { Self::Memory { ty } } @@ -180,7 +180,7 @@ impl Extern { } /// Get the kind of the external value - pub fn kind(&self) -> ExternalKind { + pub const fn kind(&self) -> ExternalKind { match self { Self::Global { .. } => ExternalKind::Global, Self::Table { .. } => ExternalKind::Table, @@ -257,14 +257,14 @@ pub(crate) struct ResolvedImports { } impl ResolvedImports { - pub(crate) fn new() -> Self { + pub(crate) const fn new() -> Self { Self { globals: Vec::new(), tables: Vec::new(), memories: Vec::new(), funcs: Vec::new() } } } impl Imports { /// Create a new empty import set - pub fn new() -> Self { + pub const fn new() -> Self { Self { values: BTreeMap::new(), modules: BTreeMap::new() } } diff --git a/crates/tinywasm/src/instance.rs b/crates/tinywasm/src/instance.rs index 45542f9..340bfd6 100644 --- a/crates/tinywasm/src/instance.rs +++ b/crates/tinywasm/src/instance.rs @@ -36,6 +36,7 @@ pub(crate) struct ModuleInstanceInner { } impl ModuleInstanceInner { + #[inline] pub(crate) fn func_ty(&self, addr: FuncAddr) -> &FuncType { match self.types.get(addr as usize) { Some(ty) => ty, @@ -43,11 +44,13 @@ impl ModuleInstanceInner { } } + #[inline] pub(crate) fn func_addrs(&self) -> &[FuncAddr] { &self.func_addrs } // resolve a function address to the global store address + #[inline] pub(crate) fn resolve_func_addr(&self, addr: FuncAddr) -> FuncAddr { match self.func_addrs.get(addr as usize) { Some(addr) => *addr, @@ -56,6 +59,7 @@ impl ModuleInstanceInner { } // resolve a table address to the global store address + #[inline] pub(crate) fn resolve_table_addr(&self, addr: TableAddr) -> TableAddr { match self.table_addrs.get(addr as usize) { Some(addr) => *addr, @@ -64,6 +68,7 @@ impl ModuleInstanceInner { } // resolve a memory address to the global store address + #[inline] pub(crate) fn resolve_mem_addr(&self, addr: MemAddr) -> MemAddr { match self.mem_addrs.get(addr as usize) { Some(addr) => *addr, @@ -72,6 +77,7 @@ impl ModuleInstanceInner { } // resolve a data address to the global store address + #[inline] pub(crate) fn resolve_data_addr(&self, addr: DataAddr) -> DataAddr { match self.data_addrs.get(addr as usize) { Some(addr) => *addr, @@ -80,6 +86,7 @@ impl ModuleInstanceInner { } // resolve a memory address to the global store address + #[inline] pub(crate) fn resolve_elem_addr(&self, addr: ElemAddr) -> ElemAddr { match self.elem_addrs.get(addr as usize) { Some(addr) => *addr, @@ -88,6 +95,7 @@ impl ModuleInstanceInner { } // resolve a global address to the global store address + #[inline] pub(crate) fn resolve_global_addr(&self, addr: GlobalAddr) -> GlobalAddr { match self.global_addrs.get(addr as usize) { Some(addr) => *addr, diff --git a/crates/tinywasm/src/interpreter/executor.rs b/crates/tinywasm/src/interpreter/executor.rs index bf76e84..d5e6fea 100644 --- a/crates/tinywasm/src/interpreter/executor.rs +++ b/crates/tinywasm/src/interpreter/executor.rs @@ -114,36 +114,36 @@ impl<'store> Executor<'store> { return ControlFlow::Continue(()); } DropKeepSmall { base32, keep32, base64, keep64, base128, keep128, base_ref, keep_ref } => { - let b32 = self.cf.stack_base.s32 + *base32 as usize; + let b32 = self.cf.stack_base().s32 + *base32 as usize; let k32 = *keep32 as usize; self.store.stack.values.stack_32.truncate_keep(b32, k32); - let b64 = self.cf.stack_base.s64 + *base64 as usize; + let b64 = self.cf.stack_base().s64 + *base64 as usize; let k64 = *keep64 as usize; self.store.stack.values.stack_64.truncate_keep(b64, k64); - let b128 = self.cf.stack_base.s128 + *base128 as usize; + let b128 = self.cf.stack_base().s128 + *base128 as usize; let k128 = *keep128 as usize; self.store.stack.values.stack_128.truncate_keep(b128, k128); - let bref = self.cf.stack_base.sref + *base_ref as usize; + let bref = self.cf.stack_base().sref + *base_ref as usize; let kref = *keep_ref as usize; self.store.stack.values.stack_ref.truncate_keep(bref, kref); } DropKeep32(base, keep) => { - let b = self.cf.stack_base.s32 + *base as usize; + let b = self.cf.stack_base().s32 + *base as usize; let k = *keep as usize; self.store.stack.values.stack_32.truncate_keep(b, k); } DropKeep64(base, keep) => { - let b = self.cf.stack_base.s64 + *base as usize; + let b = self.cf.stack_base().s64 + *base as usize; let k = *keep as usize; self.store.stack.values.stack_64.truncate_keep(b, k); } DropKeep128(base, keep) => { - let b = self.cf.stack_base.s128 + *base as usize; + let b = self.cf.stack_base().s128 + *base as usize; let k = *keep as usize; self.store.stack.values.stack_128.truncate_keep(b, k); } DropKeepRef(base, keep) => { - let b = self.cf.stack_base.sref + *base as usize; + let b = self.cf.stack_base().sref + *base as usize; let k = *keep as usize; self.store.stack.values.stack_ref.truncate_keep(b, k); } @@ -163,22 +163,58 @@ impl<'store> Executor<'store> { return ControlFlow::Continue(()); } Return => return self.exec_return(), - LocalGet32(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value32>(*local_index)).to_cf()?, - LocalGet64(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value64>(*local_index)).to_cf()?, - LocalGet128(local_index) => self.store.stack.values.push(self.cf.locals.get::<Value128>(*local_index)).to_cf()?, - LocalGetRef(local_index) => self.store.stack.values.push(self.cf.locals.get::<ValueRef>(*local_index)).to_cf()?, - LocalSet32(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value32>()), - LocalSet64(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value64>()), - LocalSet128(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<Value128>()), - LocalSetRef(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.pop::<ValueRef>()), - LocalCopy32(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value32>(*from)), - LocalCopy64(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value64>(*from)), - LocalCopy128(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<Value128>(*from)), - LocalCopyRef(from, to) => self.cf.locals.set(*to, self.cf.locals.get::<ValueRef>(*from)), - LocalTee32(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value32>()), - LocalTee64(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value64>()), - LocalTee128(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<Value128>()), - LocalTeeRef(local_index) => self.cf.locals.set(*local_index, self.store.stack.values.peek::<ValueRef>()), + LocalGet32(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_32(&self.cf, *local_index)).to_cf()?, + LocalGet64(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_64(&self.cf, *local_index)).to_cf()?, + LocalGet128(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_128(&self.cf, *local_index)).to_cf()?, + LocalGetRef(local_index) => self.store.stack.values.push(self.store.stack.values.local_get_ref(&self.cf, *local_index)).to_cf()?, + LocalSet32(local_index) => { + let val = self.store.stack.values.pop::<Value32>(); + self.store.stack.values.local_set_32(&self.cf, *local_index, val); + } + LocalSet64(local_index) => { + let val = self.store.stack.values.pop::<Value64>(); + self.store.stack.values.local_set_64(&self.cf, *local_index, val); + } + LocalSet128(local_index) => { + let val = self.store.stack.values.pop::<Value128>(); + self.store.stack.values.local_set_128(&self.cf, *local_index, val); + } + LocalSetRef(local_index) => { + let val = self.store.stack.values.pop::<ValueRef>(); + self.store.stack.values.local_set_ref(&self.cf, *local_index, val); + } + LocalCopy32(from, to) => { + let val = self.store.stack.values.local_get_32(&self.cf, *from); + self.store.stack.values.local_set_32(&self.cf, *to, val); + } + LocalCopy64(from, to) => { + let val = self.store.stack.values.local_get_64(&self.cf, *from); + self.store.stack.values.local_set_64(&self.cf, *to, val); + } + LocalCopy128(from, to) => { + let val = self.store.stack.values.local_get_128(&self.cf, *from); + self.store.stack.values.local_set_128(&self.cf, *to, val); + } + LocalCopyRef(from, to) => { + let val = self.store.stack.values.local_get_ref(&self.cf, *from); + self.store.stack.values.local_set_ref(&self.cf, *to, val); + } + LocalTee32(local_index) => { + let val = self.store.stack.values.peek::<Value32>(); + self.store.stack.values.local_set_32(&self.cf, *local_index, val); + } + LocalTee64(local_index) => { + let val = self.store.stack.values.peek::<Value64>(); + self.store.stack.values.local_set_64(&self.cf, *local_index, val); + } + LocalTee128(local_index) => { + let val = self.store.stack.values.peek::<Value128>(); + self.store.stack.values.local_set_128(&self.cf, *local_index, val); + } + LocalTeeRef(local_index) => { + let val = self.store.stack.values.peek::<ValueRef>(); + self.store.stack.values.local_set_ref(&self.cf, *local_index, val); + } GlobalGet(global_index) => self.exec_global_get(*global_index).to_cf()?, GlobalSet32(global_index) => self.exec_global_set::<Value32>(*global_index), GlobalSet64(global_index) => self.exec_global_set::<Value64>(*global_index), @@ -627,20 +663,35 @@ impl<'store> Executor<'store> { func_addr: FuncAddr, owner: ModuleInstanceAddr, ) -> ControlFlow<Option<Error>> { + if !IS_RETURN_CALL && self.store.stack.call_stack.is_full() { + return ControlFlow::Break(Some(Trap::CallStackOverflow.into())); + } + if !Rc::ptr_eq(&self.func, &wasm_func) { self.func = wasm_func.clone(); } if IS_RETURN_CALL { - let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals); - let stack_base = self.store.stack.values.height(); - self.cf.reuse_for(func_addr, locals, owner, stack_base); + self.store.stack.values.truncate_keep_counts(self.cf.locals_base, wasm_func.params); + } + + let (locals_base, _stack_base, stack_offset) = + match self.store.stack.values.enter_locals(wasm_func.params, wasm_func.locals) { + Ok(v) => v, + Err(Error::Trap(Trap::ValueStackOverflow)) if !IS_RETURN_CALL => { + return ControlFlow::Break(Some(Trap::CallStackOverflow.into())); + } + Err(err) => return ControlFlow::Break(Some(err)), + }; + + let new_call_frame = CallFrame::new(func_addr, owner, locals_base, stack_offset); + + if IS_RETURN_CALL { + self.cf = new_call_frame; } else { - let locals = self.store.stack.values.pop_locals(wasm_func.params, wasm_func.locals); - let stack_base = self.store.stack.values.height(); - let new_call_frame = CallFrame::new(func_addr, owner, locals, stack_base); self.cf.incr_instr_ptr(); // skip the call instruction - self.store.stack.call_stack.push(core::mem::replace(&mut self.cf, new_call_frame)).to_cf()?; + self.store.stack.call_stack.push(self.cf).to_cf()?; + self.cf = new_call_frame; } if self.cf.module_addr != self.module.idx { @@ -709,6 +760,9 @@ impl<'store> Executor<'store> { } fn exec_return(&mut self) -> ControlFlow<Option<Error>> { + let result_counts = ValueCountsSmall::from(self.func.ty.results.iter()); + self.store.stack.values.truncate_keep_counts(self.cf.locals_base, result_counts); + let Some(cf) = self.store.stack.call_stack.pop() else { return ControlFlow::Break(None) }; if cf.func_addr != self.cf.func_addr { @@ -718,7 +772,6 @@ impl<'store> Executor<'store> { self.module = self.store.get_module_instance_raw(cf.module_addr).clone(); } } - self.cf = cf; ControlFlow::Continue(()) } diff --git a/crates/tinywasm/src/interpreter/no_std_floats.rs b/crates/tinywasm/src/interpreter/no_std_floats.rs index 0698f5d..b6ce998 100644 --- a/crates/tinywasm/src/interpreter/no_std_floats.rs +++ b/crates/tinywasm/src/interpreter/no_std_floats.rs @@ -9,18 +9,18 @@ pub(super) trait NoStdFloatExt { #[rustfmt::skip] impl NoStdFloatExt for f64 { - fn round(self) -> Self { libm::round(self) } - fn ceil(self) -> Self { libm::ceil(self) } - fn floor(self) -> Self { libm::floor(self) } - fn trunc(self) -> Self { libm::trunc(self) } - fn sqrt(self) -> Self { libm::sqrt(self) } + #[inline] fn round(self) -> Self { libm::round(self) } + #[inline] fn ceil(self) -> Self { libm::ceil(self) } + #[inline] fn floor(self) -> Self { libm::floor(self) } + #[inline] fn trunc(self) -> Self { libm::trunc(self) } + #[inline] fn sqrt(self) -> Self { libm::sqrt(self) } } #[rustfmt::skip] impl NoStdFloatExt for f32 { - fn round(self) -> Self { libm::roundf(self) } - fn ceil(self) -> Self { libm::ceilf(self) } - fn floor(self) -> Self { libm::floorf(self) } - fn trunc(self) -> Self { libm::truncf(self) } - fn sqrt(self) -> Self { libm::sqrtf(self) } + #[inline] fn round(self) -> Self { libm::roundf(self) } + #[inline] fn ceil(self) -> Self { libm::ceilf(self) } + #[inline] fn floor(self) -> Self { libm::floorf(self) } + #[inline] fn trunc(self) -> Self { libm::truncf(self) } + #[inline] fn sqrt(self) -> Self { libm::sqrtf(self) } } diff --git a/crates/tinywasm/src/interpreter/num_helpers.rs b/crates/tinywasm/src/interpreter/num_helpers.rs index f2b617d..f800575 100644 --- a/crates/tinywasm/src/interpreter/num_helpers.rs +++ b/crates/tinywasm/src/interpreter/num_helpers.rs @@ -70,6 +70,7 @@ macro_rules! impl_wasm_float_ops { ($($t:ty)*) => ($( impl TinywasmFloatExt for $t { // https://webassembly.github.io/spec/core/exec/numerics.html#op-fnearest + #[inline] fn tw_nearest(self) -> Self { match self { #[cfg(not(feature = "canonicalize_nans"))] @@ -94,6 +95,7 @@ macro_rules! impl_wasm_float_ops { // https://webassembly.github.io/spec/core/exec/numerics.html#op-fmin // Based on f32::minimum (which is not yet stable) + #[inline] fn tw_minimum(self, other: Self) -> Self { match self.partial_cmp(&other) { Some(core::cmp::Ordering::Less) => self, @@ -108,6 +110,7 @@ macro_rules! impl_wasm_float_ops { // https://webassembly.github.io/spec/core/exec/numerics.html#op-fmax // Based on f32::maximum (which is not yet stable) + #[inline] fn tw_maximum(self, other: Self) -> Self { match self.partial_cmp(&other) { Some(core::cmp::Ordering::Greater) => self, @@ -135,18 +138,22 @@ pub(crate) trait WasmIntOps { macro_rules! impl_wrapping_self_sh { ($($t:ty)*) => ($( impl WasmIntOps for $t { + #[inline] fn wasm_shl(self, rhs: Self) -> Self { self.wrapping_shl(rhs as u32) } + #[inline] fn wasm_shr(self, rhs: Self) -> Self { self.wrapping_shr(rhs as u32) } + #[inline] fn wasm_rotl(self, rhs: Self) -> Self { self.rotate_left(rhs as u32) } + #[inline] fn wasm_rotr(self, rhs: Self) -> Self { self.rotate_right(rhs as u32) } diff --git a/crates/tinywasm/src/interpreter/stack/call_stack.rs b/crates/tinywasm/src/interpreter/stack/call_stack.rs index fc2e1fc..2409d88 100644 --- a/crates/tinywasm/src/interpreter/stack/call_stack.rs +++ b/crates/tinywasm/src/interpreter/stack/call_stack.rs @@ -1,45 +1,56 @@ -use crate::interpreter::{Value128, values::*}; use crate::{Result, Trap, unlikely}; -use alloc::boxed::Box; use alloc::vec::Vec; -use tinywasm_types::{FuncAddr, LocalAddr, ModuleInstanceAddr, ValueCounts, WasmValue}; +use tinywasm_types::{FuncAddr, ModuleInstanceAddr, ValueCountsSmall}; #[derive(Debug)] pub(crate) struct CallStack { stack: Vec<CallFrame>, + len: usize, } impl CallStack { pub(crate) fn new(config: &crate::engine::Config) -> Self { - Self { stack: Vec::with_capacity(config.call_stack_size) } + let mut stack = Vec::with_capacity(config.call_stack_size); + stack.resize_with(config.call_stack_size, CallFrame::default); + Self { stack, len: 0 } } pub(crate) fn clear(&mut self) { - self.stack.clear(); + self.len = 0; } pub(crate) fn pop(&mut self) -> Option<CallFrame> { - self.stack.pop() + if self.len == 0 { + return None; + } + + self.len -= 1; + Some(self.stack[self.len]) + } + + pub(crate) fn is_full(&self) -> bool { + self.len >= self.stack.len() } pub(crate) fn push(&mut self, call_frame: CallFrame) -> Result<()> { - if unlikely(self.stack.len() >= self.stack.capacity()) { + if unlikely(self.is_full()) { return Err(Trap::CallStackOverflow.into()); } - self.stack.push(call_frame); + self.stack[self.len] = call_frame; + self.len += 1; Ok(()) } } -#[derive(Debug)] +#[derive(Debug, Clone, Copy, Default)] pub(crate) struct CallFrame { pub(crate) instr_ptr: usize, - pub(crate) locals: Locals, pub(crate) module_addr: ModuleInstanceAddr, pub(crate) func_addr: FuncAddr, - pub(crate) stack_base: StackBase, + pub(crate) locals_base: StackBase, + pub(crate) stack_offset: ValueCountsSmall, } #[derive(Debug, Clone, Copy, Default)] @@ -50,86 +61,27 @@ pub(crate) struct StackBase { pub(crate) sref: usize, } -#[derive(Debug)] -pub(crate) struct Locals { - pub(crate) locals_32: Box<[Value32]>, - pub(crate) locals_64: Box<[Value64]>, - pub(crate) locals_128: Box<[Value128]>, - pub(crate) locals_ref: Box<[ValueRef]>, -} - -impl Locals { - pub(crate) fn get<T: InternalValue>(&self, local_index: LocalAddr) -> T { - T::local_get(self, local_index) - } - - pub(crate) fn set<T: InternalValue>(&mut self, local_index: LocalAddr, value: T) { - T::local_set(self, local_index, value); - } -} - impl CallFrame { pub(crate) fn new( func_addr: FuncAddr, module_addr: ModuleInstanceAddr, - locals: Locals, - stack_base: StackBase, + locals_base: StackBase, + stack_offset: ValueCountsSmall, ) -> Self { - Self { instr_ptr: 0, func_addr, module_addr, locals, stack_base } + Self { instr_ptr: 0, func_addr, module_addr, locals_base, stack_offset } } - pub(crate) fn new_with_params( - local_count: ValueCounts, - func_addr: FuncAddr, - module_addr: ModuleInstanceAddr, - params: &[WasmValue], - ) -> Self { - let locals = { - let mut locals_32 = Vec::with_capacity(local_count.c32 as usize); - let mut locals_64 = Vec::with_capacity(local_count.c64 as usize); - let mut locals_128 = Vec::with_capacity(local_count.c128 as usize); - let mut locals_ref = Vec::with_capacity(local_count.cref as usize); - - for p in params { - match p.into() { - TinyWasmValue::Value32(v) => locals_32.push(v), - TinyWasmValue::Value64(v) => locals_64.push(v), - TinyWasmValue::Value128(v) => locals_128.push(v), - TinyWasmValue::ValueRef(v) => locals_ref.push(v), - } - } - - locals_32.resize_with(local_count.c32 as usize, Default::default); - locals_64.resize_with(local_count.c64 as usize, Default::default); - locals_128.resize_with(local_count.c128 as usize, Default::default); - locals_ref.resize_with(local_count.cref as usize, Default::default); - - Locals { - locals_32: locals_32.into_boxed_slice(), - locals_64: locals_64.into_boxed_slice(), - locals_128: locals_128.into_boxed_slice(), - locals_ref: locals_ref.into_boxed_slice(), - } - }; - - Self::new(func_addr, module_addr, locals, StackBase::default()) + #[inline] + pub(crate) fn stack_base(&self) -> StackBase { + StackBase { + s32: self.locals_base.s32 + self.stack_offset.c32 as usize, + s64: self.locals_base.s64 + self.stack_offset.c64 as usize, + s128: self.locals_base.s128 + self.stack_offset.c128 as usize, + sref: self.locals_base.sref + self.stack_offset.cref as usize, + } } pub(crate) fn incr_instr_ptr(&mut self) { self.instr_ptr += 1; } - - pub(crate) fn reuse_for( - &mut self, - func_addr: FuncAddr, - locals: Locals, - module_addr: ModuleInstanceAddr, - stack_base: StackBase, - ) { - self.func_addr = func_addr; - self.module_addr = module_addr; - self.locals = locals; - self.stack_base = stack_base; - self.instr_ptr = 0; - } } diff --git a/crates/tinywasm/src/interpreter/stack/mod.rs b/crates/tinywasm/src/interpreter/stack/mod.rs index 5912de1..59456d3 100644 --- a/crates/tinywasm/src/interpreter/stack/mod.rs +++ b/crates/tinywasm/src/interpreter/stack/mod.rs @@ -1,7 +1,7 @@ mod call_stack; mod value_stack; -pub(crate) use call_stack::{CallFrame, CallStack, Locals, StackBase}; +pub(crate) use call_stack::{CallFrame, CallStack, StackBase}; pub(crate) use value_stack::ValueStack; use crate::engine::Config; diff --git a/crates/tinywasm/src/interpreter/stack/value_stack.rs b/crates/tinywasm/src/interpreter/stack/value_stack.rs index 47672d7..be79912 100644 --- a/crates/tinywasm/src/interpreter/stack/value_stack.rs +++ b/crates/tinywasm/src/interpreter/stack/value_stack.rs @@ -1,10 +1,10 @@ use alloc::boxed::Box; use alloc::vec::Vec; -use tinywasm_types::{ExternRef, FuncRef, ValType, ValueCounts, ValueCountsSmall, WasmValue}; +use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValType, ValueCounts, ValueCountsSmall, WasmValue}; use crate::{Result, Trap, engine::Config, interpreter::*}; -use super::{Locals, StackBase}; +use super::{CallFrame, StackBase}; #[derive(Debug)] pub(crate) struct ValueStack { @@ -68,6 +68,20 @@ impl<T: Copy + Default> Stack<T> { &mut self.data[self.len - 1] } + pub(crate) fn get(&self, index: usize) -> T { + match self.data.get(index) { + Some(v) => *v, + None => unreachable!("Stack index out of bounds, this is a bug"), + } + } + + pub(crate) fn set(&mut self, index: usize, value: T) { + match self.data.get_mut(index) { + Some(v) => *v = value, + None => unreachable!("Stack index out of bounds, this is a bug"), + } + } + pub(crate) fn truncate_keep(&mut self, n: usize, end_keep: usize) { if self.len <= n { return; @@ -85,20 +99,19 @@ impl<T: Copy + Default> Stack<T> { self.len = n + keep_tail; } - pub(crate) fn pop_to_locals(&mut self, param_count: usize, local_count: usize) -> Box<[T]> { - if local_count == 0 { - debug_assert!(param_count == 0, "param count exceeds local count"); - return Box::new([]); - } - - let mut locals = alloc::vec![T::default(); local_count].into_boxed_slice(); + pub(crate) fn enter_locals(&mut self, param_count: usize, local_count: usize) -> Result<(usize, usize)> { + debug_assert!(param_count <= local_count, "param count exceeds local count"); let start = self.len.checked_sub(param_count).unwrap_or_else(|| unreachable!("value stack underflow, this is a bug")); - debug_assert!(param_count <= local_count, "param count exceeds local count"); - locals[..param_count].copy_from_slice(&self.data[start..self.len]); - self.len = start; - locals + let end = start + local_count; + if end > self.data.len() { + return Err(Trap::ValueStackOverflow.into()); + } + + self.data[(start + param_count)..end].fill(T::default()); + self.len = end; + Ok((start, end)) } } @@ -123,15 +136,6 @@ impl ValueStack { self.stack_32.len() + self.stack_64.len() + self.stack_128.len() + self.stack_ref.len() } - pub(crate) fn height(&self) -> StackBase { - StackBase { - s32: self.stack_32.len(), - s64: self.stack_64.len(), - s128: self.stack_128.len(), - sref: self.stack_ref.len(), - } - } - pub(crate) fn peek<T: InternalValue>(&self) -> T { T::stack_peek(self) } @@ -206,13 +210,77 @@ impl ValueStack { val_types.into_iter().map(|val_type| self.pop_wasmvalue(*val_type)) } - pub(crate) fn pop_locals(&mut self, pc: ValueCountsSmall, lc: ValueCounts) -> Locals { - Locals { - locals_32: self.stack_32.pop_to_locals(pc.c32 as usize, lc.c32 as usize), - locals_64: self.stack_64.pop_to_locals(pc.c64 as usize, lc.c64 as usize), - locals_128: self.stack_128.pop_to_locals(pc.c128 as usize, lc.c128 as usize), - locals_ref: self.stack_ref.pop_to_locals(pc.cref as usize, lc.cref as usize), - } + pub(crate) fn enter_locals( + &mut self, + params: ValueCountsSmall, + locals: ValueCounts, + ) -> Result<(StackBase, StackBase, ValueCountsSmall)> { + let stack_offset = ValueCountsSmall { + c32: u16::try_from(locals.c32).unwrap_or_else(|_| unreachable!("local count exceeds u16")), + c64: u16::try_from(locals.c64).unwrap_or_else(|_| unreachable!("local count exceeds u16")), + c128: u16::try_from(locals.c128).unwrap_or_else(|_| unreachable!("local count exceeds u16")), + cref: u16::try_from(locals.cref).unwrap_or_else(|_| unreachable!("local count exceeds u16")), + }; + + let (locals_base32, stack_base32) = self.stack_32.enter_locals(params.c32 as usize, locals.c32 as usize)?; + let (locals_base64, stack_base64) = self.stack_64.enter_locals(params.c64 as usize, locals.c64 as usize)?; + let (locals_base128, stack_base128) = + self.stack_128.enter_locals(params.c128 as usize, locals.c128 as usize)?; + let (locals_baseref, stack_baseref) = + self.stack_ref.enter_locals(params.cref as usize, locals.cref as usize)?; + + Ok(( + StackBase { s32: locals_base32, s64: locals_base64, s128: locals_base128, sref: locals_baseref }, + StackBase { s32: stack_base32, s64: stack_base64, s128: stack_base128, sref: stack_baseref }, + stack_offset, + )) + } + + pub(crate) fn truncate_keep_counts(&mut self, base: StackBase, keep: ValueCountsSmall) { + self.stack_32.truncate_keep(base.s32, keep.c32 as usize); + self.stack_64.truncate_keep(base.s64, keep.c64 as usize); + self.stack_128.truncate_keep(base.s128, keep.c128 as usize); + self.stack_ref.truncate_keep(base.sref, keep.cref as usize); + } + + #[inline] + pub(crate) fn local_get_32(&self, frame: &CallFrame, index: LocalAddr) -> Value32 { + self.stack_32.get(frame.locals_base.s32 + index as usize) + } + + #[inline] + pub(crate) fn local_get_64(&self, frame: &CallFrame, index: LocalAddr) -> Value64 { + self.stack_64.get(frame.locals_base.s64 + index as usize) + } + + #[inline] + pub(crate) fn local_get_128(&self, frame: &CallFrame, index: LocalAddr) -> Value128 { + self.stack_128.get(frame.locals_base.s128 + index as usize) + } + + #[inline] + pub(crate) fn local_get_ref(&self, frame: &CallFrame, index: LocalAddr) -> ValueRef { + self.stack_ref.get(frame.locals_base.sref + index as usize) + } + + #[inline] + pub(crate) fn local_set_32(&mut self, frame: &CallFrame, index: LocalAddr, value: Value32) { + self.stack_32.set(frame.locals_base.s32 + index as usize, value); + } + + #[inline] + pub(crate) fn local_set_64(&mut self, frame: &CallFrame, index: LocalAddr, value: Value64) { + self.stack_64.set(frame.locals_base.s64 + index as usize, value); + } + + #[inline] + pub(crate) fn local_set_128(&mut self, frame: &CallFrame, index: LocalAddr, value: Value128) { + self.stack_128.set(frame.locals_base.s128 + index as usize, value); + } + + #[inline] + pub(crate) fn local_set_ref(&mut self, frame: &CallFrame, index: LocalAddr, value: ValueRef) { + self.stack_ref.set(frame.locals_base.sref + index as usize, value); } pub(crate) fn push_dyn(&mut self, value: TinyWasmValue) -> Result<()> { diff --git a/crates/tinywasm/src/interpreter/value128.rs b/crates/tinywasm/src/interpreter/value128.rs index a16327f..edcf50a 100644 --- a/crates/tinywasm/src/interpreter/value128.rs +++ b/crates/tinywasm/src/interpreter/value128.rs @@ -124,28 +124,33 @@ impl Value128 { Self::from_le_bytes([x[0].to_bits().to_le_bytes()[0], x[0].to_bits().to_le_bytes()[1], x[0].to_bits().to_le_bytes()[2], x[0].to_bits().to_le_bytes()[3], x[0].to_bits().to_le_bytes()[4], x[0].to_bits().to_le_bytes()[5], x[0].to_bits().to_le_bytes()[6], x[0].to_bits().to_le_bytes()[7], x[1].to_bits().to_le_bytes()[0], x[1].to_bits().to_le_bytes()[1], x[1].to_bits().to_le_bytes()[2], x[1].to_bits().to_le_bytes()[3], x[1].to_bits().to_le_bytes()[4], x[1].to_bits().to_le_bytes()[5], x[1].to_bits().to_le_bytes()[6], x[1].to_bits().to_le_bytes()[7]]) } + #[inline(always)] fn map_f32x4(self, mut op: impl FnMut(f32) -> f32) -> Self { let lanes = self.as_f32x4(); Self::from_f32x4([op(lanes[0]), op(lanes[1]), op(lanes[2]), op(lanes[3])]) } + #[inline(always)] fn zip_f32x4(self, rhs: Self, mut op: impl FnMut(f32, f32) -> f32) -> Self { let a = self.as_f32x4(); let b = rhs.as_f32x4(); Self::from_f32x4([op(a[0], b[0]), op(a[1], b[1]), op(a[2], b[2]), op(a[3], b[3])]) } + #[inline(always)] fn map_f64x2(self, mut op: impl FnMut(f64) -> f64) -> Self { let lanes = self.as_f64x2(); Self::from_f64x2([op(lanes[0]), op(lanes[1])]) } + #[inline(always)] fn zip_f64x2(self, rhs: Self, mut op: impl FnMut(f64, f64) -> f64) -> Self { let a = self.as_f64x2(); let b = rhs.as_f64x2(); Self::from_f64x2([op(a[0], b[0]), op(a[1], b[1])]) } + #[inline] pub const fn reduce_or(self) -> u8 { let mut result = 0u8; let bytes = self.to_le_bytes(); diff --git a/crates/tinywasm/src/interpreter/values.rs b/crates/tinywasm/src/interpreter/values.rs index 41db383..b1530e7 100644 --- a/crates/tinywasm/src/interpreter/values.rs +++ b/crates/tinywasm/src/interpreter/values.rs @@ -1,7 +1,7 @@ use crate::{Result, interpreter::value128::Value128}; -use super::stack::{Locals, ValueStack}; -use tinywasm_types::{ExternRef, FuncRef, LocalAddr, ValType, WasmValue}; +use super::stack::ValueStack; +use tinywasm_types::{ExternRef, FuncRef, ValType, WasmValue}; pub(crate) type Value32 = u32; pub(crate) type Value64 = u64; @@ -121,12 +121,10 @@ pub(crate) trait InternalValue: sealed::Sealed + Into<TinyWasmValue> { fn stack_peek(stack: &ValueStack) -> Self where Self: Sized; - fn local_get(locals: &Locals, index: LocalAddr) -> Self; - fn local_set(locals: &mut Locals, index: LocalAddr, value: Self); } macro_rules! impl_internalvalue { - ($( $variant:ident, $stack:ident, $locals:ident, $internal:ty, $outer:ty, $to_internal:expr, $to_outer:expr )*) => { + ($( $variant:ident, $stack:ident, $internal:ty, $outer:ty, $to_internal:expr, $to_outer:expr )*) => { $( impl sealed::Sealed for $outer {} @@ -137,18 +135,22 @@ macro_rules! impl_internalvalue { } impl InternalValue for $outer { + #[inline] fn stack_push(stack: &mut ValueStack, value: Self) -> Result<()> { stack.$stack.push($to_internal(value)) } + #[inline] fn stack_pop(stack: &mut ValueStack) -> Self { $to_outer(stack.$stack.pop()) } + #[inline] fn stack_peek(stack: &ValueStack) -> Self { $to_outer(*stack.$stack.last()) } + #[inline] fn stack_calculate(stack: &mut ValueStack, func: impl FnOnce(Self, Self) -> Result<Self>) -> Result<()> { let v2 = stack.$stack.pop(); let v1 = stack.$stack.last_mut(); @@ -156,6 +158,7 @@ macro_rules! impl_internalvalue { Ok(()) } + #[inline] fn stack_calculate3(stack: &mut ValueStack, func: impl FnOnce(Self, Self, Self) -> Result<Self>) -> Result<()> { let v3 = stack.$stack.pop(); let v2 = stack.$stack.pop(); @@ -164,37 +167,24 @@ macro_rules! impl_internalvalue { Ok(()) } + #[inline] fn replace_top(stack: &mut ValueStack, func: impl FnOnce(Self) -> Result<Self>) -> Result<()> { let v = stack.$stack.last_mut(); *v = $to_internal(func($to_outer(*v))?); Ok(()) } - - fn local_get(locals: &Locals, index: LocalAddr) -> Self { - match locals.$locals.get(index as usize) { - Some(v) => $to_outer(*v), - None => unreachable!("Local variable out of bounds, this is a bug"), - } - } - - fn local_set(locals: &mut Locals, index: LocalAddr, value: Self) { - match locals.$locals.get_mut(index as usize) { - Some(v) => *v = $to_internal(value), - None => unreachable!("Local variable out of bounds, this is a bug"), - } - } } )* }; } impl_internalvalue! { - Value32, stack_32, locals_32, u32, u32, |v| v, |v| v - Value64, stack_64, locals_64, u64, u64, |v| v, |v| v - Value32, stack_32, locals_32, u32, i32, |v: i32| u32::from_ne_bytes(v.to_ne_bytes()), |v: u32| i32::from_ne_bytes(v.to_ne_bytes()) - Value64, stack_64, locals_64, u64, i64, |v: i64| u64::from_ne_bytes(v.to_ne_bytes()), |v: u64| i64::from_ne_bytes(v.to_ne_bytes()) - Value32, stack_32, locals_32, u32, f32, f32::to_bits, f32::from_bits - Value64, stack_64, locals_64, u64, f64, f64::to_bits, f64::from_bits - ValueRef, stack_ref, locals_ref, ValueRef, ValueRef, |v| v, |v| v - Value128, stack_128, locals_128, Value128, Value128, |v| v, |v| v + Value32, stack_32, u32, u32, |v| v, |v| v + Value64, stack_64, u64, u64, |v| v, |v| v + Value32, stack_32, u32, i32, |v: i32| u32::from_ne_bytes(v.to_ne_bytes()), |v: u32| i32::from_ne_bytes(v.to_ne_bytes()) + Value64, stack_64, u64, i64, |v: i64| u64::from_ne_bytes(v.to_ne_bytes()), |v: u64| i64::from_ne_bytes(v.to_ne_bytes()) + Value32, stack_32, u32, f32, f32::to_bits, f32::from_bits + Value64, stack_64, u64, f64, f64::to_bits, f64::from_bits + ValueRef, stack_ref, ValueRef, ValueRef, |v| v, |v| v + Value128, stack_128, Value128, Value128, |v| v, |v| v } diff --git a/crates/tinywasm/src/store/memory.rs b/crates/tinywasm/src/store/memory.rs index a37a9e6..5c08ab9 100644 --- a/crates/tinywasm/src/store/memory.rs +++ b/crates/tinywasm/src/store/memory.rs @@ -28,15 +28,15 @@ impl MemoryInstance { } } - pub(crate) fn is_64bit(&self) -> bool { + pub(crate) const fn is_64bit(&self) -> bool { matches!(self.kind.arch(), MemoryArch::I64) } - pub(crate) fn len(&self) -> usize { + pub(crate) const fn len(&self) -> usize { self.data.len() } - fn trap_oob(&self, addr: usize, len: usize) -> Error { + const fn trap_oob(&self, addr: usize, len: usize) -> Error { Error::Trap(crate::Trap::MemoryOutOfBounds { offset: addr, len, max: self.data.len() }) } @@ -166,10 +166,12 @@ macro_rules! impl_mem_traits { ($($ty:ty, $size:expr),*) => { $( impl MemValue<$size> for $ty { + #[inline(always)] fn from_mem_bytes(bytes: [u8; $size]) -> Self { <$ty>::from_le_bytes(bytes.into()) } + #[inline(always)] fn to_mem_bytes(self) -> [u8; $size] { self.to_le_bytes().into() } diff --git a/crates/tinywasm/src/store/mod.rs b/crates/tinywasm/src/store/mod.rs index c1d20e6..c175b8e 100644 --- a/crates/tinywasm/src/store/mod.rs +++ b/crates/tinywasm/src/store/mod.rs @@ -62,8 +62,12 @@ impl Store { Some(ModuleInstance(self.module_instances.get(addr as usize)?.clone())) } + #[inline] pub(crate) fn get_module_instance_raw(&self, addr: ModuleInstanceAddr) -> &Rc<ModuleInstanceInner> { - &self.module_instances[addr as usize] + match self.module_instances.get(addr as usize) { + Some(instance) => instance, + None => unreachable!("module instance {addr} not found. This should be unreachable"), + } } } diff --git a/crates/types/src/instructions.rs b/crates/types/src/instructions.rs index f3acbf7..b884319 100644 --- a/crates/types/src/instructions.rs +++ b/crates/types/src/instructions.rs @@ -4,22 +4,26 @@ use crate::{ConstIdx, DataAddr, ElemAddr, ExternAddr, MemAddr}; /// Represents a memory immediate in a WebAssembly memory instruction. #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "archive", derive(serde::Serialize, serde::Deserialize))] -pub struct MemoryArg([u8; 12]); +#[repr(Rust, packed)] +pub struct MemoryArg { + offset: u64, + mem_addr: MemAddr, +} impl MemoryArg { - pub fn new(offset: u64, mem_addr: MemAddr) -> Self { - let mut bytes = [0; 12]; - bytes[0..8].copy_from_slice(&offset.to_le_bytes()); - bytes[8..12].copy_from_slice(&mem_addr.to_le_bytes()); - Self(bytes) + #[inline] + pub const fn new(offset: u64, mem_addr: MemAddr) -> Self { + Self { offset, mem_addr } } - pub fn offset(&self) -> u64 { - u64::from_le_bytes(self.0[0..8].try_into().expect("invalid offset")) + #[inline] + pub const fn offset(self) -> u64 { + self.offset } - pub fn mem_addr(&self) -> MemAddr { - MemAddr::from_le_bytes(self.0[8..12].try_into().expect("invalid mem_addr")) + #[inline] + pub const fn mem_addr(self) -> MemAddr { + self.mem_addr } } diff --git a/crates/types/src/lib.rs b/crates/types/src/lib.rs index ba2cb56..7112834 100644 --- a/crates/types/src/lib.rs +++ b/crates/types/src/lib.rs @@ -169,7 +169,8 @@ pub enum ExternVal { } impl ExternVal { - pub fn kind(&self) -> ExternalKind { + #[inline] + pub const fn kind(&self) -> ExternalKind { match self { Self::Func(_) => ExternalKind::Func, Self::Table(_) => ExternalKind::Table, @@ -178,7 +179,8 @@ impl ExternVal { } } - pub fn new(kind: ExternalKind, addr: Addr) -> Self { + #[inline] + pub const fn new(kind: ExternalKind, addr: Addr) -> Self { match kind { ExternalKind::Func => Self::Func(addr), ExternalKind::Table => Self::Table(addr), @@ -217,6 +219,7 @@ pub struct ValueCountsSmall { } impl<'a, T: IntoIterator<Item = &'a ValType>> From<T> for ValueCounts { + #[inline] fn from(types: T) -> Self { let mut counts = Self::default(); for ty in types { @@ -232,6 +235,7 @@ impl<'a, T: IntoIterator<Item = &'a ValType>> From<T> for ValueCounts { } impl<'a, T: IntoIterator<Item = &'a ValType>> From<T> for ValueCountsSmall { + #[inline] fn from(types: T) -> Self { let mut counts = Self::default(); for ty in types { @@ -363,31 +367,42 @@ pub struct MemoryType { } impl MemoryType { - pub fn new(arch: MemoryArch, page_count_initial: u64, page_count_max: Option<u64>, page_size: Option<u64>) -> Self { + pub const fn new( + arch: MemoryArch, + page_count_initial: u64, + page_count_max: Option<u64>, + page_size: Option<u64>, + ) -> Self { Self { arch, page_count_initial, page_count_max, page_size } } - pub fn arch(&self) -> MemoryArch { + #[inline] + pub const fn arch(&self) -> MemoryArch { self.arch } - pub fn page_count_initial(&self) -> u64 { + #[inline] + pub const fn page_count_initial(&self) -> u64 { self.page_count_initial } - pub fn page_count_max(&self) -> u64 { - self.page_count_max.unwrap_or_else(|| max_page_count(self.page_size())) + #[inline] + pub const fn page_count_max(&self) -> u64 { + if let Some(page_count_max) = self.page_count_max { page_count_max } else { max_page_count(self.page_size()) } } - pub fn page_size(&self) -> u64 { - self.page_size.unwrap_or(MEM_PAGE_SIZE) + #[inline] + pub const fn page_size(&self) -> u64 { + if let Some(page_size) = self.page_size { page_size } else { MEM_PAGE_SIZE } } - pub fn initial_size(&self) -> u64 { + #[inline] + pub const fn initial_size(&self) -> u64 { self.page_count_initial * self.page_size() } - pub fn max_size(&self) -> u64 { + #[inline] + pub const fn max_size(&self) -> u64 { self.page_count_max() * self.page_size() } } diff --git a/crates/types/src/value.rs b/crates/types/src/value.rs index aa9e8c5..7b58948 100644 --- a/crates/types/src/value.rs +++ b/crates/types/src/value.rs @@ -106,7 +106,7 @@ impl ExternRef { impl WasmValue { #[doc(hidden)] #[inline] - pub fn const_instr(&self) -> ConstInstruction { + pub const fn const_instr(&self) -> ConstInstruction { match self { Self::I32(i) => ConstInstruction::I32Const(*i), Self::I64(i) => ConstInstruction::I64Const(*i), @@ -114,13 +114,13 @@ impl WasmValue { Self::F64(i) => ConstInstruction::F64Const(*i), Self::V128(i) => ConstInstruction::V128Const(*i), Self::RefFunc(i) => ConstInstruction::RefFunc(i.addr()), - Self::RefExtern(_) => unimplemented!("no const_instr for RefExtern"), + Self::RefExtern(i) => ConstInstruction::RefExtern(i.addr()), } } /// Get the default value for a given type. #[inline] - pub fn default_for(ty: ValType) -> Self { + pub const fn default_for(ty: ValType) -> Self { match ty { ValType::I32 => Self::I32(0), ValType::I64 => Self::I64(0), @@ -212,7 +212,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_i32(&self) -> Option<i32> { + pub const fn as_i32(&self) -> Option<i32> { match self { Self::I32(i) => Some(*i), _ => None, @@ -220,7 +220,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_i64(&self) -> Option<i64> { + pub const fn as_i64(&self) -> Option<i64> { match self { Self::I64(i) => Some(*i), _ => None, @@ -228,7 +228,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_f32(&self) -> Option<f32> { + pub const fn as_f32(&self) -> Option<f32> { match self { Self::F32(i) => Some(*i), _ => None, @@ -236,7 +236,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_f64(&self) -> Option<f64> { + pub const fn as_f64(&self) -> Option<f64> { match self { Self::F64(i) => Some(*i), _ => None, @@ -244,7 +244,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_v128(&self) -> Option<i128> { + pub const fn as_v128(&self) -> Option<i128> { match self { Self::V128(i) => Some(*i), _ => None, @@ -252,7 +252,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_ref_extern(&self) -> Option<ExternRef> { + pub const fn as_ref_extern(&self) -> Option<ExternRef> { match self { Self::RefExtern(ref_extern) => Some(*ref_extern), _ => None, @@ -260,7 +260,7 @@ impl WasmValue { } #[doc(hidden)] - pub fn as_ref_func(&self) -> Option<FuncRef> { + pub const fn as_ref_func(&self) -> Option<FuncRef> { match self { Self::RefFunc(ref_func) => Some(*ref_func), _ => None, @@ -268,9 +268,6 @@ impl WasmValue { } } -#[cold] -fn cold() {} - impl Debug for WasmValue { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { @@ -288,7 +285,7 @@ impl Debug for WasmValue { impl WasmValue { /// Get the type of a [`WasmValue`] #[inline] - pub fn val_type(&self) -> ValType { + pub const fn val_type(&self) -> ValType { match self { Self::I32(_) => ValType::I32, Self::I64(_) => ValType::I64, @@ -323,13 +320,13 @@ pub enum ValType { impl ValType { #[inline] - pub fn default_value(&self) -> WasmValue { + pub const fn default_value(&self) -> WasmValue { WasmValue::default_for(*self) } #[doc(hidden)] #[inline] - pub fn is_simd(&self) -> bool { + pub const fn is_simd(&self) -> bool { matches!(self, Self::V128) } } @@ -354,7 +351,6 @@ macro_rules! impl_conversion_for_wasmvalue { if let WasmValue::$variant(i) = value { Ok(i) } else { - cold(); Err(()) } } diff --git a/examples/rust/build.sh b/examples/rust/build.sh index e1d320f..567ed56 100755 --- a/examples/rust/build.sh +++ b/examples/rust/build.sh @@ -6,8 +6,8 @@ exclude_wat=("tinywasm") out_dir="./target/wasm32-unknown-unknown/wasm" dest_dir="out" -rust_features="+reference-types,+bulk-memory,+mutable-globals,+multivalue,+sign-ext,+nontrapping-fptoint" -wasmopt_features="--enable-reference-types --enable-bulk-memory --enable-mutable-globals --enable-multivalue --enable-sign-ext --enable-nontrapping-float-to-int" +rust_features="+simd128,+reference-types,+bulk-memory,+mutable-globals,+multivalue,+sign-ext,+nontrapping-fptoint" +wasmopt_features="--enable-simd --enable-reference-types --enable-bulk-memory --enable-mutable-globals --enable-multivalue --enable-sign-ext --enable-nontrapping-float-to-int" # ensure out dir exists mkdir -p "$dest_dir" |
