load(libdir + "eqArrayHelper.js"); // These tests ensure that the gc related errors in bug 1744663 are resolved. { let catchlessTry = ` (try (do (call $gc) (throw $exn)))`; let rethrow0 = ` (try (do (call $gc) (throw $exn)) (catch $exn (rethrow 0)))`; let rethrow1 = ` (try (do (throw $exn)) (catch_all (try (do (throw $exn)) (catch $exn (rethrow 1)))))`; let delegate0 = ` (try (do (call $gc) (throw $exn)) (delegate 0))`; let delegate1 = ` (block (try (do (call $gc) (throw $exn)) (delegate 1)))`; let delegate0InCatch = ` (try (do (throw $exn)) (catch_all (try (do (call $gc) (throw $exn)) (delegate 0))))`; let delegate1InCatch = ` (try (do (throw $exn)) (catch_all (try (do (call $gc) (throw $exn)) (delegate 1))))`; let rethrowingBodies = [catchlessTry, rethrow0, delegate0, delegate1, rethrow1, delegate0InCatch, delegate1InCatch]; function rethrowingIndirectly(rethrowingBody) { let exports = wasmEvalText( `(module (tag $exn (export "exn")) (import "js" "gc" (func $gc)) (func $throwExn (export "throwExn") ${rethrowingBody}))`, {js: {gc: () => { gc(); }}} ).exports; let mod = `(module (type $exnType (func)) (type $indirectFunctype (func)) (import "m" "exn" (tag $exn (type $exnType))) (import "m" "throwExn" (func $throwExn (type $indirectFunctype))) (table funcref (elem $throwExn)) (func (export "testFunc") (result i32) (try (result i32) (do (call_indirect (type $indirectFunctype) (i32.const 0)) (i32.const 0)) (catch $exn (i32.const 1)))))`; let testFunction = wasmEvalText(mod, { m : exports}).exports.testFunc; assertEq(testFunction(), 1); }; for (let rethrowingBody of rethrowingBodies) { //console.log("Calling rethrowingIndirectly with rethrowingBody = " + rethrowingBody); rethrowingIndirectly(rethrowingBody); } } // The full test case that caused the original failure. { gczeal(2,1); // Collect after every allocation. let v128Type = " i32"; let wrongV128 = "(i32.const 0)"; let correctV128 = "(i32.const 1)"; let checkV128Value = ""; if (wasmSimdEnabled()) { v128Type = " v128"; wrongV128 = "(v128.const i32x4 11 22 33 44)"; correctV128 = "(v128.const i32x4 55 66 77 88)"; checkV128Value = `;; Check the V128 value (v128.const i32x4 55 66 77 88) (i32x4.eq) (i32x4.all_true)`; } let exports = wasmEvalText( `(module (type $exnType (func (param i32 i64 f32 f64 externref ${v128Type}))) (type $indirectFunctype (func (param i32 i64 f32 f64 externref ${v128Type}) (result i32 i64 f32 f64 externref ${v128Type}))) (tag $exn (export "exn") (type $exnType)) (tag $emptyExn (export "emptyExn")) (func $throwExn (export "throwExn") (param i32 i64 f32 f64 externref ${v128Type}) (result i32 i64 f32 f64 externref ${v128Type}) (local $ifPredicate i32) (local.get 0) ;; i32 (local.get 1) ;; i64 (local.get 2) ;; f32 (local.get 3) ;; f64 (local.get 4) ;; ref (local.get 5) ;; v128 or i32 (try (param i32 i64 f32 f64 externref ${v128Type}) (do (if (param i32 i64 f32 f64 externref ${v128Type}) (local.get $ifPredicate) (then (throw $exn)) (else (throw $exn)))) (catch $exn (try (param i32 i64 f32 f64 externref ${v128Type}) (do (throw $exn)) (catch_all (rethrow 1)))) (catch_all)) unreachable) (func $throwEmptyExn (export "throwEmptyExn") (param i32 i64 f32 f64 externref ${v128Type}) (result i32 i64 f32 f64 externref ${v128Type}) (throw $emptyExn) unreachable) (func $returnArgs (export "returnArgs") (param i32 i64 f32 f64 externref ${v128Type}) (result i32 i64 f32 f64 externref ${v128Type}) (local.get 0) ;; i32 (local.get 1) ;; i64 (local.get 2) ;; f32 (local.get 3) ;; f64 (local.get 4) ;; ref (local.get 5)) (table (export "tab") funcref (elem $throwExn ;; 0 $throwEmptyExn ;; 1 $returnArgs)) ;; 2 )`).exports; var mod = `(module (type $exnType (func (param i32 i64 f32 f64 externref ${v128Type}))) (type $indirectFunctype (func (param i32 i64 f32 f64 externref ${v128Type}) (result i32 i64 f32 f64 externref ${v128Type}))) (import "m" "exn" (tag $exn (type $exnType))) (import "m" "emptyExn" (tag $emptyExn)) (import "m" "throwExn" (func $throwExn (type $indirectFunctype))) (import "m" "throwEmptyExn" (func $throwEmptyExn (type $indirectFunctype))) (import "m" "returnArgs" (func $returnArgs (type $indirectFunctype))) (import "m" "tab" (table 3 funcref)) (func (export "testFunc") (param $correctRef externref) (param $wrongRef externref) ;; The last i32 result is the v128 check. (result i32 i64 f32 f64 externref i32) (local $ifPredicate i32) (try (result i32 i64 f32 f64 externref i32) (do ;; Wrong values (i32.const 5) (i64.const 6) (f32.const 0.1) (f64.const 0.6437) (local.get $wrongRef) ${wrongV128} ;; throwEmptyExn (call_indirect (type $indirectFunctype) (i32.const 1)) drop ;; Drop the last v128 value. (i32.const 0)) (catch_all (try (result i32 i64 f32 f64 externref ${v128Type}) (do ;; Values to throw. (i32.const 2) (i64.const 3) (f32.const 4) (f64.const 13.37) (local.get $correctRef) ${correctV128} (call_indirect (type $indirectFunctype) (i32.const 2)) ;; returnArgs (call_indirect (type $indirectFunctype) (i32.const 0)) ;; throwExn drop drop ;; Drop v128 and externref to do trivial and irrelevant ops. (f64.const 5) (f64.add) (local.get $wrongRef) ${wrongV128} ;; throwEmptyExn (call_indirect (type $indirectFunctype) (i32.const 1)) unreachable) (catch $emptyExn ;; Wrong values (i32.const 5) (i64.const 6) (f32.const 0.1) (f64.const 0.6437) (local.get $wrongRef) ${wrongV128}) (catch $exn) (catch_all ;; Wrong values (i32.const 5) (i64.const 6) (f32.const 0.1) (f64.const 0.6437) (local.get $wrongRef) ${wrongV128})) ${checkV128Value}))))`; let testAllValtypes = wasmEvalText(mod, { m : exports}).exports.testFunc; assertEqArray(testAllValtypes("foo", "bar"), [2, 3n, 4, 13.37, "foo", 1]); }