@@ -8,7 +8,7 @@ use alloc::boxed::Box;
88use alloc:: vec:: Vec ;
99
1010use alloc:: sync:: Arc ;
11- use interpreter:: stack:: { CallFrame , ValueStack } ;
11+ use interpreter:: stack:: CallFrame ;
1212use tinywasm_types:: * ;
1313
1414use super :: ExecState ;
@@ -30,19 +30,6 @@ pub(crate) struct Executor<'store, const BUDGETED: bool> {
3030}
3131
3232impl < ' store , const BUDGETED : bool > Executor < ' store , BUDGETED > {
33- #[ inline( always) ]
34- fn pop_memory_addr < const N : usize > (
35- stack : & mut ValueStack ,
36- mem : & MemoryInstance ,
37- offset : u64 ,
38- ) -> Result < usize , Trap > {
39- if mem. is_64bit ( ) {
40- mem. effective_addr_64 :: < N > ( <i64 >:: stack_pop ( stack) as u64 , offset)
41- } else {
42- mem. effective_addr_32 :: < N > ( <i32 >:: stack_pop ( stack) as u32 , offset)
43- }
44- }
45-
4633 pub ( crate ) fn new ( store : & ' store mut Store , cf : CallFrame , call_stack_base : u32 ) -> Self {
4734 let wasm_func = store. state . get_wasm_func ( cf. func_addr ) ;
4835 let module = store
@@ -1133,7 +1120,7 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
11331120 self . store . host_params = params;
11341121 let res = cold_err ! ( result) . map_err ( |error| Trap :: HostFunction ( Box :: new ( error) ) ) ?;
11351122
1136- self . store . value_stack . extend_from_wasmvalues ( & res) ?;
1123+ self . store . value_stack . extend_wasmvalues ( res. iter ( ) . copied ( ) ) ?;
11371124 if TAIL {
11381125 Ok ( self . exec_return ( ) )
11391126 } else {
@@ -1304,10 +1291,22 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
13041291 addr_local : u8 ,
13051292 value_local : u8 ,
13061293 ) -> Result < ( ) , Trap > {
1307- let base = u32:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) ;
13081294 let value = T :: local_get ( & self . store . value_stack , & self . cf , u16:: from ( value_local) ) ;
1309- let mem = self . store . state . get_mem_mut ( self . module . resolve_mem_addr ( memarg. mem_addr ( ) ) ) ;
1310- let addr = mem. effective_addr_32 :: < N > ( base, memarg. offset ( ) ) ?;
1295+ let mem_addr = self . module . resolve_mem_addr ( memarg. mem_addr ( ) ) ;
1296+ let mem = self . store . state . get_mem ( mem_addr) ;
1297+ let addr = if mem. is_64bit ( ) {
1298+ let base = u64:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) ;
1299+ let base = cold_err ! ( usize :: try_from( base) . map_err( |_| Trap :: MemoryOutOfBounds {
1300+ offset: usize :: MAX ,
1301+ len: N ,
1302+ max: mem. inner. len( ) ,
1303+ } ) ) ?;
1304+ mem. effective_addr :: < N > ( base, memarg. offset ( ) ) ?
1305+ } else {
1306+ let base = u32:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) ;
1307+ mem. effective_addr :: < N > ( base as usize , memarg. offset ( ) ) ?
1308+ } ;
1309+ let mem = self . store . state . get_mem_mut ( mem_addr) ;
13111310 value. store_at ( & mut * mem. inner , addr)
13121311 }
13131312
@@ -1322,10 +1321,15 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
13221321 let mem = self . store . state . get_mem ( mem_addr) ;
13231322 let addr = if mem. is_64bit ( ) {
13241323 let base = i64:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) as u64 ;
1325- mem. effective_addr_64 :: < N > ( base, memarg. offset ( ) ) ?
1324+ let base = cold_err ! ( usize :: try_from( base) . map_err( |_| Trap :: MemoryOutOfBounds {
1325+ offset: usize :: MAX ,
1326+ len: N ,
1327+ max: mem. inner. len( ) ,
1328+ } ) ) ?;
1329+ mem. effective_addr :: < N > ( base, memarg. offset ( ) ) ?
13261330 } else {
13271331 let base = u32:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) ;
1328- mem. effective_addr_32 :: < N > ( base, memarg. offset ( ) ) ?
1332+ mem. effective_addr :: < N > ( base as usize , memarg. offset ( ) ) ?
13291333 } ;
13301334
13311335 let mem = self . store . state . get_mem_mut ( mem_addr) ;
@@ -1344,10 +1348,12 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
13441348 let rhs = T :: stack_pop ( & mut self . store . value_stack ) ;
13451349 let lhs = T :: stack_pop ( & mut self . store . value_stack ) ;
13461350 let acc = T :: stack_pop ( & mut self . store . value_stack ) ;
1347- let addr = i32:: stack_pop ( & mut self . store . value_stack ) ;
13481351 let fma = acc + lhs * rhs;
1349- let mem = self . store . state . get_mem_mut ( self . module . resolve_mem_addr ( m. mem_addr ( ) ) ) ;
1350- let addr = mem. effective_addr_32 :: < N > ( addr as u32 , m. offset ( ) ) ?;
1352+ let mem_addr = self . module . resolve_mem_addr ( m. mem_addr ( ) ) ;
1353+ let mem = self . store . state . get_mem ( mem_addr) ;
1354+ let base = self . store . value_stack . pop_memory_operand ( mem. kind . arch ( ) ) ?;
1355+ let addr = mem. effective_addr :: < N > ( base, m. offset ( ) ) ?;
1356+ let mem = self . store . state . get_mem_mut ( mem_addr) ;
13511357 fma. store_at ( & mut * mem. inner , addr) ?;
13521358 Ok ( ( ) )
13531359 }
@@ -1361,10 +1367,15 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
13611367 let mem = self . store . state . get_mem ( self . module . resolve_mem_addr ( memarg. mem_addr ( ) ) ) ;
13621368 let addr = if mem. is_64bit ( ) {
13631369 let base = i64:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) as u64 ;
1364- mem. effective_addr_64 :: < N > ( base, memarg. offset ( ) ) ?
1370+ let base = cold_err ! ( usize :: try_from( base) . map_err( |_| Trap :: MemoryOutOfBounds {
1371+ offset: usize :: MAX ,
1372+ len: N ,
1373+ max: mem. inner. len( ) ,
1374+ } ) ) ?;
1375+ mem. effective_addr :: < N > ( base, memarg. offset ( ) ) ?
13651376 } else {
13661377 let base = u32:: local_get ( & self . store . value_stack , & self . cf , u16:: from ( addr_local) ) ;
1367- mem. effective_addr_32 :: < N > ( base, memarg. offset ( ) ) ?
1378+ mem. effective_addr :: < N > ( base as usize , memarg. offset ( ) ) ?
13681379 } ;
13691380 T :: load_at ( & * mem. inner , addr)
13701381 }
@@ -1659,56 +1670,69 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
16591670 }
16601671
16611672 fn exec_memory_copy ( & mut self , dst_mem : u32 , src_mem : u32 ) -> Result < ( ) , Trap > {
1662- let size = i32:: stack_pop ( & mut self . store . value_stack ) ;
1663- let src = i32:: stack_pop ( & mut self . store . value_stack ) ;
1664- let dst = i32:: stack_pop ( & mut self . store . value_stack ) ;
16651673 let dst_mem_addr = self . module . resolve_mem_addr ( dst_mem) ;
1674+ let src_mem_addr = self . module . resolve_mem_addr ( src_mem) ;
1675+ let dst_arch = self . store . state . get_mem ( dst_mem_addr) . kind . arch ( ) ;
1676+ let src_arch = self . store . state . get_mem ( src_mem_addr) . kind . arch ( ) ;
1677+ let len_arch =
1678+ if dst_arch == MemoryArch :: I32 || src_arch == MemoryArch :: I32 { MemoryArch :: I32 } else { MemoryArch :: I64 } ;
1679+ let size = self . store . value_stack . pop_memory_operand ( len_arch) ?;
1680+ let src = self . store . value_stack . pop_memory_operand ( src_arch) ?;
1681+ let dst = self . store . value_stack . pop_memory_operand ( dst_arch) ?;
16661682
16671683 if dst_mem == src_mem {
16681684 // copy within the same memory
16691685 let mem = self . store . state . get_mem_mut ( dst_mem_addr) ;
1670- mem. copy_within ( dst as usize , src as usize , size as usize ) ?;
1686+ mem. copy_within ( dst, src, size) ?;
16711687 } else {
16721688 // copy between two memories
1673- let src_mem_addr = self . module . resolve_mem_addr ( src_mem) ;
16741689 let ( dst_memory, src_memory) = self . store . state . get_mems_mut ( dst_mem_addr, src_mem_addr) ;
1675- dst_memory. copy_from_memory ( dst as usize , src_memory, src as usize , size as usize ) ?;
1690+ dst_memory. copy_from_memory ( dst, src_memory, src, size) ?;
16761691 }
16771692 Ok ( ( ) )
16781693 }
16791694
16801695 fn exec_memory_fill ( & mut self , addr : u32 ) -> Result < ( ) , Trap > {
1681- let size = i32:: stack_pop ( & mut self . store . value_stack ) ;
1696+ let mem_addr = self . module . resolve_mem_addr ( addr) ;
1697+ let arch = self . store . state . get_mem ( mem_addr) . kind . arch ( ) ;
1698+ let size = self . store . value_stack . pop_memory_operand ( arch) ?;
16821699 let val = i32:: stack_pop ( & mut self . store . value_stack ) ;
1683- let dst = i32 :: stack_pop ( & mut self . store . value_stack ) ;
1684- self . exec_memory_fill_impl ( addr , dst, val as u8 , size)
1700+ let dst = self . store . value_stack . pop_memory_operand ( arch ) ? ;
1701+ self . exec_memory_fill_impl ( mem_addr , dst, val as u8 , size)
16851702 }
16861703
16871704 fn exec_memory_fill_imm ( & mut self , addr : u32 , val : u8 , size : i32 ) -> Result < ( ) , Trap > {
1688- let dst = i32:: stack_pop ( & mut self . store . value_stack ) ;
1689- self . exec_memory_fill_impl ( addr, dst, val, size)
1705+ let mem_addr = self . module . resolve_mem_addr ( addr) ;
1706+ let arch = self . store . state . get_mem ( mem_addr) . kind . arch ( ) ;
1707+ let dst = self . store . value_stack . pop_memory_operand ( arch) ?;
1708+ self . exec_memory_fill_impl ( mem_addr, dst, val, size as u32 as usize )
16901709 }
16911710
1692- fn exec_memory_fill_impl ( & mut self , addr : u32 , dst : i32 , val : u8 , size : i32 ) -> Result < ( ) , Trap > {
1693- let mem = self . store . state . get_mem_mut ( self . module . resolve_mem_addr ( addr ) ) ;
1711+ fn exec_memory_fill_impl ( & mut self , mem_addr : MemAddr , dst : usize , val : u8 , size : usize ) -> Result < ( ) , Trap > {
1712+ let mem = self . store . state . get_mem_mut ( mem_addr ) ;
16941713 let max = mem. inner . len ( ) ;
1695- if mem. inner . fill ( dst as usize , size as usize , val) . is_none ( ) {
1696- return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: dst as usize , len: size as usize , max } ) ) ;
1714+ if mem. inner . fill ( dst, size, val) ? . is_none ( ) {
1715+ return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: dst, len: size, max } ) ) ;
16971716 }
16981717 Ok ( ( ) )
16991718 }
17001719
17011720 fn exec_memory_init ( & mut self , data_index : u32 , mem_index : u32 ) -> Result < ( ) , Trap > {
1702- let size = i32:: stack_pop ( & mut self . store . value_stack ) ;
1703- let offset = i32:: stack_pop ( & mut self . store . value_stack ) ;
1704- let dst = i32:: stack_pop ( & mut self . store . value_stack ) ;
1721+ let size = u32:: stack_pop ( & mut self . store . value_stack ) as usize ;
1722+ let offset = u32:: stack_pop ( & mut self . store . value_stack ) as usize ;
1723+ let mem_addr = self . module . resolve_mem_addr ( mem_index) ;
1724+ let arch = self . store . state . get_mem ( mem_addr) . kind . arch ( ) ;
1725+ let dst = self . store . value_stack . pop_memory_operand ( arch) ?;
17051726
17061727 let data = & self . store . state . data [ self . module . resolve_data_addr ( data_index) as usize ] ;
1707- let mem = & mut self . store . state . memories [ self . module . resolve_mem_addr ( mem_index ) as usize ] ;
1728+ let mem = & mut self . store . state . memories [ mem_addr as usize ] ;
17081729 let data_len = data. data . as_ref ( ) . map_or ( 0 , |d| d. len ( ) ) ;
17091730 let mem_len = mem. inner . len ( ) ;
1710- if ( ( size + offset) as usize > data_len) || ( ( dst + size) as usize > mem_len) {
1711- return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: offset as usize , len: size as usize , max: data_len } ) ) ;
1731+ if offset. checked_add ( size) . is_none_or ( |end| end > data_len) {
1732+ return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset, len: size, max: data_len } ) ) ;
1733+ }
1734+ if dst. checked_add ( size) . is_none_or ( |end| end > mem_len) {
1735+ return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: dst, len: size, max: mem_len } ) ) ;
17121736 }
17131737
17141738 if size == 0 {
@@ -1719,8 +1743,8 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
17191743 return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: 0 , len: 0 , max: 0 } ) ) ;
17201744 } ;
17211745
1722- if mem. inner . write_all ( dst as usize , & data[ offset as usize .. ( ( offset + size) as usize ) ] ) . is_none ( ) {
1723- return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: dst as usize , len: size as usize , max: mem_len } ) ) ;
1746+ if mem. inner . write_all ( dst, & data[ offset.. offset + size] ) ? . is_none ( ) {
1747+ return cold ! ( Err ( Trap :: MemoryOutOfBounds { offset: dst, len: size, max: mem_len } ) ) ;
17241748 }
17251749 Ok ( ( ) )
17261750 }
@@ -1753,7 +1777,8 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
17531777 lane : u8 ,
17541778 ) -> Result < ( ) , Trap > {
17551779 let mem = self . store . state . get_mem ( self . module . resolve_mem_addr ( mem_addr) ) ;
1756- let addr = Self :: pop_memory_addr :: < LOAD_SIZE > ( & mut self . store . value_stack , mem, offset) ?;
1780+ let base = self . store . value_stack . pop_memory_operand ( mem. kind . arch ( ) ) ?;
1781+ let addr = mem. effective_addr :: < LOAD_SIZE > ( base, offset) ?;
17571782 let val = LOAD :: load_at ( & * mem. inner , addr) ?;
17581783 let offset = lane as usize * LOAD_SIZE ;
17591784 let mut imm = <Value128 >:: stack_pop ( & mut self . store . value_stack ) . to_mem_bytes ( ) ;
@@ -1770,7 +1795,8 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
17701795 cast : impl Fn ( LOAD ) -> TARGET ,
17711796 ) -> Result < ( ) , Trap > {
17721797 let mem = self . store . state . get_mem ( self . module . resolve_mem_addr ( mem_addr) ) ;
1773- let addr = Self :: pop_memory_addr :: < LOAD_SIZE > ( & mut self . store . value_stack , mem, offset) ?;
1798+ let base = self . store . value_stack . pop_memory_operand ( mem. kind . arch ( ) ) ?;
1799+ let addr = mem. effective_addr :: < LOAD_SIZE > ( base, offset) ?;
17741800 let value = cold_err ! ( LOAD :: load_at( & * mem. inner, addr) ) ?;
17751801 self . store . value_stack . push ( cast ( value) )
17761802 }
@@ -1787,8 +1813,10 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
17871813 val_bytes. copy_from_slice ( & bytes[ lane_offset..lane_offset + N ] ) ;
17881814 let val = U :: from_mem_bytes ( val_bytes) ;
17891815 let mem_addr = self . module . resolve_mem_addr ( mem_addr) ;
1816+ let mem = self . store . state . get_mem ( mem_addr) ;
1817+ let base = self . store . value_stack . pop_memory_operand ( mem. kind . arch ( ) ) ?;
1818+ let addr = mem. effective_addr :: < N > ( base, offset) ?;
17901819 let mem = self . store . state . get_mem_mut ( mem_addr) ;
1791- let addr = Self :: pop_memory_addr :: < N > ( & mut self . store . value_stack , mem, offset) ?;
17921820 cold_err ! ( val. store_at( & mut * mem. inner, addr) ) ?;
17931821 Ok ( ( ) )
17941822 }
@@ -1803,8 +1831,10 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
18031831 let val = cast ( val) ;
18041832
18051833 let mem_addr = self . module . resolve_mem_addr ( mem_addr) ;
1834+ let mem = self . store . state . get_mem ( mem_addr) ;
1835+ let base = self . store . value_stack . pop_memory_operand ( mem. kind . arch ( ) ) ?;
1836+ let addr = mem. effective_addr :: < N > ( base, offset) ?;
18061837 let mem = self . store . state . get_mem_mut ( mem_addr) ;
1807- let addr = Self :: pop_memory_addr :: < N > ( & mut self . store . value_stack , mem, offset) ?;
18081838 cold_err ! ( val. store_at( & mut * mem. inner, addr) ) ?;
18091839 Ok ( ( ) )
18101840 }
@@ -1876,7 +1906,11 @@ impl<'store, const BUDGETED: bool> Executor<'store, BUDGETED> {
18761906 MemoryArch :: I32 => <i32 >:: stack_pop ( & mut self . store . value_stack ) as u32 as u64 ,
18771907 MemoryArch :: I64 => <i64 >:: stack_pop ( & mut self . store . value_stack ) as u64 ,
18781908 } ;
1879- usize:: try_from ( value) . map_err ( |_| Trap :: TableOutOfBounds { offset : usize:: MAX , len : 1 , max : usize:: MAX } )
1909+ cold_err ! ( usize :: try_from( value) . map_err( |_| Trap :: TableOutOfBounds {
1910+ offset: usize :: MAX ,
1911+ len: 1 ,
1912+ max: usize :: MAX ,
1913+ } ) )
18801914 }
18811915}
18821916
0 commit comments