@@ -4,7 +4,7 @@ use core::ops::{BitAnd, BitOr, BitXor, Neg};
44use tinywasm_types:: { ElementKind , ValType } ;
55
66use super :: { InterpreterRuntime , Stack } ;
7- use crate :: runtime:: { BlockType , CallFrame , LabelFrame } ;
7+ use crate :: runtime:: { BlockFrame , BlockType , CallFrame } ;
88use crate :: { cold, log, unlikely} ;
99use crate :: { Error , FuncContext , ModuleInstance , Result , Store , Trap } ;
1010
@@ -32,8 +32,13 @@ impl InterpreterRuntime {
3232 match exec_one ( & mut cf, stack, store, & current_module) {
3333 // Continue execution at the new top of the call stack
3434 Ok ( ExecResult :: Call ) => {
35+ let old = cf. block_ptr ;
3536 cf = stack. call_stack . pop ( ) ?;
3637
38+ if old > cf. block_ptr {
39+ stack. blocks . truncate ( old) ;
40+ }
41+
3742 // keeping the pointer seperate from the call frame is about 2% faster
3843 // than storing it in the call frame
3944 if cf. func_instance . 1 != current_module. id ( ) {
@@ -123,7 +128,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
123128 } ;
124129
125130 let params = stack. values . pop_n_rev ( wasm_func. ty . params . len ( ) ) ?;
126- let call_frame = CallFrame :: new ( wasm_func, func_inst. owner , params) ;
131+ let call_frame = CallFrame :: new ( wasm_func, func_inst. owner , params, stack . blocks . len ( ) ) ;
127132
128133 // push the call frame
129134 cf. instr_ptr += 1 ; // skip the call instruction
@@ -180,7 +185,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
180185 }
181186
182187 let params = stack. values . pop_n_rev ( wasm_func. ty . params . len ( ) ) ?;
183- let call_frame = CallFrame :: new ( wasm_func, func_inst. owner , params) ;
188+ let call_frame = CallFrame :: new ( wasm_func, func_inst. owner , params, stack . blocks . len ( ) ) ;
184189
185190 // push the call frame
186191 cf. instr_ptr += 1 ; // skip the call instruction
@@ -194,8 +199,8 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
194199 If ( args, else_offset, end_offset) => {
195200 // truthy value is on the top of the stack, so enter the then block
196201 if stack. values . pop_t :: < i32 > ( ) ? != 0 {
197- cf. enter_label (
198- LabelFrame :: new (
202+ cf. enter_block (
203+ BlockFrame :: new (
199204 cf. instr_ptr ,
200205 cf. instr_ptr + * end_offset,
201206 stack. values . len ( ) , // - params,
@@ -204,13 +209,14 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
204209 module,
205210 ) ,
206211 & mut stack. values ,
212+ & mut stack. blocks ,
207213 ) ;
208214 return Ok ( ExecResult :: Ok ) ;
209215 }
210216
211217 // falsy value is on the top of the stack
212218 if let Some ( else_offset) = else_offset {
213- let label = LabelFrame :: new (
219+ let label = BlockFrame :: new (
214220 cf. instr_ptr + * else_offset,
215221 cf. instr_ptr + * end_offset,
216222 stack. values . len ( ) , // - params,
@@ -219,15 +225,15 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
219225 module,
220226 ) ;
221227 cf. instr_ptr += * else_offset;
222- cf. enter_label ( label, & mut stack. values ) ;
228+ cf. enter_block ( label, & mut stack. values , & mut stack . blocks ) ;
223229 } else {
224230 cf. instr_ptr += * end_offset;
225231 }
226232 }
227233
228234 Loop ( args, end_offset) => {
229- cf. enter_label (
230- LabelFrame :: new (
235+ cf. enter_block (
236+ BlockFrame :: new (
231237 cf. instr_ptr ,
232238 cf. instr_ptr + * end_offset,
233239 stack. values . len ( ) , // - params,
@@ -236,12 +242,13 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
236242 module,
237243 ) ,
238244 & mut stack. values ,
245+ & mut stack. blocks ,
239246 ) ;
240247 }
241248
242249 Block ( args, end_offset) => {
243- cf. enter_label (
244- LabelFrame :: new (
250+ cf. enter_block (
251+ BlockFrame :: new (
245252 cf. instr_ptr ,
246253 cf. instr_ptr + * end_offset,
247254 stack. values . len ( ) , // - params,
@@ -250,6 +257,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
250257 module,
251258 ) ,
252259 & mut stack. values ,
260+ & mut stack. blocks ,
253261 ) ;
254262 }
255263
@@ -291,10 +299,10 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
291299 } ,
292300
293301 EndFunc => {
294- assert ! (
295- cf . labels . len ( ) == 0 ,
296- "endfunc: block frames not empty, this should have been validated by the parser"
297- ) ;
302+ if stack . blocks . len ( ) != cf . block_ptr {
303+ cold ( ) ;
304+ panic ! ( "endfunc: block frames not empty, this should have been validated by the parser" ) ;
305+ }
298306
299307 match stack. call_stack . is_empty ( ) {
300308 true => return Ok ( ExecResult :: Return ) ,
@@ -304,7 +312,7 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
304312
305313 // We're essentially using else as a EndBlockFrame instruction for if blocks
306314 Else ( end_offset) => {
307- let Some ( block) = cf . labels . pop ( ) else {
315+ let Some ( block) = stack . blocks . pop ( ) else {
308316 cold ( ) ;
309317 panic ! ( "else: no label to end, this should have been validated by the parser" ) ;
310318 } ;
@@ -316,16 +324,28 @@ fn exec_one(cf: &mut CallFrame, stack: &mut Stack, store: &mut Store, module: &M
316324
317325 EndBlockFrame => {
318326 // remove the label from the label stack
319- let Some ( block) = cf . labels . pop ( ) else {
327+ let Some ( block) = stack . blocks . pop ( ) else {
320328 cold ( ) ;
321- panic ! ( "end: no label to end, this should have been validated by the parser" ) ;
329+ panic ! ( "end blockframe : no label to end, this should have been validated by the parser" ) ;
322330 } ;
323- stack. values . truncate_keep ( block. stack_ptr , block. results )
331+
332+ stack. values . truncate_keep ( block. stack_ptr , block. results ) ;
324333 }
325334
326335 LocalGet ( local_index) => stack. values . push ( cf. get_local ( * local_index as usize ) ) ,
327336 LocalSet ( local_index) => cf. set_local ( * local_index as usize , stack. values . pop ( ) ?) ,
328- LocalTee ( local_index) => cf. set_local ( * local_index as usize , * stack. values . last ( ) ?) ,
337+ LocalTee ( local_index) => {
338+ let last_val = match stack. values . last ( ) {
339+ Ok ( val) => val,
340+ Err ( _) => {
341+ log:: error!( "index: {}" , local_index) ;
342+ log:: error!( "stack: {:?}" , stack. values) ;
343+
344+ panic ! ( ) ;
345+ }
346+ } ;
347+ cf. set_local ( * local_index as usize , * last_val)
348+ }
329349
330350 GlobalGet ( global_index) => {
331351 let idx = module. resolve_global_addr ( * global_index) ;
0 commit comments