Bug 1210733 - Record source filenames independently of the script coverage. r=terrence
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Mon, 05 Oct 2015 17:05:08 +0200
changeset 299530 8966326bc731912b5e86d5e07eb00e4ed9baf86c
parent 299529 e54d330a1de68a83e3ccf65c75f0fc970f7d872c
child 299531 443dc9a9c21c080d0779d709c7f750d3874c10db
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1210733
milestone44.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 1210733 - Record source filenames independently of the script coverage. r=terrence
js/src/vm/CodeCoverage.cpp
js/src/vm/CodeCoverage.h
--- a/js/src/vm/CodeCoverage.cpp
+++ b/js/src/vm/CodeCoverage.cpp
@@ -69,23 +69,29 @@ LCovSource::LCovSource(LifoAlloc* alloc,
     outFNDA_(alloc),
     numFunctionsFound_(0),
     numFunctionsHit_(0),
     outBRDA_(alloc),
     numBranchesFound_(0),
     numBranchesHit_(0),
     outDA_(alloc),
     numLinesInstrumented_(0),
-    numLinesHit_(0)
+    numLinesHit_(0),
+    hasFilename_(false),
+    hasScripts_(false)
 {
 }
 
 void
 LCovSource::exportInto(GenericPrinter& out) const
 {
+    // Only write if everything got recorded.
+    if (!hasFilename_ || !hasScripts_)
+        return;
+
     outSF_.exportInto(out);
 
     outFN_.exportInto(out);
     outFNDA_.exportInto(out);
     out.printf("FNF:%d\n", numFunctionsFound_);
     out.printf("FNH:%d\n", numFunctionsHit_);
 
     outBRDA_.exportInto(out);
@@ -151,27 +157,37 @@ LCovSource::writeTopLevelScript(JSScript
 
             // Queue the script in the list of script associated to the
             // current source.
             if (!queue.append(fun.nonLazyScript()))
                 return false;
         }
     } while (!queue.empty());
 
-    return !(outFN_.hadOutOfMemory() ||
-             outFNDA_.hadOutOfMemory() ||
-             outBRDA_.hadOutOfMemory() ||
-             outDA_.hadOutOfMemory());
+    if (outFN_.hadOutOfMemory() ||
+        outFNDA_.hadOutOfMemory() ||
+        outBRDA_.hadOutOfMemory() ||
+        outDA_.hadOutOfMemory())
+    {
+        return false;
+    }
+
+    hasScripts_ = true;
+    return true;
 }
 
 bool
 LCovSource::writeSourceFilename(ScriptSourceObject* sso)
 {
     outSF_.printf("SF:%s\n", sso->source()->filename());
-    return !outSF_.hadOutOfMemory();
+    if (outSF_.hadOutOfMemory())
+        return false;
+
+    hasFilename_ = true;
+    return true;
 }
 
 bool
 LCovSource::writeScriptName(LSprinter& out, JSScript* script)
 {
     JSFunction* fun = script->functionNonDelazifying();
     if (fun && fun->displayAtom())
         return EscapedStringPrinter(out, fun->displayAtom(), 0);
@@ -306,22 +322,22 @@ LCovCompartment::collectCodeCoverageInfo
     // Skip any operation if we already some out-of memory issues.
     if (outTN_.hadOutOfMemory())
         return;
 
     // We expect to visit the source before visiting any of its scripts.
     if (!sources_)
         return;
 
-    // Lookup if there is already one entry.
-    LCovSource* source = lookup(sso);
+    // Get the existing source LCov summary, or create a new one.
+    LCovSource* source = lookupOrAdd(comp, sso);
     if (!source)
         return;
 
-    // Write code coverage data into the allocated LCovSource.
+    // Write code coverage data into the LCovSource.
     if (!source->writeTopLevelScript(topLevel)) {
         outTN_.reportOutOfMemory();
         return;
     }
 }
 
 void
 LCovCompartment::collectSourceFile(JSCompartment* comp, ScriptSourceObject* sso)
@@ -329,57 +345,59 @@ LCovCompartment::collectSourceFile(JSCom
     // Do not add sources if there is no file name associated to it.
     if (!sso->source()->filename())
         return;
 
     // Skip any operation if we already some out-of memory issues.
     if (outTN_.hadOutOfMemory())
         return;
 
-    // On the first call, write the compartment name, and allocate a LCovSource
-    // vector in the LifoAlloc.
-    if (!sources_) {
-        if (!writeCompartmentName(comp))
-            return;
-
-        LCovSourceVector* raw = alloc_.pod_malloc<LCovSourceVector>();
-        if (!raw) {
-            outTN_.reportOutOfMemory();
-            return;
-        }
+    // Get the existing source LCov summary, or create a new one.
+    LCovSource* source = lookupOrAdd(comp, sso);
+    if (!source)
+        return;
 
-        sources_ = new(raw) LCovSourceVector(alloc_);
-    }
-
-    // Allocate a new LCovSource for the current top-level.
-    if (!sources_->append(Move(LCovSource(&alloc_, sso)))) {
-        outTN_.reportOutOfMemory();
-        return;
-    }
-
-    // Write code coverage data into the allocated LCovSource.
-    if (!sources_->back().writeSourceFilename(sso)) {
+    // Write source filename into the LCovSource.
+    if (!source->writeSourceFilename(sso)) {
         outTN_.reportOutOfMemory();
         return;
     }
 }
 
 LCovSource*
-LCovCompartment::lookup(JSObject* sso)
+LCovCompartment::lookupOrAdd(JSCompartment* comp, JSObject* sso)
 {
-    if (!sources_)
-        return nullptr;
+    // On the first call, write the compartment name, and allocate a LCovSource
+    // vector in the LifoAlloc.
+    if (!sources_) {
+        if (!writeCompartmentName(comp))
+            return nullptr;
 
-    // Find the first matching source.
-    for (LCovSource& source : *sources_) {
-        if (source.match(sso))
-            return &source;
+        LCovSourceVector* raw = alloc_.pod_malloc<LCovSourceVector>();
+        if (!raw) {
+            outTN_.reportOutOfMemory();
+            return nullptr;
+        }
+
+        sources_ = new(raw) LCovSourceVector(alloc_);
+    } else {
+        // Find the first matching source.
+        for (LCovSource& source : *sources_) {
+            if (source.match(sso))
+                return &source;
+        }
     }
 
-    return nullptr;
+    // Allocate a new LCovSource for the current top-level.
+    if (!sources_->append(Move(LCovSource(&alloc_, sso)))) {
+        outTN_.reportOutOfMemory();
+        return nullptr;
+    }
+
+    return &sources_->back();
 }
 
 void
 LCovCompartment::exportInto(GenericPrinter& out) const
 {
     if (!sources_ || outTN_.hadOutOfMemory())
         return;
 
--- a/js/src/vm/CodeCoverage.h
+++ b/js/src/vm/CodeCoverage.h
@@ -76,16 +76,20 @@ class LCovSource
     LSprinter outBRDA_;
     size_t numBranchesFound_;
     size_t numBranchesHit_;
 
     // LifoAlloc string which hold lines statistics.
     LSprinter outDA_;
     size_t numLinesInstrumented_;
     size_t numLinesHit_;
+
+    // Status flags.
+    bool hasFilename_ : 1;
+    bool hasScripts_ : 1;
 };
 
 class LCovCompartment
 {
   public:
     LCovCompartment();
 
     // Collect code coverage information for the given source.
@@ -98,17 +102,17 @@ class LCovCompartment
     // the runtime code coverage trace file.
     void exportInto(GenericPrinter& out) const;
 
   private:
     // Write the script name in out.
     bool writeCompartmentName(JSCompartment* comp);
 
     // Return the LCovSource entry which matches the given ScriptSourceObject.
-    LCovSource* lookup(JSObject* sso);
+    LCovSource* lookupOrAdd(JSCompartment* comp, JSObject* sso);
 
   private:
     typedef Vector<LCovSource, 16, LifoAllocPolicy<Fallible>> LCovSourceVector;
 
     // LifoAlloc backend for all temporary allocations needed to stash the
     // strings to be written in the file.
     LifoAlloc alloc_;