diff --git a/dom/base/DOMArena.h b/dom/base/DOMArena.h index 3f6d3c680ca0..4ea0b81a67ac 100644 --- a/dom/base/DOMArena.h +++ b/dom/base/DOMArena.h @@ -10,6 +10,7 @@ #include "mozmemory.h" #include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom +#include "nsString.h" #define NS_DECL_DOMARENA_DESTROY void Destroy(void); @@ -34,10 +35,13 @@ namespace mozilla::dom { class DOMArena { public: friend class DocGroup; - DOMArena() { + explicit DOMArena(const nsACString& aLabel) { + nsCString label = PromiseFlatCString("DOMArena "_ns + aLabel); + arena_params_t params; params.mMaxDirtyIncreaseOverride = 7; params.mFlags = ARENA_FLAG_THREAD_MAIN_THREAD_ONLY; + params.mLabel = label.get(); mArenaId = moz_create_arena_with_params(¶ms); } diff --git a/dom/base/DocGroup.cpp b/dom/base/DocGroup.cpp index bbe28afe7d4c..19781ff158a9 100644 --- a/dom/base/DocGroup.cpp +++ b/dom/base/DocGroup.cpp @@ -128,7 +128,7 @@ DocGroup::DocGroup(BrowsingContextGroup* aBrowsingContextGroup, // mBrowsingContextGroup->mDocGroups as the caller does it for us. MOZ_ASSERT(NS_IsMainThread()); if (StaticPrefs::dom_arena_allocator_enabled_AtStartup()) { - mArena = new mozilla::dom::DOMArena(); + mArena = new mozilla::dom::DOMArena(aKey.mKey); } } diff --git a/js/src/util/Utility.cpp b/js/src/util/Utility.cpp index fae1ea64ce85..b7b67d0e3d17 100644 --- a/js/src/util/Utility.cpp +++ b/js/src/util/Utility.cpp @@ -101,13 +101,16 @@ JS_PUBLIC_DATA arena_id_t js::StringBufferArena; void js::InitMallocAllocator() { arena_params_t mallocArenaParams; mallocArenaParams.mMaxDirtyIncreaseOverride = 5; + mallocArenaParams.mLabel = "JS malloc"; MallocArena = moz_create_arena_with_params(&mallocArenaParams); BackgroundMallocArena = moz_create_arena_with_params(&mallocArenaParams); arena_params_t params; params.mMaxDirtyIncreaseOverride = 5; params.mFlags |= ARENA_FLAG_RANDOMIZE_SMALL_ENABLED; + params.mLabel = "Array buffer contents"; ArrayBufferContentsArena = moz_create_arena_with_params(¶ms); + params.mLabel = "String buffer contents"; StringBufferArena = moz_create_arena_with_params(¶ms); } diff --git a/memory/build/mozjemalloc.cpp b/memory/build/mozjemalloc.cpp index ce713eebf4e3..026e1a35de72 100644 --- a/memory/build/mozjemalloc.cpp +++ b/memory/build/mozjemalloc.cpp @@ -1298,6 +1298,12 @@ struct arena_t { // released after a concurrent purge completes. bool mMustDeleteAfterPurge MOZ_GUARDED_BY(mLock) = false; + // mLabel describes the label for the firefox profiler. It's stored in a + // fixed size area including a null terminating byte. The actual maximum + // length of the string is one less than LABEL_MAX_CAPACITY; + static constexpr size_t LABEL_MAX_CAPACITY = 128; + char mLabel[LABEL_MAX_CAPACITY]; + private: // Size/address-ordered tree of this arena's available runs. This tree // is used for first-best-fit run allocation. @@ -1592,6 +1598,7 @@ class ArenaCollection { arena_params_t params; // The main arena allows more dirty pages than the default for other arenas. params.mMaxDirty = opt_dirty_max; + params.mLabel = "Default"; mDefaultArena = mLock.Init() ? CreateArena(/* aIsPrivate = */ false, ¶ms) : nullptr; mPurgeListLock.Init(); @@ -2940,8 +2947,9 @@ static inline arena_t* thread_local_arena(bool enabled) { // called with `false`, but it doesn't matter at the moment. // because in practice nothing actually calls this function // with `false`, except maybe at shutdown. - arena = - gArenas.CreateArena(/* aIsPrivate = */ false, /* aParams = */ nullptr); + arena_params_t params; + params.mLabel = "Thread local"; + arena = gArenas.CreateArena(/* aIsPrivate = */ false, ¶ms); } else { arena = gArenas.GetDefault(); } @@ -5004,9 +5012,22 @@ arena_t::arena_t(arena_params_t* aParams, bool aIsPrivate) { mMaxDirtyIncreaseOverride = aParams->mMaxDirtyIncreaseOverride; mMaxDirtyDecreaseOverride = aParams->mMaxDirtyDecreaseOverride; + + if (aParams->mLabel) { + // The string may be truncated so always place a null-byte in the last + // position. + strncpy(mLabel, aParams->mLabel, LABEL_MAX_CAPACITY - 1); + mLabel[LABEL_MAX_CAPACITY - 1] = 0; + // In debug builds we assert if the string needed truncating. + MOZ_ASSERT(strlen(aParams->mLabel) < LABEL_MAX_CAPACITY); + } else { + mLabel[0] = 0; + } } else { mMaxDirtyIncreaseOverride = 0; mMaxDirtyDecreaseOverride = 0; + + mLabel[0] = 0; } mLastSignificantReuseNS = GetTimestampNS(); diff --git a/memory/build/mozjemalloc_types.h b/memory/build/mozjemalloc_types.h index 1a0ad44a210f..678ed4749bc7 100644 --- a/memory/build/mozjemalloc_types.h +++ b/memory/build/mozjemalloc_types.h @@ -82,12 +82,17 @@ typedef struct arena_params_s { uint32_t mFlags; + // The label will be copied into fixed-size storage (currently 128 bytes) + // within the arena. It may be null for unamed arenas + const char* mLabel; + #ifdef __cplusplus arena_params_s() : mMaxDirty(0), mMaxDirtyIncreaseOverride(0), mMaxDirtyDecreaseOverride(0), - mFlags(0) {} + mFlags(0), + mLabel(nullptr) {} #endif } arena_params_t;