Bug 1129780 - Report the youngest sampled frame's line number if it has optimization info. (r=djvj)

This commit is contained in:
Shu-yu Guo 2015-02-23 20:33:56 -08:00
Родитель 7c033d640a
Коммит df02b37be7
5 изменённых файлов: 115 добавлений и 34 удалений

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

@ -279,7 +279,8 @@ struct ForEachTrackedOptimizationAttemptOp
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
ForEachTrackedOptimizationAttempt(JSRuntime *rt, void *addr, ForEachTrackedOptimizationAttempt(JSRuntime *rt, void *addr,
ForEachTrackedOptimizationAttemptOp &op); ForEachTrackedOptimizationAttemptOp &op,
JSScript **scriptOut, jsbytecode **pcOut);
struct ForEachTrackedOptimizationTypeInfoOp struct ForEachTrackedOptimizationTypeInfoOp
{ {

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

@ -20,19 +20,28 @@
namespace js { namespace js {
namespace jit { namespace jit {
static inline JitcodeRegionEntry
RegionAtAddr(const JitcodeGlobalEntry::IonEntry &entry, void *ptr,
uint32_t *ptrOffset)
{
MOZ_ASSERT(entry.containsPointer(ptr));
*ptrOffset = reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<uint8_t *>(entry.nativeStartAddr());
uint32_t regionIdx = entry.regionTable()->findRegionEntry(*ptrOffset);
MOZ_ASSERT(regionIdx < entry.regionTable()->numRegions());
return entry.regionTable()->regionEntry(regionIdx);
}
bool bool
JitcodeGlobalEntry::IonEntry::callStackAtAddr(JSRuntime *rt, void *ptr, JitcodeGlobalEntry::IonEntry::callStackAtAddr(JSRuntime *rt, void *ptr,
BytecodeLocationVector &results, BytecodeLocationVector &results,
uint32_t *depth) const uint32_t *depth) const
{ {
MOZ_ASSERT(containsPointer(ptr)); uint32_t ptrOffset;
uint32_t ptrOffset = reinterpret_cast<uint8_t *>(ptr) - JitcodeRegionEntry region = RegionAtAddr(*this, ptr, &ptrOffset);
reinterpret_cast<uint8_t *>(nativeStartAddr());
uint32_t regionIdx = regionTable()->findRegionEntry(ptrOffset);
MOZ_ASSERT(regionIdx < regionTable()->numRegions());
JitcodeRegionEntry region = regionTable()->regionEntry(regionIdx);
*depth = region.scriptDepth(); *depth = region.scriptDepth();
JitcodeRegionEntry::ScriptPcIterator locationIter = region.scriptPcIterator(); JitcodeRegionEntry::ScriptPcIterator locationIter = region.scriptPcIterator();
@ -61,15 +70,10 @@ JitcodeGlobalEntry::IonEntry::callStackAtAddr(JSRuntime *rt, void *ptr,
const char **results, const char **results,
uint32_t maxResults) const uint32_t maxResults) const
{ {
MOZ_ASSERT(containsPointer(ptr));
MOZ_ASSERT(maxResults >= 1); MOZ_ASSERT(maxResults >= 1);
uint32_t ptrOffset = reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<uint8_t *>(nativeStartAddr());
uint32_t regionIdx = regionTable()->findRegionEntry(ptrOffset); uint32_t ptrOffset;
MOZ_ASSERT(regionIdx < regionTable()->numRegions()); JitcodeRegionEntry region = RegionAtAddr(*this, ptr, &ptrOffset);
JitcodeRegionEntry region = regionTable()->regionEntry(regionIdx);
JitcodeRegionEntry::ScriptPcIterator locationIter = region.scriptPcIterator(); JitcodeRegionEntry::ScriptPcIterator locationIter = region.scriptPcIterator();
MOZ_ASSERT(locationIter.hasMore()); MOZ_ASSERT(locationIter.hasMore());
@ -88,6 +92,23 @@ JitcodeGlobalEntry::IonEntry::callStackAtAddr(JSRuntime *rt, void *ptr,
return count; return count;
} }
void
JitcodeGlobalEntry::IonEntry::youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script, jsbytecode **pc) const
{
uint32_t ptrOffset;
JitcodeRegionEntry region = RegionAtAddr(*this, ptr, &ptrOffset);
JitcodeRegionEntry::ScriptPcIterator locationIter = region.scriptPcIterator();
MOZ_ASSERT(locationIter.hasMore());
uint32_t scriptIdx, pcOffset;
locationIter.readNext(&scriptIdx, &pcOffset);
pcOffset = region.findPcOffset(ptrOffset, pcOffset);
*script = getScript(scriptIdx);
*pc = (*script)->offsetToPC(pcOffset);
}
void void
JitcodeGlobalEntry::IonEntry::destroy() JitcodeGlobalEntry::IonEntry::destroy()
{ {
@ -155,6 +176,16 @@ JitcodeGlobalEntry::BaselineEntry::callStackAtAddr(JSRuntime *rt, void *ptr,
return 1; return 1;
} }
void
JitcodeGlobalEntry::BaselineEntry::youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script,
jsbytecode **pc) const
{
uint8_t *addr = reinterpret_cast<uint8_t*>(ptr);
*script = script_;
*pc = script_->baselineScript()->approximatePcForNativeAddress(script_, addr);
}
void void
JitcodeGlobalEntry::BaselineEntry::destroy() JitcodeGlobalEntry::BaselineEntry::destroy()
{ {
@ -164,19 +195,25 @@ JitcodeGlobalEntry::BaselineEntry::destroy()
str_ = nullptr; str_ = nullptr;
} }
static inline void
RejoinEntry(JSRuntime *rt, const JitcodeGlobalEntry::IonCacheEntry &cache,
void *ptr, JitcodeGlobalEntry *entry)
{
MOZ_ASSERT(cache.containsPointer(ptr));
// There must exist an entry for the rejoin addr if this entry exists.
JitRuntime *jitrt = rt->jitRuntime();
jitrt->getJitcodeGlobalTable()->lookupInfallible(cache.rejoinAddr(), entry, rt);
MOZ_ASSERT(entry->isIon());
}
bool bool
JitcodeGlobalEntry::IonCacheEntry::callStackAtAddr(JSRuntime *rt, void *ptr, JitcodeGlobalEntry::IonCacheEntry::callStackAtAddr(JSRuntime *rt, void *ptr,
BytecodeLocationVector &results, BytecodeLocationVector &results,
uint32_t *depth) const uint32_t *depth) const
{ {
MOZ_ASSERT(containsPointer(ptr));
// There must exist an entry for the rejoin addr if this entry exists.
JitRuntime *jitrt = rt->jitRuntime();
JitcodeGlobalEntry entry; JitcodeGlobalEntry entry;
jitrt->getJitcodeGlobalTable()->lookupInfallible(rejoinAddr(), &entry, rt); RejoinEntry(rt, *this, ptr, &entry);
MOZ_ASSERT(entry.isIon());
return entry.callStackAtAddr(rt, rejoinAddr(), results, depth); return entry.callStackAtAddr(rt, rejoinAddr(), results, depth);
} }
@ -185,17 +222,21 @@ JitcodeGlobalEntry::IonCacheEntry::callStackAtAddr(JSRuntime *rt, void *ptr,
const char **results, const char **results,
uint32_t maxResults) const uint32_t maxResults) const
{ {
MOZ_ASSERT(containsPointer(ptr));
// There must exist an entry for the rejoin addr if this entry exists.
JitRuntime *jitrt = rt->jitRuntime();
JitcodeGlobalEntry entry; JitcodeGlobalEntry entry;
jitrt->getJitcodeGlobalTable()->lookupInfallible(rejoinAddr(), &entry, rt); RejoinEntry(rt, *this, ptr, &entry);
MOZ_ASSERT(entry.isIon());
return entry.callStackAtAddr(rt, rejoinAddr(), results, maxResults); return entry.callStackAtAddr(rt, rejoinAddr(), results, maxResults);
} }
void
JitcodeGlobalEntry::IonCacheEntry::youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script,
jsbytecode **pc) const
{
JitcodeGlobalEntry entry;
RejoinEntry(rt, *this, ptr, &entry);
return entry.youngestFrameLocationAtAddr(rt, ptr, script, pc);
}
static int ComparePointers(const void *a, const void *b) { static int ComparePointers(const void *a, const void *b) {
const uint8_t *a_ptr = reinterpret_cast<const uint8_t *>(a); const uint8_t *a_ptr = reinterpret_cast<const uint8_t *>(a);

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

@ -210,6 +210,9 @@ class JitcodeGlobalEntry
uint32_t callStackAtAddr(JSRuntime *rt, void *ptr, const char **results, uint32_t callStackAtAddr(JSRuntime *rt, void *ptr, const char **results,
uint32_t maxResults) const; uint32_t maxResults) const;
void youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script, jsbytecode **pc) const;
bool hasTrackedOptimizations() const { bool hasTrackedOptimizations() const {
return !!optsRegionTable_; return !!optsRegionTable_;
} }
@ -278,6 +281,9 @@ class JitcodeGlobalEntry
uint32_t callStackAtAddr(JSRuntime *rt, void *ptr, const char **results, uint32_t callStackAtAddr(JSRuntime *rt, void *ptr, const char **results,
uint32_t maxResults) const; uint32_t maxResults) const;
void youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script, jsbytecode **pc) const;
}; };
struct IonCacheEntry : public BaseEntry struct IonCacheEntry : public BaseEntry
@ -302,6 +308,9 @@ class JitcodeGlobalEntry
uint32_t callStackAtAddr(JSRuntime *rt, void *ptr, const char **results, uint32_t callStackAtAddr(JSRuntime *rt, void *ptr, const char **results,
uint32_t maxResults) const; uint32_t maxResults) const;
void youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script, jsbytecode **pc) const;
}; };
// Dummy entries are created for jitcode generated when profiling is not turned on, // Dummy entries are created for jitcode generated when profiling is not turned on,
@ -326,6 +335,13 @@ class JitcodeGlobalEntry
{ {
return 0; return 0;
} }
void youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script, jsbytecode **pc) const
{
*script = nullptr;
*pc = nullptr;
}
}; };
// QueryEntry is never stored in the table, just used for queries // QueryEntry is never stored in the table, just used for queries
@ -551,6 +567,23 @@ class JitcodeGlobalEntry
return false; return false;
} }
void youngestFrameLocationAtAddr(JSRuntime *rt, void *ptr,
JSScript **script, jsbytecode **pc) const
{
switch (kind()) {
case Ion:
return ionEntry().youngestFrameLocationAtAddr(rt, ptr, script, pc);
case Baseline:
return baselineEntry().youngestFrameLocationAtAddr(rt, ptr, script, pc);
case IonCache:
return ionCacheEntry().youngestFrameLocationAtAddr(rt, ptr, script, pc);
case Dummy:
return dummyEntry().youngestFrameLocationAtAddr(rt, ptr, script, pc);
default:
MOZ_CRASH("Invalid JitcodeGlobalEntry kind.");
}
}
// Figure out the number of the (JSScript *, jsbytecode *) pairs that are active // Figure out the number of the (JSScript *, jsbytecode *) pairs that are active
// at this location. // at this location.
uint32_t lookupInlineCallDepth(void *ptr); uint32_t lookupInlineCallDepth(void *ptr);

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

@ -1123,11 +1123,13 @@ IonBuilder::trackInlineSuccessUnchecked(InliningStatus status)
JS_PUBLIC_API(void) JS_PUBLIC_API(void)
JS::ForEachTrackedOptimizationAttempt(JSRuntime *rt, void *addr, JS::ForEachTrackedOptimizationAttempt(JSRuntime *rt, void *addr,
ForEachTrackedOptimizationAttemptOp &op) ForEachTrackedOptimizationAttemptOp &op,
JSScript **scriptOut, jsbytecode **pcOut)
{ {
JitcodeGlobalTable *table = rt->jitRuntime()->getJitcodeGlobalTable(); JitcodeGlobalTable *table = rt->jitRuntime()->getJitcodeGlobalTable();
JitcodeGlobalEntry entry; JitcodeGlobalEntry entry;
table->lookupInfallible(addr, &entry, rt); table->lookupInfallible(addr, &entry, rt);
entry.youngestFrameLocationAtAddr(rt, addr, scriptOut, pcOut);
Maybe<uint8_t> index = entry.trackedOptimizationIndexAtAddr(addr); Maybe<uint8_t> index = entry.trackedOptimizationIndexAtAddr(addr);
entry.trackedOptimizationAttempts(index.value()).forEach(op); entry.trackedOptimizationAttempts(index.value()).forEach(op);
} }
@ -1143,7 +1145,7 @@ InterpretedFunctionFilenameAndLineNumber(JSFunction *fun, const char **filename,
source = fun->lazyScript()->maybeForwardedScriptSource(); source = fun->lazyScript()->maybeForwardedScriptSource();
*lineno = fun->lazyScript()->lineno(); *lineno = fun->lazyScript()->lineno();
} }
*filename = source->introducerFilename(); *filename = source->filename();
} }
static JSFunction * static JSFunction *
@ -1224,7 +1226,7 @@ class ForEachTypeInfoAdapter : public IonTrackedOptimizationsTypeInfo::ForEachOp
if (tracked.hasAllocationSite()) { if (tracked.hasAllocationSite()) {
JSScript *script = tracked.script; JSScript *script = tracked.script;
op_.readType("alloc site", buf, op_.readType("alloc site", buf,
script->maybeForwardedScriptSource()->introducerFilename(), script->maybeForwardedScriptSource()->filename(),
PCToLineNumber(script, script->offsetToPC(tracked.offset))); PCToLineNumber(script, script->offsetToPC(tracked.offset)));
return; return;
} }

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

@ -400,13 +400,17 @@ void ProfileBuffer::StreamSamplesToJSObject(JSStreamWriter& b, int aThreadId, JS
// TODOshu: cannot stream tracked optimization info if // TODOshu: cannot stream tracked optimization info if
// the JS engine has already shut down when streaming. // the JS engine has already shut down when streaming.
if (rt) { if (rt) {
JSScript *optsScript;
jsbytecode *optsPC;
b.Name("opts"); b.Name("opts");
b.BeginArray(); b.BeginArray();
StreamOptimizationTypeInfoOp typeInfoOp(b); StreamOptimizationTypeInfoOp typeInfoOp(b);
JS::ForEachTrackedOptimizationTypeInfo(rt, pc, typeInfoOp); JS::ForEachTrackedOptimizationTypeInfo(rt, pc, typeInfoOp);
StreamOptimizationAttemptsOp attemptOp(b); StreamOptimizationAttemptsOp attemptOp(b);
JS::ForEachTrackedOptimizationAttempt(rt, pc, attemptOp); JS::ForEachTrackedOptimizationAttempt(rt, pc, attemptOp,
&optsScript, &optsPC);
b.EndArray(); b.EndArray();
b.NameValue("optsLine", JS_PCToLineNumber(optsScript, optsPC));
} }
} }
b.EndObject(); b.EndObject();