summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/tinywasm/src/func.rs7
-rw-r--r--crates/tinywasm/src/imports.rs12
-rw-r--r--crates/tinywasm/src/instance.rs8
-rw-r--r--crates/tinywasm/src/interpreter/executor.rs117
-rw-r--r--crates/tinywasm/src/interpreter/no_std_floats.rs20
-rw-r--r--crates/tinywasm/src/interpreter/num_helpers.rs7
-rw-r--r--crates/tinywasm/src/interpreter/stack/call_stack.rs114
-rw-r--r--crates/tinywasm/src/interpreter/stack/mod.rs2
-rw-r--r--crates/tinywasm/src/interpreter/stack/value_stack.rs126
-rw-r--r--crates/tinywasm/src/interpreter/value128.rs5
-rw-r--r--crates/tinywasm/src/interpreter/values.rs44
-rw-r--r--crates/tinywasm/src/store/memory.rs8
-rw-r--r--crates/tinywasm/src/store/mod.rs6
-rw-r--r--crates/types/src/instructions.rs24
-rw-r--r--crates/types/src/lib.rs37
-rw-r--r--crates/types/src/value.rs30
-rwxr-xr-xexamples/rust/build.sh4
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"