tor-browser

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

gc.js (8170B)


      1 // |jit-test| skip-if: getBuildConfiguration("simulator")
      2 
      3 // Tests GC references passed as arguments during return calls.
      4 // Similar to js/src/jit-test/tests/wasm/gc/trailers-gc-stress.js
      5 
      6 let base = wasmEvalText(`(module
      7    ;; A simple pseudo-random number generator.
      8    ;; Produces numbers in the range 0 .. 2^16-1.
      9    (global $rngState (export "rngState")
     10      (mut i32) (i32.const 1)
     11    )
     12    (func $rand (export "rand") (result i32)
     13      (local $t i32)
     14      ;; update $rngState
     15      (local.set $t (global.get $rngState))
     16      (local.set $t (i32.mul (local.get $t) (i32.const 1103515245)))
     17      (local.set $t (i32.add (local.get $t) (i32.const 12345)))
     18      (global.set $rngState (local.get $t))
     19      ;; pull 16 random bits out of it
     20      (local.set $t (i32.shr_u (local.get $t) (i32.const 15)))
     21      (local.set $t (i32.and (local.get $t) (i32.const 0xFFFF)))
     22      (local.get $t)
     23    )
     24 
     25    ;; Array types
     26    (type $tArrayI32      (array (mut i32)))  ;; "secondary array" above
     27    (type $tArrayArrayI32 (array (mut (ref null $tArrayI32)))) ;; "primary array"
     28 
     29    (func $createSecondaryArrayLoop (export "createSecondaryArrayLoop")
     30        (param $i i32) (param $arr (ref $tArrayI32))
     31        (result (ref $tArrayI32))
     32        (block $cont
     33            (br_if $cont (i32.ge_u (local.get $i) (array.len (local.get $arr))))
     34            (array.set $tArrayI32 (local.get $arr) (local.get $i) (call $rand))
     35            (return_call $createSecondaryArrayLoop
     36                (i32.add (local.get $i) (i32.const 1))
     37                (local.get $arr))
     38        )
     39        (local.get $arr)
     40    )
     41    ;; Create an array ("secondary array") containing random numbers, with a
     42    ;; size between 1 and 50, also randomly chosen.
     43    (func $createSecondaryArray (export "createSecondaryArray")
     44                                (result (ref $tArrayI32))
     45      (return_call $createSecondaryArrayLoop
     46        (i32.const 0)
     47        (array.new $tArrayI32
     48          (i32.const 0)
     49          (i32.add (i32.rem_u (call $rand) (i32.const 50)) (i32.const 1)))
     50      )
     51    )
     52 
     53    (func $createPrimaryArrayLoop (export "createPrimaryArrayLoop")
     54        (param $i i32) (param $arrarr (ref $tArrayArrayI32)) 
     55        (result (ref $tArrayArrayI32))
     56        (block $cont
     57            (br_if $cont (i32.ge_u (local.get $i) (array.len (local.get $arrarr))))
     58            (array.set $tArrayArrayI32 (local.get $arrarr)
     59                                       (local.get $i) (call $createSecondaryArray))
     60            (return_call $createPrimaryArrayLoop
     61                (i32.add (local.get $i) (i32.const 1))
     62                (local.get $arrarr))
     63        )
     64        (local.get $arrarr)
     65    )
     66 )`);
     67 let t =
     68 `(module
     69    ;; Array types (the same as in the base)
     70    (type $tArrayI32      (array (mut i32)))  ;; "secondary array" above
     71    (type $tArrayArrayI32 (array (mut (ref null $tArrayI32)))) ;; "primary array"
     72 
     73    (import "" "rngState" (global $rngState (mut i32)))
     74    (import "" "rand" (func $rand (result i32)))
     75    (import "" "createSecondaryArrayLoop"
     76      (func $createSecondaryArrayLoop
     77        (param $i i32) (param $arr (ref $tArrayI32))
     78        (result (ref $tArrayI32))))
     79    (import "" "createPrimaryArrayLoop" 
     80      (func $createPrimaryArrayLoop
     81        (param $i i32) (param $arrarr (ref $tArrayArrayI32)) 
     82        (result (ref $tArrayArrayI32))))
     83 
     84    ;; Create an array ("secondary array") containing random numbers, with a
     85    ;; size between 1 and 50, also randomly chosen.
     86    ;; (Copy of the base one to create trampoline)
     87    (func $createSecondaryArray (export "createSecondaryArray")
     88                                (result (ref $tArrayI32))
     89      (return_call $createSecondaryArrayLoop
     90        (i32.const 0)
     91        (array.new $tArrayI32
     92          (i32.const 0)
     93          (i32.add (i32.rem_u (call $rand) (i32.const 50)) (i32.const 1)))
     94      )
     95    )
     96 
     97    ;; Create an array (the "primary array") of 1500 elements of
     98    ;; type ref-of-tArrayI32.
     99    (func $createPrimaryArray (export "createPrimaryArray")
    100                            (result (ref $tArrayArrayI32))
    101      (return_call $createPrimaryArrayLoop
    102        (i32.const 0)
    103        (array.new $tArrayArrayI32 (ref.null $tArrayI32) (i32.const 1500)))
    104    )
    105     
    106   ;; Use $createPrimaryArray to create an initial array.  Then randomly replace
    107   ;; elements for a while.
    108   (func $churn (export "churn") (param $thresh i32) (result i32)
    109     (local $i i32)
    110     (local $j i32)
    111     (local $finalSum i32)
    112     (local $arrarr (ref $tArrayArrayI32))
    113     (local $arr (ref null $tArrayI32))
    114     (local $arrLen i32)
    115     (local.set $arrarr (call $createPrimaryArray))
    116     ;; This loop iterates 500,000 times.  Each iteration, it chooses
    117     ;; a randomly element in $arrarr and replaces it with a new
    118     ;; random array of 32-bit ints.
    119     (loop $cont
    120       ;; make $j be a random number in 0 .. $thresh-1.
    121       ;; Then replace that index in $arrarr with a new random arrayI32.
    122       (local.set $j (i32.rem_u (call $rand) (local.get $thresh)))
    123       (array.set $tArrayArrayI32 (local.get $arrarr)
    124                                  (local.get $j) (call $createSecondaryArray))
    125       (local.set $i (i32.add (local.get $i) (i32.const 1)))
    126       (br_if $cont (i32.lt_u (local.get $i) (i32.const 500000)))
    127     )
    128 
    129     ;; Finally, compute a checksum by summing all the numbers
    130     ;; in all secondary arrays.  This simply assumes that all of the refs to
    131     ;; secondary arrays are non-null, which isn't per-se guaranteed by the
    132     ;; previous loop, but it works in this case because the RNG
    133     ;; produces each index value to overwrite at least once.
    134     (local.set $finalSum (i32.const 0))
    135     (local.set $i (i32.const 0)) ;; loop var for the outer loop
    136     (loop $outer
    137       ;; body of outer loop
    138       ;; $arr = $arrarr[i]
    139       (local.set $arr (array.get $tArrayArrayI32 (local.get $arrarr)
    140                       (local.get $i)))
    141       ;; iterate over $arr
    142       (local.set $arrLen (array.len (local.get $arr)))
    143       (local.set $j (i32.const 0)) ;; loop var for the inner loop
    144       (loop $inner
    145         ;; body of inner loop
    146         (local.set $finalSum
    147                    (i32.rotl (local.get $finalSum) (i32.const 1)))
    148         (local.set $finalSum
    149                    (i32.xor (local.get $finalSum)
    150                             (array.get $tArrayI32 (local.get $arr)
    151                                                   (local.get $j))))
    152         ;; loop control for the inner loop
    153         (local.set $j (i32.add (local.get $j) (i32.const 1)))
    154         (br_if $inner (i32.lt_u (local.get $j) (local.get $arrLen)))
    155       )
    156       ;; loop control for the outer loop
    157       (local.set $i (i32.add (local.get $i) (i32.const 1)))
    158       (br_if $outer (i32.lt_u (local.get $i) (i32.const 1500)))
    159     )
    160 
    161     ;; finally, roll in the final value of the RNG state
    162     (i32.xor (local.get $finalSum) (global.get $rngState))
    163   )
    164 )`;
    165 
    166 let i = wasmEvalText(t, {"": base.exports,});
    167 let fns = i.exports;
    168 
    169 assertEq(fns.churn(800), -575895114);
    170 assertEq(fns.churn(1200), -1164697516);
    171 
    172 wasmValidateText(`(module
    173  (rec
    174    (type $s1 (sub (struct (field i32))))
    175    (type $s2 (sub $s1 (struct (field i32 f32))))
    176  )
    177  (func (result (ref $s2))
    178    struct.new_default $s2
    179  )
    180  (func (export "f") (result (ref $s1))
    181    return_call 0
    182  )
    183 )`);
    184 
    185 wasmFailValidateText(`(module
    186  (rec
    187    (type $s1 (sub (struct (field i32))))
    188    (type $s2 (sub $s1 (struct (field i32 f32))))
    189  )
    190  (func (result (ref $s1))
    191    struct.new_default $s1
    192  )
    193  (func (export "f") (result (ref $s2))
    194    return_call 0
    195  )
    196 )`, /type mismatch/);
    197 
    198 wasmValidateText(`(module
    199  (rec
    200    (type $s1 (sub (struct (field i32))))
    201    (type $s2 (sub $s1 (struct (field i32 f32))))
    202  )
    203  (type $t (func (result (ref $s2))))
    204  (func (export "f") (param (ref $t)) (result (ref $s1))
    205    local.get 0
    206    return_call_ref $t
    207  )
    208 )`);
    209 
    210 wasmFailValidateText(`(module
    211  (rec
    212    (type $s1 (sub (struct (field i32))))
    213    (type $s2 (sub $s1 (struct (field i32 f32))))
    214  )
    215  (type $t (func (result (ref $s1))))
    216  (func (export "f") (param (ref $t)) (result (ref $s2))
    217    local.get 0
    218    return_call_ref $t
    219  )
    220 )`, /type mismatch/);