Bug 1204554 part 3.0 - Collect lcov output on the JSCompartment, and on the JSRuntime. r=terrence,bhackett

This commit is contained in:
Nicolas B. Pierron 2015-10-01 12:41:40 +02:00
Родитель 848c5c4b1c
Коммит b85acbc481
8 изменённых файлов: 135 добавлений и 3 удалений

Просмотреть файл

@ -80,7 +80,8 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
maybeAlive(true),
jitCompartment_(nullptr),
mappedArgumentsTemplate_(nullptr),
unmappedArgumentsTemplate_(nullptr)
unmappedArgumentsTemplate_(nullptr),
lcovOutput()
{
PodArrayZero(sawDeprecatedLanguageExtension);
runtime_->numCompartments++;
@ -91,6 +92,11 @@ JSCompartment::~JSCompartment()
{
reportTelemetry();
// Write the code coverage information in a file.
JSRuntime* rt = runtimeFromMainThread();
if (rt->lcovOutput.isEnabled())
rt->lcovOutput.writeLCovResult(lcovOutput);
js_delete(jitCompartment_);
js_delete(watchpointMap);
js_delete(scriptCountsMap);

Просмотреть файл

@ -662,7 +662,8 @@ struct JSCompartment
// Debugger API, or for the entire runtime.
bool collectCoverage() const {
return debuggerObservesCoverage() ||
runtimeFromAnyThread()->profilingScripts;
runtimeFromAnyThread()->profilingScripts ||
runtimeFromAnyThread()->lcovOutput.isEnabled();
}
void clearScriptCounts();
@ -746,6 +747,11 @@ struct JSCompartment
public:
void addTelemetry(const char* filename, DeprecatedLanguageExtension e);
public:
// Aggregated output used to collect JSScript hit counts when code coverage
// is enabled.
js::coverage::LCovCompartment lcovOutput;
};
inline bool

Просмотреть файл

@ -2936,6 +2936,11 @@ JSScript::finalize(FreeOp* fop)
// JSScript::Create(), but not yet finished initializing it with
// fullyInitFromEmitter() or fullyInitTrivial().
// Collect code coverage information for this script and all its inner
// scripts, and store the aggregated information on the compartment.
if (isTopLevel() && fop->runtime()->lcovOutput.isEnabled())
compartment()->lcovOutput.collectCodeCoverageInfo(compartment(), this);
fop->runtime()->spsProfiler.onScriptFinalized(this);
if (types_)

Просмотреть файл

@ -6,13 +6,23 @@
#include "vm/CodeCoverage.h"
#include "mozilla/Atomics.h"
#include "mozilla/IntegerPrintfMacros.h"
#include <stdio.h>
#if defined(XP_WIN)
# include <windows.h>
#else
# include <unistd.h>
#endif
#include "jscompartment.h"
#include "jsopcode.h"
#include "jsprf.h"
#include "jsscript.h"
#include "vm/Runtime.h"
#include "vm/Time.h"
// This file contains a few functions which are used to produce files understood
// by lcov tools. A detailed description of the format is available in the man
@ -360,6 +370,68 @@ LCovCompartment::writeCompartmentName(JSCompartment* comp)
return !outTN_.hadOutOfMemory();
}
LCovRuntime::LCovRuntime()
: out_(),
#if defined(XP_WIN)
pid_(GetCurrentProcessId())
#else
pid_(getpid())
#endif
{
}
LCovRuntime::~LCovRuntime()
{
if (out_.isInitialized())
out_.finish();
}
void
LCovRuntime::init()
{
const char* outDir = getenv("JS_CODE_COVERAGE_OUTPUT_DIR");
if (!outDir || *outDir == 0)
return;
int64_t timestamp = static_cast<double>(PRMJ_Now()) / PRMJ_USEC_PER_SEC;
static mozilla::Atomic<size_t> globalRuntimeId(0);
size_t rid = globalRuntimeId++;
char name[1024];
size_t len = JS_snprintf(name, sizeof(name), "%s/%" PRId64 "-%d-%d.info",
outDir, timestamp, size_t(pid_), rid);
if (sizeof(name) < len) {
fprintf(stderr, "Warning: LCovRuntime::init: Cannot serialize file name.");
return;
}
// If we cannot open the file, report a warning.
if (!out_.init(name))
fprintf(stderr, "Warning: LCovRuntime::init: Cannot open file named '%s'.", name);
}
void
LCovRuntime::writeLCovResult(LCovCompartment& comp)
{
if (!out_.isInitialized())
return;
#if defined(XP_WIN)
size_t p = GetCurrentProcessId();
#else
size_t p = getpid();
#endif
if (pid_ != p) {
pid_ = p;
out_.finish();
init();
if (!out_.isInitialized())
return;
}
comp.exportInto(out_);
out_.flush();
}
} // namespace coverage
} // namespace js

Просмотреть файл

@ -101,6 +101,43 @@ class LCovCompartment
LCovSourceVector* sources_;
};
class LCovRuntime
{
public:
LCovRuntime();
~LCovRuntime();
// If the environment variable JS_CODE_COVERAGE_OUTPUT_DIR is set to a
// directory, create a file inside this directory which uses the process
// ID, the thread ID and a timestamp to ensure the uniqueness of the
// file.
//
// At the end of the execution, this file should contains the LCOV output of
// all the scripts executed in the current JSRuntime.
void init();
// Check if we should collect code coverage information.
bool isEnabled() const { return out_.isInitialized(); }
// Write the aggregated result of the code coverage of a compartment
// into a file.
void writeLCovResult(LCovCompartment& comp);
private:
// When a process forks, the file will remain open, but 2 processes will
// have the same file. To avoid conflicting writes, we open a new file for
// the child process.
void maybeReopenAfterFork();
private:
// Output file which is created if code coverage is enabled.
Fprinter out_;
// The process' PID is used to watch for fork. When the process fork,
// we want to close the current file and open a new one.
size_t pid_;
};
} // namespace coverage
} // namespace js

Просмотреть файл

@ -133,7 +133,7 @@ class Fprinter final : public GenericPrinter
// Initialize this printer, returns false on error.
bool init(const char* path);
void init(FILE* fp);
bool isInitialized() {
bool isInitialized() const {
return file_ != nullptr;
}
void flush();

Просмотреть файл

@ -176,6 +176,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
simulator_(nullptr),
#endif
scriptAndCountsVector(nullptr),
lcovOutput(),
NaNValue(DoubleNaNValue()),
negativeInfinityValue(DoubleValue(NegativeInfinity<double>())),
positiveInfinityValue(DoubleValue(PositiveInfinity<double>())),
@ -242,6 +243,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime)
PodArrayZero(nativeStackQuota);
PodZero(&asmJSCacheOps);
lcovOutput.init();
}
static bool

Просмотреть файл

@ -39,6 +39,7 @@
#endif
#include "js/TraceableVector.h"
#include "js/Vector.h"
#include "vm/CodeCoverage.h"
#include "vm/CommonPropertyNames.h"
#include "vm/DateTime.h"
#include "vm/MallocProvider.h"
@ -1056,6 +1057,9 @@ struct JSRuntime : public JS::shadow::Runtime,
/* Strong references on scripts held for PCCount profiling API. */
JS::PersistentRooted<js::ScriptAndCountsVector>* scriptAndCountsVector;
/* Code coverage output. */
js::coverage::LCovRuntime lcovOutput;
/* Well-known numbers held for use by this runtime's contexts. */
const js::Value NaNValue;
const js::Value negativeInfinityValue;