Skip to content

Commit 0847f7c

Browse files
committed
Bug 1959977 - Collect sourceId of JIT frames r=iain,mstange,profiler-reviewers
Thanks to the patches from Iain before, we now have ScriptSource inside the JitCodeGlobalEntries. So we directly retrieve the sourceIds from there during serialization (because we know that they are kept alive until then). And serialization into the profile format is done the same way as index into sources table, by adding a `[sourceIndex]` at the end of the location. Differential Revision: https://phabricator.services.mozilla.com/D259255
1 parent 0b34e3e commit 0847f7c

8 files changed

Lines changed: 107 additions & 46 deletions

File tree

js/public/ProfilingFrameIterator.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,10 +238,12 @@ class MOZ_STACK_CLASS ProfiledFrameHandle {
238238
void* addr_;
239239
void* canonicalAddr_;
240240
const char* label_;
241+
uint32_t sourceId_;
241242
uint32_t depth_;
242243

243244
ProfiledFrameHandle(JSRuntime* rt, js::jit::JitcodeGlobalEntry& entry,
244-
void* addr, const char* label, uint32_t depth);
245+
void* addr, const char* label, uint32_t sourceId,
246+
uint32_t depth);
245247

246248
public:
247249
const char* label() const { return label_; }
@@ -251,6 +253,8 @@ class MOZ_STACK_CLASS ProfiledFrameHandle {
251253
JS_PUBLIC_API ProfilingFrameIterator::FrameKind frameKind() const;
252254

253255
JS_PUBLIC_API uint64_t realmID() const;
256+
257+
JS_PUBLIC_API uint32_t sourceId() const;
254258
};
255259

256260
class ProfiledFrameRange {
@@ -292,6 +296,7 @@ class ProfiledFrameRange {
292296
js::jit::JitcodeGlobalEntry* entry_;
293297
// Assume maximum inlining depth is <64
294298
const char* labels_[64];
299+
uint32_t sourceIds_[64];
295300
uint32_t depth_;
296301
};
297302

js/src/jit/JitcodeMap.cpp

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ void* IonEntry::canonicalNativeAddrFor(void* ptr) const {
4747
return (void*)(((uint8_t*)nativeStartAddr()) + region.nativeOffset());
4848
}
4949

50-
uint32_t IonEntry::callStackAtAddr(void* ptr, const char** results,
50+
uint32_t IonEntry::callStackAtAddr(void* ptr, const char** labelResults,
51+
uint32_t* sourceIdResults,
5152
uint32_t maxResults) const {
5253
MOZ_ASSERT(maxResults >= 1);
5354

@@ -63,7 +64,9 @@ uint32_t IonEntry::callStackAtAddr(void* ptr, const char** results,
6364
locationIter.readNext(&scriptIdx, &pcOffset);
6465
MOZ_ASSERT(getStr(scriptIdx));
6566

66-
results[count++] = getStr(scriptIdx);
67+
labelResults[count] = getStr(scriptIdx);
68+
sourceIdResults[count] = getScriptSource(scriptIdx).scriptSource->id();
69+
count++;
6770
if (count >= maxResults) {
6871
break;
6972
}
@@ -95,10 +98,12 @@ static IonEntry& IonEntryForIonIC(JSRuntime* rt, const IonICEntry* icEntry) {
9598
void* IonICEntry::canonicalNativeAddrFor(void* ptr) const { return ptr; }
9699

97100
uint32_t IonICEntry::callStackAtAddr(JSRuntime* rt, void* ptr,
98-
const char** results,
101+
const char** labelResults,
102+
uint32_t* sourceIdResults,
99103
uint32_t maxResults) const {
100104
const IonEntry& entry = IonEntryForIonIC(rt, this);
101-
return entry.callStackAtAddr(rejoinAddr(), results, maxResults);
105+
return entry.callStackAtAddr(rejoinAddr(), labelResults, sourceIdResults,
106+
maxResults);
102107
}
103108

104109
uint64_t IonICEntry::realmID(JSRuntime* rt) const {
@@ -112,12 +117,14 @@ void* BaselineEntry::canonicalNativeAddrFor(void* ptr) const {
112117
return ptr;
113118
}
114119

115-
uint32_t BaselineEntry::callStackAtAddr(void* ptr, const char** results,
120+
uint32_t BaselineEntry::callStackAtAddr(void* ptr, const char** labelResults,
121+
uint32_t* sourceIdResults,
116122
uint32_t maxResults) const {
117123
MOZ_ASSERT(containsPointer(ptr));
118124
MOZ_ASSERT(maxResults >= 1);
119125

120-
results[0] = str();
126+
labelResults[0] = str();
127+
sourceIdResults[0] = scriptSource().scriptSource->id();
121128
return 1;
122129
}
123130

@@ -126,7 +133,8 @@ void* BaselineInterpreterEntry::canonicalNativeAddrFor(void* ptr) const {
126133
}
127134

128135
uint32_t BaselineInterpreterEntry::callStackAtAddr(void* ptr,
129-
const char** results,
136+
const char** labelResults,
137+
uint32_t* sourceIdResults,
130138
uint32_t maxResults) const {
131139
MOZ_CRASH("shouldn't be called for BaselineInterpreter entries");
132140
}
@@ -149,11 +157,13 @@ bool RealmIndependentSharedEntry::callStackAtAddr(
149157
}
150158

151159
uint32_t RealmIndependentSharedEntry::callStackAtAddr(
152-
void* ptr, const char** results, uint32_t maxResults) const {
160+
void* ptr, const char** labelResults, uint32_t* sourceIdResults,
161+
uint32_t maxResults) const {
153162
MOZ_ASSERT(containsPointer(ptr));
154163
MOZ_ASSERT(maxResults >= 1);
155164

156-
results[0] = str();
165+
labelResults[0] = str();
166+
sourceIdResults[0] = 0;
157167
return 1;
158168
}
159169

@@ -329,22 +339,28 @@ bool JitcodeGlobalEntry::isJitcodeMarkedFromAnyThread(JSRuntime* rt) {
329339
}
330340

331341
uint32_t JitcodeGlobalEntry::callStackAtAddr(JSRuntime* rt, void* ptr,
332-
const char** results,
342+
const char** labelResults,
343+
uint32_t* sourceIdResults,
333344
uint32_t maxResults) const {
334345
switch (kind()) {
335346
case Kind::Ion:
336-
return asIon().callStackAtAddr(ptr, results, maxResults);
347+
return asIon().callStackAtAddr(ptr, labelResults, sourceIdResults,
348+
maxResults);
337349
case Kind::IonIC:
338-
return asIonIC().callStackAtAddr(rt, ptr, results, maxResults);
350+
return asIonIC().callStackAtAddr(rt, ptr, labelResults, sourceIdResults,
351+
maxResults);
339352
case Kind::Baseline:
340-
return asBaseline().callStackAtAddr(ptr, results, maxResults);
353+
return asBaseline().callStackAtAddr(ptr, labelResults, sourceIdResults,
354+
maxResults);
341355
case Kind::BaselineInterpreter:
342-
return asBaselineInterpreter().callStackAtAddr(ptr, results, maxResults);
356+
return asBaselineInterpreter().callStackAtAddr(
357+
ptr, labelResults, sourceIdResults, maxResults);
343358
case Kind::Dummy:
344-
return asDummy().callStackAtAddr(rt, ptr, results, maxResults);
359+
return asDummy().callStackAtAddr(rt, ptr, labelResults, sourceIdResults,
360+
maxResults);
345361
case Kind::RealmIndependentShared:
346-
return asRealmIndependentShared().callStackAtAddr(ptr, results,
347-
maxResults);
362+
return asRealmIndependentShared().callStackAtAddr(
363+
ptr, labelResults, sourceIdResults, maxResults);
348364
}
349365
MOZ_CRASH("Invalid kind");
350366
}
@@ -957,12 +973,13 @@ bool JitcodeIonTable::WriteIonTable(CompactBufferWriter& writer,
957973
JS::ProfiledFrameHandle::ProfiledFrameHandle(JSRuntime* rt,
958974
js::jit::JitcodeGlobalEntry& entry,
959975
void* addr, const char* label,
960-
uint32_t depth)
976+
uint32_t sourceId, uint32_t depth)
961977
: rt_(rt),
962978
entry_(entry),
963979
addr_(addr),
964980
canonicalAddr_(nullptr),
965981
label_(label),
982+
sourceId_(sourceId),
966983
depth_(depth) {
967984
if (!canonicalAddr_) {
968985
canonicalAddr_ = entry_.canonicalNativeAddrFor(rt_, addr_);
@@ -987,6 +1004,10 @@ JS_PUBLIC_API uint64_t JS::ProfiledFrameHandle::realmID() const {
9871004
return entry_.realmID(rt_);
9881005
}
9891006

1007+
JS_PUBLIC_API uint32_t JS::ProfiledFrameHandle::sourceId() const {
1008+
return sourceId_;
1009+
}
1010+
9901011
JS_PUBLIC_API JS::ProfiledFrameRange JS::GetProfiledFrames(JSContext* cx,
9911012
void* addr) {
9921013
JSRuntime* rt = cx->runtime();
@@ -997,8 +1018,8 @@ JS_PUBLIC_API JS::ProfiledFrameRange JS::GetProfiledFrames(JSContext* cx,
9971018
ProfiledFrameRange result(rt, addr, entry);
9981019

9991020
if (entry) {
1000-
result.depth_ = entry->callStackAtAddr(rt, addr, result.labels_,
1001-
std::size(result.labels_));
1021+
result.depth_ = entry->callStackAtAddr(
1022+
rt, addr, result.labels_, result.sourceIds_, std::size(result.labels_));
10021023
}
10031024
return result;
10041025
}
@@ -1008,5 +1029,6 @@ JS::ProfiledFrameHandle JS::ProfiledFrameRange::Iter::operator*() const {
10081029
// and the depth we need to pass to ProfiledFrameHandle goes down.
10091030
uint32_t depth = range_.depth_ - 1 - index_;
10101031
return ProfiledFrameHandle(range_.rt_, *range_.entry_, range_.addr_,
1011-
range_.labels_[depth], depth);
1032+
range_.labels_[depth], range_.sourceIds_[depth],
1033+
depth);
10121034
}

js/src/jit/JitcodeMap.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,10 @@ class JitcodeGlobalEntry : public JitCodeRange {
195195
void* canonicalNativeAddrFor(JSRuntime* rt, void* ptr) const;
196196

197197
// Read the inline call stack at a given point in the native code and append
198-
// into the given results buffer. Innermost (script,pc) pair will be appended
199-
// first, and outermost appended last.
200-
uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** results,
198+
// into the given results buffer. Innermost script will be appended first, and
199+
// outermost appended last.
200+
uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** labelResults,
201+
uint32_t* sourceIdResults,
201202
uint32_t maxResults) const;
202203
};
203204

@@ -285,7 +286,8 @@ class IonEntry : public JitcodeGlobalEntry {
285286

286287
void* canonicalNativeAddrFor(void* ptr) const;
287288

288-
uint32_t callStackAtAddr(void* ptr, const char** results,
289+
uint32_t callStackAtAddr(void* ptr, const char** labelResults,
290+
uint32_t* sourceIdResults,
289291
uint32_t maxResults) const;
290292

291293
uint64_t realmID() const { return realmId_; }
@@ -310,7 +312,8 @@ class IonICEntry : public JitcodeGlobalEntry {
310312

311313
void* canonicalNativeAddrFor(void* ptr) const;
312314

313-
uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** results,
315+
uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** labelResults,
316+
uint32_t* sourceIdResults,
314317
uint32_t maxResults) const;
315318

316319
uint64_t realmID(JSRuntime* rt) const;
@@ -340,7 +343,8 @@ class BaselineEntry : public JitcodeGlobalEntry {
340343

341344
void* canonicalNativeAddrFor(void* ptr) const;
342345

343-
uint32_t callStackAtAddr(void* ptr, const char** results,
346+
uint32_t callStackAtAddr(void* ptr, const char** labelResults,
347+
uint32_t* sourceIdResults,
344348
uint32_t maxResults) const;
345349

346350
uint64_t realmID() const { return realmId_; }
@@ -367,7 +371,8 @@ class RealmIndependentSharedEntry : public JitcodeGlobalEntry {
367371
[[nodiscard]] bool callStackAtAddr(void* ptr, BytecodeLocationVector& results,
368372
uint32_t* depth) const;
369373

370-
uint32_t callStackAtAddr(void* ptr, const char** results,
374+
uint32_t callStackAtAddr(void* ptr, const char** labelResults,
375+
uint32_t* sourceIdResults,
371376
uint32_t maxResults) const;
372377

373378
uint64_t realmID() const;
@@ -382,7 +387,8 @@ class BaselineInterpreterEntry : public JitcodeGlobalEntry {
382387

383388
void* canonicalNativeAddrFor(void* ptr) const;
384389

385-
uint32_t callStackAtAddr(void* ptr, const char** results,
390+
uint32_t callStackAtAddr(void* ptr, const char** labelResults,
391+
uint32_t* sourceIdResults,
386392
uint32_t maxResults) const;
387393

388394
uint64_t realmID() const;
@@ -400,7 +406,8 @@ class DummyEntry : public JitcodeGlobalEntry {
400406
return nullptr;
401407
}
402408

403-
uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** results,
409+
uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** labelResults,
410+
uint32_t* sourceIdResults,
404411
uint32_t maxResults) const {
405412
return 0;
406413
}

js/src/vm/Stack.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,16 +764,18 @@ uint32_t JS::ProfilingFrameIterator::extractStack(Frame* frames,
764764

765765
// Extract the stack for the entry. Assume maximum inlining depth is <64
766766
const char* labels[64];
767+
uint32_t sourceIds[64];
767768
uint32_t depth = entry->callStackAtAddr(cx_->runtime(),
768769
jsJitIter().resumePCinCurrentFrame(),
769-
labels, std::size(labels));
770+
labels, sourceIds, std::size(labels));
770771
MOZ_ASSERT(depth < std::size(labels));
771772
for (uint32_t i = 0; i < depth; i++) {
772773
if (offset + i >= end) {
773774
return i;
774775
}
775776
frames[offset + i] = physicalFrame.value();
776777
frames[offset + i].label = labels[i];
778+
frames[offset + i].sourceId = sourceIds[i];
777779
}
778780

779781
return depth;

tools/profiler/core/ProfileBuffer.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ class ProfileBuffer final {
5959
// for the given thread.
6060
void AddJITInfoForRange(uint64_t aRangeStart, ProfilerThreadId aThreadId,
6161
JSContext* aContext, JITFrameInfo& aJITFrameInfo,
62-
mozilla::ProgressLogger aProgressLogger) const;
62+
mozilla::ProgressLogger aProgressLogger,
63+
const nsTHashMap<SourceId, IndexIntoSourceTable>*
64+
aSourceIdToIndexMap = nullptr) const;
6365

6466
// Stream JSON for samples in the buffer to aWriter, using the supplied
6567
// UniqueStacks object.

tools/profiler/core/ProfileBufferEntry.cpp

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,9 @@ void UniqueStacks::StreamNonJITFrame(const FrameKey& aFrame) {
549549

550550
static void StreamJITFrame(JSContext* aContext, SpliceableJSONWriter& aWriter,
551551
UniqueJSONStrings& aUniqueStrings,
552-
const JS::ProfiledFrameHandle& aJITFrame) {
552+
const JS::ProfiledFrameHandle& aJITFrame,
553+
const nsTHashMap<SourceId, IndexIntoSourceTable>*
554+
aSourceIdToIndexMap = nullptr) {
553555
enum Schema : uint32_t {
554556
LOCATION = 0,
555557
RELEVANT_FOR_JS = 1,
@@ -563,7 +565,18 @@ static void StreamJITFrame(JSContext* aContext, SpliceableJSONWriter& aWriter,
563565

564566
AutoArraySchemaWithStringsWriter writer(aWriter, aUniqueStrings);
565567

566-
writer.StringElement(LOCATION, MakeStringSpan(aJITFrame.label()));
568+
uint32_t sourceId = aJITFrame.sourceId();
569+
nsCString labelWithSourceIndex(aJITFrame.label());
570+
if (sourceId && aSourceIdToIndexMap) {
571+
auto index = aSourceIdToIndexMap->MaybeGet(sourceId);
572+
if (index) {
573+
labelWithSourceIndex.AppendLiteral("[");
574+
labelWithSourceIndex.AppendInt(*index);
575+
labelWithSourceIndex.AppendLiteral("]");
576+
}
577+
}
578+
writer.StringElement(LOCATION, labelWithSourceIndex);
579+
567580
writer.BoolElement(RELEVANT_FOR_JS, false);
568581

569582
// It's okay to convert uint64_t to double here because DOM always creates IDs
@@ -587,20 +600,24 @@ static void StreamJITFrame(JSContext* aContext, SpliceableJSONWriter& aWriter,
587600
writer.IntElement(SUBCATEGORY, info.mSubcategoryIndex);
588601
}
589602

590-
static nsCString JSONForJITFrame(JSContext* aContext,
591-
const JS::ProfiledFrameHandle& aJITFrame,
592-
UniqueJSONStrings& aUniqueStrings) {
603+
static nsCString JSONForJITFrame(
604+
JSContext* aContext, const JS::ProfiledFrameHandle& aJITFrame,
605+
UniqueJSONStrings& aUniqueStrings,
606+
const nsTHashMap<SourceId, IndexIntoSourceTable>* aSourceIdToIndexMap =
607+
nullptr) {
593608
nsCString json;
594609
JSONStringRefWriteFunc jw(json);
595610
SpliceableJSONWriter writer(jw, aUniqueStrings.SourceFailureLatch());
596-
StreamJITFrame(aContext, writer, aUniqueStrings, aJITFrame);
611+
StreamJITFrame(aContext, writer, aUniqueStrings, aJITFrame,
612+
aSourceIdToIndexMap);
597613
return json;
598614
}
599615

600616
void JITFrameInfo::AddInfoForRange(
601617
uint64_t aRangeStart, uint64_t aRangeEnd, JSContext* aCx,
602618
const std::function<void(const std::function<void(void*)>&)>&
603-
aJITAddressProvider) {
619+
aJITAddressProvider,
620+
const nsTHashMap<SourceId, IndexIntoSourceTable>* aSourceIdToIndexMap) {
604621
if (mLocalFailureLatchSource.Failed()) {
605622
return;
606623
}
@@ -635,7 +652,8 @@ void JITFrameInfo::AddInfoForRange(
635652
if (!frameEntry) {
636653
if (!jitFrameToFrameJSONMap.add(
637654
frameEntry, jitFrameKey,
638-
JSONForJITFrame(aCx, handle, *mUniqueStrings))) {
655+
JSONForJITFrame(aCx, handle, *mUniqueStrings,
656+
aSourceIdToIndexMap))) {
639657
mLocalFailureLatchSource.SetFailure(
640658
"OOM in JITFrameInfo::AddInfoForRange adding jit->frame map");
641659
return;
@@ -1742,8 +1760,9 @@ void ProfileBuffer::StreamSamplesAndMarkersToJSON(
17421760

17431761
void ProfileBuffer::AddJITInfoForRange(
17441762
uint64_t aRangeStart, ProfilerThreadId aThreadId, JSContext* aContext,
1745-
JITFrameInfo& aJITFrameInfo,
1746-
mozilla::ProgressLogger aProgressLogger) const {
1763+
JITFrameInfo& aJITFrameInfo, mozilla::ProgressLogger aProgressLogger,
1764+
const nsTHashMap<SourceId, IndexIntoSourceTable>* aSourceIdToIndexMap)
1765+
const {
17471766
// We can only process JitReturnAddr entries if we have a JSContext.
17481767
MOZ_RELEASE_ASSERT(aContext);
17491768

@@ -1837,7 +1856,8 @@ void ProfileBuffer::AddJITInfoForRange(
18371856
}
18381857
}
18391858
});
1840-
});
1859+
},
1860+
aSourceIdToIndexMap);
18411861
}
18421862

18431863
void ProfileBuffer::StreamMarkersToJSON(

0 commit comments

Comments
 (0)