diff --git a/benchmarks/wasm/wasmfx/fun-pipes-strip.wast b/benchmarks/wasm/wasmfx/fun-pipes-strip.wast index b837f4414..621d7890e 100644 --- a/benchmarks/wasm/wasmfx/fun-pipes-strip.wast +++ b/benchmarks/wasm/wasmfx/fun-pipes-strip.wast @@ -9,13 +9,18 @@ (type (;7;) (func (result i32 (ref 2)))) (type (;8;) (func (param (ref 2) (ref 3)))) (type (;9;) (func)) - (import "spectest" "print_i32" (func (;0;) (type 4))) + ;; (import "spectest" "print_i32" (func (;0;) (type 4))) + (tag (;0;) (type 4) (param i32)) (tag (;1;) (type 0) (result i32)) (export "pipe" (func 3)) (export "run" (func 6)) (start 7) + (export "main" (func 7)) (elem (;0;) declare func 4 5) + (func (type 4) (param i32) + ) + (func (;1;) (type 5) (param i32 (ref 2) (ref 3)) block (result (ref 3)) ;; label = @1 local.get 0 @@ -68,7 +73,7 @@ ) (func (;5;) (type 1) (param i32) (result i32) (local i32 i32) - i32.const 10 + i32.const 3 local.set 1 i32.const 0 local.set 2 @@ -105,7 +110,7 @@ call 3 ) (func (;7;) (type 9) - i32.const 0 + i32.const 1 call 6 ) ) \ No newline at end of file diff --git a/benchmarks/wasm/wasmfx/fun-pipes.trace b/benchmarks/wasm/wasmfx/fun-pipes.trace new file mode 100644 index 000000000..112a19b5a --- /dev/null +++ b/benchmarks/wasm/wasmfx/fun-pipes.trace @@ -0,0 +1,388 @@ ++1: i32.const[1] | | ++3: call[func=6] | | 1 + +1: local.get[0] | 1 | + +3: ref.func[func=4] | 1 | 1 + +5: cont.new[cont=3] | 1 | 1 + +7: cont.bind[cont=3,cont=2] | 1 | 1 + +10: ref.func[func=5] | 1 | + +12: cont.new[cont=3] | 1 | + +14: call[func=3] | 1 | + +1: i32.const[-1] | | + +3: local.get[0] | | 4294967295 + +5: local.get[1] | | 4294967295 + +7: call[func=1] | | 4294967295 + +1: block[(ref cont #3)] | 4294967295 | + +4: local.get[0] | 4294967295 | + +6: local.get[2] | 4294967295 | 4294967295 + +8: resume[cont=3,1...] | 4294967295 | 4294967295 ++3: i32.const[3] | 4294967295 0 0 | ++5: local.set[1] | 4294967295 0 0 | 3 ++7: i32.const[0] | 4294967295 3 0 | ++9: local.set[2] | 4294967295 3 0 | 0 ++11: loop[] | 4294967295 3 0 | ++13: local.get[2] | 4294967295 3 0 | ++15: suspend[tag=1] | 4294967295 3 0 | 0 + +15: end | 4294967295 | + +16: local.set[2] | 4294967295 | + +18: local.get[2] | 4294967295 | + +20: local.get[1] | 4294967295 | + +22: return_call[func=2] | 4294967295 | + +3: block[[] -> [i32 (ref cont #2)]] | 0 | + +5: local.get[1] | 0 | + +7: resume[cont=2,1...] | 0 | ++1: loop[] | 1 | ++3: i32.const[-1] | 1 | ++5: call[func=0] | 1 | 4294967295 + +1: end | 4294967295 | ++7: local.get[0] | 1 | ++9: call[func=0] | 1 | 1 + +1: end | 1 | ++11: local.get[0] | 1 | ++13: suspend[tag=0] | 1 | 1 + +14: end | 0 | 1 + +15: local.set[1] | 0 | 1 + +17: local.set[2] | 0 | 1 + +19: local.get[2] | 1 | + +21: local.get[1] | 1 | 1 + +23: local.get[0] | 1 | 1 + +25: return_call[func=1] | 1 | 1 + +1: block[(ref cont #3)] | 1 | + +4: local.get[0] | 1 | + +6: local.get[2] | 1 | 1 + +8: resume[cont=3,1...] | 1 | 1 ++17: i32.const[55555] | 4294967295 3 0 | 0 1 ++21: call[func=0] | 4294967295 3 0 | 0 1 55555 + +1: end | 55555 | ++23: i32.add | 4294967295 3 0 | 0 1 ++24: local.set[2] | 4294967295 3 0 | 1 ++26: i32.const[-2] | 4294967295 3 1 | ++28: call[func=0] | 4294967295 3 1 | 4294967294 + +1: end | 4294967294 | ++30: local.get[2] | 4294967295 3 1 | ++32: call[func=0] | 4294967295 3 1 | 1 + +1: end | 1 | ++34: local.get[1] | 4294967295 3 1 | ++36: i32.const[1] | 4294967295 3 1 | 3 ++38: i32.sub | 4294967295 3 1 | 3 1 ++39: local.set[1] | 4294967295 3 1 | 2 ++41: local.get[1] | 4294967295 2 1 | ++43: i32.const[0] | 4294967295 2 1 | 2 ++45: i32.ne | 4294967295 2 1 | 2 0 ++46: br_if[depth=0] | 4294967295 2 1 | 1 ++11: loop[] | 4294967295 2 1 | ++13: local.get[2] | 4294967295 2 1 | ++15: suspend[tag=1] | 4294967295 2 1 | 1 + +15: end | 1 | + +16: local.set[2] | 1 | + +18: local.get[2] | 1 | + +20: local.get[1] | 1 | + +22: return_call[func=2] | 1 | + +3: block[[] -> [i32 (ref cont #2)]] | 0 | + +5: local.get[1] | 0 | + +7: resume[cont=2,1...] | 0 | ++15: i32.const[44444] | 1 | ++19: call[func=0] | 1 | 44444 + +1: end | 44444 | ++21: local.get[0] | 1 | ++23: i32.const[1] | 1 | 1 ++25: i32.add | 1 | 1 1 ++26: local.set[0] | 1 | 2 ++28: br[depth=0] | 2 | ++1: loop[] | 2 | ++3: i32.const[-1] | 2 | ++5: call[func=0] | 2 | 4294967295 + +1: end | 4294967295 | ++7: local.get[0] | 2 | ++9: call[func=0] | 2 | 2 + +1: end | 2 | ++11: local.get[0] | 2 | ++13: suspend[tag=0] | 2 | 2 + +14: end | 0 | 2 + +15: local.set[1] | 0 | 2 + +17: local.set[2] | 0 | 2 + +19: local.get[2] | 2 | + +21: local.get[1] | 2 | 2 + +23: local.get[0] | 2 | 2 + +25: return_call[func=1] | 2 | 2 + +1: block[(ref cont #3)] | 2 | + +4: local.get[0] | 2 | + +6: local.get[2] | 2 | 2 + +8: resume[cont=3,1...] | 2 | 2 ++17: i32.const[55555] | 4294967295 2 1 | 1 2 ++21: call[func=0] | 4294967295 2 1 | 1 2 55555 + +1: end | 55555 | ++23: i32.add | 4294967295 2 1 | 1 2 ++24: local.set[2] | 4294967295 2 1 | 3 ++26: i32.const[-2] | 4294967295 2 3 | ++28: call[func=0] | 4294967295 2 3 | 4294967294 + +1: end | 4294967294 | ++30: local.get[2] | 4294967295 2 3 | ++32: call[func=0] | 4294967295 2 3 | 3 + +1: end | 3 | ++34: local.get[1] | 4294967295 2 3 | ++36: i32.const[1] | 4294967295 2 3 | 2 ++38: i32.sub | 4294967295 2 3 | 2 1 ++39: local.set[1] | 4294967295 2 3 | 1 ++41: local.get[1] | 4294967295 1 3 | ++43: i32.const[0] | 4294967295 1 3 | 1 ++45: i32.ne | 4294967295 1 3 | 1 0 ++46: br_if[depth=0] | 4294967295 1 3 | 1 ++11: loop[] | 4294967295 1 3 | ++13: local.get[2] | 4294967295 1 3 | ++15: suspend[tag=1] | 4294967295 1 3 | 3 + +15: end | 2 | + +16: local.set[2] | 2 | + +18: local.get[2] | 2 | + +20: local.get[1] | 2 | + +22: return_call[func=2] | 2 | + +3: block[[] -> [i32 (ref cont #2)]] | 0 | + +5: local.get[1] | 0 | + +7: resume[cont=2,1...] | 0 | ++15: i32.const[44444] | 2 | ++19: call[func=0] | 2 | 44444 + +1: end | 44444 | ++21: local.get[0] | 2 | ++23: i32.const[1] | 2 | 2 ++25: i32.add | 2 | 2 1 ++26: local.set[0] | 2 | 3 ++28: br[depth=0] | 3 | ++1: loop[] | 3 | ++3: i32.const[-1] | 3 | ++5: call[func=0] | 3 | 4294967295 + +1: end | 4294967295 | ++7: local.get[0] | 3 | ++9: call[func=0] | 3 | 3 + +1: end | 3 | ++11: local.get[0] | 3 | ++13: suspend[tag=0] | 3 | 3 + +14: end | 0 | 3 + +15: local.set[1] | 0 | 3 + +17: local.set[2] | 0 | 3 + +19: local.get[2] | 3 | + +21: local.get[1] | 3 | 3 + +23: local.get[0] | 3 | 3 + +25: return_call[func=1] | 3 | 3 + +1: block[(ref cont #3)] | 3 | + +4: local.get[0] | 3 | + +6: local.get[2] | 3 | 3 + +8: resume[cont=3,1...] | 3 | 3 ++17: i32.const[55555] | 4294967295 1 3 | 3 3 ++21: call[func=0] | 4294967295 1 3 | 3 3 55555 + +1: end | 55555 | ++23: i32.add | 4294967295 1 3 | 3 3 ++24: local.set[2] | 4294967295 1 3 | 6 ++26: i32.const[-2] | 4294967295 1 6 | ++28: call[func=0] | 4294967295 1 6 | 4294967294 + +1: end | 4294967294 | ++30: local.get[2] | 4294967295 1 6 | ++32: call[func=0] | 4294967295 1 6 | 6 + +1: end | 6 | ++34: local.get[1] | 4294967295 1 6 | ++36: i32.const[1] | 4294967295 1 6 | 1 ++38: i32.sub | 4294967295 1 6 | 1 1 ++39: local.set[1] | 4294967295 1 6 | 0 ++41: local.get[1] | 4294967295 0 6 | ++43: i32.const[0] | 4294967295 0 6 | 0 ++45: i32.ne | 4294967295 0 6 | 0 0 ++46: br_if[depth=0] | 4294967295 0 6 | 0 ++48: end | 4294967295 0 6 | ++49: local.get[2] | 4294967295 0 6 | ++51: return | 4294967295 0 6 | 6 + +14: return | 3 | 6 + +9: end | | + +16: end | 1 | ++5: end | | ++1: i32.const[1] | | ++3: call[func=6] | | 1 + +1: local.get[0] | 1 | + +3: ref.func[func=4] | 1 | 1 + +5: cont.new[cont=3] | 1 | 1 + +7: cont.bind[cont=3,cont=2] | 1 | 1 + +10: ref.func[func=5] | 1 | + +12: cont.new[cont=3] | 1 | + +14: call[func=3] | 1 | + +1: i32.const[-1] | | + +3: local.get[0] | | 4294967295 + +5: local.get[1] | | 4294967295 + +7: call[func=1] | | 4294967295 + +1: block[(ref cont #3)] | 4294967295 | + +4: local.get[0] | 4294967295 | + +6: local.get[2] | 4294967295 | 4294967295 + +8: resume[cont=3,1...] | 4294967295 | 4294967295 ++3: i32.const[3] | 4294967295 0 0 | ++5: local.set[1] | 4294967295 0 0 | 3 ++7: i32.const[0] | 4294967295 3 0 | ++9: local.set[2] | 4294967295 3 0 | 0 ++11: loop[] | 4294967295 3 0 | ++13: local.get[2] | 4294967295 3 0 | ++15: suspend[tag=1] | 4294967295 3 0 | 0 + +15: end | 4294967295 | + +16: local.set[2] | 4294967295 | + +18: local.get[2] | 4294967295 | + +20: local.get[1] | 4294967295 | + +22: return_call[func=2] | 4294967295 | + +3: block[[] -> [i32 (ref cont #2)]] | 0 | + +5: local.get[1] | 0 | + +7: resume[cont=2,1...] | 0 | ++1: loop[] | 1 | ++3: i32.const[-1] | 1 | ++5: call[func=0] | 1 | 4294967295 + +1: end | 4294967295 | ++7: local.get[0] | 1 | ++9: call[func=0] | 1 | 1 + +1: end | 1 | ++11: local.get[0] | 1 | ++13: suspend[tag=0] | 1 | 1 + +14: end | 0 | 1 + +15: local.set[1] | 0 | 1 + +17: local.set[2] | 0 | 1 + +19: local.get[2] | 1 | + +21: local.get[1] | 1 | 1 + +23: local.get[0] | 1 | 1 + +25: return_call[func=1] | 1 | 1 + +1: block[(ref cont #3)] | 1 | + +4: local.get[0] | 1 | + +6: local.get[2] | 1 | 1 + +8: resume[cont=3,1...] | 1 | 1 ++17: i32.const[55555] | 4294967295 3 0 | 0 1 ++21: call[func=0] | 4294967295 3 0 | 0 1 55555 + +1: end | 55555 | ++23: i32.add | 4294967295 3 0 | 0 1 ++24: local.set[2] | 4294967295 3 0 | 1 ++26: i32.const[-2] | 4294967295 3 1 | ++28: call[func=0] | 4294967295 3 1 | 4294967294 + +1: end | 4294967294 | ++30: local.get[2] | 4294967295 3 1 | ++32: call[func=0] | 4294967295 3 1 | 1 + +1: end | 1 | ++34: local.get[1] | 4294967295 3 1 | ++36: i32.const[1] | 4294967295 3 1 | 3 ++38: i32.sub | 4294967295 3 1 | 3 1 ++39: local.set[1] | 4294967295 3 1 | 2 ++41: local.get[1] | 4294967295 2 1 | ++43: i32.const[0] | 4294967295 2 1 | 2 ++45: i32.ne | 4294967295 2 1 | 2 0 ++46: br_if[depth=0] | 4294967295 2 1 | 1 ++11: loop[] | 4294967295 2 1 | ++13: local.get[2] | 4294967295 2 1 | ++15: suspend[tag=1] | 4294967295 2 1 | 1 + +15: end | 1 | + +16: local.set[2] | 1 | + +18: local.get[2] | 1 | + +20: local.get[1] | 1 | + +22: return_call[func=2] | 1 | + +3: block[[] -> [i32 (ref cont #2)]] | 0 | + +5: local.get[1] | 0 | + +7: resume[cont=2,1...] | 0 | ++15: i32.const[44444] | 1 | ++19: call[func=0] | 1 | 44444 + +1: end | 44444 | ++21: local.get[0] | 1 | ++23: i32.const[1] | 1 | 1 ++25: i32.add | 1 | 1 1 ++26: local.set[0] | 1 | 2 ++28: br[depth=0] | 2 | ++1: loop[] | 2 | ++3: i32.const[-1] | 2 | ++5: call[func=0] | 2 | 4294967295 + +1: end | 4294967295 | ++7: local.get[0] | 2 | ++9: call[func=0] | 2 | 2 + +1: end | 2 | ++11: local.get[0] | 2 | ++13: suspend[tag=0] | 2 | 2 + +14: end | 0 | 2 + +15: local.set[1] | 0 | 2 + +17: local.set[2] | 0 | 2 + +19: local.get[2] | 2 | + +21: local.get[1] | 2 | 2 + +23: local.get[0] | 2 | 2 + +25: return_call[func=1] | 2 | 2 + +1: block[(ref cont #3)] | 2 | + +4: local.get[0] | 2 | + +6: local.get[2] | 2 | 2 + +8: resume[cont=3,1...] | 2 | 2 ++17: i32.const[55555] | 4294967295 2 1 | 1 2 ++21: call[func=0] | 4294967295 2 1 | 1 2 55555 + +1: end | 55555 | ++23: i32.add | 4294967295 2 1 | 1 2 ++24: local.set[2] | 4294967295 2 1 | 3 ++26: i32.const[-2] | 4294967295 2 3 | ++28: call[func=0] | 4294967295 2 3 | 4294967294 + +1: end | 4294967294 | ++30: local.get[2] | 4294967295 2 3 | ++32: call[func=0] | 4294967295 2 3 | 3 + +1: end | 3 | ++34: local.get[1] | 4294967295 2 3 | ++36: i32.const[1] | 4294967295 2 3 | 2 ++38: i32.sub | 4294967295 2 3 | 2 1 ++39: local.set[1] | 4294967295 2 3 | 1 ++41: local.get[1] | 4294967295 1 3 | ++43: i32.const[0] | 4294967295 1 3 | 1 ++45: i32.ne | 4294967295 1 3 | 1 0 ++46: br_if[depth=0] | 4294967295 1 3 | 1 ++11: loop[] | 4294967295 1 3 | ++13: local.get[2] | 4294967295 1 3 | ++15: suspend[tag=1] | 4294967295 1 3 | 3 + +15: end | 2 | + +16: local.set[2] | 2 | + +18: local.get[2] | 2 | + +20: local.get[1] | 2 | + +22: return_call[func=2] | 2 | + +3: block[[] -> [i32 (ref cont #2)]] | 0 | + +5: local.get[1] | 0 | + +7: resume[cont=2,1...] | 0 | ++15: i32.const[44444] | 2 | ++19: call[func=0] | 2 | 44444 + +1: end | 44444 | ++21: local.get[0] | 2 | ++23: i32.const[1] | 2 | 2 ++25: i32.add | 2 | 2 1 ++26: local.set[0] | 2 | 3 ++28: br[depth=0] | 3 | ++1: loop[] | 3 | ++3: i32.const[-1] | 3 | ++5: call[func=0] | 3 | 4294967295 + +1: end | 4294967295 | ++7: local.get[0] | 3 | ++9: call[func=0] | 3 | 3 + +1: end | 3 | ++11: local.get[0] | 3 | ++13: suspend[tag=0] | 3 | 3 + +14: end | 0 | 3 + +15: local.set[1] | 0 | 3 + +17: local.set[2] | 0 | 3 + +19: local.get[2] | 3 | + +21: local.get[1] | 3 | 3 + +23: local.get[0] | 3 | 3 + +25: return_call[func=1] | 3 | 3 + +1: block[(ref cont #3)] | 3 | + +4: local.get[0] | 3 | + +6: local.get[2] | 3 | 3 + +8: resume[cont=3,1...] | 3 | 3 ++17: i32.const[55555] | 4294967295 1 3 | 3 3 ++21: call[func=0] | 4294967295 1 3 | 3 3 55555 + +1: end | 55555 | ++23: i32.add | 4294967295 1 3 | 3 3 ++24: local.set[2] | 4294967295 1 3 | 6 ++26: i32.const[-2] | 4294967295 1 6 | ++28: call[func=0] | 4294967295 1 6 | 4294967294 + +1: end | 4294967294 | ++30: local.get[2] | 4294967295 1 6 | ++32: call[func=0] | 4294967295 1 6 | 6 + +1: end | 6 | ++34: local.get[1] | 4294967295 1 6 | ++36: i32.const[1] | 4294967295 1 6 | 1 ++38: i32.sub | 4294967295 1 6 | 1 1 ++39: local.set[1] | 4294967295 1 6 | 0 ++41: local.get[1] | 4294967295 0 6 | ++43: i32.const[0] | 4294967295 0 6 | 0 ++45: i32.ne | 4294967295 0 6 | 0 0 ++46: br_if[depth=0] | 4294967295 0 6 | 0 ++48: end | 4294967295 0 6 | ++49: local.get[2] | 4294967295 0 6 | ++51: return | 4294967295 0 6 | 6 + +14: return | 3 | 6 + +9: end | | + +16: end | 1 | ++5: end | | diff --git a/benchmarks/wasm/wasmfx/fun-pipes.trace1 b/benchmarks/wasm/wasmfx/fun-pipes.trace1 new file mode 100644 index 000000000..456da1ed0 --- /dev/null +++ b/benchmarks/wasm/wasmfx/fun-pipes.trace1 @@ -0,0 +1,151 @@ +[DEBUG] Const(I32V(1)) | Frame(ArrayBuffer()) | List() +[DEBUG] Call(6) | Frame(ArrayBuffer()) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] RefFunc(4) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] ContNew(3) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1), RefFuncV(4)) +[DEBUG] ContBind(3,2) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@b0ce19e)) +[DEBUG] RefFunc(5) | Frame(ArrayBuffer(I32V(1))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] ContNew(3) | Frame(ArrayBuffer(I32V(1))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), RefFuncV(5)) +[DEBUG] Call(3) | Frame(ArrayBuffer(I32V(1))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220)) +[DEBUG] Const(I32V(-1)) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List() +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List(I32V(-1)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Call(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220)) +[DEBUG] Block(...) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List() +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List() +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List(I32V(-1)) +[DEBUG] Resume(3,List(Handler(1,0))) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220)) +[DEBUG] Const(I32V(3)) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(0))) | List() +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(0))) | List(I32V(3)) +[DEBUG] Const(I32V(0)) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List() +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List(I32V(0)) +[DEBUG] Loop(...) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List() +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List() +[DEBUG] Suspend(1) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List(I32V(0)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$449/0x000076069f2a2c60@16482220))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d)) +[DEBUG] ReturnCall(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Block(...) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List() +[DEBUG] Resume(2,List(Handler(0,0))) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Loop(...) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Const(I32V(-1)) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(-1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Suspend(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), I32V(0))) | List(I32V(1)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), I32V(1))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615)) +[DEBUG] ReturnCall(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d)) +[DEBUG] Block(...) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List() +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List() +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List(I32V(1)) +[DEBUG] Resume(3,List(Handler(1,0))) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@2a142615), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d)) +[DEBUG] Const(I32V(55555)) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List(I32V(0), I32V(1)) +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List(I32V(0), I32V(1), I32V(55555)) +[DEBUG] Binary(Add(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List(I32V(0), I32V(1)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(0))) | List(I32V(1)) +[DEBUG] Const(I32V(-2)) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List(I32V(-2)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List() +[DEBUG] Const(I32V(1)) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List(I32V(3)) +[DEBUG] Binary(Sub(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List(I32V(3), I32V(1)) +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(I32V(-1), I32V(3), I32V(1))) | List(I32V(2)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List() +[DEBUG] Const(I32V(0)) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(2)) +[DEBUG] Compare(Ne(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(2), I32V(0)) +[DEBUG] BrIf(0) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List() +[DEBUG] Suspend(1) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(1)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@3c95c61d))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f)) +[DEBUG] ReturnCall(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Block(...) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List() +[DEBUG] Resume(2,List(Handler(0,0))) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Loop(...) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Const(I32V(-1)) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(-1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Suspend(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), I32V(0))) | List(I32V(1)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), I32V(1))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7)) +[DEBUG] ReturnCall(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f)) +[DEBUG] Block(...) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List() +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List() +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List(I32V(1)) +[DEBUG] Resume(3,List(Handler(1,0))) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@5ea80a7), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f)) +[DEBUG] Const(I32V(55555)) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(1), I32V(1)) +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(1), I32V(1), I32V(55555)) +[DEBUG] Binary(Add(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(1), I32V(1)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(1))) | List(I32V(2)) +[DEBUG] Const(I32V(-2)) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List(I32V(-2)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List(I32V(2)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List() +[DEBUG] Const(I32V(1)) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List(I32V(2)) +[DEBUG] Binary(Sub(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List(I32V(2), I32V(1)) +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(I32V(-1), I32V(2), I32V(2))) | List(I32V(1)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List() +[DEBUG] Const(I32V(0)) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(1)) +[DEBUG] Compare(Ne(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(1), I32V(0)) +[DEBUG] BrIf(0) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(1)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List() +[DEBUG] Suspend(1) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(2)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@175d097f))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81)) +[DEBUG] ReturnCall(2) | Frame(ArrayBuffer(I32V(-1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Block(...) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List() +[DEBUG] Resume(2,List(Handler(0,0))) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241)) +[DEBUG] Loop(...) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Const(I32V(-1)) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(-1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1))) | List() +[DEBUG] Suspend(0) | Frame(ArrayBuffer(I32V(1))) | List(I32V(1)) +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$450/0x000076069f2a3c40@3a698241), I32V(0))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), I32V(0))) | List(I32V(1)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), I32V(1))) | List() +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), I32V(1))) | List(I32V(1)) +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9)) +[DEBUG] ReturnCall(1) | Frame(ArrayBuffer(ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), I32V(1))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81)) +[DEBUG] Block(...) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List() +[DEBUG] LocalGet(0) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List() +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List(I32V(1)) +[DEBUG] Resume(3,List(Handler(1,0))) | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81)) +[DEBUG] Const(I32V(55555)) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(2), I32V(1)) +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(2), I32V(1), I32V(55555)) +[DEBUG] Binary(Add(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(2), I32V(1)) +[DEBUG] LocalSet(2) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(2))) | List(I32V(3)) +[DEBUG] Const(I32V(-2)) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List(I32V(-2)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List() +[DEBUG] Call(0) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List(I32V(3)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List() +[DEBUG] Const(I32V(1)) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List(I32V(1)) +[DEBUG] Binary(Sub(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List(I32V(1), I32V(1)) +[DEBUG] LocalSet(1) | Frame(ArrayBuffer(I32V(-1), I32V(1), I32V(3))) | List(I32V(0)) +[DEBUG] LocalGet(1) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(3))) | List() +[DEBUG] Const(I32V(0)) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(3))) | List(I32V(0)) +[DEBUG] Compare(Ne(NumType(I32Type))) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(3))) | List(I32V(0), I32V(0)) +[DEBUG] BrIf(0) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(3))) | List(I32V(0)) +[DEBUG] LocalGet(2) | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(3))) | List() +[DEBUG] Return | Frame(ArrayBuffer(I32V(-1), I32V(0), I32V(3))) | List(I32V(3)) +[DEBUG] Return | Frame(ArrayBuffer(I32V(1), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@4b1f77c9), ContV(gensym.wasm.miniwasm.EvaluatorFX$$Lambda$454/0x000076069f2aacb8@e452a81))) | List(I32V(3)) \ No newline at end of file diff --git a/benchmarks/wasm/wasmfx/fun-state-strip.wat b/benchmarks/wasm/wasmfx/fun-state-strip.wat new file mode 100644 index 000000000..3a05afade --- /dev/null +++ b/benchmarks/wasm/wasmfx/fun-state-strip.wat @@ -0,0 +1,59 @@ +(module + (type (;0;) (func (param i32) (result i32))) + (type (;1;) (func (result i32))) + (type (;2;) (cont 0)) + (type (;3;) (cont 1)) + (type (;4;) (func (param i32))) + (type (;5;) (func (param (ref 2) i32) (result i32))) + (type (;6;) (func (result i32 (ref 3)))) + (type (;7;) (func (param i32 (ref 3)) (result i32))) + (tag (;0;) (type 1) (result i32)) + (tag (;1;) (type 4) (param i32)) + (export "main" (func 3)) + (start 3) + (elem (;0;) declare func 2) + (func (;0;) (type 5) (param (ref 2) i32) (result i32) + block (result (ref 2)) ;; label = @1 + block (type 6) (result i32 (ref 3)) ;; label = @2 + local.get 1 + local.get 0 + resume 2 (on 0 1 (;@1;)) (on 1 0 (;@2;)) + return + end + return_call 1 + end + local.get 1 + return_call 0 + ) + (func (;1;) (type 7) (param i32 (ref 3)) (result i32) + block (result (ref 2)) ;; label = @1 + block (type 6) (result i32 (ref 3)) ;; label = @2 + local.get 1 + resume 3 (on 0 1 (;@1;)) (on 1 0 (;@2;)) + return + end + return_call 1 + end + local.get 0 + return_call 0 + ) + (func (;2;) (type 1) (result i32) + i32.const 7 + suspend 1 + suspend 0 + i32.const 2 + i32.const 3 + suspend 1 + i32.const 3 + suspend 0 + i32.add + i32.mul + i32.add + ) + (func (;3;) (type 1) (result i32) + i32.const 0 + ref.func 2 + cont.new 3 + call 1 + ) +) diff --git a/benchmarks/wasm/wasmfx/fun-state.bin.wast b/benchmarks/wasm/wasmfx/fun-state.bin.wast new file mode 100644 index 000000000..fe7d9b340 --- /dev/null +++ b/benchmarks/wasm/wasmfx/fun-state.bin.wast @@ -0,0 +1,18 @@ +(module definition $state binary + "\00\61\73\6d\01\00\00\00\01\a6\80\80\80\00\08\60" + "\01\7f\01\7f\60\00\01\7f\5d\00\5d\01\60\01\7f\00" + "\60\02\64\02\7f\01\7f\60\00\02\7f\64\03\60\02\7f" + "\64\03\01\7f\03\85\80\80\80\00\04\05\07\01\01\0d" + "\85\80\80\80\00\02\00\01\00\04\07\87\80\80\80\00" + "\01\03\72\75\6e\00\03\09\85\80\80\80\00\01\03\00" + "\01\02\0a\ec\80\80\80\00\04\9d\80\80\80\00\00\02" + "\64\02\02\06\20\01\20\00\e3\02\02\00\00\01\00\01" + "\00\0f\0b\12\01\0b\20\01\12\00\0b\9b\80\80\80\00" + "\00\02\64\02\02\06\20\01\e3\03\02\00\00\01\00\01" + "\00\0f\0b\12\01\0b\20\00\12\00\0b\95\80\80\80\00" + "\00\41\07\e2\01\e2\00\41\02\41\03\e2\01\41\03\e2" + "\00\6a\6c\6a\0b\8a\80\80\80\00\00\41\00\d2\02\e0" + "\03\10\01\0b" +) +(module instance $state $state) +(assert_return (invoke "run") (i32.const 0x13)) diff --git a/benchmarks/wasm/wasmfx/fun-state.strip.wat b/benchmarks/wasm/wasmfx/fun-state.strip.wat deleted file mode 100644 index 399640459..000000000 --- a/benchmarks/wasm/wasmfx/fun-state.strip.wat +++ /dev/null @@ -1,59 +0,0 @@ -(module $state - (type $gf (;0;) (func (param i32) (result i32))) - (type $sf (;1;) (func (result i32))) - (type $gk (;2;) (cont $gf)) - (type $sk (;3;) (cont $sf)) - (type (;4;) (func (param i32))) - (type (;5;) (func (param (ref $gk) i32) (result i32))) - (type (;6;) (func (result i32 (ref $sk)))) - (type (;7;) (func (param i32 (ref $sk)) (result i32))) - (tag $get (;0;) (type $sf) (result i32)) - (tag $set (;1;) (type 4) (param i32)) - ;; (export "run" (func $run)) - (export "main" (func $run)) - (elem (;0;) declare func $f) - (func $getting (;0;) (type 5) (param $k (ref $gk)) (param $s i32) (result i32) - block $on_get (result (ref $gk)) - block $on_set (type 6) (result i32 (ref $sk)) - local.get $s - local.get $k - resume $gk (on $get $on_get) (on $set $on_set) - return - end - return_call $setting - end - local.get $s - return_call $getting - ) - (func $setting (;1;) (type 7) (param $s i32) (param $k (ref $sk)) (result i32) - block $on_get (result (ref $gk)) - block $on_set (type 6) (result i32 (ref $sk)) - local.get $k - resume $sk (on $get $on_get) (on $set $on_set) - return - end - return_call $setting - end - local.get $s - return_call $getting - ) - (func $f (;2;) (type $sf) (result i32) - i32.const 7 - suspend $set - suspend $get - i32.const 2 - i32.const 3 - suspend $set - i32.const 3 - suspend $get - i32.add - i32.mul - i32.add - ) - (func $run (;3;) (type $sf) (result i32) - i32.const 0 - ref.func $f - cont.new $sk - call $setting - ) -) diff --git a/benchmarks/wasm/wasmfx/fun-state.wast b/benchmarks/wasm/wasmfx/fun-state.wast index 4e43943f4..c5d8712cd 100644 --- a/benchmarks/wasm/wasmfx/fun-state.wast +++ b/benchmarks/wasm/wasmfx/fun-state.wast @@ -58,4 +58,4 @@ ) ) -;; (assert_return (invoke "run") (i32.const 19)) \ No newline at end of file +(assert_return (invoke "run") (i32.const 19)) \ No newline at end of file diff --git a/src/main/scala/wasm/AST.scala b/src/main/scala/wasm/AST.scala index 623e271ae..93506e15f 100644 --- a/src/main/scala/wasm/AST.scala +++ b/src/main/scala/wasm/AST.scala @@ -62,9 +62,13 @@ case object Drop extends Instr case object Alloc extends Instr case object Free extends Instr case class Select(ty: Option[List[ValueType]]) extends Instr -case class Block(ty: BlockType, instrs: List[Instr]) extends Instr +case class Block(ty: BlockType, instrs: List[Instr]) extends Instr { + override def toString: String = s"Block(...)" +} case class IdBlock(id: Int, ty: BlockType, instrs: List[Instr]) extends Instr -case class Loop(ty: BlockType, instrs: List[Instr]) extends Instr +case class Loop(ty: BlockType, instrs: List[Instr]) extends Instr { + override def toString: String = s"Loop(...)" +} case class IdLoop(id: Int, ty: BlockType, instrs: List[Instr]) extends Instr case class If(ty: BlockType, thenInstrs: List[Instr], elseInstrs: List[Instr]) extends Instr case class IdIf(ty: BlockType, thenInstrs: IdBlock, elseInstrs: IdBlock) extends Instr diff --git a/src/main/scala/wasm/MiniWasmFX.scala b/src/main/scala/wasm/MiniWasmFX.scala index f1a9eda6d..ec49aa47e 100644 --- a/src/main/scala/wasm/MiniWasmFX.scala +++ b/src/main/scala/wasm/MiniWasmFX.scala @@ -15,7 +15,7 @@ case class EvaluatorFX(module: ModuleInstance) { type Stack = List[Value] trait Cont[A] { - def apply(stack: Stack, trail: Trail[A], mcont: MCont[A]): A + def apply(stack: Stack, trail: Trail[A], mcont: MCont[A], handler: Handlers[A]): A } type Trail[A] = List[(Cont[A], List[Int])] // trail items are pairs of continuation and tags type MCont[A] = Stack => A @@ -25,37 +25,40 @@ case class EvaluatorFX(module: ModuleInstance) { case class ContV[A](k: (Stack, Cont[A], Trail[A], MCont[A], Handlers[A]) => A) extends Value { def tipe(implicit m: ModuleInstance): ValueType = ??? - } + // override def toString: String = "ContV" + } // initK is a continuation that simply returns the inputed stack - def initK[Ans](s: Stack, trail: Trail[Ans], mkont: MCont[Ans]): Ans = + def initK[Ans](s: Stack, trail: Trail[Ans], mkont: MCont[Ans], hs: Handlers[Ans]): Ans = trail match { - case (k1, _) :: trail => k1(s, trail, mkont) + case (k1, _) :: trail => k1(s, trail, mkont, hs) case Nil => mkont(s) } def eval1[Ans](inst: Instr, stack: Stack, frame: Frame, kont: Cont[Ans], trail: Trail[Ans], mkont: MCont[Ans], - brTable: List[Cont[Ans]], hs: Handlers[Ans]): Ans = + brTable: List[Cont[Ans]], hs: Handlers[Ans]): Ans = { + System.err.println(f"[DEBUG] ${inst} | ${frame} | ${stack.reverse}"); + // System.err.println(f"[DEBUG] brTable: ${brTable} "); inst match { - case Drop => kont(stack.tail, trail, mkont) + case Drop => kont(stack.tail, trail, mkont, hs) case Select(_) => val I32V(cond) :: v2 :: v1 :: newStack = stack val value = if (cond == 0) v1 else v2 - kont(value :: newStack, trail, mkont) + kont(value :: newStack, trail, mkont, hs) case LocalGet(i) => - kont(frame.locals(i) :: stack, trail, mkont) + kont(frame.locals(i) :: stack, trail, mkont, hs) case LocalSet(i) => val value :: newStack = stack frame.locals(i) = value - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, hs) case LocalTee(i) => val value :: newStack = stack frame.locals(i) = value - kont(stack, trail, mkont) + kont(stack, trail, mkont, hs) case GlobalGet(i) => - kont(module.globals(i).value :: stack, trail, mkont) + kont(module.globals(i).value :: stack, trail, mkont, hs) case GlobalSet(i) => val value :: newStack = stack module.globals(i).ty match { @@ -64,16 +67,16 @@ case class EvaluatorFX(module: ModuleInstance) { case GlobalType(_, true) => throw new Exception("Invalid type") case _ => throw new Exception("Cannot set immutable global") } - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, hs) case MemorySize => - kont(I32V(module.memory.head.size) :: stack, trail, mkont) + kont(I32V(module.memory.head.size) :: stack, trail, mkont, hs) case MemoryGrow => val I32V(delta) :: newStack = stack val mem = module.memory.head val oldSize = mem.size mem.grow(delta) match { - case Some(e) => kont(I32V(-1) :: newStack, trail, mkont) - case _ => kont(I32V(oldSize) :: newStack, trail, mkont) + case Some(e) => kont(I32V(-1) :: newStack, trail, mkont, hs) + case _ => kont(I32V(oldSize) :: newStack, trail, mkont, hs) } case MemoryFill => val I32V(value) :: I32V(offset) :: I32V(size) :: newStack = stack @@ -81,7 +84,7 @@ case class EvaluatorFX(module: ModuleInstance) { throw new Exception("Out of bounds memory access") // GW: turn this into a `trap`? else { module.memory.head.fill(offset, size, value.toByte) - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, hs) } case MemoryCopy => val I32V(n) :: I32V(src) :: I32V(dest) :: newStack = stack @@ -89,80 +92,83 @@ case class EvaluatorFX(module: ModuleInstance) { throw new Exception("Out of bounds memory access") else { module.memory.head.copy(dest, src, n) - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, hs) } - case Const(n) => kont(n :: stack, trail, mkont) + case Const(n) => kont(n :: stack, trail, mkont, hs) case Binary(op) => val v2 :: v1 :: newStack = stack - kont(evalBinOp(op, v1, v2) :: newStack, trail, mkont) + kont(evalBinOp(op, v1, v2) :: newStack, trail, mkont, hs) case Unary(op) => val v :: newStack = stack - kont(evalUnaryOp(op, v) :: newStack, trail, mkont) + kont(evalUnaryOp(op, v) :: newStack, trail, mkont, hs) case Compare(op) => val v2 :: v1 :: newStack = stack - kont(evalRelOp(op, v1, v2) :: newStack, trail, mkont) + kont(evalRelOp(op, v1, v2) :: newStack, trail, mkont, hs) case Test(op) => val v :: newStack = stack - kont(evalTestOp(op, v) :: newStack, trail, mkont) + kont(evalTestOp(op, v) :: newStack, trail, mkont, hs) case Store(StoreOp(align, offset, ty, None)) => val I32V(v) :: I32V(addr) :: newStack = stack module.memory(0).storeInt(addr + offset, v) - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, hs) case Load(LoadOp(align, offset, ty, None, None)) => val I32V(addr) :: newStack = stack val value = module.memory(0).loadInt(addr + offset) - kont(I32V(value) :: newStack, trail, mkont) - case Nop => kont(stack, trail, mkont) + kont(I32V(value) :: newStack, trail, mkont, hs) + case Nop => kont(stack, trail, mkont, hs) case Unreachable => throw Trap() case Block(ty, inner) => val funcTy = getFuncType(ty) val (inputs, restStack) = stack.splitAt(funcTy.inps.size) - val escape: Cont[Ans] = (s1, t1, m1) => kont(s1.take(funcTy.out.size) ++ restStack, t1, m1) + val escape: Cont[Ans] = (s1, t1, m1, h1) => kont(s1.take(funcTy.out.size) ++ restStack, t1, m1, h1) evalList(inner, inputs, frame, escape, trail, mkont, escape::brTable, hs) case Loop(ty, inner) => val funcTy = getFuncType(ty) val (inputs, restStack) = stack.splitAt(funcTy.inps.size) - val escape: Cont[Ans] = (s1, t1, m1) => kont(s1.take(funcTy.out.size) ++ restStack, t1, m1) - def loop(retStack: List[Value], trail1: Trail[Ans], mkont: MCont[Ans]): Ans = + val escape: Cont[Ans] = (s1, t1, m1, h1) => kont(s1.take(funcTy.out.size) ++ restStack, t1, m1, h1) + def loop(retStack: List[Value], trail1: Trail[Ans], mkont: MCont[Ans], h1: Handlers[Ans]): Ans = evalList(inner, retStack.take(funcTy.inps.size), frame, escape, trail, mkont, (loop _ : Cont[Ans])::brTable, hs) - loop(inputs, trail, mkont) + loop(inputs, trail, mkont, hs) case If(ty, thn, els) => val funcTy = getFuncType(ty) val I32V(cond) :: newStack = stack val inner = if (cond != 0) thn else els val (inputs, restStack) = newStack.splitAt(funcTy.inps.size) - val escape: Cont[Ans] = (s1, t1, m1) => kont(s1.take(funcTy.out.size) ++ restStack, t1, m1) + val escape: Cont[Ans] = (s1, t1, m1, h1) => kont(s1.take(funcTy.out.size) ++ restStack, t1, m1, h1) evalList(inner, inputs, frame, escape, trail, mkont, escape::brTable, hs) case Br(label) => - brTable(label)(stack, trail, mkont) + brTable(label)(stack, trail, mkont, hs) case BrIf(label) => val I32V(cond) :: newStack = stack - if (cond != 0) brTable(label)(newStack, trail, mkont) - else kont(newStack, trail, mkont) + if (cond != 0) brTable(label)(newStack, trail, mkont, hs) + else kont(newStack, trail, mkont, hs) case BrTable(labels, default) => val I32V(cond) :: newStack = stack val goto = if (cond < labels.length) labels(cond) else default - brTable(goto)(newStack, trail, mkont) - case Return => brTable.last(stack, trail, mkont) + brTable(goto)(newStack, trail, mkont, hs) + case Return => + brTable.last(stack, trail, mkont, hs) case Call(f) => evalCall1(f, stack, frame, kont, trail, mkont, brTable, hs, false) - case ReturnCall(f) => evalCall1(f, stack, frame, kont, trail, mkont, brTable, hs, true) + case ReturnCall(f) => + // System.err.println(s"[DEBUG] return call: $f") + evalCall1(f, stack, frame, kont, trail, mkont, brTable, hs, true) case RefFunc(f) => // TODO: RefFuncV stores an applicable function, instead of a syntactic structure - kont(RefFuncV(f) :: stack, trail, mkont) + kont(RefFuncV(f) :: stack, trail, mkont, hs) // resumable try-catch exception handling: // NOTE(GW): so far we haven't use trail at all, could consider removing it case TryCatch(es1, es2) => val newHandler: Handler[Ans] = (s1, k1, _, m1) => evalList(es2, s1, frame, k1, List(), m1, List(), hs) - val m1: MCont[Ans] = (s1) => kont(s1, List(), mkont) + val m1: MCont[Ans] = (s1) => kont(s1, List(), mkont, hs) evalList(es1, List(), frame, initK[Ans], List(), m1, List(), List((-1, newHandler)) ++ hs) case Resume0() => val (resume: ContV[Ans]) :: newStack = stack resume.k(List(), kont, List(), mkont, List()) case Throw() => val err :: newStack = stack - def kr(s: Stack, k1: Cont[Ans], t1: Trail[Ans], m1: MCont[Ans], hs: Handlers[Ans]): Ans = - kont(s, List(), s1 => k1(s1, List(), m1)) + def kr(s: Stack, k1: Cont[Ans], t1: Trail[Ans], m1: MCont[Ans], h1: Handlers[Ans]): Ans = + kont(s, List(), s1 => k1(s1, List(), m1, hs), hs) hs.head._2(List(err, ContV(kr)), initK[Ans], List(), mkont) // WasmFX effect handlers: @@ -171,15 +177,16 @@ case class EvaluatorFX(module: ModuleInstance) { def kr(s: Stack, k1: Cont[Ans], t1: Trail[Ans], m1: MCont[Ans], hs: Handlers[Ans]): Ans = { evalCall1(f, s, frame/*?*/, k1, t1, m1, List(), hs, false) } - kont(ContV(kr) :: newStack, trail, mkont) + kont(ContV(kr) :: newStack, trail, mkont, hs) case Suspend(tagId) => val FuncType(_, inps, out) = module.tags(tagId) val (inputs, restStack) = stack.splitAt(inps.size) - val kr = (s: Stack, _: Cont[Ans], t1: Trail[Ans], m1: MCont[Ans], hs: Handlers[Ans]) => { - // FIXME: handlers are lost here + // System.err.println(s"[DEBUG] handlers: $hs") + // System.err.println(s"[DEBUG] trail: $trail") + val kr = (s: Stack, _: Cont[Ans], t1: Trail[Ans], m1: MCont[Ans], hs1: Handlers[Ans]) => { val index = trail.indexWhere { case (_, tags) => tags.contains(tagId) } val newTrail = if (index >= 0) trail.take(index) else trail - kont(s ++ restStack, newTrail ++ t1, m1) // mkont lost here, and it's safe if we never modify it + kont(s ++ restStack, newTrail ++ t1, m1, hs1) // mkont lost here, and it's safe if we never modify it } val newStack = ContV(kr) :: inputs hs.find(_._1 == tagId) match { @@ -195,7 +202,7 @@ case class EvaluatorFX(module: ModuleInstance) { val (inputs, restStack) = newStack.splitAt(inps.size) val newHs: List[(Int, Handler[Ans])] = handler.map { case Handler(tagId, labelId) => - val hh: Handler[Ans] = (s1, _k1, _t1, m1) => brTable(labelId)(s1, trail, mkont/*???*/) + val hh: Handler[Ans] = (s1, _k1, _t1, m1) => brTable(labelId)(s1, trail, mkont/*???*/, hs) (tagId, hh) } val tags = handler.map(_.tag) @@ -216,7 +223,7 @@ case class EvaluatorFX(module: ModuleInstance) { def kr(s: Stack, k1: Cont[Ans], t1: Trail[Ans], mk: MCont[Ans], handlers: Handlers[Ans]): Ans = { f.k(s ++ inputs, k1, t1, mk, handlers) } - kont(ContV(kr) :: restStack, trail, mkont) + kont(ContV(kr) :: restStack, trail, mkont, hs) case CallRef(ty) => val RefFuncV(f) :: newStack = stack @@ -226,14 +233,15 @@ case class EvaluatorFX(module: ModuleInstance) { println(inst) throw new Exception(s"instruction $inst not implemented") } + } def evalList[Ans](insts: List[Instr], stack: Stack, frame: Frame, kont: Cont[Ans], trail1: Trail[Ans], mkont: MCont[Ans], brTable: List[Cont[Ans]], hs: Handlers[Ans]): Ans = { insts match { - case Nil => kont(stack, trail1, mkont) + case Nil => kont(stack, trail1, mkont, hs) case inst :: rest => - val newKont: Cont[Ans] = (s1, t1, m1) => evalList(rest, s1, frame, kont, t1, m1, brTable, hs) + val newKont: Cont[Ans] = (s1, t1, m1, h1) => evalList(rest, s1, frame, kont, t1, m1, brTable, h1) eval1(inst, stack, frame, newKont, trail1, mkont, brTable, hs) } } @@ -253,11 +261,12 @@ case class EvaluatorFX(module: ModuleInstance) { val newStack = stack.drop(ty.inps.size) val frameLocals = args ++ locals.map(zero(_)) val newFrame = Frame(ArrayBuffer(frameLocals: _*)) - if (isTail) + if (isTail) { // when tail call, share the continuation for returning with the callee - evalList(body, List(), newFrame, kont, trail, mkont, List(kont), h) + evalList(body, List(), newFrame, brTable.last, trail, mkont, List(brTable.last), h) + } else { - val restK: Cont[Ans] = (s1, t1, m1) => kont(s1.take(ty.out.size) ++ newStack, t1, m1) + val restK: Cont[Ans] = (s1, t1, m1, h1) => kont(s1.take(ty.out.size) ++ newStack, t1, m1, h1) // We make a new brTable by `restK`, since function creates a new block to escape // (more or less like `return`) evalList(body, List(), newFrame, restK, trail, mkont, List(restK), h) @@ -266,12 +275,12 @@ case class EvaluatorFX(module: ModuleInstance) { // println(s"[DEBUG] current stack: $stack") val I32V(v) :: newStack = stack println(v) - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, h) case Import("spectest", "print_i32", _) => // println(s"[DEBUG] current stack: $stack") val I32V(v) :: newStack = stack println(v) - kont(newStack, trail, mkont) + kont(newStack, trail, mkont, h) case Import(_, _, _) => throw new Exception(s"Unknown import at $funcIndex") case _ => throw new Exception(s"Definition at $funcIndex is not callable") } @@ -333,3 +342,4 @@ case class EvaluatorFX(module: ModuleInstance) { def evalTop(m: ModuleInstance): Unit = evalTop(initK[Unit], stack => ()) } + diff --git a/src/main/scala/wasm/Parser.scala b/src/main/scala/wasm/Parser.scala index bae387a37..6c83a152c 100644 --- a/src/main/scala/wasm/Parser.scala +++ b/src/main/scala/wasm/Parser.scala @@ -302,7 +302,7 @@ class GSWasmVisitor extends WatParserBaseVisitor[WIR] { } else if (ctx.RETURN_CALL() != null) { val id = getVar(ctx.idx(0)) - try Call(id.toInt) catch { + try ReturnCall(id.toInt) catch { case _: java.lang.NumberFormatException => if (fnMap.contains(id)) ReturnCall(fnMap(id)) else CallUnresolved(id) diff --git a/src/test/scala/genwasym/TestFx.scala b/src/test/scala/genwasym/TestFx.scala index 6c17c5121..5d293d4d0 100644 --- a/src/test/scala/genwasym/TestFx.scala +++ b/src/test/scala/genwasym/TestFx.scala @@ -208,19 +208,17 @@ class TestFx extends FunSuite { } test("suspend16") { - // TODO: fails this test!!! - // testWastFile("./benchmarks/wasm/wasmfx/suspend16.bin.wast") - testFile("./benchmarks/wasm/wasmfx/suspend16-strip.wast") + testWastFile("./benchmarks/wasm/wasmfx/suspend16.bin.wast") + // testFile("./benchmarks/wasm/wasmfx/suspend16-strip.wast") + } + + test("fun-state") { + testWastFile("./benchmarks/wasm/wasmfx/fun-state.bin.wast") } - /* - // TODO: the following two tests fails - // test("pipes") { - // testFile("./benchmarks/wasm/wasmfx/fun-pipes-strip.wast") - // } - - // test("fun-state") { - // testWastFile("./benchmarks/wasm/wasmfx/fun-state.bin.wast") - // } - */ + // TOOD: FIXME + test("pipes") { + testFile("./benchmarks/wasm/wasmfx/fun-pipes-strip.wast") + } + }