tor-browser

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

udivormod-fallible.js (3430B)


      1 // Test case for fallible unsigned division and modulus instructions.
      2 //
      3 // Doesn't include test that bailouts are correctly implemented.
      4 
      5 // |MBinaryInstruction::unsignedOperands()| calls MustBeUInt32, which only
      6 // treats MUrsh as unsigned when bailouts are disabled.
      7 //
      8 // |MUrsh::collectRangeInfoPreTrunc()| sets |MUrsh::bailoutsDisabled_| if
      9 // the lower bound of the lhs operand is >= 0 and the lower bound of the rhs
     10 // operand is >= 1.
     11 //
     12 // Use |Math.max(v, 0)| below to ensure the operand is non-negative, so that
     13 // the |MUrsh| is marked as bailouts disabled.
     14 
     15 // MMod::computeRange sets |MMod::unsigned_| flag.
     16 //
     17 // Range Analysis uses IsUint32Type to check for Uint32 types. IsUint32Type
     18 // doesn't require that |Ursh| is marked as bailouts disabled.
     19 //
     20 // These don't need an explicit bit-or operation to mark as truncated.
     21 function umod_by_constant(x) {
     22  return (x >>> 0) % 3;
     23 }
     24 function umod_by_constant_pow_two(x) {
     25  return (x >>> 0) % 4;
     26 }
     27 function umod(dividend, divisor) {
     28  // Ensure range of |divisor| doesn't include zero.
     29  divisor = Math.min(Math.max(divisor, 1), 10);
     30 
     31  // Make sure |IsUint32Type| returns true for both operands.
     32  return (dividend >>> 0) % (divisor >>> 0);
     33 }
     34 
     35 // |MMod::computeRange| also marks the operation as unsigned when the lower
     36 // bound of the dividend is >= 0 (and the divisor's range doesn't include zero.)
     37 function umod_by_constant_no_ursh(dividend, divisor) {
     38  // Ensure lower bound of |dividend| range is >= 0.
     39  dividend = Math.max(dividend, 0);
     40 
     41  return dividend % 5;
     42 }
     43 function umod_no_ursh(dividend, divisor) {
     44  // Ensure lower bound of |dividend| range is >= 0.
     45  dividend = Math.max(dividend, 0);
     46 
     47  // Ensure range of |divisor| doesn't include zero.
     48  divisor = Math.min(Math.max(divisor, 1), 10);
     49 
     50  return dividend % divisor;
     51 }
     52 
     53 // MMod::truncate sets |MMod::unsigned_| flag. Bit-or is needed to mark as truncated.
     54 function umod_truncate(dividend, divisor) {
     55  dividend = Math.max(dividend, 0);
     56  divisor = Math.max(divisor, 0);
     57  return ((dividend >>> 0) % (divisor >>> 0))|0;
     58 }
     59 
     60 // MDiv::truncate sets |MDiv::unsigned_| flag. Bit-or is needed to mark as truncated.
     61 //
     62 // Note: MDiv::computeRange never sets |MDiv::unsigned_|.
     63 function udiv_by_constant(dividend) {
     64  dividend = Math.max(dividend, 0);
     65  return ((dividend >>> 0) / 3)|0;
     66 }
     67 function udiv_by_constant_pow_two(dividend) {
     68  dividend = Math.max(dividend, 0);
     69  return ((dividend >>> 0) / 8)|0;
     70 }
     71 function udiv(dividend, divisor) {
     72  dividend = Math.max(dividend, 0);
     73  divisor = Math.max(divisor, 0);
     74  return ((dividend >>> 0) / (divisor >>> 0))|0;
     75 }
     76 
     77 // Don't Ion compile the top-level script.
     78 with ({});
     79 
     80 for (let i = 0; i < 100; ++i) {
     81  assertEq(umod_by_constant(i), i % 3);
     82  assertEq(umod_by_constant_pow_two(i), i % 4);
     83 
     84  assertEq(umod(i, 1), i % 1);
     85  assertEq(umod(i, 3), i % 3);
     86  assertEq(umod(i, 5), i % 5);
     87 
     88  assertEq(umod_by_constant_no_ursh(i), i % 5);
     89 
     90  assertEq(umod_no_ursh(i, 1), i % 1);
     91  assertEq(umod_no_ursh(i, 7), i % 7);
     92  assertEq(umod_no_ursh(i, 9), i % 9);
     93 
     94  assertEq(umod_truncate(i, 1), i % 1);
     95  assertEq(umod_truncate(i, 6), i % 6);
     96  assertEq(umod_truncate(i, 11), i % 11);
     97 
     98  // Use multiples of the divisor to ensure CacheIR doesn't emit a Double division. (bug 1554721)
     99  assertEq(udiv_by_constant(i * 3), i);
    100  assertEq(udiv_by_constant_pow_two(i * 8), i);
    101 
    102  assertEq(udiv(i * 1, 1), i);
    103  assertEq(udiv(i * 3, 3), i);
    104  assertEq(udiv(i * 5, 5), i);
    105 }