diff --git a/js/src/frontend/BytecodeCompiler.cpp b/js/src/frontend/BytecodeCompiler.cpp index b014146f66cf..b72808efffb6 100644 --- a/js/src/frontend/BytecodeCompiler.cpp +++ b/js/src/frontend/BytecodeCompiler.cpp @@ -417,7 +417,7 @@ bool BytecodeCompiler::canLazilyParse() const { return options.canLazilyParse && !cx->realm()->behaviors().disableLazyParsing() && !cx->realm()->behaviors().discardSource() && !options.sourceIsLazy && - !cx->lcovEnabled() && + !coverage::IsLCovEnabled() && // Disabled during record/replay. The replay debugger requires // scripts to be constructed in a consistent order, which might not // happen with lazy parsing. diff --git a/js/src/gc/GC.cpp b/js/src/gc/GC.cpp index a082a51cde80..4f0d40b1bdfe 100644 --- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -8175,7 +8175,7 @@ void GCRuntime::mergeRealms(Realm* source, Realm* target) { atomMarking.adoptMarkedAtoms(target->zone(), source->zone()); // Merge script name maps in the target realm's map. - if (rt->lcovOutput().isEnabled() && source->scriptNameMap) { + if (coverage::IsLCovEnabled() && source->scriptNameMap) { AutoEnterOOMUnsafeRegion oomUnsafe; if (!target->scriptNameMap) { diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index d3d6f857ffab..0403b4b5b1ce 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -10542,7 +10542,6 @@ static bool SetContextOptions(JSContext* cx, const OptionParser& op) { reportWarnings = op.getBoolOption('w'); compileOnly = op.getBoolOption('c'); printTiming = op.getBoolOption('b'); - enableCodeCoverage = op.getBoolOption("code-coverage"); enableDisassemblyDumps = op.getBoolOption('D'); cx->runtime()->profilingScripts = enableCodeCoverage || enableDisassemblyDumps; @@ -11228,6 +11227,11 @@ int main(int argc, char** argv, char** envp) { js::DisableExtraThreads(); } + enableCodeCoverage = op.getBoolOption("code-coverage"); + if (enableCodeCoverage) { + coverage::EnableLCov(); + } + AutoLibraryLoader loader; MultiStringRange dllPaths = op.getMultiStringOption("dll"); while (!dllPaths.empty()) { diff --git a/js/src/vm/CodeCoverage.cpp b/js/src/vm/CodeCoverage.cpp index 15a9b66a6279..ce21f9591428 100644 --- a/js/src/vm/CodeCoverage.cpp +++ b/js/src/vm/CodeCoverage.cpp @@ -599,6 +599,21 @@ bool LCovRealm::writeRealmName(JS::Realm* realm) { return !outTN_.hadOutOfMemory(); } +bool gLCovIsEnabled = false; + +void InitLCov() { + const char* outDir = getenv("JS_CODE_COVERAGE_OUTPUT_DIR"); + if (outDir && *outDir != 0) { + EnableLCov(); + } +} + +void EnableLCov() { + MOZ_ASSERT(!JSRuntime::hasLiveRuntimes(), + "EnableLCov must not be called after creating a runtime!"); + gLCovIsEnabled = true; +} + LCovRuntime::LCovRuntime() : out_(), pid_(getpid()), isEmpty_(true) {} LCovRuntime::~LCovRuntime() { diff --git a/js/src/vm/CodeCoverage.h b/js/src/vm/CodeCoverage.h index 31b81d97e5bf..f95ac67fe1ff 100644 --- a/js/src/vm/CodeCoverage.h +++ b/js/src/vm/CodeCoverage.h @@ -125,15 +125,6 @@ class LCovRuntime { // all the scripts executed in the current JSRuntime. void init(); - // Check if we should collect code coverage information. - bool isEnabled() const { - static bool isEnabled_ = ([]() { - const char* outDir = getenv("JS_CODE_COVERAGE_OUTPUT_DIR"); - return outDir && *outDir != 0; - })(); - return isEnabled_; - } - // Write the aggregated result of the code coverage of a realm // into a file. void writeLCovResult(LCovRealm& realm); @@ -166,6 +157,15 @@ class LCovRuntime { bool isEmpty_; }; +extern void InitLCov(); + +extern void EnableLCov(); + +inline bool IsLCovEnabled() { + extern bool gLCovIsEnabled; + return gLCovIsEnabled; +} + } // namespace coverage } // namespace js diff --git a/js/src/vm/Initialization.cpp b/js/src/vm/Initialization.cpp index ed7fbf3ba663..080dc34c5643 100644 --- a/js/src/vm/Initialization.cpp +++ b/js/src/vm/Initialization.cpp @@ -114,6 +114,8 @@ JS_PUBLIC_API const char* JS::detail::InitWithFailureDiagnostic( js::gc::InitMemorySubsystem(); // Ensure gc::SystemPageSize() works. + js::coverage::InitLCov(); + RETURN_IF_FAIL(js::jit::InitProcessExecutableMemory()); RETURN_IF_FAIL(js::MemoryProtectionExceptionHandler::install()); diff --git a/js/src/vm/JSContext.h b/js/src/vm/JSContext.h index d1628568f571..1bffa8740542 100644 --- a/js/src/vm/JSContext.h +++ b/js/src/vm/JSContext.h @@ -287,7 +287,6 @@ struct JSContext : public JS::RootingContext, return runtime_->jitSupportsUnalignedAccesses; } bool jitSupportsSimd() const { return runtime_->jitSupportsSimd; } - bool lcovEnabled() const { return runtime_->lcovOutput().isEnabled(); } /* * "Entering" a realm changes cx->realm (which changes cx->global). Note diff --git a/js/src/vm/JSScript.cpp b/js/src/vm/JSScript.cpp index 8ae803a1e22c..57e28b79054c 100644 --- a/js/src/vm/JSScript.cpp +++ b/js/src/vm/JSScript.cpp @@ -3361,7 +3361,7 @@ JSScript* JSScript::Create(JSContext* cx, const ReadOnlyCompileOptions& options, script->setFlag(MutableFlags::TrackRecordReplayProgress, ShouldTrackRecordReplayProgress(script)); - if (cx->runtime()->lcovOutput().isEnabled()) { + if (coverage::IsLCovEnabled()) { if (!script->initScriptName(cx)) { return nullptr; } @@ -3714,8 +3714,8 @@ void JSScript::finalize(FreeOp* fop) { // Collect code coverage information for this script and all its inner // scripts, and store the aggregated information on the realm. - MOZ_ASSERT_IF(hasScriptName(), fop->runtime()->lcovOutput().isEnabled()); - if (fop->runtime()->lcovOutput().isEnabled() && hasScriptName()) { + MOZ_ASSERT_IF(hasScriptName(), coverage::IsLCovEnabled()); + if (coverage::IsLCovEnabled() && hasScriptName()) { realm()->lcovOutput.collectCodeCoverageInfo(realm(), this, getScriptName()); destroyScriptName(); } diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp index 2b3ca1dae31e..f41679a6a4c3 100644 --- a/js/src/vm/Realm.cpp +++ b/js/src/vm/Realm.cpp @@ -62,9 +62,8 @@ Realm::~Realm() { MOZ_ASSERT(!hasBeenEnteredIgnoringJit()); // Write the code coverage information in a file. - JSRuntime* rt = runtimeFromMainThread(); - if (rt->lcovOutput().isEnabled()) { - rt->lcovOutput().writeLCovResult(lcovOutput); + if (coverage::IsLCovEnabled()) { + runtime_->lcovOutput().writeLCovResult(lcovOutput); } MOZ_ASSERT(runtime_->numRealms > 0); @@ -826,9 +825,7 @@ bool Realm::collectCoverageForPGO() const { } bool Realm::collectCoverageForDebug() const { - return debuggerObservesCoverage() || - runtimeFromAnyThread()->profilingScripts || - runtimeFromAnyThread()->lcovOutput().isEnabled(); + return debuggerObservesCoverage() || coverage::IsLCovEnabled(); } void Realm::clearScriptCounts() {