tor-browser

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

ad-hack-binop-preamble.js (12561B)


      1 // |jit-test| skip-if: true
      2 
      3 // Common code to test simple binary operators.  See runSimpleBinopTest below.
      4 
      5 function expandConstantBinopInputs(op, memtype, inputs) {
      6    let s = '';
      7    let ident = 0;
      8    for ( let [a, b] of inputs ) {
      9        let constlhs = `${memtype.layoutName} ${a.map(jsValueToWasmName).join(' ')}`;
     10        let constrhs = `${memtype.layoutName} ${b.map(jsValueToWasmName).join(' ')}`;
     11        s += `
     12    ;; lhs is constant, rhs is variable
     13    (func (export "run_constlhs${ident}")
     14      (v128.store (i32.const 0)
     15        (call $doit_constlhs${ident} (v128.const ${constrhs}))))
     16    (func $doit_constlhs${ident} (param $b v128) (result v128)
     17      (${op} (v128.const ${constlhs}) (local.get $b)))
     18 
     19    ;; rhs is constant, lhs is variable
     20    (func (export "run_constrhs${ident}")
     21      (v128.store (i32.const 0)
     22        (call $doit_constrhs${ident} (v128.const ${constlhs}))))
     23    (func $doit_constrhs${ident} (param $a v128) (result v128)
     24      (${op} (local.get $a) (v128.const ${constrhs})))
     25 
     26    ;; both operands are constant
     27    (func (export "run_constboth${ident}")
     28      (v128.store (i32.const 0)
     29        (call $doit_constboth${ident})))
     30    (func $doit_constboth${ident} (result v128)
     31      (${op} (v128.const ${constlhs}) (v128.const ${constrhs})))`
     32        ident++;
     33    }
     34    return s;
     35 }
     36 
     37 function insAndMemBinop(op, memtype, resultmemtype, inputs) {
     38    var ins = wasmEvalText(`
     39  (module
     40    (memory (export "mem") 1 1)
     41 
     42    ;; both arguments are variable
     43    (func (export "run")
     44      (v128.store (i32.const 0)
     45        (call $doit (v128.load (i32.const 16)) (v128.load (i32.const 32)))))
     46    (func $doit (param $a v128) (param $b v128) (result v128)
     47      (${op} (local.get $a) (local.get $b)))
     48 
     49    ${expandConstantBinopInputs(op, memtype, inputs)})`);
     50    var mem = new memtype(ins.exports.mem.buffer);
     51    var resultmem = !resultmemtype || memtype == resultmemtype ? mem : new resultmemtype(ins.exports.mem.buffer);
     52    return [ins, mem, resultmem];
     53 }
     54 
     55 function add(bits) { return (x, y) => sign_extend(x+y, bits) }
     56 function add64(x, y) { return sign_extend(BigInt(x)+BigInt(y), 64) }
     57 function sub(bits) { return (x, y) => sign_extend(x-y, bits) }
     58 function sub64(x, y) { return sign_extend(BigInt(x)-BigInt(y), 64) }
     59 // Even 32-bit multiply can overflow a Number, so always use BigInt
     60 function mul(bits) { return (x, y) => sign_extend(BigInt(x)*BigInt(y), bits) }
     61 function div(x, y) { return x/y }
     62 function min(x, y) { return x < y ? x : y }
     63 function max(x, y) { return x > y ? x : y }
     64 function and(x, y) { return zero_extend(x&y, 8) }
     65 function or(x, y) { return zero_extend(x|y, 8) }
     66 function xor(x, y) { return zero_extend(x^y, 8) }
     67 function andnot(x, y) { return zero_extend(x&~y, 8) }
     68 function avgr(x, y) { return (x + y + 1) >> 1; }
     69 function eq(truth) { return (x,y) => x==y ? truth : 0 }
     70 function ne(truth) { return (x,y) => x!=y ? truth : 0 }
     71 function lt(truth) { return (x, y) => x < y ? truth : 0 }
     72 function gt(truth) { return (x, y) => x > y ? truth : 0 }
     73 function le(truth) { return (x, y) => x <= y ? truth : 0 }
     74 function ge(truth) { return (x, y) => x >= y ? truth : 0 }
     75 
     76 function fadd(x, y) { return Math.fround(x+y) }
     77 function fsub(x, y) { return Math.fround(x-y) }
     78 function fmul(x, y) { return Math.fround(x*y) }
     79 function fdiv(x, y) { return Math.fround(x/y) }
     80 function fmin(x, y) {
     81    if (x == y) return x;
     82    if (x < y) return x;
     83    if (y < x) return y;
     84    if (isNaN(x)) return x;
     85    return y;
     86 }
     87 function fmax(x, y) {
     88    if (x == y) return x;
     89    if (x > y) return x;
     90    if (y > x) return y;
     91    if (isNaN(x)) return x;
     92    return y;
     93 }
     94 function dadd(x, y) { return x+y }
     95 function dsub(x, y) { return x-y }
     96 function dmul(x, y) { return x*y }
     97 function ddiv(x, y) { return x/y }
     98 var dmax = fmax;
     99 var dmin = fmin;
    100 
    101 function op_sat_s(bits, op) {
    102    return (x, y) => {
    103        return signed_saturate(op(sign_extend(x, bits),
    104                                  sign_extend(y, bits)),
    105                               bits);
    106    }
    107 }
    108 
    109 function op_sat_u(bits, op) {
    110    return (x, y) => {
    111        return unsigned_saturate(op(zero_extend(x, bits),
    112                                    zero_extend(y, bits)),
    113                                 bits);
    114    }
    115 }
    116 
    117 function add_sat_s(bits) {
    118    return op_sat_s(bits, (x,y) => x+y);
    119 }
    120 function sub_sat_s(bits) {
    121    return op_sat_s(bits, (x,y) => x-y);
    122 }
    123 function add_sat_u(bits) {
    124    return op_sat_u(bits, (x,y) => x+y);
    125 }
    126 function sub_sat_u(bits) {
    127    return op_sat_u(bits, (x,y) => x-y);
    128 }
    129 
    130 function max_s(bits) {
    131    return (x, y) => {
    132        return sign_extend(max(sign_extend(x, bits),
    133                               sign_extend(y, bits)),
    134                           bits);
    135    }
    136 }
    137 
    138 function min_s(bits) {
    139    return (x, y) => {
    140        return sign_extend(min(sign_extend(x, bits),
    141                               sign_extend(y, bits)),
    142                           bits);
    143    }
    144 }
    145 
    146 function max_u(bits) {
    147    return (x, y) => {
    148        return max(zero_extend(x, bits),
    149                   zero_extend(y, bits));
    150    }
    151 }
    152 
    153 function min_u(bits) {
    154    return (x, y) => {
    155        return min(zero_extend(x, bits),
    156                   zero_extend(y, bits));
    157    }
    158 }
    159 
    160 function pmin(x, y) { return y < x ? y : x }
    161 function pmax(x, y) { return x < y ? y : x }
    162 
    163 assertEq(max_s(8)(1, 2), 2);
    164 assertEq(max_s(8)(1, 128), 1);
    165 assertEq(min_s(8)(1, 2), 1);
    166 assertEq(min_s(8)(1, 128), -128);
    167 assertEq(max_u(8)(1, 2), 2);
    168 assertEq(max_u(8)(1, 128), 128);
    169 assertEq(min_u(8)(1, 2), 1);
    170 assertEq(min_u(8)(1, 128), 1);
    171 
    172 var binopTests =
    173    [['i8x16.add', Int8Array, add(8)],
    174     ['i16x8.add', Int16Array, add(16)],
    175     ['i32x4.add', Int32Array, add(32)],
    176     ['i64x2.add', BigInt64Array, add64],
    177     ['i8x16.sub', Int8Array, sub(8)],
    178     ['i16x8.sub', Int16Array, sub(16)],
    179     ['i32x4.sub', Int32Array, sub(32)],
    180     ['i64x2.sub', BigInt64Array, sub64],
    181     ['i8x16.add_sat_s', Int8Array, add_sat_s(8)],
    182     ['i8x16.add_sat_u', Uint8Array, add_sat_u(8)],
    183     ['i16x8.add_sat_s', Int16Array, add_sat_s(16)],
    184     ['i16x8.add_sat_u', Uint16Array, add_sat_u(16)],
    185     ['i8x16.sub_sat_s', Int8Array, sub_sat_s(8)],
    186     ['i8x16.sub_sat_u', Uint8Array, sub_sat_u(8)],
    187     ['i16x8.sub_sat_s', Int16Array, sub_sat_s(16)],
    188     ['i16x8.sub_sat_u', Uint16Array, sub_sat_u(16)],
    189     ['i16x8.mul', Int16Array, mul(16)],
    190     ['i32x4.mul', Int32Array, mul(32)],
    191     ['i64x2.mul', BigInt64Array, mul(64)],
    192     ['i8x16.avgr_u', Uint8Array, avgr],
    193     ['i16x8.avgr_u', Uint16Array, avgr],
    194     ['i8x16.max_s', Int8Array, max_s(8)],
    195     ['i8x16.max_u', Uint8Array, max_u(8)],
    196     ['i8x16.min_s', Int8Array, min_s(8)],
    197     ['i8x16.min_u', Uint8Array, min_u(8)],
    198     ['i16x8.max_s', Int16Array, max_s(16)],
    199     ['i16x8.max_u', Uint16Array, max_u(16)],
    200     ['i16x8.min_s', Int16Array, min_s(16)],
    201     ['i16x8.min_u', Uint16Array, min_u(16)],
    202     ['i32x4.max_s', Int32Array, max_s(32)],
    203     ['i32x4.max_u', Uint32Array, max_u(32)],
    204     ['i32x4.min_s', Int32Array, min_s(32)],
    205     ['i32x4.min_u', Uint32Array, min_u(32)],
    206     ['v128.and', Uint8Array, and],
    207     ['v128.or', Uint8Array, or],
    208     ['v128.xor', Uint8Array, xor],
    209     ['v128.andnot', Uint8Array, andnot],
    210     ['f32x4.add', Float32Array, fadd],
    211     ['f32x4.sub', Float32Array, fsub],
    212     ['f32x4.mul', Float32Array, fmul],
    213     ['f32x4.div', Float32Array, fdiv],
    214     ['f32x4.min', Float32Array, fmin],
    215     ['f32x4.max', Float32Array, fmax],
    216     ['f64x2.add', Float64Array, dadd],
    217     ['f64x2.sub', Float64Array, dsub],
    218     ['f64x2.mul', Float64Array, dmul],
    219     ['f64x2.div', Float64Array, ddiv],
    220     ['f64x2.min', Float64Array, dmin],
    221     ['f64x2.max', Float64Array, dmax],
    222     ['i8x16.eq', Int8Array, eq(-1)],
    223     ['i8x16.ne', Int8Array, ne(-1)],
    224     ['i8x16.lt_s', Int8Array, lt(-1)],
    225     ['i8x16.gt_s', Int8Array, gt(-1)],
    226     ['i8x16.le_s', Int8Array, le(-1)],
    227     ['i8x16.ge_s', Int8Array, ge(-1)],
    228     ['i8x16.gt_u', Uint8Array, gt(0xFF)],
    229     ['i8x16.ge_u', Uint8Array, ge(0xFF)],
    230     ['i8x16.lt_u', Uint8Array, lt(0xFF)],
    231     ['i8x16.le_u', Uint8Array, le(0xFF)],
    232     ['i16x8.eq', Int16Array, eq(-1)],
    233     ['i16x8.ne', Int16Array, ne(-1)],
    234     ['i16x8.lt_s', Int16Array, lt(-1)],
    235     ['i16x8.gt_s', Int16Array, gt(-1)],
    236     ['i16x8.le_s', Int16Array, le(-1)],
    237     ['i16x8.ge_s', Int16Array, ge(-1)],
    238     ['i16x8.gt_u', Uint16Array, gt(0xFFFF)],
    239     ['i16x8.ge_u', Uint16Array, ge(0xFFFF)],
    240     ['i16x8.lt_u', Uint16Array, lt(0xFFFF)],
    241     ['i16x8.le_u', Uint16Array, le(0xFFFF)],
    242     ['i32x4.eq', Int32Array, eq(-1)],
    243     ['i32x4.ne', Int32Array, ne(-1)],
    244     ['i32x4.lt_s', Int32Array, lt(-1)],
    245     ['i32x4.gt_s', Int32Array, gt(-1)],
    246     ['i32x4.le_s', Int32Array, le(-1)],
    247     ['i32x4.ge_s', Int32Array, ge(-1)],
    248     ['i32x4.gt_u', Uint32Array, gt(0xFFFFFFFF)],
    249     ['i32x4.ge_u', Uint32Array, ge(0xFFFFFFFF)],
    250     ['i32x4.lt_u', Uint32Array, lt(0xFFFFFFFF)],
    251     ['i32x4.le_u', Uint32Array, le(0xFFFFFFFF)],
    252     ['f32x4.eq', Float32Array, eq(-1), Int32Array],
    253     ['f32x4.ne', Float32Array, ne(-1), Int32Array],
    254     ['f32x4.lt', Float32Array, lt(-1), Int32Array],
    255     ['f32x4.gt', Float32Array, gt(-1), Int32Array],
    256     ['f32x4.le', Float32Array, le(-1), Int32Array],
    257     ['f32x4.ge', Float32Array, ge(-1), Int32Array],
    258     ['f64x2.eq', Float64Array, eq(-1), BigInt64Array],
    259     ['f64x2.ne', Float64Array, ne(-1), BigInt64Array],
    260     ['f64x2.lt', Float64Array, lt(-1), BigInt64Array],
    261     ['f64x2.gt', Float64Array, gt(-1), BigInt64Array],
    262     ['f64x2.le', Float64Array, le(-1), BigInt64Array],
    263     ['f64x2.ge', Float64Array, ge(-1), BigInt64Array],
    264     ['f32x4.pmin', Float32Array, pmin],
    265     ['f32x4.pmax', Float32Array, pmax],
    266     ['f64x2.pmin', Float64Array, pmin],
    267     ['f64x2.pmax', Float64Array, pmax]]
    268 
    269 // Run v128 x v128 -> v128 tests.  Inputs are taken from the common input sets,
    270 // placed in memory, the test is run, and the result is extracted and checked.
    271 //
    272 // Runs tests with both operands as variables, either as constant, or both as
    273 // constant.  Also checks NaN behavior when appropriate.
    274 //
    275 // All runners that call this should use the same value for `ofParts` and should
    276 // pass different values for `part`, up to `ofParts` - 1.
    277 
    278 function runSimpleBinopTest(part, ofParts) {
    279    let partSize = Math.ceil(binopTests.length / ofParts);
    280    let start = part * partSize;
    281    let end = Math.min((part + 1) * partSize, binopTests.length);
    282    for ( let [op, memtype, rop, resultmemtype] of binopTests.slice(start, end) ) {
    283        let inputs = cross(memtype.inputs);
    284        let len = 16/memtype.BYTES_PER_ELEMENT;
    285        let xs = iota(len);
    286        let zero = xs.map(_ => 0);
    287        let [ins, mem, resultmem] = insAndMemBinop(op, memtype, resultmemtype, inputs);
    288        let bitsForF32 = memtype == Float32Array ? new Uint32Array(mem.buffer) : null;
    289        let bitsForF64 = memtype == Float64Array ? new BigInt64Array(mem.buffer) : null;
    290 
    291        function testIt(a,b,r) {
    292            set(mem, len, a);
    293            set(mem, len*2, b);
    294            ins.exports.run();
    295            assertSame(get(resultmem, 0, len), r);
    296 
    297            // Test signalling NaN superficially by replacing QNaN inputs with SNaN
    298            if (bitsForF32 != null && (a.some(isNaN) || b.some(isNaN))) {
    299                a.forEach((x, i) => { if (isNaN(x)) { bitsForF32[len+i] = 0x7FA0_0000; } });
    300                b.forEach((x, i) => { if (isNaN(x)) { bitsForF32[(len*2)+i] = 0x7FA0_0000; } });
    301                ins.exports.run();
    302                assertSame(get(resultmem, 0, len), r);
    303            }
    304            if (bitsForF64 != null && (a.some(isNaN) || b.some(isNaN))) {
    305                a.forEach((x, i) => { if (isNaN(x)) { bitsForF64[len+i] = 0x7FF4_0000_0000_0000n; } });
    306                b.forEach((x, i) => { if (isNaN(x)) { bitsForF64[(len*2)+i] = 0x7FF4_0000_0000_0000n; } });
    307                ins.exports.run();
    308                assertSame(get(resultmem, 0, len), r);
    309            }
    310        }
    311 
    312        function testConstIt(i,r) {
    313            set(resultmem, 0, zero);
    314            ins.exports["run_constlhs" + i]();
    315            assertSame(get(resultmem, 0, len), r);
    316 
    317            set(resultmem, 0, zero);
    318            ins.exports["run_constrhs" + i]();
    319            assertSame(get(resultmem, 0, len), r);
    320 
    321            set(resultmem, 0, zero);
    322            ins.exports["run_constboth" + i]();
    323            assertSame(get(resultmem, 0, len), r);
    324        }
    325 
    326        let i = 0;
    327        for (let [a,b] of inputs) {
    328            let r = xs.map((i) => rop(a[i], b[i]));
    329            testIt(a,b,r);
    330            testConstIt(i,r);
    331            i++;
    332        }
    333    }
    334 }