mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1234985 - Odin: make names optional and supplied at the end (r=bbouvier)
This commit is contained in:
parent
e9a675dbb6
commit
84a3c0a3e6
@ -2274,6 +2274,13 @@ class MOZ_STACK_CLASS ModuleValidator
|
||||
return false;
|
||||
}
|
||||
|
||||
CacheableCharsVector funcNames;
|
||||
for (const Func* func : functions_) {
|
||||
CacheableChars funcName = StringToNewUTF8CharsZ(cx_, *func->name());
|
||||
if (!funcName || !funcNames.emplaceBack(Move(funcName)))
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t endBeforeCurly = tokenStream().currentToken().pos.end;
|
||||
module_->srcLength = endBeforeCurly - module_->srcStart;
|
||||
|
||||
@ -2284,7 +2291,7 @@ class MOZ_STACK_CLASS ModuleValidator
|
||||
|
||||
UniqueModuleData base;
|
||||
UniqueStaticLinkData link;
|
||||
if (!mg_.finish(heap, Move(filename), &base, &link, slowFuncs))
|
||||
if (!mg_.finish(heap, Move(filename), Move(funcNames), &base, &link, slowFuncs))
|
||||
return false;
|
||||
|
||||
moduleObj.set(WasmModuleObject::create(cx_));
|
||||
@ -2633,11 +2640,11 @@ class MOZ_STACK_CLASS FunctionValidator
|
||||
ExclusiveContext* cx() const { return m_.cx(); }
|
||||
ParseNode* fn() const { return fn_; }
|
||||
|
||||
bool init(PropertyName* name, unsigned line, unsigned column) {
|
||||
bool init(PropertyName* name, unsigned line) {
|
||||
if (!locals_.init() || !labels_.init())
|
||||
return false;
|
||||
|
||||
if (!m_.mg().startFuncDef(name, line, column, &fg_))
|
||||
if (!m_.mg().startFuncDef(line, &fg_))
|
||||
return false;
|
||||
|
||||
encoder_.emplace(fg_.bytecode());
|
||||
@ -6706,12 +6713,12 @@ CheckStatement(FunctionValidator& f, ParseNode* stmt)
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line, unsigned* column)
|
||||
ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line)
|
||||
{
|
||||
TokenStream& tokenStream = m.tokenStream();
|
||||
|
||||
tokenStream.consumeKnownToken(TOK_FUNCTION, TokenStream::Operand);
|
||||
tokenStream.srcCoords.lineNumAndColumnIndex(tokenStream.currentToken().pos.end, line, column);
|
||||
*line = tokenStream.srcCoords.lineNum(tokenStream.currentToken().pos.end);
|
||||
|
||||
RootedPropertyName name(m.cx());
|
||||
|
||||
@ -6778,15 +6785,15 @@ CheckFunction(ModuleValidator& m)
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
ParseNode* fn = nullptr;
|
||||
unsigned line = 0, column = 0;
|
||||
if (!ParseFunction(m, &fn, &line, &column))
|
||||
unsigned line = 0;
|
||||
if (!ParseFunction(m, &fn, &line))
|
||||
return false;
|
||||
|
||||
if (!CheckFunctionHead(m, fn))
|
||||
return false;
|
||||
|
||||
FunctionValidator f(m, fn);
|
||||
if (!f.init(FunctionName(fn), line, column))
|
||||
if (!f.init(FunctionName(fn), line))
|
||||
return m.fail(fn, "internal compiler failure (probably out of memory)");
|
||||
|
||||
ParseNode* stmtIter = ListHead(FunctionStatementList(fn));
|
||||
@ -8279,12 +8286,11 @@ BuildConsoleMessage(ExclusiveContext* cx, AsmJSModule& module, unsigned time,
|
||||
|
||||
for (unsigned i = 0; i < slowFuncs.length(); i++) {
|
||||
const SlowFunction& func = slowFuncs[i];
|
||||
JSAutoByteString name;
|
||||
if (!AtomToPrintableString(cx, func.name, &name))
|
||||
return nullptr;
|
||||
|
||||
slowText.reset(JS_smprintf("%s%s:%u:%u (%ums)%s", slowText.get(),
|
||||
name.ptr(), func.line, func.column, func.ms,
|
||||
slowText.reset(JS_smprintf("%s%s:%u (%ums)%s",
|
||||
slowText.get(),
|
||||
module.prettyFuncName(func.index),
|
||||
func.lineOrBytecode,
|
||||
func.ms,
|
||||
i+1 < slowFuncs.length() ? ", " : ""));
|
||||
if (!slowText)
|
||||
return nullptr;
|
||||
|
@ -603,15 +603,10 @@ typedef Vector<SourceCoords, 0, SystemAllocPolicy> SourceCoordsVector;
|
||||
class FuncBytecode
|
||||
{
|
||||
// Function metadata
|
||||
SourceCoordsVector callSourceCoords_;
|
||||
const DeclaredSig& sig_;
|
||||
ValTypeVector locals_;
|
||||
|
||||
// Note: this unrooted field assumes AutoKeepAtoms via TokenStream via
|
||||
// asm.js compilation.
|
||||
PropertyName* name_;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
uint32_t lineOrBytecode_;
|
||||
SourceCoordsVector callSourceCoords_;
|
||||
|
||||
// Compilation bookkeeping
|
||||
uint32_t index_;
|
||||
@ -620,21 +615,17 @@ class FuncBytecode
|
||||
UniqueBytecode bytecode_;
|
||||
|
||||
public:
|
||||
FuncBytecode(PropertyName* name,
|
||||
unsigned line,
|
||||
unsigned column,
|
||||
SourceCoordsVector&& sourceCoords,
|
||||
uint32_t index,
|
||||
FuncBytecode(uint32_t index,
|
||||
const DeclaredSig& sig,
|
||||
UniqueBytecode bytecode,
|
||||
ValTypeVector&& locals,
|
||||
uint32_t lineOrBytecode,
|
||||
SourceCoordsVector&& sourceCoords,
|
||||
unsigned generateTime)
|
||||
: callSourceCoords_(Move(sourceCoords)),
|
||||
sig_(sig),
|
||||
: sig_(sig),
|
||||
locals_(Move(locals)),
|
||||
name_(name),
|
||||
line_(line),
|
||||
column_(column),
|
||||
lineOrBytecode_(lineOrBytecode),
|
||||
callSourceCoords_(Move(sourceCoords)),
|
||||
index_(index),
|
||||
generateTime_(generateTime),
|
||||
bytecode_(Move(bytecode))
|
||||
@ -642,9 +633,7 @@ class FuncBytecode
|
||||
|
||||
UniqueBytecode recycleBytecode() { return Move(bytecode_); }
|
||||
|
||||
PropertyName* name() const { return name_; }
|
||||
unsigned line() const { return line_; }
|
||||
unsigned column() const { return column_; }
|
||||
uint32_t lineOrBytecode() const { return lineOrBytecode_; }
|
||||
const SourceCoords& sourceCoords(size_t i) const { return callSourceCoords_[i]; }
|
||||
|
||||
uint32_t index() const { return index_; }
|
||||
|
@ -106,7 +106,13 @@ FrameIterator::functionDisplayAtom() const
|
||||
{
|
||||
MOZ_ASSERT(!done());
|
||||
|
||||
const char* chars = module_->functionName(codeRange_->funcNameIndex());
|
||||
UniqueChars owner;
|
||||
const char* chars = module_->getFuncName(cx_, codeRange_->funcIndex(), &owner);
|
||||
if (!chars) {
|
||||
cx_->clearPendingException();
|
||||
return cx_->names().empty;
|
||||
}
|
||||
|
||||
JSAtom* atom = AtomizeUTF8Chars(cx_, chars, strlen(chars));
|
||||
if (!atom) {
|
||||
cx_->clearPendingException();
|
||||
@ -693,7 +699,7 @@ ProfilingFrameIterator::label() const
|
||||
}
|
||||
|
||||
switch (codeRange_->kind()) {
|
||||
case CodeRange::Function: return module_->profilingLabel(codeRange_->funcNameIndex());
|
||||
case CodeRange::Function: return module_->profilingLabel(codeRange_->funcIndex());
|
||||
case CodeRange::Entry: return "entry trampoline (in asm.js)";
|
||||
case CodeRange::ImportJitExit: return importJitDescription;
|
||||
case CodeRange::ImportInterpExit: return importInterpDescription;
|
||||
|
@ -38,7 +38,6 @@ ModuleGenerator::ModuleGenerator(ExclusiveContext* cx)
|
||||
jcx_(CompileRuntime::get(cx->compartment()->runtimeFromAnyThread())),
|
||||
slowFuncs_(cx),
|
||||
numSigs_(0),
|
||||
numFuncSigs_(0),
|
||||
lifo_(GENERATOR_LIFO_DEFAULT_CHUNK_SIZE),
|
||||
alloc_(&lifo_),
|
||||
masm_(MacroAssembler::AsmJSToken(), alloc_),
|
||||
@ -125,7 +124,7 @@ ModuleGenerator::init(UniqueModuleGeneratorData shared, ModuleKind kind)
|
||||
shared_ = Move(shared);
|
||||
if (kind == ModuleKind::Wasm) {
|
||||
numSigs_ = shared_->sigs.length();
|
||||
numFuncSigs_ = shared_->funcSigs.length();
|
||||
module_->numFuncs = shared_->funcSigs.length();
|
||||
for (uint32_t i = 0; i < shared_->imports.length(); i++) {
|
||||
if (!addImport(*shared_->imports[i].sig, shared_->imports[i].globalDataOffset))
|
||||
return false;
|
||||
@ -189,19 +188,13 @@ ModuleGenerator::finishTask(IonCompileTask* task)
|
||||
MOZ_ASSERT(masm_.size() == offsetInWhole + results.masm().size());
|
||||
|
||||
// Add the CodeRange for this function.
|
||||
CacheableChars funcName = StringToNewUTF8CharsZ(cx_, *func.name());
|
||||
if (!funcName)
|
||||
return false;
|
||||
uint32_t nameIndex = module_->funcNames.length();
|
||||
if (!module_->funcNames.emplaceBack(Move(funcName)))
|
||||
return false;
|
||||
if (!module_->codeRanges.emplaceBack(nameIndex, func.line(), results.offsets()))
|
||||
if (!module_->codeRanges.emplaceBack(func.index(), func.lineOrBytecode(), results.offsets()))
|
||||
return false;
|
||||
|
||||
// Keep a record of slow functions for printing in the final console message.
|
||||
unsigned totalTime = func.generateTime() + results.compileTime();
|
||||
if (totalTime >= SlowFunction::msThreshold) {
|
||||
if (!slowFuncs_.emplaceBack(func.name(), totalTime, func.line(), func.column()))
|
||||
if (!slowFuncs_.emplaceBack(func.index(), totalTime, func.lineOrBytecode()))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -287,10 +280,10 @@ bool
|
||||
ModuleGenerator::initFuncSig(uint32_t funcIndex, uint32_t sigIndex)
|
||||
{
|
||||
MOZ_ASSERT(module_->kind == ModuleKind::AsmJS);
|
||||
MOZ_ASSERT(funcIndex == numFuncSigs_);
|
||||
MOZ_ASSERT(funcIndex == module_->numFuncs);
|
||||
MOZ_ASSERT(!shared_->funcSigs[funcIndex]);
|
||||
|
||||
numFuncSigs_++;
|
||||
module_->numFuncs++;
|
||||
shared_->funcSigs[funcIndex] = &shared_->sigs[sigIndex];
|
||||
return true;
|
||||
}
|
||||
@ -430,8 +423,7 @@ ModuleGenerator::startFuncDefs()
|
||||
}
|
||||
|
||||
bool
|
||||
ModuleGenerator::startFuncDef(PropertyName* name, unsigned line, unsigned column,
|
||||
FunctionGenerator* fg)
|
||||
ModuleGenerator::startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg)
|
||||
{
|
||||
MOZ_ASSERT(startedFuncDefs());
|
||||
MOZ_ASSERT(!activeFunc_);
|
||||
@ -451,9 +443,7 @@ ModuleGenerator::startFuncDef(PropertyName* name, unsigned line, unsigned column
|
||||
return false;
|
||||
}
|
||||
|
||||
fg->name_= name;
|
||||
fg->line_ = line;
|
||||
fg->column_ = column;
|
||||
fg->lineOrBytecode_ = lineOrBytecode;
|
||||
fg->m_ = this;
|
||||
fg->task_ = task;
|
||||
activeFunc_ = fg;
|
||||
@ -466,14 +456,12 @@ ModuleGenerator::finishFuncDef(uint32_t funcIndex, unsigned generateTime, Functi
|
||||
MOZ_ASSERT(activeFunc_ == fg);
|
||||
|
||||
UniqueFuncBytecode func =
|
||||
js::MakeUnique<FuncBytecode>(fg->name_,
|
||||
fg->line_,
|
||||
fg->column_,
|
||||
Move(fg->callSourceCoords_),
|
||||
funcIndex,
|
||||
js::MakeUnique<FuncBytecode>(funcIndex,
|
||||
funcSig(funcIndex),
|
||||
Move(fg->bytecode_),
|
||||
Move(fg->localVars_),
|
||||
fg->lineOrBytecode_,
|
||||
Move(fg->callSourceCoords_),
|
||||
generateTime);
|
||||
if (!func)
|
||||
return false;
|
||||
@ -607,6 +595,7 @@ ModuleGenerator::defineOutOfBoundsStub(Offsets offsets)
|
||||
bool
|
||||
ModuleGenerator::finish(HeapUsage heapUsage,
|
||||
CacheableChars filename,
|
||||
CacheableCharsVector&& prettyFuncNames,
|
||||
UniqueModuleData* module,
|
||||
UniqueStaticLinkData* linkData,
|
||||
SlowFunctionVector* slowFuncs)
|
||||
@ -616,6 +605,7 @@ ModuleGenerator::finish(HeapUsage heapUsage,
|
||||
|
||||
module_->heapUsage = heapUsage;
|
||||
module_->filename = Move(filename);
|
||||
module_->prettyFuncNames = Move(prettyFuncNames);
|
||||
|
||||
if (!GenerateStubs(*this, UsesHeap(heapUsage)))
|
||||
return false;
|
||||
|
@ -35,16 +35,15 @@ typedef Vector<uint32_t, 0, SystemAllocPolicy> Uint32Vector;
|
||||
|
||||
struct SlowFunction
|
||||
{
|
||||
SlowFunction(PropertyName* name, unsigned ms, unsigned line, unsigned column)
|
||||
: name(name), ms(ms), line(line), column(column)
|
||||
SlowFunction(uint32_t index, unsigned ms, unsigned lineOrBytecode)
|
||||
: index(index), ms(ms), lineOrBytecode(lineOrBytecode)
|
||||
{}
|
||||
|
||||
static const unsigned msThreshold = 250;
|
||||
|
||||
PropertyName* name;
|
||||
uint32_t index;
|
||||
unsigned ms;
|
||||
unsigned line;
|
||||
unsigned column;
|
||||
unsigned lineOrBytecode;
|
||||
};
|
||||
typedef Vector<SlowFunction> SlowFunctionVector;
|
||||
|
||||
@ -138,7 +137,6 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
// Data scoped to the ModuleGenerator's lifetime
|
||||
UniqueModuleGeneratorData shared_;
|
||||
uint32_t numSigs_;
|
||||
uint32_t numFuncSigs_;
|
||||
LifoAlloc lifo_;
|
||||
jit::TempAllocator alloc_;
|
||||
jit::MacroAssembler masm_;
|
||||
@ -160,6 +158,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
bool finishOutstandingTask();
|
||||
bool finishTask(IonCompileTask* task);
|
||||
bool addImport(const Sig& sig, uint32_t globalDataOffset);
|
||||
bool startedFuncDefs() const { return !!threadView_; }
|
||||
|
||||
public:
|
||||
explicit ModuleGenerator(ExclusiveContext* cx);
|
||||
@ -183,7 +182,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
|
||||
// Function declarations:
|
||||
bool initFuncSig(uint32_t funcIndex, uint32_t sigIndex);
|
||||
uint32_t numFuncSigs() const { return numFuncSigs_; }
|
||||
uint32_t numFuncSigs() const { return module_->numFuncs; }
|
||||
const DeclaredSig& funcSig(uint32_t funcIndex) const;
|
||||
|
||||
// Imports:
|
||||
@ -201,8 +200,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
|
||||
// Function definitions:
|
||||
bool startFuncDefs();
|
||||
bool startedFuncDefs() const { return !!threadView_; }
|
||||
bool startFuncDef(PropertyName* name, unsigned line, unsigned column, FunctionGenerator* fg);
|
||||
bool startFuncDef(uint32_t lineOrBytecode, FunctionGenerator* fg);
|
||||
bool finishFuncDef(uint32_t funcIndex, unsigned generateTime, FunctionGenerator* fg);
|
||||
bool finishFuncDefs();
|
||||
|
||||
@ -222,6 +220,7 @@ class MOZ_STACK_CLASS ModuleGenerator
|
||||
// functions that took a long time to compile.
|
||||
bool finish(HeapUsage heapUsage,
|
||||
CacheableChars filename,
|
||||
CacheableCharsVector&& prettyFuncNames,
|
||||
UniqueModuleData* module,
|
||||
UniqueStaticLinkData* staticLinkData,
|
||||
SlowFunctionVector* slowFuncs);
|
||||
@ -246,19 +245,11 @@ class MOZ_STACK_CLASS FunctionGenerator
|
||||
SourceCoordsVector callSourceCoords_;
|
||||
ValTypeVector localVars_;
|
||||
|
||||
// Note: this unrooted field assumes AutoKeepAtoms via TokenStream via
|
||||
// asm.js compilation.
|
||||
PropertyName* name_;
|
||||
unsigned line_;
|
||||
unsigned column_;
|
||||
uint32_t lineOrBytecode_;
|
||||
|
||||
public:
|
||||
FunctionGenerator()
|
||||
: m_(nullptr),
|
||||
task_(nullptr),
|
||||
name_(nullptr),
|
||||
line_(0),
|
||||
column_(0)
|
||||
: m_(nullptr), task_(nullptr), lineOrBytecode_(0)
|
||||
{}
|
||||
|
||||
Bytecode& bytecode() const {
|
||||
|
@ -351,8 +351,8 @@ Import::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
}
|
||||
|
||||
CodeRange::CodeRange(Kind kind, Offsets offsets)
|
||||
: nameIndex_(0),
|
||||
lineNumber_(0),
|
||||
: funcIndex_(0),
|
||||
funcLineOrBytecode_(0),
|
||||
begin_(offsets.begin),
|
||||
profilingReturn_(0),
|
||||
end_(offsets.end)
|
||||
@ -365,8 +365,8 @@ CodeRange::CodeRange(Kind kind, Offsets offsets)
|
||||
}
|
||||
|
||||
CodeRange::CodeRange(Kind kind, ProfilingOffsets offsets)
|
||||
: nameIndex_(0),
|
||||
lineNumber_(0),
|
||||
: funcIndex_(0),
|
||||
funcLineOrBytecode_(0),
|
||||
begin_(offsets.begin),
|
||||
profilingReturn_(offsets.profilingReturn),
|
||||
end_(offsets.end)
|
||||
@ -379,9 +379,9 @@ CodeRange::CodeRange(Kind kind, ProfilingOffsets offsets)
|
||||
MOZ_ASSERT(u.kind_ == ImportJitExit || u.kind_ == ImportInterpExit || u.kind_ == Interrupt);
|
||||
}
|
||||
|
||||
CodeRange::CodeRange(uint32_t nameIndex, uint32_t lineNumber, FuncOffsets offsets)
|
||||
: nameIndex_(nameIndex),
|
||||
lineNumber_(lineNumber)
|
||||
CodeRange::CodeRange(uint32_t funcIndex, uint32_t funcLineOrBytecode, FuncOffsets offsets)
|
||||
: funcIndex_(funcIndex),
|
||||
funcLineOrBytecode_(funcLineOrBytecode)
|
||||
{
|
||||
PodZero(&u); // zero padding for Valgrind
|
||||
u.kind_ = Function;
|
||||
@ -509,7 +509,7 @@ ModuleData::serializedSize() const
|
||||
SerializedPodVectorSize(heapAccesses) +
|
||||
SerializedPodVectorSize(codeRanges) +
|
||||
SerializedPodVectorSize(callSites) +
|
||||
SerializedVectorSize(funcNames) +
|
||||
SerializedVectorSize(prettyFuncNames) +
|
||||
filename.serializedSize();
|
||||
}
|
||||
|
||||
@ -523,7 +523,7 @@ ModuleData::serialize(uint8_t* cursor) const
|
||||
cursor = SerializePodVector(cursor, heapAccesses);
|
||||
cursor = SerializePodVector(cursor, codeRanges);
|
||||
cursor = SerializePodVector(cursor, callSites);
|
||||
cursor = SerializeVector(cursor, funcNames);
|
||||
cursor = SerializeVector(cursor, prettyFuncNames);
|
||||
cursor = filename.serialize(cursor);
|
||||
return cursor;
|
||||
}
|
||||
@ -543,7 +543,7 @@ ModuleData::deserialize(ExclusiveContext* cx, const uint8_t* cursor)
|
||||
(cursor = DeserializePodVector(cx, cursor, &heapAccesses)) &&
|
||||
(cursor = DeserializePodVector(cx, cursor, &codeRanges)) &&
|
||||
(cursor = DeserializePodVector(cx, cursor, &callSites)) &&
|
||||
(cursor = DeserializeVector(cx, cursor, &funcNames)) &&
|
||||
(cursor = DeserializeVector(cx, cursor, &prettyFuncNames)) &&
|
||||
(cursor = filename.deserialize(cx, cursor));
|
||||
return cursor;
|
||||
}
|
||||
@ -563,7 +563,7 @@ ModuleData::clone(JSContext* cx, ModuleData* out) const
|
||||
ClonePodVector(cx, heapAccesses, &out->heapAccesses) &&
|
||||
ClonePodVector(cx, codeRanges, &out->codeRanges) &&
|
||||
ClonePodVector(cx, callSites, &out->callSites) &&
|
||||
CloneVector(cx, funcNames, &out->funcNames) &&
|
||||
CloneVector(cx, prettyFuncNames, &out->prettyFuncNames) &&
|
||||
filename.clone(cx, &out->filename);
|
||||
}
|
||||
|
||||
@ -576,7 +576,7 @@ ModuleData::sizeOfExcludingThis(MallocSizeOf mallocSizeOf) const
|
||||
heapAccesses.sizeOfExcludingThis(mallocSizeOf) +
|
||||
codeRanges.sizeOfExcludingThis(mallocSizeOf) +
|
||||
callSites.sizeOfExcludingThis(mallocSizeOf) +
|
||||
funcNames.sizeOfExcludingThis(mallocSizeOf) +
|
||||
prettyFuncNames.sizeOfExcludingThis(mallocSizeOf) +
|
||||
filename.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
@ -680,41 +680,50 @@ Module::despecializeFromHeap(ArrayBufferObjectMaybeShared* heap)
|
||||
rawHeapPtr() = nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
Module::sendCodeRangesToProfiler(JSContext* cx)
|
||||
{
|
||||
bool enabled = false;
|
||||
#ifdef JS_ION_PERF
|
||||
if (PerfFuncEnabled()) {
|
||||
for (const CodeRange& codeRange : module_->codeRanges) {
|
||||
if (!codeRange.isFunction())
|
||||
continue;
|
||||
|
||||
uintptr_t start = uintptr_t(code() + codeRange.begin());
|
||||
uintptr_t end = uintptr_t(code() + codeRange.end());
|
||||
uintptr_t size = end - start;
|
||||
const char* file = module_->filename.get();
|
||||
unsigned line = codeRange.funcLineNumber();
|
||||
unsigned column = 0;
|
||||
const char* name = module_->funcNames[codeRange.funcNameIndex()].get();
|
||||
|
||||
writePerfSpewerAsmJSFunctionMap(start, size, file, line, column, name);
|
||||
}
|
||||
}
|
||||
enabled |= PerfFuncEnabled();
|
||||
#endif
|
||||
#ifdef MOZ_VTUNE
|
||||
if (IsVTuneProfilingActive()) {
|
||||
for (const CodeRange& codeRange : module_->codeRanges) {
|
||||
if (!codeRange.isFunction())
|
||||
continue;
|
||||
enabled |= IsVTuneProfilingActive();
|
||||
#endif
|
||||
if (!enabled)
|
||||
return true;
|
||||
|
||||
uintptr_t start = uintptr_t(code() + codeRange.begin());
|
||||
uintptr_t end = uintptr_t(code() + codeRange.end());
|
||||
uintptr_t size = end - start;
|
||||
const char* name = module_->funcNames[codeRange.funcNameIndex()].get();
|
||||
for (const CodeRange& codeRange : module_->codeRanges) {
|
||||
if (!codeRange.isFunction())
|
||||
continue;
|
||||
|
||||
uintptr_t start = uintptr_t(code() + codeRange.begin());
|
||||
uintptr_t end = uintptr_t(code() + codeRange.end());
|
||||
uintptr_t size = end - start;
|
||||
|
||||
UniqueChars owner;
|
||||
const char* name = getFuncName(cx, codeRange.funcIndex(), &owner);
|
||||
if (!name)
|
||||
return false;
|
||||
|
||||
// Avoid "unused" warnings
|
||||
(void)start;
|
||||
(void)size;
|
||||
(void)name;
|
||||
|
||||
#ifdef JS_ION_PERF
|
||||
if (PerfFuncEnabled()) {
|
||||
const char* file = module_->filename.get();
|
||||
unsigned line = codeRange.funcLineOrBytecode();
|
||||
unsigned column = 0;
|
||||
writePerfSpewerAsmJSFunctionMap(start, size, file, line, column, name);
|
||||
}
|
||||
#endif
|
||||
#ifdef MOZ_VTUNE
|
||||
if (IsVTuneProfilingActive()) {
|
||||
unsigned method_id = iJIT_GetNewMethodID();
|
||||
if (method_id == 0)
|
||||
return;
|
||||
return true;
|
||||
iJIT_Method_Load method;
|
||||
method.method_id = method_id;
|
||||
method.method_name = const_cast<char*>(name);
|
||||
@ -727,8 +736,10 @@ Module::sendCodeRangesToProfiler(JSContext* cx)
|
||||
method.source_file_name = nullptr;
|
||||
iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, (void*)&method);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -745,21 +756,29 @@ Module::setProfilingEnabled(JSContext* cx, bool enabled)
|
||||
// do it now since, once we start sampling, we'll be in a signal-handing
|
||||
// context where we cannot malloc.
|
||||
if (enabled) {
|
||||
if (!funcLabels_.resize(module_->funcNames.length())) {
|
||||
if (!funcLabels_.resize(module_->numFuncs)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
for (const CodeRange& codeRange : module_->codeRanges) {
|
||||
if (!codeRange.isFunction())
|
||||
continue;
|
||||
unsigned lineno = codeRange.funcLineNumber();
|
||||
const char* name = module_->funcNames[codeRange.funcNameIndex()].get();
|
||||
UniqueChars label(JS_smprintf("%s (%s:%u)", name, module_->filename.get(), lineno));
|
||||
|
||||
UniqueChars owner;
|
||||
const char* funcName = getFuncName(cx, codeRange.funcIndex(), &owner);
|
||||
if (!funcName)
|
||||
return false;
|
||||
|
||||
UniqueChars label(JS_smprintf("%s (%s:%u)",
|
||||
funcName,
|
||||
module_->filename.get(),
|
||||
codeRange.funcLineOrBytecode()));
|
||||
if (!label) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
funcLabels_[codeRange.funcNameIndex()] = Move(label);
|
||||
|
||||
funcLabels_[codeRange.funcIndex()] = Move(label);
|
||||
}
|
||||
} else {
|
||||
funcLabels_.clear();
|
||||
@ -1082,8 +1101,7 @@ Module::dynamicallyLink(JSContext* cx, Handle<ArrayBufferObjectMaybeShared*> hea
|
||||
return false;
|
||||
}
|
||||
|
||||
sendCodeRangesToProfiler(cx);
|
||||
return true;
|
||||
return sendCodeRangesToProfiler(cx);
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -1408,6 +1426,28 @@ Module::callImport(JSContext* cx, uint32_t importIndex, unsigned argc, const Val
|
||||
return true;
|
||||
}
|
||||
|
||||
const char*
|
||||
Module::prettyFuncName(uint32_t funcIndex) const
|
||||
{
|
||||
return module_->prettyFuncNames[funcIndex].get();
|
||||
}
|
||||
|
||||
const char*
|
||||
Module::getFuncName(JSContext* cx, uint32_t funcIndex, UniqueChars* owner) const
|
||||
{
|
||||
if (!module_->prettyFuncNames.empty())
|
||||
return prettyFuncName(funcIndex);
|
||||
|
||||
char* chars = JS_smprintf("wasm-function[%u]", funcIndex);
|
||||
if (!chars) {
|
||||
ReportOutOfMemory(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
owner->reset(chars);
|
||||
return chars;
|
||||
}
|
||||
|
||||
const char*
|
||||
Module::profilingLabel(uint32_t funcIndex) const
|
||||
{
|
||||
|
@ -197,8 +197,8 @@ typedef Vector<Import, 0, SystemAllocPolicy> ImportVector;
|
||||
class CodeRange
|
||||
{
|
||||
// All fields are treated as cacheable POD:
|
||||
uint32_t nameIndex_;
|
||||
uint32_t lineNumber_;
|
||||
uint32_t funcIndex_;
|
||||
uint32_t funcLineOrBytecode_;
|
||||
uint32_t begin_;
|
||||
uint32_t profilingReturn_;
|
||||
uint32_t end_;
|
||||
@ -220,7 +220,7 @@ class CodeRange
|
||||
CodeRange() = default;
|
||||
CodeRange(Kind kind, Offsets offsets);
|
||||
CodeRange(Kind kind, ProfilingOffsets offsets);
|
||||
CodeRange(uint32_t nameIndex, uint32_t lineNumber, FuncOffsets offsets);
|
||||
CodeRange(uint32_t funcIndex, uint32_t lineOrBytecode, FuncOffsets offsets);
|
||||
|
||||
// All CodeRanges have a begin and end.
|
||||
|
||||
@ -265,13 +265,13 @@ class CodeRange
|
||||
MOZ_ASSERT(isFunction());
|
||||
return profilingReturn_ - u.func.profilingEpilogueToProfilingReturn_;
|
||||
}
|
||||
uint32_t funcNameIndex() const {
|
||||
uint32_t funcIndex() const {
|
||||
MOZ_ASSERT(isFunction());
|
||||
return nameIndex_;
|
||||
return funcIndex_;
|
||||
}
|
||||
uint32_t funcLineNumber() const {
|
||||
uint32_t funcLineOrBytecode() const {
|
||||
MOZ_ASSERT(isFunction());
|
||||
return lineNumber_;
|
||||
return funcLineOrBytecode_;
|
||||
}
|
||||
|
||||
// A sorted array of CodeRanges can be looked up via BinarySearch and PC.
|
||||
@ -366,6 +366,7 @@ struct ModuleCacheablePod
|
||||
uint32_t functionBytes;
|
||||
uint32_t codeBytes;
|
||||
uint32_t globalBytes;
|
||||
uint32_t numFuncs;
|
||||
ModuleKind kind;
|
||||
HeapUsage heapUsage;
|
||||
CompileArgs compileArgs;
|
||||
@ -389,7 +390,7 @@ struct ModuleData : ModuleCacheablePod
|
||||
HeapAccessVector heapAccesses;
|
||||
CodeRangeVector codeRanges;
|
||||
CallSiteVector callSites;
|
||||
CacheableCharsVector funcNames;
|
||||
CacheableCharsVector prettyFuncNames;
|
||||
CacheableChars filename;
|
||||
bool loadedFromCache;
|
||||
|
||||
@ -466,7 +467,7 @@ class Module
|
||||
WasmActivation*& activation();
|
||||
void specializeToHeap(ArrayBufferObjectMaybeShared* heap);
|
||||
void despecializeFromHeap(ArrayBufferObjectMaybeShared* heap);
|
||||
void sendCodeRangesToProfiler(JSContext* cx);
|
||||
bool sendCodeRangesToProfiler(JSContext* cx);
|
||||
MOZ_WARN_UNUSED_RESULT bool setProfilingEnabled(JSContext* cx, bool enabled);
|
||||
ImportExit& importToExit(const Import& import);
|
||||
|
||||
@ -496,7 +497,6 @@ class Module
|
||||
CompileArgs compileArgs() const { return module_->compileArgs; }
|
||||
const ImportVector& imports() const { return module_->imports; }
|
||||
const ExportVector& exports() const { return module_->exports; }
|
||||
const char* functionName(uint32_t i) const { return module_->funcNames[i].get(); }
|
||||
const char* filename() const { return module_->filename.get(); }
|
||||
bool loadedFromCache() const { return module_->loadedFromCache; }
|
||||
bool staticallyLinked() const { return staticallyLinked_; }
|
||||
@ -573,6 +573,13 @@ class Module
|
||||
uint8_t* interrupt() const { MOZ_ASSERT(staticallyLinked_); return interrupt_; }
|
||||
uint8_t* outOfBounds() const { MOZ_ASSERT(staticallyLinked_); return outOfBounds_; }
|
||||
|
||||
// Every function has an associated display atom which is either the pretty
|
||||
// name given by the asm.js function name or wasm symbols or something
|
||||
// generated from the function index.
|
||||
|
||||
const char* prettyFuncName(uint32_t funcIndex) const;
|
||||
const char* getFuncName(JSContext* cx, uint32_t funcIndex, UniqueChars* owner) const;
|
||||
|
||||
// Each Module has a profilingEnabled state which is updated to match
|
||||
// SPSProfiler::enabled() on the next Module::callExport when there are no
|
||||
// frames from the Module on the stack. The ProfilingFrameIterator only
|
||||
|
Loading…
Reference in New Issue
Block a user