Bug 1191289 part 2 - JS Lcov output: Handle throw statements. r=bhackett
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Sat, 29 Aug 2015 01:32:37 +0200
changeset 259916 70a4840a6680e14e9bbbaa8d84e06bf9c6da4650
parent 259915 8c305052960d89707587d12e37431019be00ed64
child 259917 681ee47b9ea8add7cf47d87cae0d85364f5df1fb
push id29296
push userryanvm@gmail.com
push dateSun, 30 Aug 2015 19:45:10 +0000
treeherdermozilla-central@2ad5077d86ba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs1191289
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1191289 part 2 - JS Lcov output: Handle throw statements. r=bhackett
js/src/jit-test/tests/coverage/simple.js
js/src/jsopcode.cpp
--- a/js/src/jit-test/tests/coverage/simple.js
+++ b/js/src/jit-test/tests/coverage/simple.js
@@ -49,16 +49,17 @@ function checkLcov(fun) {
   g.eval(source);
   var lcovResRaw = getLcovInfo(g);
 
   // Check that all the lines are present the result.
   var lcovRes = lcovResRaw.split('\n');
   for (ref of lcovRef) {
     if (lcovRes.indexOf(ref) == -1) {
       print("Cannot find `" + ref + "` in the following Lcov result:\n", lcovResRaw);
+      print("In the following source:\n", source);
       assertEq(true, false);
     }
   }
 }
 
 checkLcov(function () { //FN:$,top-level //FNDA:1,%
   ",".split(','); //DA:$,1
   //FNF:1
@@ -146,8 +147,69 @@ checkLcov(function () { //FN:$,top-level
     //BRH:1
   }
 
   f(5);           //DA:$,1
   f(5);           //DA:$,1
   //FNF:2
   //FNH:2
 });
+
+checkLcov(function () { //FN:$,top-level //FNDA:1,%
+  try {                     //DA:$,1
+    var l = ",".split(','); //DA:$,1
+    if (l.length == 2) {    //DA:$,1 // BRDA:$,0
+      l.push('');           //DA:$,1
+      throw l;              //DA:$,1
+    }
+    l.pop();                //DA:$,0
+  } catch (x) {             //DA:$,1
+    x.pop();                //DA:$,1
+  }
+  //FNF:1
+  //FNH:1
+  //LF:9 // Expected LF:8 , Apparently if the first statement is a try, the
+         // statement following the "try{" statement is visited twice.
+  //LH:8 // Expected LH:7
+  //BRF:1
+  //BRH:1
+});
+
+checkLcov(function () { //FN:$,top-level //FNDA:1,%
+  var l = ",".split(',');   //DA:$,1
+  try {                     //DA:$,1
+    try {                   //DA:$,1
+      if (l.length == 2) {  //DA:$,1 // BRDA:$,0
+        l.push('');         //DA:$,1
+        throw l;            //DA:$,1
+      }
+      l.pop();              //DA:$,0 // BRDA:$,-
+    } finally {             //DA:$,1
+      l.pop();              //DA:$,1
+    }
+  } catch (x) {             //DA:$,1
+  }
+  //FNF:1
+  //FNH:1
+  //LF:10
+  //LH:9
+  //BRF:2
+  //BRH:1
+});
+
+checkLcov(function () { //FN:$,top-level //FNDA:1,%
+  function f() {            //FN:$,f //FNDA:1,%
+    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
+  }
+  //FNF:2
+  //FNH:2
+  //LF:7
+  //LH:5
+  //BRF:0
+  //BRH:0
+});
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -2052,16 +2052,24 @@ LcovWriteScript(JSContext* cx, LcovSourc
 
                 // Count the number of lines instrumented & hit.
                 lsf.numLinesInstrumented++;
                 if (hits)
                     lsf.numLinesHit++;
             }
         }
 
+        // If the current instruction has thrown, then decrement the hit counts
+        // with the number of throws.
+        if (sc) {
+            const PCCounts* counts = sc->maybeGetThrowCounts(script->pcToOffset(pc));
+            if (counts)
+                hits -= counts->numExec();
+        }
+
         // If the current pc corresponds to a conditional jump instruction, then reports
         // branch hits.
         if (jump && fallsthrough) {
             jsbytecode* target = pc + GET_JUMP_OFFSET(pc);
             jsbytecode* fallthroughTarget = GetNextPc(pc);
             uint64_t fallthroughHits = 0;
             if (sc) {
                 const PCCounts* counts = sc->maybeGetPCCounts(script->pcToOffset(fallthroughTarget));