tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

structs.js (23241B)


      1 // |jit-test| test-also=--gc-zeal=2
      2 
      3 // This tests a bunch of wasm struct stuff, but not i8 or i16 fields.
      4 // See structs2.js for i8/i16 field tests.
      5 
      6 var bin = wasmTextToBinary(
      7    `(module
      8      (func $x1 (import "m" "x1") (type $f1))
      9      (func $x2 (import "m" "x2") (type $f2))
     10 
     11      (table 2 funcref)
     12      (elem (i32.const 0) $doit $doitagain)
     13 
     14      ;; Type array has a mix of types
     15 
     16      (type $f1 (func (param i32) (result i32)))
     17 
     18      (type $point (struct
     19                    (field $point_x i32)
     20                    (field $point_y i32)))
     21 
     22      (type $f2 (func (param f64) (result f64)))
     23 
     24      (type $int_node (struct
     25                       (field $intbox_val (mut i32))
     26                       (field $intbox_next (mut externref))))
     27 
     28      ;; Test all the types.
     29 
     30      (type $omni (struct
     31                   (field $omni_i32 i32)
     32                   (field $omni_i32m (mut i32))
     33                   (field $omni_i64 i64)
     34                   (field $omni_i64m (mut i64))
     35                   (field $omni_f32 f32)
     36                   (field $omni_f32m (mut f32))
     37                   (field $omni_f64 f64)
     38                   (field $omni_f64m (mut f64))
     39                   (field $omni_externref externref)
     40                   (field $omni_externrefm (mut externref))))
     41 
     42      ;; Various ways to reference a type in the middle of the
     43      ;; type array, make sure we get the right one
     44 
     45      (func (export "hello") (param f64) (param i32) (result f64)
     46       (call_indirect (type $f2) (local.get 0) (local.get 1)))
     47 
     48      (func $doit (param f64) (result f64)
     49       (f64.sqrt (local.get 0)))
     50 
     51      (func $doitagain (param f64) (result f64)
     52       (f64.mul (local.get 0) (local.get 0)))
     53 
     54      (func (export "x1") (param i32) (result i32)
     55       (call $x1 (local.get 0)))
     56 
     57      (func (export "x2") (param f64) (result f64)
     58       (call $x2 (local.get 0)))
     59 
     60      ;; Useful for testing to ensure that the type is not type #0 here.
     61 
     62      (func (export "mk_point") (result eqref)
     63       (struct.new $point (i32.const 37) (i32.const 42)))
     64 
     65      (func (export "mk_int_node") (param i32) (param externref) (result eqref)
     66       (struct.new $int_node (local.get 0) (local.get 1)))
     67 
     68      ;; Too big to fit in an inline WasmGcObject.
     69 
     70      (type $bigger (struct
     71                     (field $a i32)
     72                     (field $b i32)
     73                     (field $c i32)
     74                     (field $d i32)
     75                     (field $e i32)
     76                     (field $f i32)
     77                     (field $g i32)
     78                     (field $h i32)
     79                     (field $i i32)
     80                     (field $j i32)
     81                     (field $k i32)
     82                     (field $l i32)
     83                     (field $m i32)
     84                     (field $n i32)
     85                     (field $o i32)
     86                     (field $p i32)
     87                     (field $q i32)
     88                     (field $r i32)
     89                     (field $s i32)
     90                     (field $t i32)
     91                     (field $u i32)
     92                     (field $v i32)
     93                     (field $w i32)
     94                     (field $x i32)
     95                     (field $y i32)
     96                     (field $z i32)
     97                     (field $aa i32)
     98                     (field $ab i32)
     99                     (field $ac i32)
    100                     (field $ad i32)
    101                     (field $ae i32)
    102                     (field $af i32)
    103                     (field $ag i32)
    104                     (field $ah i32)
    105                     (field $ai i32)
    106                     (field $aj i32)
    107                     (field $ak i32)
    108                     (field $al i32)
    109                     (field $am i32)
    110                     (field $an i32)
    111                     (field $ao i32)
    112                     (field $ap i32)
    113                     (field $aq i32)
    114                     (field $ar i32)
    115                     (field $as i32)
    116                     (field $at i32)
    117                     (field $au i32)
    118                     (field $av i32)
    119                     (field $aw i32)
    120                     (field $ax i32)
    121                     (field $ay i32)
    122                     (field $az i32)))
    123 
    124      (func (export "mk_bigger") (result eqref)
    125            (struct.new $bigger
    126                       (i32.const 0)
    127                       (i32.const 1)
    128                       (i32.const 2)
    129                       (i32.const 3)
    130                       (i32.const 4)
    131                       (i32.const 5)
    132                       (i32.const 6)
    133                       (i32.const 7)
    134                       (i32.const 8)
    135                       (i32.const 9)
    136                       (i32.const 10)
    137                       (i32.const 11)
    138                       (i32.const 12)
    139                       (i32.const 13)
    140                       (i32.const 14)
    141                       (i32.const 15)
    142                       (i32.const 16)
    143                       (i32.const 17)
    144                       (i32.const 18)
    145                       (i32.const 19)
    146                       (i32.const 20)
    147                       (i32.const 21)
    148                       (i32.const 22)
    149                       (i32.const 23)
    150                       (i32.const 24)
    151                       (i32.const 25)
    152                       (i32.const 26)
    153                       (i32.const 27)
    154                       (i32.const 28)
    155                       (i32.const 29)
    156                       (i32.const 30)
    157                       (i32.const 31)
    158                       (i32.const 32)
    159                       (i32.const 33)
    160                       (i32.const 34)
    161                       (i32.const 35)
    162                       (i32.const 36)
    163                       (i32.const 37)
    164                       (i32.const 38)
    165                       (i32.const 39)
    166                       (i32.const 40)
    167                       (i32.const 41)
    168                       (i32.const 42)
    169                       (i32.const 43)
    170                       (i32.const 44)
    171                       (i32.const 45)
    172                       (i32.const 46)
    173                       (i32.const 47)
    174                       (i32.const 48)
    175                       (i32.const 49)
    176                       (i32.const 50)
    177                       (i32.const 51)))
    178 
    179      (type $withfloats (struct
    180                         (field $f1 f32)
    181                         (field $f2 f64)
    182                         (field $f3 externref)
    183                         (field $f4 f32)
    184                         (field $f5 i32)))
    185 
    186      (func (export "mk_withfloats")
    187            (param f32) (param f64) (param externref) (param f32) (param i32)
    188            (result eqref)
    189            (struct.new $withfloats (local.get 0) (local.get 1) (local.get 2) (local.get 3) (local.get 4)))
    190 
    191     )`)
    192 
    193 var mod = new WebAssembly.Module(bin);
    194 var ins = new WebAssembly.Instance(mod, {m:{x1(x){ return x*3 }, x2(x){ return Math.PI }}}).exports;
    195 
    196 assertEq(ins.hello(4.0, 0), 2.0)
    197 assertEq(ins.hello(4.0, 1), 16.0)
    198 
    199 assertEq(ins.x1(12), 36)
    200 assertEq(ins.x2(8), Math.PI)
    201 
    202 var point = ins.mk_point();
    203 assertEq(wasmGcReadField(point, 0), 37);
    204 assertEq(wasmGcReadField(point, 1), 42);
    205 
    206 var int_node = ins.mk_int_node(78, point);
    207 assertEq(wasmGcReadField(int_node, 0), 78);
    208 assertEq(wasmGcReadField(int_node, 1), point);
    209 
    210 var bigger = ins.mk_bigger();
    211 for ( let i=0; i < 52; i++ )
    212    assertEq(wasmGcReadField(bigger, i), i);
    213 
    214 var withfloats = ins.mk_withfloats(1/3, Math.PI, bigger, 5/6, 0x1337);
    215 assertEq(wasmGcReadField(withfloats, 0), Math.fround(1/3));
    216 assertEq(wasmGcReadField(withfloats, 1), Math.PI);
    217 assertEq(wasmGcReadField(withfloats, 2), bigger);
    218 assertEq(wasmGcReadField(withfloats, 3), Math.fround(5/6));
    219 assertEq(wasmGcReadField(withfloats, 4), 0x1337);
    220 
    221 // A simple stress test
    222 
    223 var stress = wasmTextToBinary(
    224    `(module
    225      (type $node (struct (field i32) (field (ref null $node))))
    226      (func (export "iota1") (param $n i32) (result eqref)
    227       (local $list (ref null $node))
    228       (block $exit
    229        (loop $loop
    230         (br_if $exit (i32.eqz (local.get $n)))
    231         (local.set $list (struct.new $node (local.get $n) (local.get $list)))
    232         (local.set $n (i32.sub (local.get $n) (i32.const 1)))
    233         (br $loop)))
    234       (local.get $list)))`);
    235 var stressIns = new WebAssembly.Instance(new WebAssembly.Module(stress)).exports;
    236 var stressLevel =
    237    getBuildConfiguration("x64") && !getBuildConfiguration("tsan") &&
    238            !getBuildConfiguration("asan") && !getBuildConfiguration("valgrind")
    239        ? 100000
    240        : 1000;
    241 var the_list = stressIns.iota1(stressLevel);
    242 for (let i=1; i <= stressLevel; i++) {
    243    assertEq(wasmGcReadField(the_list, 0), i);
    244    the_list = wasmGcReadField(the_list, 1);
    245 }
    246 assertEq(the_list, null);
    247 
    248 // Fields and their exposure in JS.  We can't export types yet so hide them
    249 // inside the module with globals.
    250 
    251 // i64 fields.
    252 
    253 {
    254    let txt =
    255        `(module
    256          (type $big (struct
    257                      (field (mut i32))
    258                      (field (mut i64))
    259                      (field (mut i32))))
    260 
    261          (func (export "set") (param eqref)
    262           (local (ref null $big))
    263           (local.set 1 (ref.cast (ref null $big) (local.get 0)))
    264           (struct.set $big 1 (local.get 1) (i64.const 0x3333333376544567)))
    265 
    266          (func (export "set2") (param $p eqref)
    267           (struct.set $big 1
    268            (ref.cast (ref null $big) (local.get $p))
    269            (i64.const 0x3141592653589793)))
    270 
    271          (func (export "low") (param $p eqref) (result i32)
    272           (i32.wrap_i64 (struct.get $big 1 (ref.cast (ref null $big) (local.get $p)))))
    273 
    274          (func (export "high") (param $p eqref) (result i32)
    275           (i32.wrap_i64 (i64.shr_u
    276                          (struct.get $big 1 (ref.cast (ref null $big) (local.get $p)))
    277                          (i64.const 32))))
    278 
    279          (func (export "mk") (result eqref)
    280           (struct.new $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb)))
    281 
    282         )`;
    283 
    284    let ins = wasmEvalText(txt).exports;
    285 
    286    let v = ins.mk();
    287    assertEq(typeof v, "object");
    288    assertEq(wasmGcReadField(v, 0), 0x7aaaaaaa);
    289    assertEq(wasmGcReadField(v, 1), 0x4201020337n);
    290    assertEq(ins.low(v), 0x01020337);
    291    assertEq(ins.high(v), 0x42);
    292    assertEq(wasmGcReadField(v, 2), 0x6bbbbbbb);
    293 
    294    ins.set(v);
    295    assertEq(wasmGcReadField(v, 0), 0x7aaaaaaa);
    296    assertEq(wasmGcReadField(v, 1), 0x3333333376544567n);
    297    assertEq(wasmGcReadField(v, 2), 0x6bbbbbbb);
    298 
    299    ins.set2(v);
    300    assertEq(wasmGcReadField(v, 1), 0x3141592653589793n);
    301    assertEq(ins.low(v), 0x53589793);
    302    assertEq(ins.high(v), 0x31415926)
    303 }
    304 
    305 {
    306    let txt =
    307        `(module
    308          (type $big (struct
    309                      (field (mut i32))
    310                      (field (mut i64))
    311                      (field (mut i32))))
    312 
    313          (global $g (mut (ref null $big)) (ref.null $big))
    314 
    315          (func (export "make") (result eqref)
    316           (global.set $g
    317            (struct.new $big (i32.const 0x7aaaaaaa) (i64.const 0x4201020337) (i32.const 0x6bbbbbbb)))
    318           (global.get $g))
    319 
    320          (func (export "update0") (param $x i32)
    321           (struct.set $big 0 (global.get $g) (local.get $x)))
    322 
    323          (func (export "get0") (result i32)
    324           (struct.get $big 0 (global.get $g)))
    325 
    326          (func (export "update1") (param $hi i32) (param $lo i32)
    327           (struct.set $big 1 (global.get $g)
    328            (i64.or
    329             (i64.shl (i64.extend_i32_u (local.get $hi)) (i64.const 32))
    330             (i64.extend_i32_u (local.get $lo)))))
    331 
    332          (func (export "get1_low") (result i32)
    333           (i32.wrap_i64 (struct.get $big 1 (global.get $g))))
    334 
    335          (func (export "get1_high") (result i32)
    336           (i32.wrap_i64
    337            (i64.shr_u (struct.get $big 1 (global.get $g)) (i64.const 32))))
    338 
    339          (func (export "update2") (param $x i32)
    340           (struct.set $big 2 (global.get $g) (local.get $x)))
    341 
    342          (func (export "get2") (result i32)
    343           (struct.get $big 2 (global.get $g)))
    344 
    345         )`;
    346 
    347    let ins = wasmEvalText(txt).exports;
    348 
    349    let v = ins.make();
    350    assertEq(wasmGcReadField(v, 0), 0x7aaaaaaa);
    351    assertEq(wasmGcReadField(v, 1), 0x4201020337n);
    352    assertEq(wasmGcReadField(v, 2), 0x6bbbbbbb);
    353 
    354    ins.update0(0x45367101);
    355    assertEq(wasmGcReadField(v, 0), 0x45367101);
    356    assertEq(ins.get0(), 0x45367101);
    357    assertEq(wasmGcReadField(v, 1), 0x4201020337n);
    358    assertEq(wasmGcReadField(v, 2), 0x6bbbbbbb);
    359 
    360    ins.update2(0x62345123);
    361    assertEq(wasmGcReadField(v, 0), 0x45367101);
    362    assertEq(wasmGcReadField(v, 1), 0x4201020337n);
    363    assertEq(ins.get2(), 0x62345123);
    364    assertEq(wasmGcReadField(v, 2), 0x62345123);
    365 
    366    ins.update1(0x77777777, 0x22222222);
    367    assertEq(wasmGcReadField(v, 0), 0x45367101);
    368    assertEq(ins.get1_low(), 0x22222222);
    369    assertEq(ins.get1_high(), 0x77777777);
    370    assertEq(wasmGcReadField(v, 1), 0x7777777722222222n);
    371    assertEq(wasmGcReadField(v, 2), 0x62345123);
    372 }
    373 
    374 
    375 var bin = wasmTextToBinary(
    376    `(module
    377      (type $cons (struct (field i32) (field (ref null $cons))))
    378 
    379      (global $g (mut (ref null $cons)) (ref.null $cons))
    380 
    381      (func (export "push") (param i32)
    382       (global.set $g (struct.new $cons (local.get 0) (global.get $g))))
    383 
    384      (func (export "top") (result i32)
    385       (struct.get $cons 0 (global.get $g)))
    386 
    387      (func (export "pop")
    388       (global.set $g (struct.get $cons 1 (global.get $g))))
    389 
    390      (func (export "is_empty") (result i32)
    391       (ref.is_null (global.get $g)))
    392 
    393      )`);
    394 
    395 var mod = new WebAssembly.Module(bin);
    396 var ins = new WebAssembly.Instance(mod).exports;
    397 ins.push(37);
    398 ins.push(42);
    399 ins.push(86);
    400 assertEq(ins.top(), 86);
    401 ins.pop();
    402 assertEq(ins.top(), 42);
    403 ins.pop();
    404 assertEq(ins.top(), 37);
    405 ins.pop();
    406 assertEq(ins.is_empty(), 1);
    407 assertErrorMessage(() => ins.pop(),
    408                   WebAssembly.RuntimeError,
    409                   /dereferencing null pointer/);
    410 
    411 // Check that a wrapped object cannot be passed as an eqref even if the wrapper
    412 // points to the right type.  This is a temporary restriction, until we're able
    413 // to avoid dealing with wrappers inside the engine.
    414 
    415 {
    416    var ins = wasmEvalText(
    417        `(module
    418          (type $Node (struct (field i32)))
    419          (func (export "mk") (result eqref)
    420           (struct.new $Node (i32.const 37)))
    421          (func (export "f") (param $n eqref) (result eqref)
    422           (ref.cast (ref null $Node) (local.get $n))))`).exports;
    423    var n = ins.mk();
    424    assertEq(ins.f(n), n);
    425    assertErrorMessage(() => ins.f(wrapWithProto(n, {})), TypeError, /can only pass a WebAssembly GC object/);
    426 }
    427 
    428 // Field names.
    429 
    430 // Test that names map to the right fields.
    431 
    432 {
    433    let ins = new WebAssembly.Instance(new WebAssembly.Module(wasmTextToBinary(
    434        `(module
    435          (type $s (struct
    436                    (field $x i32)
    437                    (field $y i32)))
    438 
    439          (func $f (param $p (ref null $s)) (result i32)
    440           (struct.get $s $x (local.get $p)))
    441 
    442          (func $g (param $p (ref null $s)) (result i32)
    443           (struct.get $s $y (local.get $p)))
    444 
    445          (func (export "testf") (param $n i32) (result i32)
    446           (call $f (struct.new $s (local.get $n) (i32.mul (local.get $n) (i32.const 2)))))
    447 
    448          (func (export "testg") (param $n i32) (result i32)
    449           (call $g (struct.new $s (local.get $n) (i32.mul (local.get $n) (i32.const 2)))))
    450 
    451         )`))).exports;
    452 
    453    assertEq(ins.testf(10), 10);
    454    assertEq(ins.testg(10), 20);
    455 }
    456 
    457 // negative tests
    458 
    459 // Wrong type passed as initializer
    460 
    461 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
    462 (module
    463  (type $r (struct (field i32)))
    464  (func $f (param f64) (result eqref)
    465    (struct.new $r (local.get 0)))
    466 )`)),
    467 WebAssembly.CompileError, /type mismatch/);
    468 
    469 // Too few values passed for initializer
    470 
    471 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
    472 (module
    473  (type $r (struct (field i32) (field i32)))
    474  (func $f (result eqref)
    475    (struct.new $r (i32.const 0)))
    476 )`)),
    477 WebAssembly.CompileError, /popping value from empty stack/);
    478 
    479 // Too many values passed for initializer, sort of
    480 
    481 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
    482 (module
    483  (type $r (struct (field i32) (field i32)))
    484  (func $f (result eqref)
    485    (i32.const 0)
    486    (i32.const 1)
    487    (i32.const 2)
    488    struct.new $r)
    489 )`)),
    490 WebAssembly.CompileError, /unused values/);
    491 
    492 // Not referencing a structure type
    493 
    494 assertErrorMessage(() => new WebAssembly.Module(wasmTextToBinary(`
    495 (module
    496  (type (func (param i32) (result i32)))
    497  (func $f (result eqref)
    498    (struct.new 0))
    499 )`)),
    500 WebAssembly.CompileError, /not a struct type/);
    501 
    502 // Nominal type equivalence for structs, but the prefix rule allows this
    503 // conversion to succeed.
    504 
    505 wasmEvalText(`
    506 (module
    507   (type $p (struct (field i32)))
    508   (type $q (struct (field i32)))
    509   (func $f (result (ref null $p))
    510    (struct.new $q (i32.const 0))))
    511 `);
    512 
    513 // The field name is optional, so this should work.
    514 
    515 wasmEvalText(`
    516 (module
    517 (type $s (struct (field i32))))
    518 `)
    519 
    520 // Empty structs are OK.
    521 
    522 wasmEvalText(`
    523 (module
    524 (type $s (struct)))
    525 `)
    526 
    527 // Multiply defined structures.
    528 
    529 assertErrorMessage(() => wasmEvalText(`
    530 (module
    531 (type $s (struct (field $x i32)))
    532 (type $s (struct (field $y i32))))
    533 `),
    534 SyntaxError, /duplicate type identifier/);
    535 
    536 // Bogus type definition syntax.
    537 
    538 assertErrorMessage(() => wasmEvalText(`
    539 (module
    540 (type $s))
    541 `),
    542 SyntaxError, /wasm text error/);
    543 
    544 assertErrorMessage(() => wasmEvalText(`
    545 (module
    546 (type $s (field $x i32)))
    547 `),
    548 SyntaxError, /expected one of: `func`, `struct`, `array`/);
    549 
    550 assertErrorMessage(() => wasmEvalText(`
    551 (module
    552 (type $s (struct (field $x i31))))
    553 `),
    554 SyntaxError, /wasm text error/);
    555 
    556 assertErrorMessage(() => wasmEvalText(`
    557 (module
    558 (type $s (struct (fjeld $x i32))))
    559 `),
    560 SyntaxError, /wasm text error/);
    561 
    562 assertErrorMessage(() => wasmEvalText(`
    563 (module
    564 (type $s (struct abracadabra)))
    565 `),
    566 SyntaxError, /wasm text error/);
    567 
    568 // Function should not reference struct type: syntactic test
    569 
    570 assertErrorMessage(() => wasmEvalText(`
    571 (module
    572 (type $s (struct))
    573 (type $f (func (param i32) (result i32)))
    574 (func (type 0) (param i32) (result i32) (unreachable)))
    575 `),
    576 SyntaxError, /not a function type/);
    577 
    578 // Can't set immutable fields from JS
    579 
    580 {
    581    let ins = wasmEvalText(
    582        `(module
    583          (type $s (struct
    584                    (field i32)
    585                    (field (mut i64))))
    586          (func (export "make") (result eqref)
    587           (struct.new $s (i32.const 37) (i64.const 42))))`).exports;
    588    let v = ins.make();
    589    assertErrorMessage(() => v[0] = 12, TypeError, /can't modify/);
    590    assertErrorMessage(() => v[1] = 12, TypeError, /can't modify/);
    591 }
    592 
    593 // Function should not reference struct type: binary test
    594 
    595 var bad = new Uint8Array([0x00, 0x61, 0x73, 0x6d,
    596                          0x01, 0x00, 0x00, 0x00,
    597 
    598                          0x01,                   // Type section
    599                          0x03,                   // Section size
    600                          0x01,                   // One type
    601                          0x5f,                   // Struct
    602                          0x00,                   // Zero fields
    603 
    604                          0x03,                   // Function section
    605                          0x02,                   // Section size
    606                          0x01,                   // One function
    607                          0x00,                   // Type of function
    608 
    609                          0x0a,                   // Code section
    610                          0x05,                   // Section size
    611                          0x01,                   // One body
    612                          0x03,                   // Body size
    613                          0x00,                   // Zero locals
    614                          0x00,                   // UNREACHABLE
    615                          0x0b]);                 // END
    616 
    617 assertErrorMessage(() => new WebAssembly.Module(bad),
    618                   WebAssembly.CompileError, /signature index references non-signature/);
    619 
    620 // Exercise alias-analysis code for struct access
    621 {
    622    let txt =
    623    `(module
    624       (type $meh (struct))
    625       (type $hasOOL (struct
    626                      ;; In-line storage
    627                      (field i64) (field i64)
    628                      (field $ILnonref (mut i64)) (field $ILref (mut eqref))
    629                      (field i64) (field i64) (field i64) (field i64)
    630                      (field i64) (field i64) (field i64) (field i64)
    631                      (field i64) (field i64) (field i64) (field i64)
    632                      ;; Out-of-line storage (or maybe it starts earlier, but
    633                      ;; definitely not after this point).
    634                      (field $OOLnonref (mut i64)) (field $OOLref (mut eqref)))
    635       )
    636       (func (export "create") (result eqref)
    637         (struct.new $hasOOL
    638           (i64.const 1)    (i64.const 2)
    639           (i64.const 9876) (ref.null $meh)
    640           (i64.const 3)    (i64.const 4)   (i64.const 5)   (i64.const 6)
    641           (i64.const 7)    (i64.const 8)   (i64.const 9)   (i64.const 10)
    642           (i64.const 11)   (i64.const 12)  (i64.const 13)  (i64.const 14)
    643           (i64.const 4321) (ref.null $meh))
    644       )
    645       ;; Write to an OOL field, then an IL field, then to an OOL field, so
    646       ;; that we can at least check (from inspection of the optimised MIR)
    647       ;; that the GVN+alias analysis causes the OOL block pointer not to be
    648       ;; reloaded for the second OOL write.  First for non-ref fields ..
    649       (func (export "threeSetsNonReffy") (param eqref)
    650         (local (ref $hasOOL))
    651         (local.set 1 (ref.as_non_null (ref.cast (ref null $hasOOL) (local.get 0))))
    652         (struct.set $hasOOL 16 (local.get 1) (i64.const 1337)) ;; set $OOLnonref
    653         (struct.set $hasOOL 2  (local.get 1) (i64.const 7331)) ;; set $ILnonref
    654         (struct.set $hasOOL 16 (local.get 1) (i64.const 9009)) ;; set $OOLnonref
    655       )
    656       ;; and the same for ref fields.
    657       (func (export "threeSetsReffy") (param eqref)
    658         (local (ref $hasOOL))
    659         (local.set 1 (ref.as_non_null (ref.cast (ref null $hasOOL) (local.get 0))))
    660         (struct.set $hasOOL 17 (local.get 1) (ref.null $meh)) ;; set $OOLref
    661         (struct.set $hasOOL 3  (local.get 1) (ref.null $meh)) ;; set $ILref
    662         (struct.set $hasOOL 17 (local.get 1) (ref.null $meh)) ;; set $OOLref
    663       )
    664     )`;
    665    let exports = wasmEvalText(txt).exports;
    666 }
    667 
    668 // Exercise stack maps and GC
    669 {
    670  // Zeal will cause us to allocate structs via instance call, requiring live registers
    671  // to be spilled, and then GC values traced while on the stack.
    672  gczeal(2, 1);
    673 
    674  {
    675    const { test } = wasmEvalText(`(module
    676      (type $s (struct (field i32)))
    677      (func (export "test") (param i32) (result i32)
    678        local.get 0
    679        (struct.new $s (i32.const 234))
    680        (struct.new $s (i32.const 345))
    681        drop
    682        drop
    683      )
    684    )`).exports;
    685    assertEq(test(123), 123);
    686  }
    687  {
    688    const { test } = wasmEvalText(`(module
    689      (type $s (struct (field f32)))
    690      (func (export "test") (param f32) (result f32)
    691        local.get 0
    692        (struct.new $s (f32.const 234))
    693        (struct.new $s (f32.const 345))
    694        drop
    695        drop
    696      )
    697    )`).exports;
    698    assertEq(test(123), 123);
    699  }
    700 
    701  gczeal(0);
    702 }