diff options
| -rw-r--r-- | crates/parser/src/conversion.rs | 2 | ||||
| -rw-r--r-- | crates/parser/src/visit.rs | 3 | ||||
| -rw-r--r-- | crates/tinywasm/src/lib.rs | 1 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/interpreter/mod.rs | 27 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/call_stack.rs | 2 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/stack/value_stack.rs | 44 | ||||
| -rw-r--r-- | crates/tinywasm/src/runtime/value.rs | 28 |
7 files changed, 75 insertions, 32 deletions
diff --git a/crates/parser/src/conversion.rs b/crates/parser/src/conversion.rs index 4e4434b..31056a3 100644 --- a/crates/parser/src/conversion.rs +++ b/crates/parser/src/conversion.rs @@ -137,7 +137,7 @@ pub(crate) fn convert_module_table(table: wasmparser::Table<'_>) -> Result<Table None => None, }; - Ok(TableType { element_type: convert_reftype(&table.ty.element_type), size_initial: size_initial, size_max }) + Ok(TableType { element_type: convert_reftype(&table.ty.element_type), size_initial, size_max }) } pub(crate) fn convert_module_globals<'a, T: IntoIterator<Item = wasmparser::Result<wasmparser::Global<'a>>>>( diff --git a/crates/parser/src/visit.rs b/crates/parser/src/visit.rs index 8b9e15d..df6fc7a 100644 --- a/crates/parser/src/visit.rs +++ b/crates/parser/src/visit.rs @@ -110,7 +110,8 @@ impl FunctionBuilder { #[inline] fn visit(&mut self, op: Instruction) -> Result<()> { - Ok(self.instructions.push(op)) + self.instructions.push(op); + Ok(()) } } diff --git a/crates/tinywasm/src/lib.rs b/crates/tinywasm/src/lib.rs index 4a644fd..0bc17d6 100644 --- a/crates/tinywasm/src/lib.rs +++ b/crates/tinywasm/src/lib.rs @@ -3,6 +3,7 @@ no_crate_inject, attr(deny(warnings, rust_2018_idioms), allow(dead_code, unused_assignments, unused_variables)) ))] +#![allow(unexpected_cfgs, clippy::reserve_after_initialization)] #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] #![cfg_attr(nightly, feature(error_in_core))] #![cfg_attr(not(feature = "unsafe"), deny(unsafe_code))] diff --git a/crates/tinywasm/src/runtime/interpreter/mod.rs b/crates/tinywasm/src/runtime/interpreter/mod.rs index 5e1500f..404e4fe 100644 --- a/crates/tinywasm/src/runtime/interpreter/mod.rs +++ b/crates/tinywasm/src/runtime/interpreter/mod.rs @@ -138,7 +138,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M CallIndirect(type_addr, table_addr) => { let table = store.get_table(module.resolve_table_addr(*table_addr))?; - let table_idx = stack.values.pop_t::<u32>()?; + let table_idx: u32 = stack.values.pop()?.into(); // verify that the table is of the right type, this should be validated by the parser already let func_ref = { @@ -188,7 +188,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M If(args, else_offset, end_offset) => { // truthy value is on the top of the stack, so enter the then block - if stack.values.pop_t::<i32>()? != 0 { + if i32::from(stack.values.pop()?) != 0 { cf.enter_block( BlockFrame::new( cf.instr_ptr, @@ -259,8 +259,8 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M return Err(Error::Other(format!("br_table out of bounds: {} >= {}", end, cf.instructions().len()))); } - let idx = stack.values.pop_t::<i32>()? as usize; - match cf.instructions()[start..end].get(idx) { + let idx: i32 = stack.values.pop()?.into(); + match cf.instructions()[start..end].get(idx as usize) { None => break_to!(cf, stack, default), Some(BrLabel(to)) => break_to!(cf, stack, to), _ => return Err(Error::Other("br_table with invalid label".to_string())), @@ -269,7 +269,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M Br(v) => break_to!(cf, stack, v), BrIf(v) => { - if stack.values.pop_t::<i32>()? != 0 { + if i32::from(stack.values.pop()?) != 0 { break_to!(cf, stack, v); } } @@ -329,8 +329,9 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M let mem = store.get_mem(module.resolve_mem_addr(*addr))?; let mut mem = mem.borrow_mut(); let prev_size = mem.page_count() as i32; + let pages_delta: i32 = stack.values.pop()?.into(); - match mem.grow(stack.values.pop_t::<i32>()?) { + match mem.grow(pages_delta) { Some(_) => stack.values.push(prev_size.into()), None => stack.values.push((-1).into()), } @@ -366,9 +367,9 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M } MemoryInit(data_index, mem_index) => { - let size = stack.values.pop_t::<i32>()? as usize; - let offset = stack.values.pop_t::<i32>()? as usize; - let dst = stack.values.pop_t::<i32>()? as usize; + let size = i32::from(stack.values.pop()?) as usize; + let offset = i32::from(stack.values.pop()?) as usize; + let dst = i32::from(stack.values.pop()?) as usize; let data = match &store.get_data(module.resolve_data_addr(*data_index))?.data { Some(data) => data, @@ -561,7 +562,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M TableGet(table_index) => { let table_idx = module.resolve_table_addr(*table_index); let table = store.get_table(table_idx)?; - let idx = stack.values.pop_t::<u32>()?; + let idx: u32 = stack.values.pop()?.into(); let v = table.borrow().get_wasm_val(idx)?; stack.values.push(v.into()); } @@ -569,8 +570,8 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M TableSet(table_index) => { let table_idx = module.resolve_table_addr(*table_index); let table = store.get_table(table_idx)?; - let val = stack.values.pop_t::<u32>()?; - let idx = stack.values.pop_t::<u32>()?; + let val = stack.values.pop()?.into(); + let idx = stack.values.pop()?.into(); table.borrow_mut().set(idx, val)?; } @@ -632,7 +633,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M stack.values.push((local + *val).into()); } I32StoreLocal { local, const_i32: consti32, offset, mem_addr } => { - let (mem_addr, offset) = (*mem_addr as u32, *offset as u32); + let (mem_addr, offset) = (*mem_addr as u32, *offset); let mem = store.get_mem(module.resolve_mem_addr(mem_addr))?; let val = consti32.to_le_bytes(); let addr: u64 = cf.get_local(*local).into(); diff --git a/crates/tinywasm/src/runtime/stack/call_stack.rs b/crates/tinywasm/src/runtime/stack/call_stack.rs index 060d530..8002385 100644 --- a/crates/tinywasm/src/runtime/stack/call_stack.rs +++ b/crates/tinywasm/src/runtime/stack/call_stack.rs @@ -20,7 +20,7 @@ impl CallStack { let mut stack = Vec::new(); stack.reserve_exact(CALL_STACK_SIZE); - let mut stack = Self { stack: stack }; + let mut stack = Self { stack }; stack.push(initial_frame).unwrap(); stack } diff --git a/crates/tinywasm/src/runtime/stack/value_stack.rs b/crates/tinywasm/src/runtime/stack/value_stack.rs index 354898e..8a3f3fa 100644 --- a/crates/tinywasm/src/runtime/stack/value_stack.rs +++ b/crates/tinywasm/src/runtime/stack/value_stack.rs @@ -82,17 +82,6 @@ impl ValueStack { } #[inline] - pub(crate) fn pop_t<T: From<RawWasmValue>>(&mut self) -> Result<T> { - match self.stack.pop() { - Some(v) => Ok(v.into()), - None => { - cold(); // 20+ performance improvement most of the time - Err(Error::ValueStackUnderflow) - } - } - } - - #[inline] pub(crate) fn pop(&mut self) -> Result<RawWasmValue> { match self.stack.pop() { Some(v) => Ok(v), @@ -144,11 +133,38 @@ mod tests { stack.push(2.into()); stack.push(3.into()); assert_eq!(stack.len(), 3); - assert_eq!(stack.pop_t::<i32>().unwrap(), 3); + assert_eq!(i32::from(stack.pop().unwrap()), 3); assert_eq!(stack.len(), 2); - assert_eq!(stack.pop_t::<i32>().unwrap(), 2); + assert_eq!(i32::from(stack.pop().unwrap()), 2); assert_eq!(stack.len(), 1); - assert_eq!(stack.pop_t::<i32>().unwrap(), 1); + assert_eq!(i32::from(stack.pop().unwrap()), 1); assert_eq!(stack.len(), 0); } + + #[test] + fn test_truncate_keep() { + macro_rules! test_macro { + ($( $n:expr, $end_keep:expr, $expected:expr ),*) => { + $( + let mut stack = ValueStack::default(); + stack.push(1.into()); + stack.push(2.into()); + stack.push(3.into()); + stack.push(4.into()); + stack.push(5.into()); + stack.truncate_keep($n, $end_keep); + assert_eq!(stack.len(), $expected); + )* + }; + } + + test_macro! { + 0, 0, 0, + 1, 0, 1, + 0, 1, 1, + 1, 1, 2, + 2, 1, 3, + 2, 2, 4 + } + } } diff --git a/crates/tinywasm/src/runtime/value.rs b/crates/tinywasm/src/runtime/value.rs index 55aa9fe..2865308 100644 --- a/crates/tinywasm/src/runtime/value.rs +++ b/crates/tinywasm/src/runtime/value.rs @@ -83,12 +83,36 @@ impl_from_raw_wasm_value!(i64, |x| x as u64, |x: [u8; 8]| i64::from_ne_bytes(x[0 impl_from_raw_wasm_value!(u8, |x| x as u64, |x: [u8; 8]| u8::from_ne_bytes(x[0..1].try_into().unwrap())); impl_from_raw_wasm_value!(u16, |x| x as u64, |x: [u8; 8]| u16::from_ne_bytes(x[0..2].try_into().unwrap())); impl_from_raw_wasm_value!(u32, |x| x as u64, |x: [u8; 8]| u32::from_ne_bytes(x[0..4].try_into().unwrap())); -impl_from_raw_wasm_value!(u64, |x| x as u64, |x: [u8; 8]| u64::from_ne_bytes(x[0..8].try_into().unwrap())); +impl_from_raw_wasm_value!(u64, |x| x, |x: [u8; 8]| u64::from_ne_bytes(x[0..8].try_into().unwrap())); impl_from_raw_wasm_value!(i8, |x| x as u64, |x: [u8; 8]| i8::from_ne_bytes(x[0..1].try_into().unwrap())); impl_from_raw_wasm_value!(i16, |x| x as u64, |x: [u8; 8]| i16::from_ne_bytes(x[0..2].try_into().unwrap())); impl_from_raw_wasm_value!(f32, |x| f32::to_bits(x) as u64, |x: [u8; 8]| f32::from_bits(u32::from_ne_bytes( x[0..4].try_into().unwrap() ))); -impl_from_raw_wasm_value!(f64, |x| f64::to_bits(x) as u64, |x: [u8; 8]| f64::from_bits(u64::from_ne_bytes( +impl_from_raw_wasm_value!(f64, f64::to_bits, |x: [u8; 8]| f64::from_bits(u64::from_ne_bytes( x[0..8].try_into().unwrap() ))); + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_raw_wasm_value() { + macro_rules! test_macro { + ($( $ty:ty => $val:expr ),*) => { + $( + let raw: RawWasmValue = $val.into(); + let val: $ty = raw.into(); + assert_eq!(val, $val); + )* + }; + } + + test_macro! { + i32 => 0, i64 => 0, u8 => 0, u16 => 0, u32 => 0, u64 => 0, i8 => 0, i16 => 0, f32 => 0.0, f64 => 0.0, + i32 => i32::MIN, i64 => i64::MIN, u8 => u8::MIN, u16 => u16::MIN, u32 => u32::MIN, u64 => u64::MIN, i8 => i8::MIN, i16 => i16::MIN, f32 => f32::MIN, f64 => f64::MIN, + i32 => i32::MAX, i64 => i64::MAX, u8 => u8::MAX, u16 => u16::MAX, u32 => u32::MAX, u64 => u64::MAX, i8 => i8::MAX, i16 => i16::MAX, f32 => f32::MAX, f64 => f64::MAX + } + } +} |
