--- a/js/public/ProfilingStack.h
+++ b/js/public/ProfilingStack.h
@@ -140,18 +140,17 @@ class ProfilingStackFrame
mozilla::Atomic<const char*, mozilla::ReleaseAcquire> dynamicString_;
// Stack pointer for non-JS stack frames, the script pointer otherwise.
mozilla::Atomic<void*, mozilla::ReleaseAcquire> spOrScript;
// Line number for non-JS stack frames, the bytecode offset otherwise.
mozilla::Atomic<int32_t, mozilla::ReleaseAcquire> lineOrPcOffset;
- // Bits 0...1 hold the Kind. Bits 2...3 are unused. Bits 4...12 hold the
- // Category.
+ // Bits 0...1 hold the Kind. Bits 2...31 hold the category.
mozilla::Atomic<uint32_t, mozilla::ReleaseAcquire> kindAndCategory_;
static int32_t pcToOffset(JSScript* aScript, jsbytecode* aPc);
public:
ProfilingStackFrame() = default;
ProfilingStackFrame& operator=(const ProfilingStackFrame& other)
{
@@ -180,39 +179,38 @@ class ProfilingStackFrame
// A normal JS frame.
JS_NORMAL = 2,
// An interpreter JS frame that has OSR-ed into baseline. JS_NORMAL
// frames can be converted to JS_OSR and back. JS_OSR frames are
// ignored.
JS_OSR = 3,
- KIND_MASK = 0x3,
+ KIND_BITCOUNT = 2,
+ KIND_MASK = (1 << KIND_BITCOUNT) - 1
};
// Keep these in sync with devtools/client/performance/modules/categories.js
enum class Category : uint32_t {
- OTHER = 1u << 4,
- CSS = 1u << 5,
- JS = 1u << 6,
- GC = 1u << 7,
- CC = 1u << 8,
- NETWORK = 1u << 9,
- GRAPHICS = 1u << 10,
- STORAGE = 1u << 11,
- EVENTS = 1u << 12,
+ OTHER,
+ CSS,
+ JS,
+ GC,
+ CC,
+ NETWORK,
+ GRAPHICS,
+ STORAGE,
+ EVENTS,
FIRST = OTHER,
LAST = EVENTS,
-
- CATEGORY_MASK = ~uint32_t(Kind::KIND_MASK),
};
- static_assert((uint32_t(Category::FIRST) & uint32_t(Kind::KIND_MASK)) == 0,
- "Category overlaps with Kind");
+ static_assert(uint32_t(Category::LAST) <= (UINT32_MAX >> uint32_t(Kind::KIND_BITCOUNT)),
+ "Too many categories to fit into u32 with two bits reserved for the kind");
bool isLabelFrame() const
{
return kind() == Kind::LABEL;
}
bool isSpMarkerFrame() const
{
@@ -232,51 +230,51 @@ class ProfilingStackFrame
void initLabelFrame(const char* aLabel, const char* aDynamicString, void* sp,
uint32_t aLine, Category aCategory)
{
label_ = aLabel;
dynamicString_ = aDynamicString;
spOrScript = sp;
lineOrPcOffset = static_cast<int32_t>(aLine);
- kindAndCategory_ = uint32_t(Kind::LABEL) | uint32_t(aCategory);
+ kindAndCategory_ = uint32_t(Kind::LABEL) | (uint32_t(aCategory) << uint32_t(Kind::KIND_BITCOUNT));
MOZ_ASSERT(isLabelFrame());
}
void initSpMarkerFrame(void* sp)
{
label_ = "";
dynamicString_ = nullptr;
spOrScript = sp;
lineOrPcOffset = 0;
- kindAndCategory_ = uint32_t(Kind::SP_MARKER) | uint32_t(ProfilingStackFrame::Category::OTHER);
+ kindAndCategory_ = uint32_t(Kind::SP_MARKER) | (uint32_t(Category::OTHER) << uint32_t(Kind::KIND_BITCOUNT));
MOZ_ASSERT(isSpMarkerFrame());
}
void initJsFrame(const char* aLabel, const char* aDynamicString, JSScript* aScript,
jsbytecode* aPc)
{
label_ = aLabel;
dynamicString_ = aDynamicString;
spOrScript = aScript;
lineOrPcOffset = pcToOffset(aScript, aPc);
- kindAndCategory_ = uint32_t(Kind::JS_NORMAL) | uint32_t(Category::JS);
+ kindAndCategory_ = uint32_t(Kind::JS_NORMAL) | (uint32_t(Category::JS) << uint32_t(Kind::KIND_BITCOUNT));
MOZ_ASSERT(isJsFrame());
}
void setKind(Kind aKind) {
- kindAndCategory_ = uint32_t(aKind) | uint32_t(category());
+ kindAndCategory_ = uint32_t(aKind) | (uint32_t(category()) << uint32_t(Kind::KIND_BITCOUNT));
}
Kind kind() const {
return Kind(kindAndCategory_ & uint32_t(Kind::KIND_MASK));
}
Category category() const {
- return Category(kindAndCategory_ & uint32_t(Category::CATEGORY_MASK));
+ return Category(kindAndCategory_ >> uint32_t(Kind::KIND_BITCOUNT));
}
void* stackAddress() const {
MOZ_ASSERT(!isJsFrame());
return spOrScript;
}
JS_PUBLIC_API(JSScript*) script() const;