commit edc1a996fb42b1106098c9604a263285a247098c
parent 597a75d7a4231d5d85a3d0b55b0c7b4cec9b691f
Author: Nazım Can Altınova <canaltinova@gmail.com>
Date: Wed, 26 Nov 2025 10:52:44 +0000
Bug 2002397 - Add CallStackFrameInfo struct for the JitcodeGlobalEntry::callStackAtAddr return values r=iain
Previously, we were returning multiple return arguments for the label
and sourceId return values. It's better to use a struct to return a
single argument with these values instead, so it'll be easier to extend
in the future.
I would like to add line/column information for the stack frames in the
later patches. That's why having this will be beneficial for that patch.
Differential Revision: https://phabricator.services.mozilla.com/D274056
Diffstat:
4 files changed, 52 insertions(+), 58 deletions(-)
diff --git a/js/public/ProfilingFrameIterator.h b/js/public/ProfilingFrameIterator.h
@@ -23,6 +23,17 @@ namespace jit {
class JitActivation;
class JSJitProfilingFrameIterator;
class JitcodeGlobalEntry;
+
+// Information about a single frame in a JIT call stack, returned by
+// JitcodeGlobalEntry::callStackAtAddr.
+struct CallStackFrameInfo {
+ // The function name or label for this frame.
+ const char* label;
+ // The script source ID for this frame. Used to identify which script source
+ // this frame belongs to.
+ uint32_t sourceId;
+};
+
} // namespace jit
namespace wasm {
class ProfilingFrameIterator;
@@ -295,8 +306,7 @@ class ProfiledFrameRange {
void* addr_;
js::jit::JitcodeGlobalEntry* entry_;
// Assume maximum inlining depth is <64
- const char* labels_[64];
- uint32_t sourceIds_[64];
+ js::jit::CallStackFrameInfo frames_[64];
uint32_t depth_;
};
diff --git a/js/src/jit/JitcodeMap.cpp b/js/src/jit/JitcodeMap.cpp
@@ -45,8 +45,7 @@ void* IonEntry::canonicalNativeAddrFor(void* ptr) const {
return (void*)(((uint8_t*)nativeStartAddr()) + region.nativeOffset());
}
-uint32_t IonEntry::callStackAtAddr(void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+uint32_t IonEntry::callStackAtAddr(void* ptr, CallStackFrameInfo* results,
uint32_t maxResults) const {
MOZ_ASSERT(maxResults >= 1);
@@ -62,8 +61,8 @@ uint32_t IonEntry::callStackAtAddr(void* ptr, const char** labelResults,
locationIter.readNext(&scriptIdx, &pcOffset);
MOZ_ASSERT(getStr(scriptIdx));
- labelResults[count] = getStr(scriptIdx);
- sourceIdResults[count] = getScriptSource(scriptIdx).scriptSource->id();
+ results[count].label = getStr(scriptIdx);
+ results[count].sourceId = getScriptSource(scriptIdx).scriptSource->id();
count++;
if (count >= maxResults) {
break;
@@ -96,12 +95,10 @@ static IonEntry& IonEntryForIonIC(JSRuntime* rt, const IonICEntry* icEntry) {
void* IonICEntry::canonicalNativeAddrFor(void* ptr) const { return ptr; }
uint32_t IonICEntry::callStackAtAddr(JSRuntime* rt, void* ptr,
- const char** labelResults,
- uint32_t* sourceIdResults,
+ CallStackFrameInfo* results,
uint32_t maxResults) const {
const IonEntry& entry = IonEntryForIonIC(rt, this);
- return entry.callStackAtAddr(rejoinAddr(), labelResults, sourceIdResults,
- maxResults);
+ return entry.callStackAtAddr(rejoinAddr(), results, maxResults);
}
uint64_t IonICEntry::realmID(JSRuntime* rt) const {
@@ -115,14 +112,13 @@ void* BaselineEntry::canonicalNativeAddrFor(void* ptr) const {
return ptr;
}
-uint32_t BaselineEntry::callStackAtAddr(void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+uint32_t BaselineEntry::callStackAtAddr(void* ptr, CallStackFrameInfo* results,
uint32_t maxResults) const {
MOZ_ASSERT(containsPointer(ptr));
MOZ_ASSERT(maxResults >= 1);
- labelResults[0] = str();
- sourceIdResults[0] = scriptSource().scriptSource->id();
+ results[0].label = str();
+ results[0].sourceId = scriptSource().scriptSource->id();
return 1;
}
@@ -131,8 +127,7 @@ void* BaselineInterpreterEntry::canonicalNativeAddrFor(void* ptr) const {
}
uint32_t BaselineInterpreterEntry::callStackAtAddr(void* ptr,
- const char** labelResults,
- uint32_t* sourceIdResults,
+ CallStackFrameInfo* results,
uint32_t maxResults) const {
MOZ_CRASH("shouldn't be called for BaselineInterpreter entries");
}
@@ -155,13 +150,12 @@ bool RealmIndependentSharedEntry::callStackAtAddr(
}
uint32_t RealmIndependentSharedEntry::callStackAtAddr(
- void* ptr, const char** labelResults, uint32_t* sourceIdResults,
- uint32_t maxResults) const {
+ void* ptr, CallStackFrameInfo* results, uint32_t maxResults) const {
MOZ_ASSERT(containsPointer(ptr));
MOZ_ASSERT(maxResults >= 1);
- labelResults[0] = str();
- sourceIdResults[0] = 0;
+ results[0].label = str();
+ results[0].sourceId = 0;
return 1;
}
@@ -337,28 +331,22 @@ bool JitcodeGlobalEntry::isJitcodeMarkedFromAnyThread(JSRuntime* rt) {
}
uint32_t JitcodeGlobalEntry::callStackAtAddr(JSRuntime* rt, void* ptr,
- const char** labelResults,
- uint32_t* sourceIdResults,
+ CallStackFrameInfo* results,
uint32_t maxResults) const {
switch (kind()) {
case Kind::Ion:
- return asIon().callStackAtAddr(ptr, labelResults, sourceIdResults,
- maxResults);
+ return asIon().callStackAtAddr(ptr, results, maxResults);
case Kind::IonIC:
- return asIonIC().callStackAtAddr(rt, ptr, labelResults, sourceIdResults,
- maxResults);
+ return asIonIC().callStackAtAddr(rt, ptr, results, maxResults);
case Kind::Baseline:
- return asBaseline().callStackAtAddr(ptr, labelResults, sourceIdResults,
- maxResults);
+ return asBaseline().callStackAtAddr(ptr, results, maxResults);
case Kind::BaselineInterpreter:
- return asBaselineInterpreter().callStackAtAddr(
- ptr, labelResults, sourceIdResults, maxResults);
+ return asBaselineInterpreter().callStackAtAddr(ptr, results, maxResults);
case Kind::Dummy:
- return asDummy().callStackAtAddr(rt, ptr, labelResults, sourceIdResults,
- maxResults);
+ return asDummy().callStackAtAddr(rt, ptr, results, maxResults);
case Kind::RealmIndependentShared:
- return asRealmIndependentShared().callStackAtAddr(
- ptr, labelResults, sourceIdResults, maxResults);
+ return asRealmIndependentShared().callStackAtAddr(ptr, results,
+ maxResults);
}
MOZ_CRASH("Invalid kind");
}
@@ -1016,8 +1004,8 @@ JS_PUBLIC_API JS::ProfiledFrameRange JS::GetProfiledFrames(JSContext* cx,
ProfiledFrameRange result(rt, addr, entry);
if (entry) {
- result.depth_ = entry->callStackAtAddr(
- rt, addr, result.labels_, result.sourceIds_, std::size(result.labels_));
+ result.depth_ = entry->callStackAtAddr(rt, addr, result.frames_,
+ std::size(result.frames_));
}
return result;
}
@@ -1027,6 +1015,6 @@ JS::ProfiledFrameHandle JS::ProfiledFrameRange::Iter::operator*() const {
// and the depth we need to pass to ProfiledFrameHandle goes down.
uint32_t depth = range_.depth_ - 1 - index_;
return ProfiledFrameHandle(range_.rt_, *range_.entry_, range_.addr_,
- range_.labels_[depth], range_.sourceIds_[depth],
- depth);
+ range_.frames_[depth].label,
+ range_.frames_[depth].sourceId, depth);
}
diff --git a/js/src/jit/JitcodeMap.h b/js/src/jit/JitcodeMap.h
@@ -16,6 +16,7 @@
#include "jit/CompactBuffer.h" // CompactBufferReader, CompactBufferWriter
#include "jit/shared/Assembler-shared.h" // CodeOffset
#include "js/AllocPolicy.h" // SystemAllocPolicy
+#include "js/ProfilingFrameIterator.h" // CallStackFrameInfo
#include "js/TypeDecls.h" // jsbytecode
#include "js/Vector.h" // Vector
#include "vm/BytecodeLocation.h" // BytecodeLocation
@@ -197,8 +198,8 @@ class JitcodeGlobalEntry : public JitCodeRange {
// Read the inline call stack at a given point in the native code and append
// into the given results buffer. Innermost script will be appended first, and
// outermost appended last.
- uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(JSRuntime* rt, void* ptr,
+ CallStackFrameInfo* results,
uint32_t maxResults) const;
};
@@ -286,8 +287,7 @@ class IonEntry : public JitcodeGlobalEntry {
void* canonicalNativeAddrFor(void* ptr) const;
- uint32_t callStackAtAddr(void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(void* ptr, CallStackFrameInfo* results,
uint32_t maxResults) const;
uint64_t realmID() const { return realmId_; }
@@ -312,8 +312,8 @@ class IonICEntry : public JitcodeGlobalEntry {
void* canonicalNativeAddrFor(void* ptr) const;
- uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(JSRuntime* rt, void* ptr,
+ CallStackFrameInfo* results,
uint32_t maxResults) const;
uint64_t realmID(JSRuntime* rt) const;
@@ -343,8 +343,7 @@ class BaselineEntry : public JitcodeGlobalEntry {
void* canonicalNativeAddrFor(void* ptr) const;
- uint32_t callStackAtAddr(void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(void* ptr, CallStackFrameInfo* results,
uint32_t maxResults) const;
uint64_t realmID() const { return realmId_; }
@@ -371,8 +370,7 @@ class RealmIndependentSharedEntry : public JitcodeGlobalEntry {
[[nodiscard]] bool callStackAtAddr(void* ptr, BytecodeLocationVector& results,
uint32_t* depth) const;
- uint32_t callStackAtAddr(void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(void* ptr, CallStackFrameInfo* results,
uint32_t maxResults) const;
uint64_t realmID() const;
@@ -387,8 +385,7 @@ class BaselineInterpreterEntry : public JitcodeGlobalEntry {
void* canonicalNativeAddrFor(void* ptr) const;
- uint32_t callStackAtAddr(void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(void* ptr, CallStackFrameInfo* results,
uint32_t maxResults) const;
uint64_t realmID() const;
@@ -406,8 +403,8 @@ class DummyEntry : public JitcodeGlobalEntry {
return nullptr;
}
- uint32_t callStackAtAddr(JSRuntime* rt, void* ptr, const char** labelResults,
- uint32_t* sourceIdResults,
+ uint32_t callStackAtAddr(JSRuntime* rt, void* ptr,
+ CallStackFrameInfo* results,
uint32_t maxResults) const {
return 0;
}
diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp
@@ -762,19 +762,18 @@ uint32_t JS::ProfilingFrameIterator::extractStack(Frame* frames,
}
// Extract the stack for the entry. Assume maximum inlining depth is <64
- const char* labels[64];
- uint32_t sourceIds[64];
+ jit::CallStackFrameInfo frameInfos[64];
uint32_t depth = entry->callStackAtAddr(cx_->runtime(),
jsJitIter().resumePCinCurrentFrame(),
- labels, sourceIds, std::size(labels));
- MOZ_ASSERT(depth < std::size(labels));
+ frameInfos, std::size(frameInfos));
+ MOZ_ASSERT(depth < std::size(frameInfos));
for (uint32_t i = 0; i < depth; i++) {
if (offset + i >= end) {
return i;
}
frames[offset + i] = physicalFrame.value();
- frames[offset + i].label = labels[i];
- frames[offset + i].sourceId = sourceIds[i];
+ frames[offset + i].label = frameInfos[i].label;
+ frames[offset + i].sourceId = frameInfos[i].sourceId;
}
return depth;