tor-browser

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

testFloat32.js (12140B)


      1 // |jit-test| --baseline-warmup-threshold=20
      2 
      3 // This test checks that we are able to optimize float32 inputs.  As
      4 // GetElementIC (float32 array accesses) output is not specialized with Float32
      5 // output types, we should not force inline caches.
      6 if (getJitCompilerOptions()["ion.forceinlineCaches"])
      7    setJitCompilerOption("ion.forceinlineCaches", 0);
      8 
      9 // Fuzz tests
     10 (function(){
     11    //
     12    (function(){
     13        var g = {};
     14        x = new Float32Array()
     15        Function('g', "g.o = x[1]")(g);
     16    })();
     17    //
     18    (function() {
     19        var g = new Float32Array(16);
     20        var h = new Float64Array(16);
     21        var farrays = [ g, h ];
     22        for (aridx = 0; aridx < farrays.length; ++aridx) {
     23            ar  = farrays[aridx];
     24            !(ar[ar.length-2] == (NaN / Infinity)[ar.length-2])
     25        }
     26    })();
     27    //
     28    (function () {
     29        var v = new Float32Array(32);
     30        for (var i = 0; i < v.length; ++i)
     31        v[i] = i;
     32    var t = (false  );
     33    for (var i = 0; i < i .length; ++i)
     34        t += v[i];
     35    })();
     36    //
     37    (function() {
     38        x = y = {};
     39        z = new Float32Array(6)
     40        for (c in this) {
     41            Array.prototype.unshift.call(x, new ArrayBuffer())
     42        }
     43        Array.prototype.sort.call(x, (function (j) {
     44            y.s = z[2]
     45        }))
     46    })();
     47    //
     48    (function() {
     49        // bug 1134298
     50        for (var k = 0; k < 1; k++) {
     51            Math.fround(Math.ceil(Math.fround(Math.acos(3.0))))
     52        }
     53    })();
     54 })();
     55 //
     56 // ION TESTS
     57 //
     58 // The assertFloat32 function is deactivated in --ion-eager mode, as the first time, the function Math.fround
     59 // would be guarded against modifications (typeguard on Math and then on fround). In this case, Math.fround is
     60 // not inlined and the compiler will consider the return value to be a double, not a float32, making the
     61 // assertions fail. Note that as assertFloat32 is declared unsafe for fuzzing, this can't happen in fuzzed code.
     62 //
     63 // To be able to test it, we still need ion compilation though. A nice solution
     64 // is to manually lower the ion warm-up trigger.
     65 setJitCompilerOption("ion.warmup.trigger", 50);
     66 
     67 function test(f) {
     68    f32[0] = .5;
     69    for(var n = 110; n; n--)
     70        f();
     71 }
     72 
     73 var f32 = new Float32Array(4);
     74 var f64 = new Float64Array(4);
     75 
     76 function acceptAdd() {
     77    var use = f32[0] + 1;
     78    assertFloat32(use, true);
     79    f32[0] = use;
     80 }
     81 test(acceptAdd);
     82 
     83 function acceptAddSeveral() {
     84    var sum1 = f32[0] + 0.5;
     85    var sum2 = f32[0] + 0.5;
     86    f32[0] = sum1;
     87    f32[0] = sum2;
     88    assertFloat32(sum1, true);
     89    assertFloat32(sum2, true);
     90 }
     91 test(acceptAddSeveral);
     92 
     93 function acceptAddVar() {
     94    var x = f32[0] + 1;
     95    f32[0] = x;
     96    f32[1] = x;
     97    assertFloat32(x, true);
     98 }
     99 test(acceptAddVar);
    100 
    101 function refuseAddCst() {
    102    var x = f32[0] + 1234567890; // this constant can't be precisely represented as a float32
    103    f32[0] = x;
    104    assertFloat32(x, false);
    105 }
    106 test(refuseAddCst);
    107 
    108 function refuseAddVar() {
    109    var x = f32[0] + 1;
    110    f32[0] = x;
    111    f32[1] = x;
    112    f64[1] = x; // non consumer
    113    assertFloat32(x, false);
    114 }
    115 test(refuseAddVar);
    116 
    117 function refuseAddStore64() {
    118    var x = f32[0] + 1;
    119    f64[0] = x; // non consumer
    120    f32[0] = f64[0];
    121    assertFloat32(x, false);
    122 }
    123 test(refuseAddStore64);
    124 
    125 function refuseAddStoreObj() {
    126    var o = {}
    127    var x = f32[0] + 1;
    128    o.x = x; // non consumer
    129    f32[0] = o['x'];
    130    assertFloat32(x, false);
    131 }
    132 test(refuseAddStoreObj);
    133 
    134 function refuseAddSeveral() {
    135    var sum = (f32[0] + 2) - 1; // second addition is not a consumer
    136    f32[0] = sum;
    137    assertFloat32(sum, false);
    138 }
    139 test(refuseAddSeveral);
    140 
    141 function refuseAddFunctionCall() {
    142    function plusOne(x) { return Math.cos(x+1)*13.37; }
    143    var res = plusOne(f32[0]); // func call is not a consumer
    144    f32[0] = res;
    145    assertFloat32(res, false);
    146 }
    147 test(refuseAddFunctionCall);
    148 
    149 function acceptSqrt() {
    150    var res = Math.sqrt(f32[0]);
    151    assertFloat32(res, true);
    152    f32[0] = res;
    153 }
    154 test(acceptSqrt);
    155 
    156 function refuseSqrt() {
    157    var res = Math.sqrt(f32[0]);
    158    assertFloat32(res, false);
    159    f32[0] = res + 1;
    160 }
    161 test(refuseSqrt);
    162 
    163 function acceptMin() {
    164    var res = Math.min(f32[0], f32[1]);
    165    assertFloat32(res, true);
    166    f64[0] = res;
    167 }
    168 test(acceptMin);
    169 
    170 // In theory, we could do it, as Math.min/max actually behave as a Phi (it's a
    171 // float32 producer iff its inputs are producers, it's a consumer iff its uses
    172 // are consumers). In practice, this would involve some overhead for big chains
    173 // of min/max.
    174 function refuseMinAdd() {
    175    var res = Math.min(f32[0], f32[1]) + f32[2];
    176    assertFloat32(res, false);
    177    f32[3] = res;
    178 }
    179 test(refuseMinAdd);
    180 
    181 function acceptSeveralMinMax() {
    182    var x = Math.min(f32[0], f32[1]);
    183    var y = Math.max(f32[2], f32[3]);
    184    var res = Math.min(x, y);
    185    assertFloat32(res, true);
    186    f64[0] = res;
    187 }
    188 test(acceptSeveralMinMax);
    189 
    190 function acceptSeveralMinMax2() {
    191    var res = Math.min(f32[0], f32[1], f32[2], f32[3]);
    192    assertFloat32(res, true);
    193    f64[0] = res;
    194 }
    195 test(acceptSeveralMinMax2);
    196 
    197 function partialMinMax() {
    198    var x = Math.min(f32[0], f32[1]);
    199    var y = Math.min(f64[0], f32[1]);
    200    var res  = Math.min(x, y);
    201    assertFloat32(x, true);
    202    assertFloat32(y, false);
    203    assertFloat32(res, false);
    204    f64[0] = res;
    205 }
    206 test(partialMinMax);
    207 
    208 function refuseSeveralMinMax() {
    209    var res = Math.min(f32[0], f32[1] + f32[2], f32[2], f32[3]);
    210    assertFloat32(res, false);
    211    f64[0] = res;
    212 }
    213 test(refuseSeveralMinMax);
    214 
    215 function refuseMin() {
    216    var res = Math.min(f32[0], 42.13 + f32[1]);
    217    assertFloat32(res, false);
    218    f64[0] = res;
    219 }
    220 test(refuseMin);
    221 
    222 function acceptMax() {
    223    var res = Math.max(f32[0], f32[1]);
    224    assertFloat32(res, true);
    225    f64[0] = res;
    226 }
    227 test(acceptMax);
    228 
    229 function refuseMax() {
    230    var res = Math.max(f32[0], 42.13 + f32[1]);
    231    assertFloat32(res, false);
    232    f64[0] = res;
    233 }
    234 test(refuseMax);
    235 
    236 function acceptAbs() {
    237    var res = Math.abs(f32[0]);
    238    assertFloat32(res, true);
    239    f32[0] = res;
    240 }
    241 test(acceptAbs);
    242 
    243 function refuseAbs() {
    244    var res = Math.abs(f32[0]);
    245    assertFloat32(res, false);
    246    f64[0] = res + 1;
    247 }
    248 test(refuseAbs);
    249 
    250 function acceptFilterTypeSet() {
    251    var res = f32[0];
    252    if (!res) {
    253    } else {
    254        f32[0] = res;
    255        assertFloat32(res, true);
    256    }
    257 }
    258 test(acceptFilterTypeSet);
    259 
    260 function acceptFilterTypeSet2() {
    261    var res = f32[0];
    262    if (!res) {
    263    } else {
    264        var res1 = Math.abs(res);
    265        f32[0] = res1;
    266        assertFloat32(res1, true);
    267    }
    268 }
    269 test(acceptFilterTypeSet2);
    270 
    271 function refuseFilterTypeSet() {
    272    var res = f32[0];
    273    if (!res) {
    274    } else {
    275        var res1 = Math.abs(res);
    276        f64[0] = res1 + 1;
    277        assertFloat32(res1, false);
    278    }
    279 }
    280 test(refuseFilterTypeSet);
    281 
    282 function refuseTrigo() {
    283    var res = Math.cos(f32[0]);
    284    f32[0] = res;
    285    assertFloat32(res, false);
    286 
    287    var res = Math.sin(f32[0]);
    288    f32[0] = res;
    289    assertFloat32(res, false);
    290 
    291    var res = Math.tan(f32[0]);
    292    f32[0] = res;
    293    assertFloat32(res, false);
    294 
    295    var res = Math.acos(f32[0]);
    296    f32[0] = res;
    297    assertFloat32(res, false);
    298 
    299    var res = Math.asin(f32[0]);
    300    f32[0] = res;
    301    assertFloat32(res, false);
    302 
    303    res = Math.atan(f32[0]);
    304    f32[0] = res;
    305    assertFloat32(res, false);
    306 }
    307 test(refuseTrigo);
    308 
    309 function acceptCeil() {
    310    // Specialize for floating-point output.
    311    f32[0] = NaN;
    312    f32[1] = Infinity;
    313    f32[2] = -0;
    314    f32[3] = 0.5;
    315 
    316    var res = Math.ceil(f32[0]);
    317    f32[0] = res;
    318    assertFloat32(res, true);
    319 }
    320 test(acceptCeil);
    321 
    322 function acceptFloor() {
    323    // Specialize for floating-point output.
    324    f32[0] = NaN;
    325    f32[1] = Infinity;
    326    f32[2] = -0;
    327    f32[3] = 0.5;
    328 
    329    var res = Math.floor(f32[0]);
    330    f32[0] = res;
    331    assertFloat32(res, true);
    332 }
    333 test(acceptFloor);
    334 
    335 function acceptRound() {
    336    // Specialize for floating-point output.
    337    f32[0] = NaN;
    338    f32[1] = Infinity;
    339    f32[2] = -0;
    340    f32[3] = 0.5;
    341 
    342    var res = Math.round(f32[0]);
    343    f32[0] = res;
    344    assertFloat32(res, true);
    345 }
    346 test(acceptRound);
    347 
    348 function acceptTrunc() {
    349    // Specialize for floating-point output.
    350    f32[0] = NaN;
    351    f32[1] = Infinity;
    352    f32[2] = -0;
    353    f32[3] = 0.5;
    354 
    355    var res = Math.trunc(f32[0]);
    356    f32[0] = res;
    357    assertFloat32(res, true);
    358 }
    359 test(acceptTrunc);
    360 
    361 function refuseMath() {
    362    var res = Math.log(f32[0]);
    363    f32[0] = res;
    364    assertFloat32(res, false);
    365 
    366    var res = Math.log10(f32[0]);
    367    f32[0] = res;
    368    assertFloat32(res, false);
    369 
    370    res = Math.log2(f32[0]);
    371    f32[0] = res;
    372    assertFloat32(res, false);
    373 
    374    res = Math.log1p(f32[0]);
    375    f32[0] = res;
    376    assertFloat32(res, false);
    377 
    378    res = Math.exp(f32[0]);
    379    f32[0] = res;
    380    assertFloat32(res, false);
    381 
    382    res = Math.expm1(f32[0]);
    383    f32[0] = res;
    384    assertFloat32(res, false);
    385 
    386    res = Math.cosh(f32[0]);
    387    f32[0] = res;
    388    assertFloat32(res, false);
    389 
    390    res = Math.sinh(f32[0]);
    391    f32[0] = res;
    392    assertFloat32(res, false);
    393 
    394    res = Math.tanh(f32[0]);
    395    f32[0] = res;
    396    assertFloat32(res, false);
    397 
    398    res = Math.acosh(f32[0]);
    399    f32[0] = res;
    400    assertFloat32(res, false);
    401 
    402    res = Math.asinh(f32[0]);
    403    f32[0] = res;
    404    assertFloat32(res, false);
    405 
    406    res = Math.atanh(f32[0]);
    407    f32[0] = res;
    408    assertFloat32(res, false);
    409 
    410    res = Math.cbrt(f32[0]);
    411    f32[0] = res;
    412    assertFloat32(res, false);
    413 
    414    res = Math.sign(f32[0]);
    415    f32[0] = res;
    416    assertFloat32(res, false);
    417 }
    418 test(refuseMath);
    419 
    420 function refuseLoop() {
    421    var res = f32[0],
    422        n = 10;
    423    while (n--) {
    424        res = res + 1; // this loop is equivalent to several additions => second addition is not a consumer
    425        assertFloat32(res, false);
    426    }
    427    assertFloat32(res, false);
    428    f32[0] = res;
    429 }
    430 test(refuseLoop);
    431 
    432 function acceptLoop() {
    433    // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773).
    434    return;
    435 
    436    var res = f32[0],
    437        n = 10;
    438    while (n--) {
    439        var sum = res + 1;
    440        res = Math.fround(sum);
    441        assertFloat32(sum, true);
    442    }
    443    assertFloat32(res, true);
    444    f32[0] = res;
    445 }
    446 test(acceptLoop);
    447 
    448 function alternateCond(n) {
    449    var x = f32[0];
    450    if (n > 0) {
    451        var s1 = x + 1;
    452        f32[0] = s1;
    453        assertFloat32(s1, true);
    454    } else {
    455        var s2 = x + 1;
    456        f64[0] = s2; // non consumer
    457        assertFloat32(s2, false);
    458    }
    459 }
    460 (function() {
    461    f32[0] = 0;
    462    for (var n = 110; n; n--) {
    463        alternateCond(n % 2);
    464    }
    465 })();
    466 
    467 function phiTest(n) {
    468    // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773).
    469    return;
    470 
    471    var x = (f32[0]);
    472    var y = n;
    473    if (n > 0) {
    474        x = x + 2;
    475        assertFloat32(x, true);
    476    } else {
    477        if (n < -10) {
    478            x = Math.fround(Math.sqrt(y));
    479            assertFloat32(x, true);
    480        } else {
    481            x = x - 1;
    482            assertFloat32(x, true);
    483        }
    484    }
    485    assertFloat32(x, true);
    486    f32[0] = x;
    487 }
    488 (function() {
    489    f32[0] = 0;
    490    for (var n = 100; n; n--) {
    491        phiTest( ((n % 3) - 1) * 15 );
    492    }
    493 })();
    494 
    495 function mixedPhiTest(n) {
    496    // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773).
    497    return;
    498 
    499    var x = (f32[0]);
    500    var y = n;
    501    if (n > 0) {
    502        x = x + 2; // non consumer because of (1)
    503        assertFloat32(x, false);
    504    } else {
    505        if (n < -10) {
    506            x = Math.fround(Math.sqrt(y)); // new producer
    507            assertFloat32(x, true);
    508        } else {
    509            x = x - 1; // non consumer because of (1)
    510            assertFloat32(x, false);
    511        }
    512    }
    513    assertFloat32(x, false);
    514    x = x + 1; // (1) non consumer
    515    f32[0] = x;
    516 }
    517 (function() {
    518    f32[0] = 0;
    519    for (var n = 100; n; n--) {
    520        mixedPhiTest( ((n % 3) - 1) * 15 );
    521    }
    522 })();
    523 
    524 function phiTest2(n) {
    525    // TODO(post-Warp): Support Float32 with Phi nodes (bug 1655773).
    526    return;
    527 
    528    var x = f32[0];
    529    while (n >= 0) {
    530        x = Math.fround(Math.fround(x) + 1);
    531        assertFloat32(x, true);
    532        if (n < 10) {
    533            x = f32[0] + 1;
    534            assertFloat32(x, true);
    535        }
    536        n = n - 1;
    537    }
    538 }
    539 (function(){
    540    f32[0] = 0;
    541    for (var n = 100; n > 10; n--) {
    542        phiTest2(n);
    543    }
    544 })();