summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/asm.js/testProfiling.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/jit-test/tests/asm.js/testProfiling.js
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/asm.js/testProfiling.js')
-rw-r--r--js/src/jit-test/tests/asm.js/testProfiling.js232
1 files changed, 232 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/asm.js/testProfiling.js b/js/src/jit-test/tests/asm.js/testProfiling.js
new file mode 100644
index 0000000000..35113f0a29
--- /dev/null
+++ b/js/src/jit-test/tests/asm.js/testProfiling.js
@@ -0,0 +1,232 @@
+// |jit-test| skip-if: !isAsmJSCompilationAvailable() || !getBuildConfiguration("arm-simulator")
+// Single-step profiling currently only works in the ARM simulator
+
+load(libdir + "asm.js");
+load(libdir + "asserts.js");
+
+function checkSubSequence(got, expect)
+{
+ var got_i = 0;
+ EXP: for (var exp_i = 0; exp_i < expect.length; exp_i++) {
+ var item = expect[exp_i];
+ // Scan for next match in got.
+ while (got_i < got.length) {
+ if (got[got_i++] == expect[exp_i])
+ continue EXP;
+ }
+ print("MISMATCH: " + got.join(",") + "\n" +
+ " VS " + expect.join(","));
+ return false;
+ }
+ return true;
+}
+
+function assertStackContainsSeq(got, expect)
+{
+ var normalized = [];
+
+ for (var i = 0; i < got.length; i++) {
+ if (got[i].length == 0)
+ continue;
+ var parts = got[i].split(',');
+ for (var j = 0; j < parts.length; j++) {
+ var frame = parts[j];
+ frame = frame.replace(/ \([^\)]*\)/g, "");
+ frame = frame.replace(/fast exit trampoline to native/g, "N");
+ frame = frame.replace(/^call to( asm.js)? native .*\(in wasm\)$/g, "N");
+ frame = frame.replace(/(fast|slow) exit trampoline/g, "<");
+ frame = frame.replace(/(fast|slow) entry trampoline/g, ">");
+ frame = frame.replace(/(\/[^\/,<]+)*\/testProfiling.js/g, "");
+ frame = frame.replace(/testBuiltinD2D/g, "");
+ frame = frame.replace(/testBuiltinF2F/g, "");
+ frame = frame.replace(/testBuiltinDD2D/g, "");
+ frame = frame.replace(/assertThrowsInstanceOf/g, "");
+ frame = frame.replace(/^ffi[12]?/g, "");
+ normalized.push(frame);
+ }
+ }
+
+ var gotNorm = normalized.join(',').replace(/,+/g, ",");
+ gotNorm = gotNorm.replace(/^,/, "").replace(/,$/, "");
+
+ assertEq(checkSubSequence(gotNorm.split(','), expect.split(',')), true);
+}
+
+// Test profiling enablement while asm.js is running.
+var stacks;
+var ffi = function(enable) {
+ if (enable == +1)
+ enableGeckoProfiling();
+ enableSingleStepProfiling();
+ stacks = disableSingleStepProfiling();
+ if (enable == -1)
+ disableGeckoProfiling();
+}
+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});
+f(0);
+assertStackContainsSeq(stacks, "");
+f(+1);
+assertStackContainsSeq(stacks, "<,g,f,>");
+f(0);
+assertStackContainsSeq(stacks, "<,g,f,>");
+f(-1);
+assertStackContainsSeq(stacks, "<,g,f,>");
+f(0);
+assertStackContainsSeq(stacks, "");
+
+// Enable profiling for the rest of the tests.
+enableGeckoProfiling();
+
+var f = asmLink(asmCompile(USE_ASM + "function f() { return 42 } return f"));
+enableSingleStepProfiling();
+assertEq(f(), 42);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,>");
+
+var m = asmCompile(USE_ASM + "function g(i) { i=i|0; return (i+1)|0 } function f() { return g(42)|0 } return f");
+for (var i = 0; i < 3; i++) {
+ var f = asmLink(m);
+ enableSingleStepProfiling();
+ assertEq(f(), 43);
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,g,f,>,f,>,>");
+}
+
+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");
+for (var i = 0; i < 3; i++) {
+ var f = asmLink(m);
+ enableSingleStepProfiling();
+ assertEq(f(0), 1);
+ assertEq(f(1), 2);
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,g1,f,>,f,>,>,>,f,>,g2,f,>,f,>,>");
+}
+
+function testBuiltinD2D(name) {
+ var m = asmCompile('g', USE_ASM + "var fun=g.Math." + name + "; function f(d) { d=+d; return +fun(d) } return f");
+ for (var i = 0; i < 3; i++) {
+ var f = asmLink(m, this);
+ enableSingleStepProfiling();
+ assertEq(f(.1), eval("Math." + name + "(.1)"));
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,N,f,>,f,>,>");
+ }
+}
+for (name of ['sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'ceil', 'floor', 'exp', 'log'])
+ testBuiltinD2D(name);
+
+function testBuiltinF2F(name) {
+ 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");
+ for (var i = 0; i < 3; i++) {
+ var f = asmLink(m, this);
+ enableSingleStepProfiling();
+ assertEq(f(.1), eval("Math.fround(Math." + name + "(Math.fround(.1)))"));
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,N,f,>,f,>,>");
+ }
+}
+for (name of ['ceil', 'floor'])
+ testBuiltinF2F(name);
+
+function testBuiltinDD2D(name) {
+ 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");
+ for (var i = 0; i < 3; i++) {
+ var f = asmLink(m, this);
+ enableSingleStepProfiling();
+ assertEq(f(.1, .2), eval("Math." + name + "(.1, .2)"));
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f,>,N,f,>,f,>,>");
+ }
+}
+for (name of ['atan2', 'pow'])
+ testBuiltinDD2D(name);
+
+// FFI tests:
+setJitCompilerOption("ion.warmup.trigger", 10);
+setJitCompilerOption("baseline.warmup.trigger", 0);
+setJitCompilerOption("offthread-compilation.enable", 0);
+
+var m = asmCompile('g','ffis', USE_ASM + "var ffi1=ffis.ffi1, ffi2=ffis.ffi2; function f() { return ((ffi1()|0) + (ffi2()|0))|0 } return f");
+
+var ffi1 = function() { return 10 }
+var ffi2 = function() { return 73 }
+var f = asmLink(m, null, {ffi1,ffi2});
+
+// Interp FFI exit
+enableSingleStepProfiling();
+assertEq(f(), 83);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>");
+
+// Ion FFI exit
+for (var i = 0; i < 20; i++)
+ assertEq(f(), 83);
+enableSingleStepProfiling();
+assertEq(f(), 83);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>");
+
+var ffi1 = function() { return { valueOf() { return 20 } } }
+var ffi2 = function() { return { valueOf() { return 74 } } }
+var f = asmLink(m, null, {ffi1,ffi2});
+
+// Interp FFI exit
+enableSingleStepProfiling();
+assertEq(f(), 94);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up
+
+// Ion FFI exit
+for (var i = 0; i < 20; i++)
+ assertEq(f(), 94);
+enableSingleStepProfiling();
+assertEq(f(), 94);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f,>,<,f,>,f,>,<,f,>,f,>,>"); // TODO: add 'valueOf' once interp shows up
+
+var ffi1 = function() { return 15 }
+var ffi2 = function() { return f2() + 17 }
+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});
+// Interpreter FFI exit
+enableSingleStepProfiling();
+assertEq(f1(), 32);
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>");
+
+
+// Ion FFI exit
+var jitOptions = getJitCompilerOptions();
+if (jitOptions['baseline.enable']) {
+ for (var i = 0; i < 20; i++)
+ assertEq(f1(), 32);
+ enableSingleStepProfiling();
+ assertEq(f1(), 32);
+ var stacks = disableSingleStepProfiling();
+ assertStackContainsSeq(stacks, ">,f1,>,<,f1,>,>,<,f1,>,f2,>,<,f1,>,<,f2,>,<,f1,>,f2,>,<,f1,>,>,<,f1,>,<,f1,>,f1,>,>");
+}
+
+// Thunks
+setJitCompilerOption("jump-threshold", 0);
+var h = asmLink(asmCompile(USE_ASM + 'function f() {} function g() { f() } function h() { g() } return h'));
+enableSingleStepProfiling();
+h();
+var stacks = disableSingleStepProfiling();
+assertStackContainsSeq(stacks, ">,h,>,g,h,>,f,g,h,>,g,h,>,h,>,>");
+setJitCompilerOption("jump-threshold", -1);
+
+// This takes forever to run.
+// Stack-overflow exit test
+//var limit = -1;
+//var maxct = 0;
+//function ffi(ct) { if (ct == limit) { enableSingleStepProfiling(); print("enabled"); } maxct = ct; }
+//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});
+//// First find the stack limit:
+//var caught = false;
+//try { f() } catch (e) { caught = true; assertEq(String(e).indexOf("too much recursion") >= 0, true) }
+//assertEq(caught, true);
+//limit = maxct;
+//print("Setting limit");
+//var caught = false;
+//try { f() } catch (e) { caught = true; print("caught"); assertEq(String(e).indexOf("too much recursion") >= 0, true) }
+//var stacks = disableSingleStepProfiling();
+//assertEq(String(stacks).indexOf("rec") >= 0, true);