Bug 1585372 - Compute script name in InitScriptCoverage. r=nbp

To avoid calling JSScript::function() from finalizer, we need to read the
name earlier in process.

Differential Revision: https://phabricator.services.mozilla.com/D51474

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ted Campbell 2019-11-04 16:33:35 +00:00
Родитель bed71ec642
Коммит b3ca3e3f9b
3 изменённых файлов: 49 добавлений и 31 удалений

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

@ -121,27 +121,13 @@ void LCovSource::exportInto(GenericPrinter& out) {
maxLineHit_ = 0;
}
bool LCovSource::writeScriptName(LSprinter& out, JSScript* script) {
JSFunction* fun = script->function();
if (fun && fun->displayAtom()) {
return EscapedStringPrinter(out, fun->displayAtom(), 0);
}
out.printf("top-level");
return true;
}
void LCovSource::writeScript(JSScript* script) {
void LCovSource::writeScript(JSScript* script, const char* scriptName) {
if (hadOutOfMemory()) {
return;
}
numFunctionsFound_++;
outFN_.printf("FN:%u,", script->lineno());
if (!writeScriptName(outFN_, script)) {
hadOOM_ = true;
return;
}
outFN_.put("\n", 1);
outFN_.printf("FN:%u,%s\n", script->lineno(), scriptName);
uint64_t hits = 0;
ScriptCounts* sc = nullptr;
@ -150,11 +136,7 @@ void LCovSource::writeScript(JSScript* script) {
numFunctionsHit_++;
const PCCounts* counts =
sc->maybeGetPCCounts(script->pcToOffset(script->main()));
outFNDA_.printf("FNDA:%" PRIu64 ",", counts->numExec());
if (!writeScriptName(outFNDA_, script)) {
hadOOM_ = true;
return;
}
outFNDA_.printf("FNDA:%" PRIu64 ",%s\n", counts->numExec(), scriptName);
outFNDA_.put("\n", 1);
// Set the hit count of the pre-main code to 1, if the function ever got
@ -492,8 +474,15 @@ void LCovRealm::collectCodeCoverageInfo(JSScript* script, const char* name) {
return;
}
// Get the formatted name of script to use
const char* scriptName = getScriptName(script);
if (!scriptName) {
outTN_.reportOutOfMemory();
return;
}
// Write code coverage data into the LCovSource.
source->writeScript(script);
source->writeScript(script, scriptName);
// Propegate OOM from LCovSource.
if (source->hadOutOfMemory()) {
@ -590,6 +579,20 @@ void LCovRealm::writeRealmName(JS::Realm* realm) {
}
}
const char* LCovRealm::getScriptName(JSScript* script) {
JSFunction* fun = script->function();
if (fun && fun->displayAtom()) {
JSAtom* atom = fun->displayAtom();
size_t lenWithNull = js::PutEscapedString(nullptr, 0, atom, 0) + 1;
char* name = alloc_.newArray<char>(lenWithNull);
if (name) {
js::PutEscapedString(name, lenWithNull, atom, 0);
}
return name;
}
return "top-level";
}
bool gLCovIsEnabled = false;
void InitLCov() {
@ -715,6 +718,13 @@ bool InitScriptCoverage(JSContext* cx, JSScript* script) {
return false;
}
// Computed the formated script name.
const char* scriptName = lcovRealm->getScriptName(script);
if (!scriptName) {
ReportOutOfMemory(cx);
return false;
}
// Create Zone::scriptLCovMap if necessary.
JS::Zone* zone = script->zone();
if (!zone->scriptLCovMap) {
@ -725,7 +735,8 @@ bool InitScriptCoverage(JSContext* cx, JSScript* script) {
}
// Save source in map for when we collect coverage.
if (!zone->scriptLCovMap->putNew(script, source)) {
if (!zone->scriptLCovMap->putNew(script,
mozilla::MakeTuple(source, scriptName))) {
ReportOutOfMemory(cx);
return false;
}
@ -746,9 +757,12 @@ void CollectScriptCoverage(JSScript* script) {
return;
}
LCovSource* source = p->value();
LCovSource* source;
const char* scriptName;
mozilla::Tie(source, scriptName) = p->value();
if (!script->isUncompleted()) {
source->writeScript(script);
source->writeScript(script, scriptName);
}
map->remove(p);
}

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

@ -36,16 +36,12 @@ class LCovSource {
// Iterate over the bytecode and collect the lcov output based on the
// ScriptCounts counters.
void writeScript(JSScript* script);
void writeScript(JSScript* script, const char* scriptName);
// Write the Lcov output in a buffer, such as the one associated with
// the runtime code coverage trace file.
void exportInto(GenericPrinter& out);
private:
// Write the script name in out.
bool writeScriptName(LSprinter& out, JSScript* script);
private:
// Name of the source file.
JS::UniqueChars name_;
@ -97,6 +93,10 @@ class LCovRealm {
// Return the LCovSource entry which matches the given ScriptSourceObject.
LCovSource* lookupOrAdd(const char* name);
// Generate escaped form of script atom and allocate inside our LifoAlloc if
// necessary.
const char* getScriptName(JSScript* script);
private:
typedef mozilla::Vector<LCovSource*, 16, LifoAllocPolicy<Fallible>>
LCovSourceVector;

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

@ -16,6 +16,7 @@
#include "mozilla/MemoryReporting.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Span.h"
#include "mozilla/Tuple.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/Utf8.h"
#include "mozilla/Variant.h"
@ -261,7 +262,10 @@ using UniqueScriptCounts = js::UniquePtr<ScriptCounts>;
using ScriptCountsMap = HashMap<JSScript*, UniqueScriptCounts,
DefaultHasher<JSScript*>, SystemAllocPolicy>;
using ScriptLCovMap = HashMap<JSScript*, coverage::LCovSource*,
// The 'const char*' for the function name is a pointer within the LCovSource's
// LifoAlloc and will be discarded at the same time.
using ScriptLCovEntry = mozilla::Tuple<coverage::LCovSource*, const char*>;
using ScriptLCovMap = HashMap<JSScript*, ScriptLCovEntry,
DefaultHasher<JSScript*>, SystemAllocPolicy>;
#ifdef MOZ_VTUNE