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);