tor-browser

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

testProfiling.js (9108B)


      1 // |jit-test| skip-if: !isAsmJSCompilationAvailable() || (!getBuildConfiguration("arm-simulator") && !getBuildConfiguration("arm64-simulator"))
      2 // Single-step profiling currently only works in the ARM simulator
      3 
      4 load(libdir + "asm.js");
      5 load(libdir + "asserts.js");
      6 
      7 var roundInstructions = [];
      8 
      9 // ARM64 doesn't call into the runtime for rounding instructions.
     10 if (!getBuildConfiguration("arm64-simulator")) {
     11    roundInstructions.push('ceil', 'floor');
     12 }
     13 
     14 function checkSubSequence(got, expect)
     15 {
     16    var got_i = 0;
     17    EXP: for (var exp_i = 0; exp_i < expect.length; exp_i++) {
     18        var item = expect[exp_i];
     19        // Scan for next match in got.
     20        while (got_i < got.length) {
     21            if (got[got_i++] == expect[exp_i])
     22                continue EXP;
     23        }
     24        print("MISMATCH: " + got.join(",") + "\n" +
     25              "    VS    " + expect.join(","));
     26        return false;
     27    }
     28    return true;
     29 }
     30 
     31 function assertStackContainsSeq(got, expect)
     32 {
     33    var normalized = [];
     34 
     35    for (var i = 0; i < got.length; i++) {
     36        if (got[i].length == 0)
     37            continue;
     38        var parts = got[i].split(',');
     39        for (var j = 0; j < parts.length; j++) {
     40            var frame = parts[j];
     41            frame = frame.replace(/ \([^\)]*\)/g, "");
     42            frame = frame.replace(/fast exit trampoline to native/g, "N");
     43            frame = frame.replace(/^call to( asm.js)? native .*\(in wasm\)$/g, "N");
     44            frame = frame.replace(/(fast|slow) exit trampoline/g, "<");
     45            frame = frame.replace(/(fast|slow) entry trampoline/g, ">");
     46            frame = frame.replace(/(\/[^\/,<]+)*\/testProfiling.js/g, "");
     47            frame = frame.replace(/testBuiltinD2D/g, "");
     48            frame = frame.replace(/testBuiltinF2F/g, "");
     49            frame = frame.replace(/testBuiltinDD2D/g, "");
     50            frame = frame.replace(/assertThrowsInstanceOf/g, "");
     51            frame = frame.replace(/^ffi[12]?/g, "");
     52            normalized.push(frame);
     53        }
     54    }
     55 
     56    var gotNorm = normalized.join(',').replace(/,+/g, ",");
     57    gotNorm = gotNorm.replace(/^,/, "").replace(/,$/, "");
     58 
     59    assertEq(checkSubSequence(gotNorm.split(','), expect.split(',')), true);
     60 }
     61 
     62 // Test profiling enablement while asm.js is running.
     63 var stacks;
     64 var ffi = function(enable) {
     65    if (enable == +1)
     66        enableGeckoProfiling();
     67    enableSingleStepProfiling();
     68    stacks = disableSingleStepProfiling();
     69    if (enable == -1)
     70        disableGeckoProfiling();
     71 }
     72 var f = asmLink(asmCompile('global','ffis',USE_ASM + "var ffi=ffis.ffi; function g(i) { i=i|0; ffi(i|0) } function f(i) { i=i|0; g(i|0) } return f"), null, {ffi});
     73 f(0);
     74 assertStackContainsSeq(stacks, "");
     75 f(+1);
     76 assertStackContainsSeq(stacks, "<,g,f,>");
     77 f(0);
     78 assertStackContainsSeq(stacks, "<,g,f,>");
     79 f(-1);
     80 assertStackContainsSeq(stacks, "<,g,f,>");
     81 f(0);
     82 assertStackContainsSeq(stacks, "");
     83 
     84 // Enable profiling for the rest of the tests.
     85 enableGeckoProfiling();
     86 
     87 var f = asmLink(asmCompile(USE_ASM + "function f() { return 42 } return f"));
     88 enableSingleStepProfiling();
     89 assertEq(f(), 42);
     90 var stacks = disableSingleStepProfiling();
     91 assertStackContainsSeq(stacks, ">,f,>,>");
     92 
     93 var m = asmCompile(USE_ASM + "function g(i) { i=i|0; return (i+1)|0 } function f() { return g(42)|0 } return f");
     94 for (var i = 0; i < 3; i++) {
     95    var f = asmLink(m);
     96    enableSingleStepProfiling();
     97    assertEq(f(), 43);
     98    var stacks = disableSingleStepProfiling();
     99    assertStackContainsSeq(stacks, ">,f,>,g,f,>,f,>,>");
    100 }
    101 
    102 var m = asmCompile(USE_ASM + "function g1() { return 1 } function g2() { return 2 } function f(i) { i=i|0; return TBL[i&1]()|0 } var TBL=[g1,g2]; return f");
    103 for (var i = 0; i < 3; i++) {
    104    var f = asmLink(m);
    105    enableSingleStepProfiling();
    106    assertEq(f(0), 1);
    107    assertEq(f(1), 2);
    108    var stacks = disableSingleStepProfiling();
    109    assertStackContainsSeq(stacks, ">,f,>,g1,f,>,f,>,>,>,f,>,g2,f,>,f,>,>");
    110 }
    111 
    112 function testBuiltinD2D(name) {
    113    var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d) { d=+d; return +fun(d) } return f");
    114    for (var i = 0; i < 3; i++) {
    115        var f = asmLink(m, this);
    116        enableSingleStepProfiling();
    117        assertEq(f(.1), eval("Math." + name + "(.1)"));
    118        var stacks = disableSingleStepProfiling();
    119        assertStackContainsSeq(stacks, ">,f,>,N,f,>,f,>,>");
    120    }
    121 }
    122 for (name of ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'exp', 'log', ...roundInstructions])
    123    testBuiltinD2D(name);
    124 
    125 function testBuiltinF2F(name) {
    126    var m = asmCompile('g', USE_ASM + "var tof=g.Math.fround; var fun=g.Math." + name + "; function f(d) { d=tof(d); return tof(fun(d)) } return f");
    127    for (var i = 0; i < 3; i++) {
    128        var f = asmLink(m, this);
    129        enableSingleStepProfiling();
    130        assertEq(f(.1), eval("Math.fround(Math." + name + "(Math.fround(.1)))"));
    131        var stacks = disableSingleStepProfiling();
    132        assertStackContainsSeq(stacks, ">,f,>,N,f,>,f,>,>");
    133    }
    134 }
    135 for (name of roundInstructions)
    136    testBuiltinF2F(name);
    137 
    138 function testBuiltinDD2D(name) {
    139    var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d, e) { d=+d; e=+e; return +fun(d,e) } return f");
    140    for (var i = 0; i < 3; i++) {
    141        var f = asmLink(m, this);
    142        enableSingleStepProfiling();
    143        assertEq(f(.1, .2), eval("Math." + name + "(.1, .2)"));
    144        var stacks = disableSingleStepProfiling();
    145        assertStackContainsSeq(stacks, ">,f,>,N,f,>,f,>,>");
    146    }
    147 }
    148 for (name of ['atan2', 'pow'])
    149    testBuiltinDD2D(name);
    150 
    151 // FFI tests:
    152 setJitCompilerOption("ion.warmup.trigger", 10);
    153 setJitCompilerOption("baseline.warmup.trigger", 0);
    154 setJitCompilerOption("offthread-compilation.enable", 0);
    155 
    156 var m = asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f() { return ((ffi1()|0) + (ffi2()|0))|0 } return f");
    157 
    158 var ffi1 = function() { return 10 }
    159 var ffi2 = function() { return 73 }
    160 var f = asmLink(m, null, {ffi1,ffi2});
    161 
    162 // Interp FFI exit
    163 enableSingleStepProfiling();
    164 assertEq(f(), 83);
    165 var stacks = disableSingleStepProfiling();
    166 assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>");
    167 
    168 // Ion FFI exit
    169 for (var i = 0; i < 20; i++)
    170    assertEq(f(), 83);
    171 enableSingleStepProfiling();
    172 assertEq(f(), 83);
    173 var stacks = disableSingleStepProfiling();
    174 assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>");
    175 
    176 var ffi1 = function() { return { valueOf() { return 20 } } }
    177 var ffi2 = function() { return { valueOf() { return 74 } } }
    178 var f = asmLink(m, null, {ffi1,ffi2});
    179 
    180 // Interp FFI exit
    181 enableSingleStepProfiling();
    182 assertEq(f(), 94);
    183 var stacks = disableSingleStepProfiling();
    184 assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up
    185 
    186 // Ion FFI exit
    187 for (var i = 0; i < 20; i++)
    188    assertEq(f(), 94);
    189 enableSingleStepProfiling();
    190 assertEq(f(), 94);
    191 var stacks = disableSingleStepProfiling();
    192 assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up
    193 
    194 var ffi1 = function() { return 15 }
    195 var ffi2 = function() { return f2() + 17 }
    196 var {f1,f2} = asmLink(asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f2() { return ffi1()|0 } function f1() { return ffi2()|0 } return {f1:f1, f2:f2}"), null, {ffi1, ffi2});
    197 // Interpreter FFI exit
    198 enableSingleStepProfiling();
    199 assertEq(f1(), 32);
    200 var stacks = disableSingleStepProfiling();
    201 assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>");
    202 
    203 
    204 // Ion FFI exit
    205 var jitOptions = getJitCompilerOptions();
    206 if (jitOptions['baseline.enable']) {
    207    for (var i = 0; i < 20; i++)
    208        assertEq(f1(), 32);
    209    enableSingleStepProfiling();
    210    assertEq(f1(), 32);
    211    var stacks = disableSingleStepProfiling();
    212    assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>");
    213 }
    214 
    215 // Thunks
    216 setJitCompilerOption("jump-threshold", 0);
    217 var h = asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h'));
    218 enableSingleStepProfiling();
    219 h();
    220 var stacks = disableSingleStepProfiling();
    221 assertStackContainsSeq(stacks, ">,h,>,g,h,>,f,g,h,>,g,h,>,h,>,>");
    222 setJitCompilerOption("jump-threshold", -1);
    223 
    224 // This takes forever to run.
    225 // Stack-overflow exit test
    226 //var limit = -1;
    227 //var maxct = 0;
    228 //function ffi(ct) { if (ct == limit) { enableSingleStepProfiling(); print("enabled"); } maxct = ct; }
    229 //var f = asmLink(asmCompile('g', 'ffis',USE_ASM + "var ffi=ffis.ffi; var ct=0; function rec(){ ct=(ct+1)|0; ffi(ct|0); rec() } function f() { ct=0; rec() } return f"), null, {ffi});
    230 //// First find the stack limit:
    231 //var caught = false;
    232 //try { f() } catch (e) { caught = true; assertEq(String(e).indexOf("too much recursion") >= 0, true) }
    233 //assertEq(caught, true);
    234 //limit = maxct;
    235 //print("Setting limit");
    236 //var caught = false;
    237 //try { f() } catch (e) { caught = true; print("caught"); assertEq(String(e).indexOf("too much recursion") >= 0, true) }
    238 //var stacks = disableSingleStepProfiling();
    239 //assertEq(String(stacks).indexOf("rec") >= 0, true);