summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/debug/Script-getOffsetsCoverage-01.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/debug/Script-getOffsetsCoverage-01.js')
-rw-r--r--js/src/jit-test/tests/debug/Script-getOffsetsCoverage-01.js501
1 files changed, 501 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/debug/Script-getOffsetsCoverage-01.js b/js/src/jit-test/tests/debug/Script-getOffsetsCoverage-01.js
new file mode 100644
index 0000000000..7757d4fbf4
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Script-getOffsetsCoverage-01.js
@@ -0,0 +1,501 @@
+// Currently the Jit integration has a few issues, let's keep this test
+// case deterministic.
+//
+// - Baseline OSR increments the loop header twice.
+// - Ion is not updating any counter yet.
+//
+if (getJitCompilerOptions()["ion.warmup.trigger"] != 30)
+ setJitCompilerOption("ion.warmup.trigger", 30);
+if (getJitCompilerOptions()["baseline.warmup.trigger"] != 10)
+ setJitCompilerOption("baseline.warmup.trigger", 10);
+
+/*
+ * These test cases are annotated with the output produced by LCOV [1]. Comment
+ * starting with //<key> without any spaces are used as a reference for the code
+ * coverage output. Any "$" in these line comments are replaced by the current
+ * line number, and any "%" are replaced with the current function name (defined
+ * by the FN key).
+ *
+ * [1] http://ltp.sourceforge.net/coverage/lcov/geninfo.1.php
+ */
+function checkGetOffsetsCoverage(fun) {
+ var keys = [ "TN", "SF", "FN", "FNDA", "FNF", "FNH", "BRDA", "BRF", "BRH", "DA", "LF", "LH" ];
+ function startsWithKey(s) {
+ for (k of keys) {
+ if (s.startsWith(k))
+ return true;
+ }
+ return false;
+ };
+
+ // Extract the body of the function, as the code to be executed.
+ var source = fun.toString();
+ source = source.slice(source.indexOf('{') + 1, source.lastIndexOf('}'));
+
+ // Extract comment starting with the previous keys, as a reference.
+ var lcovRef = [];
+ var currLine = 0;
+ var currFun = [{name: "top-level", braces: 1}];
+ for (var line of source.split('\n')) {
+ currLine++;
+
+ for (var comment of line.split("//").slice(1)) {
+ if (!startsWithKey(comment))
+ continue;
+ comment = comment.trim();
+ if (comment.startsWith("FN:"))
+ currFun.push({ name: comment.split(',')[1], braces: 0 });
+ var name = currFun[currFun.length - 1].name;
+ if (!comment.startsWith("DA:"))
+ continue;
+ comment = {
+ offset: null,
+ lineNumber: currLine,
+ columnNumber: null,
+ count: comment.split(",")[1] | 0,
+ script: (name == "top-level" ? undefined : name)
+ };
+ lcovRef.push(comment);
+ }
+
+ var deltaBraces = line.split('{').length - line.split('}').length;
+ currFun[currFun.length - 1].braces += deltaBraces;
+ if (currFun[currFun.length - 1].braces == 0)
+ currFun.pop();
+ }
+
+ // Create a new global and instrument it with a debugger, to find all scripts,
+ // created in the current global.
+ var g = newGlobal({newCompartment: true});
+ var dbg = Debugger(g);
+ dbg.collectCoverageInfo = true;
+
+ var topLevel = null;
+ dbg.onNewScript = function (s) {
+ topLevel = s;
+ dbg.onNewScript = function () {};
+ };
+
+ // Evaluate the code, and collect the hit counts for each scripts / lines.
+ g.eval(source);
+
+ var coverageRes = [];
+ function collectCoverage(s) {
+ var res = s.getOffsetsCoverage();
+ if (res == null)
+ res = [{
+ offset: null,
+ lineNumber: null,
+ columnNumber: null,
+ script: s.displayName,
+ count: 0
+ }];
+ else {
+ res.map(function (e) {
+ e.script = s.displayName;
+ return e;
+ });
+ }
+ coverageRes.push(res);
+ s.getChildScripts().forEach(collectCoverage);
+ };
+ collectCoverage(topLevel);
+ coverageRes = [].concat(...coverageRes);
+
+ // Check that all the lines are present the result.
+ function match(ref) {
+ return function (entry) {
+ return ref.lineNumber == entry.lineNumber && ref.script == entry.script;
+ }
+ }
+ function ppObj(entry) {
+ var str = "{";
+ for (var k in entry) {
+ if (entry[k] != null)
+ str += " '" + k + "': " + entry[k] + ",";
+ }
+ str += "}";
+ return str;
+ }
+ for (ref of lcovRef) {
+ var res = coverageRes.find(match(ref));
+ if (!res) {
+ // getOffsetsCoverage returns null if we have no result for the
+ // script. We added a fake entry with an undefined lineNumber, which is
+ // used to match against the modified reference.
+ var missRef = Object.create(ref);
+ missRef.lineNumber = null;
+ res = coverageRes.find(match(missRef));
+ }
+
+ if (!res || res.count != ref.count) {
+ print("Cannot find `" + ppObj(ref) + "` in the following results:\n", coverageRes.map(ppObj).join("\n"));
+ print("In the following source:\n", source);
+ assertEq(true, false);
+ }
+ }
+}
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ ",".split(','); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ function f() { //FN:$,f
+ ",".split(','); //DA:$,0
+ }
+ ",".split(','); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ function f() { //FN:$,f
+ ",".split(','); //DA:$,1
+ }
+ f(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { ','.split(','); //FN:$,top-level //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { function f() { ','.split(','); } //FN:$,top-level //FN:$,f //DA:$,1
+ f(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ if (l.length == 3) //DA:$,1
+ l.push(''); //DA:$,0
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ if (l.length == 2) //DA:$,1
+ l.push(''); //DA:$,1
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ if (l.length == 3) //DA:$,1
+ l.push(''); //DA:$,0
+ else
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ if (l.length == 2) //DA:$,1
+ l.push(''); //DA:$,1
+ else
+ l.pop(); //DA:$,0
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ if (l.length == 2) //DA:$,1
+ l.push(''); //DA:$,1
+ else {
+ if (l.length == 1) //DA:$,0
+ l.pop(); //DA:$,0
+ }
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ function f(i) { //FN:$,f
+ var x = 0; //DA:$,2
+ while (i--) { // Currently OSR wrongly count the loop header twice.
+ // So instead of DA:$,12 , we have DA:$,13 .
+ x += i; //DA:$,10
+ x = x / 2; //DA:$,10
+ }
+ return x; //DA:$,2
+ }
+
+ f(5); //DA:$,1
+ f(5); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ try { //DA:$,1
+ var l = ",".split(','); //DA:$,1
+ if (l.length == 2) { //DA:$,1
+ l.push(''); //DA:$,1
+ throw l; //DA:$,1
+ }
+ l.pop(); //DA:$,0
+ } catch (x) { //DA:$,1
+ x.pop(); //DA:$,1
+ }
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ try { //DA:$,1
+ try { //DA:$,1
+ if (l.length == 2) { //DA:$,1
+ l.push(''); //DA:$,1
+ throw l; //DA:$,1
+ }
+ l.pop(); //DA:$,0
+ } finally { //DA:$,1
+ l.pop(); //DA:$,1
+ }
+ } catch (x) { //DA:$,1
+ }
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ function f() { //FN:$,f
+ throw 1; //DA:$,1
+ f(); //DA:$,0
+ }
+ var l = ",".split(','); //DA:$,1
+ try { //DA:$,1
+ f(); //DA:$,1
+ f(); //DA:$,0
+ } catch (x) { //DA:$,1
+ }
+});
+
+
+// Test TableSwitch opcode
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1
+ case 0:
+ l.push('0'); //DA:$,0
+ break;
+ case 1:
+ l.push('1'); //DA:$,0
+ break;
+ case 2:
+ l.push('2'); //DA:$,1
+ break;
+ case 3:
+ l.push('3'); //DA:$,0
+ break;
+ }
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1
+ case 0:
+ l.push('0'); //DA:$,0
+ case 1:
+ l.push('1'); //DA:$,0
+ case 2:
+ l.push('2'); //DA:$,1
+ case 3:
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1
+ case 5:
+ l.push('5'); //DA:$,0
+ case 4:
+ l.push('4'); //DA:$,0
+ case 3:
+ l.push('3'); //DA:$,0
+ case 2:
+ l.push('2'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1
+ case 2:
+ l.push('2'); //DA:$,1
+ case 5:
+ l.push('5'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1
+ case 3:
+ l.push('1'); //DA:$,0
+ case 5:
+ l.push('5'); //DA:$,0
+ }
+ l.pop(); //DA:$,1
+});
+
+// Unfortunately the differences between switch implementations leaks in the
+// code coverage reports.
+checkGetOffsetsCoverage(function () { //FN:$,top-level
+ function f(a) { //FN:$,f
+ return a; //DA:$,2
+ }
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1
+ case f(-42): //DA:$,1
+ l.push('1'); //DA:$,0
+ case f(51): //DA:$,1
+ l.push('5'); //DA:$,0
+ }
+ l.pop(); //DA:$,1
+});
+
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,1 //BRDA:$,0,2,0 //BRDA:$,0,3,0
+ case 0:
+ case 1:
+ l.push('0'); //DA:$,0
+ l.push('1'); //DA:$,0
+ case 2:
+ l.push('2'); //DA:$,1
+ case 3:
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:7
+ //LH:5
+ //BRF:4
+ //BRH:1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
+ case 0:
+ l.push('0'); //DA:$,0
+ case 1:
+ l.push('1'); //DA:$,0
+ case 2:
+ case 3:
+ l.push('2'); //DA:$,1
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:7
+ //LH:5
+ //BRF:4
+ //BRH:1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
+ case 0:
+ l.push('0'); //DA:$,0
+ case 1:
+ default:
+ l.push('1'); //DA:$,0
+ case 2:
+ l.push('2'); //DA:$,1
+ case 3:
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:7
+ //LH:5
+ //BRF:4
+ //BRH:1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0
+ case 0:
+ l.push('0'); //DA:$,0
+ case 1:
+ l.push('1'); //DA:$,0
+ default:
+ case 2:
+ l.push('2'); //DA:$,1
+ case 3:
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:7
+ //LH:5
+ //BRF:4
+ //BRH:1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,1 //BRDA:$,0,3,0 //BRDA:$,0,4,0
+ case 0:
+ l.push('0'); //DA:$,0
+ case 1:
+ l.push('1'); //DA:$,0
+ default:
+ l.push('default'); //DA:$,0
+ case 2:
+ l.push('2'); //DA:$,1
+ case 3:
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:8
+ //LH:5
+ //BRF:5
+ //BRH:1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ",".split(','); //DA:$,1
+ switch (l.length) { //DA:$,1 //BRDA:$,0,0,0 //BRDA:$,0,1,0 //BRDA:$,0,2,0 //BRDA:$,0,3,1
+ case 0:
+ l.push('0'); //DA:$,0
+ case 1:
+ l.push('1'); //DA:$,0
+ default:
+ l.push('2'); //DA:$,1
+ case 3:
+ l.push('3'); //DA:$,1
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:7
+ //LH:5
+ //BRF:4
+ //BRH:1
+});
+
+checkGetOffsetsCoverage(function () { //FN:$,top-level //FNDA:1,%
+ var l = ','.split(','); //DA:$,1
+ if (l.length === 45) { //DA:$,1 //BRDA:$,0,0,1 //BRDA:$,0,1,0
+ switch (l[0]) { //DA:$,0 //BRDA:$,1,0,- //BRDA:$,1,1,-
+ case ',':
+ l.push('0'); //DA:$,0
+ default:
+ l.push('1'); //DA:$,0
+ }
+ }
+ l.pop(); //DA:$,1
+ //FNF:1
+ //FNH:1
+ //LF:6
+ //LH:3
+ //BRF:4
+ //BRH:1
+});
+
+// If you add a test case here, do the same in
+// jit-test/tests/coverage/simple.js