tor-browser

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

ref-gvn.js (21131B)


      1 // Tests that exercise GVN and LICM. The general pattern for these tests is to
      2 // create values near the top of the function and then create situations where
      3 // equivalent values are created below, including in loops.
      4 
      5 // ref.null
      6 {
      7  let numAnyref = 0;
      8  let numExternref = 0;
      9 
     10  const { test1, test2 } = wasmEvalText(`(module
     11    (import "" "dummy1" (func $dummy1 (param anyref)))
     12    (import "" "dummy2" (func $dummy2 (param externref)))
     13    (import "" "countAnyref" (func $countAnyref))
     14    (import "" "countExternref" (func $countExternref))
     15 
     16    (func (export "test1")
     17      ;; Ensure that we keep two MWasmNullConstants with two different
     18      ;; hierarchies at the top of the graph.
     19      (call $dummy1 (ref.null none))
     20      (call $dummy2 (ref.null noextern))
     21 
     22      (ref.test anyref (ref.null none))
     23      if
     24        call $countAnyref
     25      end
     26 
     27      ;; If you're not careful, this null might be GVN'd with the null from the
     28      ;; other hierarchy, causing bad behavior.
     29      (ref.test externref (ref.null noextern))
     30      if
     31        call $countExternref
     32      end
     33    )
     34    (func (export "test2")
     35      (local i32 anyref externref)
     36 
     37      (local.tee 1 (ref.null none))
     38      call $dummy1
     39      (local.tee 2 (ref.null noextern))
     40      call $dummy2
     41 
     42      loop
     43        (ref.test anyref (local.get 1))
     44        if
     45          call $countAnyref
     46        end
     47 
     48        (ref.test externref (local.get 2))
     49        if
     50          call $countExternref
     51        end
     52 
     53        (i32.ge_s (local.get 0) (i32.const 5))
     54        if
     55          ;; Note that these use the top type instead of the bottom type.
     56          (local.set 1 (ref.null any))
     57          (local.set 2 (ref.null extern))
     58        end
     59 
     60        (local.tee 0 (i32.add (local.get 0) (i32.const 1)))
     61        (i32.lt_s (i32.const 10))
     62        br_if 0
     63      end
     64    )
     65  )`, {
     66    "": {
     67      dummy1() {},
     68      dummy2() {},
     69      countAnyref() {
     70        numAnyref += 1;
     71      },
     72      countExternref() {
     73        numExternref += 1;
     74      },
     75    },
     76  }).exports;
     77 
     78  for (let i = 0; i < 100; i++) {
     79    test1();
     80  }
     81 
     82  assertEq(numAnyref, 100);
     83  assertEq(numExternref, 100);
     84 
     85  for (let i = 0; i < 100; i++) {
     86    test2();
     87  }
     88 
     89  assertEq(numAnyref, 1100);
     90  assertEq(numExternref, 1100);
     91 }
     92 
     93 // structs and struct fields
     94 {
     95  const counts = { 100: 0, 200: 0, 300: 0, 400: 0 };
     96 
     97  const { test1, test2 } = wasmEvalText(`(module
     98    (type $a (struct (field i32)))
     99    (type $s (struct (field (ref $a)) (field (ref $a))))
    100 
    101    (import "" "dummy" (func $dummy (param anyref)))
    102    (import "" "count" (func $count (param i32)))
    103 
    104    (func (export "test1")
    105      (local anyref)
    106 
    107      (struct.new $a (i32.const 100))
    108      (struct.new $a (i32.const 200))
    109      struct.new $s
    110      local.tee 0
    111      call $dummy
    112 
    113      local.get 0
    114      ref.cast (ref $s)
    115      struct.get $s 0
    116      ref.cast (ref $a)
    117      struct.get $a 0
    118      call $count
    119 
    120      local.get 0
    121      ref.cast (ref $s)
    122      struct.get $s 1
    123      ref.cast (ref $a)
    124      struct.get $a 0
    125      call $count
    126    )
    127    (func (export "test2")
    128      (local anyref i32)
    129 
    130      (struct.new $a (i32.const 100))
    131      (struct.new $a (i32.const 200))
    132      struct.new $s
    133      local.tee 0
    134      call $dummy
    135 
    136      loop
    137        local.get 0
    138        ref.cast (ref $s)
    139        struct.get $s 0
    140        ref.cast (ref $a)
    141        struct.get $a 0
    142        call $count
    143 
    144        local.get 0
    145        ref.cast (ref $s)
    146        struct.get $s 1
    147        ref.cast (ref $a)
    148        struct.get $a 0
    149        call $count
    150 
    151        (i32.ge_s (local.get 1) (i32.const 4))
    152        if
    153          (struct.new $a (i32.const 300))
    154          (struct.new $a (i32.const 400))
    155          struct.new $s
    156          local.set 0
    157        end
    158 
    159        (local.tee 1 (i32.add (local.get 1) (i32.const 1)))
    160        (i32.lt_s (i32.const 10))
    161        br_if 0
    162      end
    163    )
    164  )`, {
    165    "": {
    166      dummy() {},
    167      count(n) {
    168        counts[n] += 1;
    169      },
    170    },
    171  }).exports;
    172 
    173  for (let i = 0; i < 100; i++) {
    174    test1();
    175  }
    176 
    177  assertEq(counts[100], 100);
    178  assertEq(counts[200], 100);
    179  assertEq(counts[300], 0);
    180  assertEq(counts[400], 0);
    181 
    182  for (let i = 0; i < 100; i++) {
    183    test2();
    184  }
    185 
    186  assertEq(counts[100], 600);
    187  assertEq(counts[200], 600);
    188  assertEq(counts[300], 500);
    189  assertEq(counts[400], 500);
    190 }
    191 
    192 // arrays and array elems
    193 {
    194  const counts = { 100: 0, 200: 0, 300: 0, 400: 0 };
    195 
    196  const { test1, test2 } = wasmEvalText(`(module
    197    (type $e (array i32))
    198    (type $a (array (ref $e)))
    199 
    200    (import "" "dummy" (func $dummy (param anyref)))
    201    (import "" "count" (func $count (param i32)))
    202 
    203    (func (export "test1")
    204      (local anyref)
    205 
    206      (array.new_fixed $e 1 (i32.const 100))
    207      (array.new_fixed $e 1 (i32.const 200))
    208      array.new_fixed $a 2
    209      local.tee 0
    210      call $dummy
    211 
    212      local.get 0
    213      ref.cast (ref $a)
    214      (array.get $a (i32.const 0))
    215      ref.cast (ref $e)
    216      (array.get $e (i32.const 0))
    217      call $count
    218 
    219      local.get 0
    220      ref.cast (ref $a)
    221      (array.get $a (i32.const 1))
    222      ref.cast (ref $e)
    223      (array.get $e (i32.const 0))
    224      call $count
    225    )
    226    (func (export "test2")
    227      (local anyref i32)
    228 
    229      (array.new_fixed $e 1 (i32.const 100))
    230      (array.new_fixed $e 1 (i32.const 200))
    231      array.new_fixed $a 2
    232      local.tee 0
    233      call $dummy
    234 
    235      loop
    236        local.get 0
    237        ref.cast (ref $a)
    238        (array.get $a (i32.const 0))
    239        ref.cast (ref $e)
    240        (array.get $e (i32.const 0))
    241        call $count
    242 
    243        local.get 0
    244        ref.cast (ref $a)
    245        (array.get $a (i32.const 1))
    246        ref.cast (ref $e)
    247        (array.get $e (i32.const 0))
    248        call $count
    249 
    250        (i32.ge_s (local.get 1) (i32.const 4))
    251        if
    252          (array.new_fixed $e 1 (i32.const 300))
    253          (array.new_fixed $e 1 (i32.const 400))
    254          array.new_fixed $a 2
    255          local.set 0
    256        end
    257 
    258        (local.tee 1 (i32.add (local.get 1) (i32.const 1)))
    259        (i32.lt_s (i32.const 10))
    260        br_if 0
    261      end
    262    )
    263  )`, {
    264    "": {
    265      dummy() {},
    266      count(n) {
    267        counts[n] += 1;
    268      },
    269    },
    270  }).exports;
    271 
    272  for (let i = 0; i < 100; i++) {
    273    test1();
    274  }
    275 
    276  assertEq(counts[100], 100);
    277  assertEq(counts[200], 100);
    278  assertEq(counts[300], 0);
    279  assertEq(counts[400], 0);
    280 
    281  for (let i = 0; i < 100; i++) {
    282    test2();
    283  }
    284 
    285  assertEq(counts[100], 600);
    286  assertEq(counts[200], 600);
    287  assertEq(counts[300], 500);
    288  assertEq(counts[400], 500);
    289 }
    290 
    291 // table elems
    292 {
    293  const counts = { 100: 0, 200: 0, 300: 0, 400: 0 };
    294 
    295  const { test1, test2 } = wasmEvalText(`(module
    296    (type $f (func))
    297 
    298    (import "" "dummy" (func $dummy (param anyref)))
    299    (import "" "count" (func $count (param i32)))
    300 
    301    (table funcref (elem (ref.func $count100) (ref.func $count200)))
    302    (table (ref null $f) (elem (ref.func $count300) (ref.func $count400)))
    303 
    304    (func $count100 (type $f)
    305      (call $count (i32.const 100))
    306    )
    307    (func $count200 (type $f)
    308      (call $count (i32.const 200))
    309    )
    310    (func $count300 (type $f)
    311      (call $count (i32.const 300))
    312    )
    313    (func $count400 (type $f)
    314      (call $count (i32.const 400))
    315    )
    316 
    317    (func (export "test1")
    318      (table.get 0 (i32.const 0))
    319      ref.cast (ref null $f)
    320      call_ref $f
    321 
    322      (table.get 0 (i32.const 1))
    323      ref.cast (ref null $f)
    324      call_ref $f
    325 
    326      (table.get 1 (i32.const 0))
    327      ref.cast (ref null $f)
    328      call_ref $f
    329 
    330      (table.get 1 (i32.const 1))
    331      ref.cast (ref null $f)
    332      call_ref $f
    333    )
    334    (func (export "test2")
    335      (local i32)
    336 
    337      (table.get 0 (i32.const 0))
    338      ref.cast (ref null $f)
    339      call_ref $f
    340 
    341      (table.get 1 (i32.const 0))
    342      ref.cast (ref null $f)
    343      call_ref $f
    344 
    345      loop
    346        (table.get 0 (i32.const 0))
    347        ref.cast (ref null $f)
    348        call_ref $f
    349 
    350        (table.get 0 (i32.const 1))
    351        ref.cast (ref null $f)
    352        call_ref $f
    353 
    354        (table.get 1 (i32.const 0))
    355        ref.cast (ref null $f)
    356        call_ref $f
    357 
    358        (table.get 1 (i32.const 1))
    359        ref.cast (ref null $f)
    360        call_ref $f
    361 
    362        (local.tee 0 (i32.add (local.get 0) (i32.const 1)))
    363        (i32.lt_s (i32.const 10))
    364        br_if 0
    365      end
    366    )
    367  )`, {
    368    "": {
    369      dummy() {},
    370      count(n) {
    371        counts[n] += 1;
    372      },
    373    },
    374  }).exports;
    375 
    376  for (let i = 0; i < 100; i++) {
    377    test1();
    378  }
    379 
    380  assertEq(counts[100], 100);
    381  assertEq(counts[200], 100);
    382  assertEq(counts[300], 100);
    383  assertEq(counts[400], 100);
    384 
    385  for (let i = 0; i < 100; i++) {
    386    test2();
    387  }
    388 
    389  assertEq(counts[100], 1200);
    390  assertEq(counts[200], 1100);
    391  assertEq(counts[300], 1200);
    392  assertEq(counts[400], 1100);
    393 }
    394 
    395 // ref.i31
    396 {
    397  const countsI31 = { 100: 0, 200: 0, 300: 0 };
    398  const countsI32 = { 100: 0, 200: 0, 300: 0 };
    399  const countsU32 = { 100: 0, 200: 0, 300: 0 };
    400 
    401  const { test1, test2 } = wasmEvalText(`(module
    402    (import "" "dummy" (func $dummy (param i31ref)))
    403    (import "" "countI31" (func $countI31 (param i31ref)))
    404    (import "" "countI32" (func $countI32 (param i32)))
    405    (import "" "countU32" (func $countU32 (param i32)))
    406 
    407    (func (export "test1")
    408      (call $dummy (ref.i31 (i32.const 100)))
    409      (call $dummy (ref.i31 (i32.const 200)))
    410 
    411      (call $countI31 (ref.i31 (i32.const 100)))
    412      (call $countI31 (ref.i31 (i32.const 200)))
    413      (call $countI32 (i31.get_s (ref.i31 (i32.const 100))))
    414      (call $countI32 (i31.get_s (ref.i31 (i32.const 200))))
    415      (call $countU32 (i31.get_u (ref.i31 (i32.const 100))))
    416      (call $countU32 (i31.get_u (ref.i31 (i32.const 200))))
    417    )
    418    (func (export "test2")
    419      (local i32 i31ref)
    420 
    421      (call $dummy (ref.i31 (i32.const 100)))
    422      (local.tee 1 (ref.i31 (i32.const 200)))
    423      call $dummy
    424 
    425      loop
    426        (call $countI31 (ref.i31 (i32.const 100)))
    427        (call $countI31 (local.get 1))
    428        (call $countI32 (i31.get_s (ref.i31 (i32.const 100))))
    429        (call $countI32 (i31.get_s (local.get 1)))
    430        (call $countU32 (i31.get_u (ref.i31 (i32.const 100))))
    431        (call $countU32 (i31.get_u (local.get 1)))
    432 
    433        (local.set 1 (ref.i31 (i32.const 300)))
    434 
    435        (local.tee 0 (i32.add (local.get 0) (i32.const 1)))
    436        (i32.lt_s (i32.const 10))
    437        br_if 0
    438      end
    439    )
    440  )`, {
    441    "": {
    442      dummy() {},
    443      countI31(n) {
    444        countsI31[n] += 1;
    445      },
    446      countI32(n) {
    447        countsI32[n] += 1;
    448      },
    449      countU32(n) {
    450        countsU32[n] += 1;
    451      },
    452    },
    453  }).exports;
    454 
    455  for (let i = 0; i < 100; i++) {
    456    test1();
    457  }
    458 
    459  assertEq(countsI31[100], 100);
    460  assertEq(countsI31[200], 100);
    461  assertEq(countsI31[300], 0);
    462  assertEq(countsI32[100], 100);
    463  assertEq(countsI32[200], 100);
    464  assertEq(countsI32[300], 0);
    465  assertEq(countsU32[100], 100);
    466  assertEq(countsU32[200], 100);
    467  assertEq(countsU32[300], 0);
    468 
    469  for (let i = 0; i < 100; i++) {
    470    test2();
    471  }
    472 
    473  assertEq(countsI31[100], 1100);
    474  assertEq(countsI31[200], 200);
    475  assertEq(countsI31[300], 900);
    476  assertEq(countsI32[100], 1100);
    477  assertEq(countsI32[200], 200);
    478  assertEq(countsI32[300], 900);
    479  assertEq(countsU32[100], 1100);
    480  assertEq(countsU32[200], 200);
    481  assertEq(countsU32[300], 900);
    482 }
    483 
    484 // parameters and calls
    485 {
    486  let numNull = 0;
    487  let numNonNull = 0;
    488 
    489  // Note that we are ok with inlining kicking in eventually (and have
    490  // constructed these tests to trigger that).
    491  const { test1, test2 } = wasmEvalText(`(module
    492    (type $f_anyref (func (param anyref)))
    493    (type $f_nullref (func (param nullref)))
    494 
    495    (import "" "thing" (global $thing externref))
    496    (import "" "countNull" (func $countNull))
    497    (import "" "countNonNull" (func $countNonNull))
    498 
    499    (table funcref (elem
    500      (ref.func $testNull_ref.is_null)
    501      (ref.func $mustNull_ref.is_null)
    502      (ref.func $testNull_ref.test)
    503      (ref.func $mustNull_ref.test)
    504    ))
    505 
    506    (func $makeNull_Loose (result anyref)
    507      ref.null any
    508    )
    509    (func $makeNonNull_Loose (result anyref)
    510      (any.convert_extern (global.get $thing))
    511    )
    512    (func $makeNull_Precise (result nullref)
    513      ref.null none
    514    )
    515    (func $makeNonNull_Precise (result (ref any))
    516      (ref.as_non_null (any.convert_extern (global.get $thing)))
    517    )
    518 
    519    (func $testNull_ref.is_null (param anyref)
    520      (ref.is_null (local.get 0))
    521      if
    522        call $countNull
    523      else
    524        call $countNonNull
    525      end
    526    )
    527    (func $mustNull_ref.is_null (param nullref)
    528      (ref.is_null (local.get 0)) ;; trivial!
    529      if
    530        call $countNull
    531      end
    532    )
    533    (func $testNull_ref.test (param anyref)
    534      (ref.test nullref (local.get 0)) ;; trivial!
    535      if
    536        call $countNull
    537      else
    538        call $countNonNull
    539      end
    540    )
    541    (func $mustNull_ref.test (param nullref)
    542      (ref.test nullref (local.get 0)) ;; trivial!
    543      if
    544        call $countNull
    545      end
    546    )
    547 
    548    (func (export "test1")
    549      (local anyref)
    550 
    551      (local.set 0 (call $makeNull_Loose))
    552      (call $testNull_ref.is_null (local.get 0))
    553      (call $testNull_ref.test (local.get 0))
    554      (call_indirect (type $f_anyref) (local.get 0) (i32.const 0))
    555      (call_indirect (type $f_anyref) (local.get 0) (i32.const 2))
    556      (ref.is_null (local.get 0)) ;; guaranteed to succeed
    557      if
    558        (call $mustNull_ref.is_null (ref.cast nullref (local.get 0)))
    559        (call $mustNull_ref.test (ref.cast nullref (local.get 0)))
    560        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 1))
    561        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 3))
    562      end
    563 
    564      (local.set 0 (call $makeNull_Precise))
    565      (call $testNull_ref.is_null (local.get 0))
    566      (call $testNull_ref.test (local.get 0))
    567      (call_indirect (type $f_anyref) (local.get 0) (i32.const 0))
    568      (call_indirect (type $f_anyref) (local.get 0) (i32.const 2))
    569      (ref.is_null (local.get 0)) ;; guaranteed to succeed
    570      if
    571        (call $mustNull_ref.is_null (ref.cast nullref (local.get 0)))
    572        (call $mustNull_ref.test (ref.cast nullref (local.get 0)))
    573        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 1))
    574        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 3))
    575      end
    576 
    577      (local.set 0 (call $makeNonNull_Loose))
    578      (call $testNull_ref.is_null (local.get 0))
    579      (call $testNull_ref.test (local.get 0))
    580      (call_indirect (type $f_anyref) (local.get 0) (i32.const 0))
    581      (call_indirect (type $f_anyref) (local.get 0) (i32.const 2))
    582      (ref.is_null (local.get 0)) ;; guaranteed to fail
    583      if
    584        (call $mustNull_ref.is_null (ref.cast nullref (local.get 0)))
    585        (call $mustNull_ref.test (ref.cast nullref (local.get 0)))
    586        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 1))
    587        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 3))
    588      end
    589 
    590      (local.set 0 (call $makeNonNull_Precise))
    591      (call $testNull_ref.is_null (local.get 0))
    592      (call $testNull_ref.test (local.get 0))
    593      (call_indirect (type $f_anyref) (local.get 0) (i32.const 0))
    594      (call_indirect (type $f_anyref) (local.get 0) (i32.const 2))
    595      (ref.is_null (local.get 0)) ;; guaranteed to fail
    596      if
    597        (call $mustNull_ref.is_null (ref.cast nullref (local.get 0)))
    598        (call $mustNull_ref.test (ref.cast nullref (local.get 0)))
    599        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 1))
    600        (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 3))
    601      end
    602    )
    603    (func (export "test2")
    604      (local anyref i32)
    605 
    606      block
    607        loop
    608          (i32.eq (local.get 1) (i32.const 0))
    609          if
    610            (local.set 0 (call $makeNull_Loose))
    611          else
    612            (i32.eq (local.get 1) (i32.const 1))
    613            if
    614              (local.set 0 (call $makeNull_Precise))
    615            else
    616              (i32.eq (local.get 1) (i32.const 2))
    617              if
    618                (local.set 0 (call $makeNonNull_Loose))
    619              else
    620                (i32.eq (local.get 1) (i32.const 3))
    621                if
    622                  (local.set 0 (call $makeNonNull_Precise))
    623                else
    624                  return
    625                end
    626              end
    627            end
    628          end
    629 
    630          (call $testNull_ref.is_null (local.get 0))
    631          (call $testNull_ref.test (local.get 0))
    632          (call_indirect (type $f_anyref) (local.get 0) (i32.const 0))
    633          (call_indirect (type $f_anyref) (local.get 0) (i32.const 2))
    634          (ref.is_null (local.get 0))
    635          if
    636            (call $mustNull_ref.is_null (ref.cast nullref (local.get 0)))
    637            (call $mustNull_ref.test (ref.cast nullref (local.get 0)))
    638            (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 1))
    639            (call_indirect (type $f_nullref) (ref.cast nullref (local.get 0)) (i32.const 3))
    640          end
    641 
    642          (local.set 1 (i32.add (local.get 1) (i32.const 1)))
    643          br 0
    644        end
    645      end
    646    )
    647  )`, {
    648    "": {
    649      "thing": "hello I am extern guy",
    650      countNull() {
    651        numNull += 1;
    652      },
    653      countNonNull() {
    654        numNonNull += 1;
    655      },
    656    },
    657  }).exports;
    658 
    659  for (let i = 0; i < 100; i++) {
    660    test1();
    661  }
    662 
    663  assertEq(numNull, 1600);
    664  assertEq(numNonNull, 800);
    665 
    666  for (let i = 0; i < 100; i++) {
    667    test2();
    668  }
    669 
    670  assertEq(numNull, 3200);
    671  assertEq(numNonNull, 1600);
    672 }
    673 
    674 // globals
    675 {
    676  const counts = { 100: 0, 200: 0 };
    677 
    678  const { test1, test2 } = wasmEvalText(`(module
    679    (type $f (func))
    680 
    681    (import "" "dummy" (func $dummy (param anyref)))
    682    (import "" "count" (func $count (param i32)))
    683 
    684    (global $a (mut (ref $f)) (ref.func $count100))
    685    (global $b (mut (ref $f)) (ref.func $count200))
    686 
    687    (func $count100 (type $f)
    688      (call $count (i32.const 100))
    689    )
    690    (func $count200 (type $f)
    691      (call $count (i32.const 200))
    692    )
    693 
    694    (func (export "test1")
    695      global.get $a
    696      call_ref $f
    697 
    698      global.get $b
    699      call_ref $f
    700    )
    701    (func (export "test2")
    702      (local funcref i32)
    703 
    704      (local.set 0 (global.get $a))
    705 
    706      loop
    707        local.get 0
    708        ref.cast (ref $f)
    709        call_ref $f
    710 
    711        (i32.ge_s (local.get 1) (i32.const 4))
    712        if
    713          (local.set 0 (global.get $b))
    714        end
    715 
    716        (local.tee 1 (i32.add (local.get 1) (i32.const 1)))
    717        (i32.lt_s (i32.const 10))
    718        br_if 0
    719      end
    720    )
    721  )`, {
    722    "": {
    723      dummy() {},
    724      count(n) {
    725        counts[n] += 1;
    726      },
    727    },
    728  }).exports;
    729 
    730  for (let i = 0; i < 100; i++) {
    731    test1();
    732  }
    733 
    734  assertEq(counts[100], 100);
    735  assertEq(counts[200], 100);
    736 
    737  for (let i = 0; i < 100; i++) {
    738    test2();
    739  }
    740 
    741  assertEq(counts[100], 600);
    742  assertEq(counts[200], 600);
    743 }
    744 
    745 // any.convert_extern and extern.convert_any
    746 {
    747  let numAnyref = 0;
    748  let numExternref = 0;
    749 
    750  const { test1, test2 } = wasmEvalText(`(module
    751    (import "" "thing" (global $extern1 externref))
    752    (import "" "thing" (global $extern2 externref))
    753    (import "" "dummy1" (func $dummy1 (param anyref)))
    754    (import "" "dummy2" (func $dummy2 (param externref)))
    755    (import "" "countAnyref" (func $countAnyref))
    756    (import "" "countExternref" (func $countExternref))
    757 
    758    (global $any1 anyref (any.convert_extern (global.get $extern1)))
    759    (global $any2 anyref (any.convert_extern (global.get $extern2)))
    760 
    761    (func (export "test1")
    762      (call $dummy1 (any.convert_extern (global.get $extern1)))
    763      (call $dummy2 (extern.convert_any (global.get $any1)))
    764 
    765      ;; These tests are trivial.
    766 
    767      (ref.test anyref (any.convert_extern (global.get $extern1)))
    768      if
    769        call $countAnyref
    770      end
    771 
    772      (ref.test externref (extern.convert_any (global.get $any1)))
    773      if
    774        call $countExternref
    775      end
    776    )
    777    (func (export "test2")
    778      (local i32 anyref externref)
    779 
    780      (local.tee 1 (any.convert_extern (global.get $extern1)))
    781      call $dummy1
    782      (local.tee 2 (extern.convert_any (global.get $any1)))
    783      call $dummy2
    784 
    785      loop
    786        ;; These tests are again trivial.
    787 
    788        (ref.test anyref (local.get 1))
    789        if
    790          call $countAnyref
    791        end
    792 
    793        (ref.test externref (local.get 2))
    794        if
    795          call $countExternref
    796        end
    797 
    798        (i32.ge_s (local.get 0) (i32.const 5))
    799        if
    800          ;; These are different values but have the same type. It will not
    801          ;; affect the types that flow into the tests.
    802          (local.set 1 (any.convert_extern (global.get $extern2)))
    803          (local.set 2 (extern.convert_any (global.get $any2)))
    804        end
    805 
    806        (local.tee 0 (i32.add (local.get 0) (i32.const 1)))
    807        (i32.lt_s (i32.const 10))
    808        br_if 0
    809      end
    810    )
    811  )`, {
    812    "": {
    813      "thing": "hello I am extern guy",
    814      dummy1() {},
    815      dummy2() {},
    816      countAnyref() {
    817        numAnyref += 1;
    818      },
    819      countExternref() {
    820        numExternref += 1;
    821      },
    822    },
    823  }).exports;
    824 
    825  for (let i = 0; i < 100; i++) {
    826    test1();
    827  }
    828 
    829  assertEq(numAnyref, 100);
    830  assertEq(numExternref, 100);
    831 
    832  for (let i = 0; i < 100; i++) {
    833    test2();
    834  }
    835 
    836  assertEq(numAnyref, 1100);
    837  assertEq(numExternref, 1100);
    838 }