@@ -10,7 +10,6 @@ use interpreter::stack::CallFrame;
1010use tinywasm_types:: * ;
1111
1212use super :: num_helpers:: * ;
13- use super :: stack:: { BlockFrame , BlockType } ;
1413use super :: values:: * ;
1514use crate :: instance:: ModuleInstanceInner ;
1615use crate :: interpreter:: Value128 ;
@@ -88,7 +87,7 @@ impl<'store> Executor<'store> {
8887
8988 #[ rustfmt:: skip]
9089 match next {
91- Nop | BrLabel ( _ ) | I32ReinterpretF32 | I64ReinterpretF64 | F32ReinterpretI32 | F64ReinterpretI64 => { }
90+ Nop | I32ReinterpretF32 | I64ReinterpretF64 | F32ReinterpretI32 | F64ReinterpretI64 => { }
9291 Unreachable => return ControlFlow :: Break ( Some ( Trap :: Unreachable . into ( ) ) ) ,
9392 Drop32 => self . store . stack . values . drop :: < Value32 > ( ) ,
9493 Drop64 => self . store . stack . values . drop :: < Value64 > ( ) ,
@@ -102,21 +101,70 @@ impl<'store> Executor<'store> {
102101 CallIndirect ( ty, table) => return self . exec_call_indirect :: < false > ( * ty, * table) ,
103102 ReturnCall ( v) => return self . exec_call_direct :: < true > ( * v) ,
104103 ReturnCallIndirect ( ty, table) => return self . exec_call_indirect :: < true > ( * ty, * table) ,
105- If ( end, el) => self . exec_if ( * end, * el, ( StackHeight :: default ( ) , StackHeight :: default ( ) ) ) ,
106- IfWithType ( ty, end, el) => self . exec_if ( * end, * el, ( StackHeight :: default ( ) , ( * ty) . into ( ) ) ) ,
107- IfWithFuncType ( ty, end, el) => self . exec_if ( * end, * el, self . resolve_functype ( * ty) ) ,
108- Else ( end_offset) => self . exec_else ( * end_offset) ,
109- Loop ( end) => self . enter_block ( * end, BlockType :: Loop , ( StackHeight :: default ( ) , StackHeight :: default ( ) ) ) ,
110- LoopWithType ( ty, end) => self . enter_block ( * end, BlockType :: Loop , ( StackHeight :: default ( ) , ( * ty) . into ( ) ) ) ,
111- LoopWithFuncType ( ty, end) => self . enter_block ( * end, BlockType :: Loop , self . resolve_functype ( * ty) ) ,
112- Block ( end) => self . enter_block ( * end, BlockType :: Block , ( StackHeight :: default ( ) , StackHeight :: default ( ) ) ) ,
113- BlockWithType ( ty, end) => self . enter_block ( * end, BlockType :: Block , ( StackHeight :: default ( ) , ( * ty) . into ( ) ) ) ,
114- BlockWithFuncType ( ty, end) => self . enter_block ( * end, BlockType :: Block , self . resolve_functype ( * ty) ) ,
115- Br ( v) => return self . exec_br ( * v) ,
116- BrIf ( v) => return self . exec_br_if ( * v) ,
117- BrTable ( default, len) => return self . exec_brtable ( * default, * len) ,
104+ Jump ( ip) => {
105+ self . cf . instr_ptr = * ip as usize ;
106+ return ControlFlow :: Continue ( ( ) ) ;
107+ }
108+ JumpIfZero ( ip) => {
109+ let cond = self . store . stack . values . pop :: < i32 > ( ) ;
110+
111+ if cond == 0 {
112+ self . cf . instr_ptr = * ip as usize ;
113+ } else {
114+ self . cf . incr_instr_ptr ( ) ;
115+ }
116+ return ControlFlow :: Continue ( ( ) ) ;
117+ }
118+ DropKeepSmall { base32, keep32, base64, keep64, base128, keep128, base_ref, keep_ref } => {
119+ let b32 = self . cf . stack_base . s32 as usize + * base32 as usize ;
120+ let k32 = * keep32 as usize ;
121+ self . store . stack . values . stack_32 . truncate_keep ( b32, k32) ;
122+ let b64 = self . cf . stack_base . s64 as usize + * base64 as usize ;
123+ let k64 = * keep64 as usize ;
124+ self . store . stack . values . stack_64 . truncate_keep ( b64, k64) ;
125+ let b128 = self . cf . stack_base . s128 as usize + * base128 as usize ;
126+ let k128 = * keep128 as usize ;
127+ self . store . stack . values . stack_128 . truncate_keep ( b128, k128) ;
128+ let bref = self . cf . stack_base . sref as usize + * base_ref as usize ;
129+ let kref = * keep_ref as usize ;
130+ self . store . stack . values . stack_ref . truncate_keep ( bref, kref) ;
131+ }
132+ DropKeep32 ( base, keep) => {
133+ let b = self . cf . stack_base . s32 as usize + * base as usize ;
134+ let k = * keep as usize ;
135+ self . store . stack . values . stack_32 . truncate_keep ( b, k) ;
136+ }
137+ DropKeep64 ( base, keep) => {
138+ let b = self . cf . stack_base . s64 as usize + * base as usize ;
139+ let k = * keep as usize ;
140+ self . store . stack . values . stack_64 . truncate_keep ( b, k) ;
141+ }
142+ DropKeep128 ( base, keep) => {
143+ let b = self . cf . stack_base . s128 as usize + * base as usize ;
144+ let k = * keep as usize ;
145+ self . store . stack . values . stack_128 . truncate_keep ( b, k) ;
146+ }
147+ DropKeepRef ( base, keep) => {
148+ let b = self . cf . stack_base . sref as usize + * base as usize ;
149+ let k = * keep as usize ;
150+ self . store . stack . values . stack_ref . truncate_keep ( b, k) ;
151+ }
152+ BranchTable ( default_ip, len) => {
153+ let idx = self . store . stack . values . pop :: < i32 > ( ) ;
154+ let start = self . cf . instr_ptr + 1 ;
155+
156+ let target_ip = if idx >= 0 && ( idx as u32 ) < * len {
157+ match self . instructions . 0 . get ( start + idx as usize ) {
158+ Some ( Instruction :: BranchTableTarget ( ip) ) => * ip,
159+ _ => * default_ip,
160+ }
161+ } else {
162+ * default_ip
163+ } ;
164+ self . cf . instr_ptr = target_ip as usize ;
165+ return ControlFlow :: Continue ( ( ) ) ;
166+ }
118167 Return => return self . exec_return ( ) ,
119- EndBlockFrame => self . exec_end_block ( ) ,
120168 LocalGet32 ( local_index) => self . store . stack . values . push ( self . cf . locals . get :: < Value32 > ( * local_index) ) . to_cf ( ) ?,
121169 LocalGet64 ( local_index) => self . store . stack . values . push ( self . cf . locals . get :: < Value64 > ( * local_index) ) . to_cf ( ) ?,
122170 LocalGet128 ( local_index) => self . store . stack . values . push ( self . cf . locals . get :: < Value128 > ( * local_index) ) . to_cf ( ) ?,
@@ -588,10 +636,12 @@ impl<'store> Executor<'store> {
588636
589637 if IS_RETURN_CALL {
590638 let locals = self . store . stack . values . pop_locals ( wasm_func. params , wasm_func. locals ) ;
591- self . cf . reuse_for ( func_addr, locals, self . store . stack . blocks . len ( ) as u32 , owner) ;
639+ let stack_base = self . store . stack . values . height ( ) ;
640+ self . cf . reuse_for ( func_addr, locals, owner, stack_base) ;
592641 } else {
593642 let locals = self . store . stack . values . pop_locals ( wasm_func. params , wasm_func. locals ) ;
594- let new_call_frame = CallFrame :: new ( func_addr, owner, locals, self . store . stack . blocks . len ( ) as u32 ) ;
643+ let stack_base = self . store . stack . values . height ( ) ;
644+ let new_call_frame = CallFrame :: new ( func_addr, owner, locals, stack_base) ;
595645 self . cf . incr_instr_ptr ( ) ; // skip the call instruction
596646 self . store . stack . call_stack . push ( core:: mem:: replace ( & mut self . cf , new_call_frame) ) . to_cf ( ) ?;
597647 }
@@ -661,84 +711,7 @@ impl<'store> Executor<'store> {
661711 }
662712 }
663713
664- fn exec_if ( & mut self , else_offset : u32 , end_offset : u32 , ( params, results) : ( StackHeight , StackHeight ) ) {
665- // truthy value is on the top of the stack, so enter the then block
666- if self . store . stack . values . pop :: < i32 > ( ) != 0 {
667- self . enter_block ( end_offset, BlockType :: If , ( params, results) ) ;
668- return ;
669- }
670-
671- // falsy value is on the top of the stack
672- if else_offset == 0 {
673- self . cf . jump ( end_offset) ;
674- return ;
675- }
676-
677- self . cf . jump ( else_offset) ;
678- self . enter_block ( end_offset - else_offset, BlockType :: Else , ( params, results) ) ;
679- }
680- fn exec_else ( & mut self , end_offset : u32 ) {
681- self . exec_end_block ( ) ;
682- self . cf . jump ( end_offset) ;
683- }
684- fn resolve_functype ( & self , idx : u32 ) -> ( StackHeight , StackHeight ) {
685- let ty = self . module . func_ty ( idx) ;
686- ( ( & * ty. params ) . into ( ) , ( & * ty. results ) . into ( ) )
687- }
688- fn enter_block ( & mut self , end_instr_offset : u32 , ty : BlockType , ( params, results) : ( StackHeight , StackHeight ) ) {
689- self . store . stack . blocks . push ( BlockFrame {
690- instr_ptr : self . cf . instr_ptr as u32 ,
691- end_instr_offset,
692- stack_ptr : self . store . stack . values . height ( ) ,
693- results,
694- params,
695- ty,
696- } )
697- }
698- fn exec_br ( & mut self , to : u32 ) -> ControlFlow < Option < Error > > {
699- if self . cf . break_to ( to, & mut self . store . stack . values , & mut self . store . stack . blocks ) . is_none ( ) {
700- return self . exec_return ( ) ;
701- }
702-
703- self . cf . incr_instr_ptr ( ) ;
704- ControlFlow :: Continue ( ( ) )
705- }
706- fn exec_br_if ( & mut self , to : u32 ) -> ControlFlow < Option < Error > > {
707- if self . store . stack . values . pop :: < i32 > ( ) != 0
708- && self . cf . break_to ( to, & mut self . store . stack . values , & mut self . store . stack . blocks ) . is_none ( )
709- {
710- return self . exec_return ( ) ;
711- }
712- self . cf . incr_instr_ptr ( ) ;
713- ControlFlow :: Continue ( ( ) )
714- }
715- fn exec_brtable ( & mut self , default : u32 , len : u32 ) -> ControlFlow < Option < Error > > {
716- let start = self . cf . instr_ptr + 1 ;
717- let end = start + len as usize ;
718- if end > self . func . instructions . len ( ) {
719- return ControlFlow :: Break ( Some ( Error :: Other ( format ! (
720- "br_table out of bounds: {} >= {}" ,
721- end,
722- self . func. instructions. len( )
723- ) ) ) ) ;
724- }
725-
726- let idx = self . store . stack . values . pop :: < i32 > ( ) ;
727- let to = match self . func . instructions [ start..end] . get ( idx as usize ) {
728- None => default,
729- Some ( Instruction :: BrLabel ( to) ) => * to,
730- _ => return ControlFlow :: Break ( Some ( Error :: Other ( "br_table out of bounds" . to_string ( ) ) ) ) ,
731- } ;
732-
733- if self . cf . break_to ( to, & mut self . store . stack . values , & mut self . store . stack . blocks ) . is_none ( ) {
734- return self . exec_return ( ) ;
735- }
736-
737- self . cf . incr_instr_ptr ( ) ;
738- ControlFlow :: Continue ( ( ) )
739- }
740714 fn exec_return ( & mut self ) -> ControlFlow < Option < Error > > {
741- let old = self . cf . block_ptr ;
742715 let Some ( cf) = self . store . stack . call_stack . pop ( ) else { return ControlFlow :: Break ( None ) } ;
743716
744717 if cf. func_addr != self . cf . func_addr {
@@ -750,18 +723,9 @@ impl<'store> Executor<'store> {
750723 }
751724 }
752725
753- if old > cf. block_ptr {
754- self . store . stack . blocks . truncate ( old) ;
755- }
756-
757726 self . cf = cf;
758727 ControlFlow :: Continue ( ( ) )
759728 }
760- fn exec_end_block ( & mut self ) {
761- let block = self . store . stack . blocks . pop ( ) ;
762- self . store . stack . values . truncate_keep ( block. stack_ptr , block. results ) ;
763- }
764-
765729 fn exec_global_get ( & mut self , global_index : u32 ) -> Result < ( ) > {
766730 self . store . stack . values . push_dyn ( self . store . state . get_global_val ( self . module . resolve_global_addr ( global_index) ) )
767731 }
0 commit comments