mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 15:52:07 +00:00
Bug 1560188 - Fix and improve display list memory reporting. r=mattwoodrow,njn
I missed in bug 1487216 that the pres arena memory reporting assumes that the entry indices are frame class ids, which means that we're reporting some display list arena entries as frames, which is obviously wrong. Cleanup a bit nsPresArena to remove the custom id concept, and report also individual display item type memory usage. Differential Revision: https://phabricator.services.mozilla.com/D35368 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
b5e0d251ee
commit
d1a9b44ea6
@ -419,8 +419,52 @@ static void CollectWindowReports(nsGlobalWindowInner* aWindow,
|
||||
"Number of event listeners in a window, including event "
|
||||
"listeners on nodes and other event targets.");
|
||||
|
||||
REPORT_SIZE("/layout/line-boxes", mArenaSizes.mLineBoxes,
|
||||
"Memory used by line boxes within a window.");
|
||||
// There are many different kinds of frames, but it is very likely
|
||||
// that only a few matter. Implement a cutoff so we don't bloat
|
||||
// about:memory with many uninteresting entries.
|
||||
const size_t ARENA_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
size_t presArenaSundriesSize = 0;
|
||||
#define ARENA_OBJECT(name_, sundries_size_, prefix_) \
|
||||
{ \
|
||||
size_t size = windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_); \
|
||||
if (size < ARENA_SUNDRIES_THRESHOLD) { \
|
||||
sundries_size_ += size; \
|
||||
} else { \
|
||||
REPORT_SUM_SIZE(prefix_ #name_, size, \
|
||||
"Memory used by objects of type " #name_ \
|
||||
" within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(name_) += size; \
|
||||
}
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
ARENA_OBJECT(name_, presArenaSundriesSize, "/layout/pres-arena/")
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
|
||||
if (presArenaSundriesSize > 0) {
|
||||
REPORT_SUM_SIZE(
|
||||
"/layout/pres-arena/sundries", presArenaSundriesSize,
|
||||
"The sum of all memory used by objects in the arena which were too "
|
||||
"small to be shown individually.");
|
||||
}
|
||||
|
||||
size_t displayListArenaSundriesSize = 0;
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) \
|
||||
ARENA_OBJECT(name_, displayListArenaSundriesSize, \
|
||||
"/layout/display-list-arena/")
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
if (displayListArenaSundriesSize > 0) {
|
||||
REPORT_SUM_SIZE(
|
||||
"/layout/display-list-arena/sundries", displayListArenaSundriesSize,
|
||||
"The sum of all memory used by objects in the DL arena which were too "
|
||||
"small to be shown individually.");
|
||||
}
|
||||
|
||||
#undef ARENA_OBJECT
|
||||
|
||||
// There are many different kinds of style structs, but it is likely that
|
||||
// only a few matter. Implement a cutoff so we don't bloat about:memory with
|
||||
@ -428,38 +472,6 @@ static void CollectWindowReports(nsGlobalWindowInner* aWindow,
|
||||
const size_t STYLE_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
// There are many different kinds of frames, but it is very likely
|
||||
// that only a few matter. Implement a cutoff so we don't bloat
|
||||
// about:memory with many uninteresting entries.
|
||||
const size_t FRAME_SUNDRIES_THRESHOLD =
|
||||
js::MemoryReportingSundriesThreshold();
|
||||
|
||||
size_t frameSundriesSize = 0;
|
||||
#define FRAME_ID(classname, ...) \
|
||||
{ \
|
||||
size_t size = windowSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname); \
|
||||
if (size < FRAME_SUNDRIES_THRESHOLD) { \
|
||||
frameSundriesSize += size; \
|
||||
} else { \
|
||||
REPORT_SUM_SIZE("/layout/frames/" #classname, size, \
|
||||
"Memory used by frames of type " #classname \
|
||||
" within a window."); \
|
||||
} \
|
||||
aWindowTotalSizes->mArenaSizes.NS_ARENA_SIZES_FIELD(classname) += size; \
|
||||
}
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
if (frameSundriesSize > 0) {
|
||||
REPORT_SUM_SIZE(
|
||||
"/layout/frames/sundries", frameSundriesSize,
|
||||
"The sum of all memory used by frames which were too small to be shown "
|
||||
"individually.");
|
||||
}
|
||||
|
||||
// This is the style structs.
|
||||
size_t styleSundriesSize = 0;
|
||||
#define STYLE_STRUCT(name_) \
|
||||
{ \
|
||||
@ -641,21 +653,26 @@ nsWindowMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
REPORT("window-objects/property-tables", windowTotalSizes.mPropertyTablesSize,
|
||||
"This is the sum of all windows' 'property-tables' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/line-boxes",
|
||||
windowTotalSizes.mArenaSizes.mLineBoxes,
|
||||
"This is the sum of all windows' 'layout/line-boxes' numbers.");
|
||||
size_t presArenaTotal = 0;
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
presArenaTotal += windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_);
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
|
||||
size_t frameTotal = 0;
|
||||
#define FRAME_ID(classname, ...) \
|
||||
frameTotal += windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
REPORT("window-objects/layout/pres-arena", presArenaTotal,
|
||||
"Memory used for the pres arena within windows. "
|
||||
"This is the sum of all windows' 'layout/pres-arena/' numbers.");
|
||||
|
||||
REPORT("window-objects/layout/frames", frameTotal,
|
||||
"Memory used for layout frames within windows. "
|
||||
"This is the sum of all windows' 'layout/frames/' numbers.");
|
||||
size_t displayListArenaTotal = 0;
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) \
|
||||
displayListArenaTotal += \
|
||||
windowTotalSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_);
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
REPORT("window-objects/layout/display-list-arena", displayListArenaTotal,
|
||||
"Memory used for the display list arena within windows. This is the "
|
||||
"sum of all windows' 'layout/display-list-arena/' numbers.");
|
||||
|
||||
size_t styleTotal = 0;
|
||||
#define STYLE_STRUCT(name_) \
|
||||
|
@ -87,56 +87,49 @@ struct nsStyleSizes {
|
||||
#define NS_ARENA_SIZES_FIELD(classname) mArena##classname
|
||||
|
||||
struct nsArenaSizes {
|
||||
#define FOR_EACH_SIZE(MACRO) MACRO(Other, mLineBoxes)
|
||||
|
||||
nsArenaSizes()
|
||||
: FOR_EACH_SIZE(ZERO_SIZE)
|
||||
#define FRAME_ID(classname, ...) NS_ARENA_SIZES_FIELD(classname)(0),
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
dummy() {
|
||||
:
|
||||
#define PRES_ARENA_OBJECT(name_) NS_ARENA_SIZES_FIELD(name_)(0),
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
dummy() {
|
||||
}
|
||||
|
||||
void addToTabSizes(nsTabSizes* aSizes) const {
|
||||
FOR_EACH_SIZE(ADD_TO_TAB_SIZES)
|
||||
|
||||
#define FRAME_ID(classname, ...) \
|
||||
aSizes->add(nsTabSizes::Other, NS_ARENA_SIZES_FIELD(classname));
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
aSizes->add(nsTabSizes::Other, NS_ARENA_SIZES_FIELD(name_));
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
}
|
||||
|
||||
size_t getTotalSize() const {
|
||||
size_t total = 0;
|
||||
|
||||
FOR_EACH_SIZE(ADD_TO_TOTAL_SIZE)
|
||||
|
||||
#define FRAME_ID(classname, ...) total += NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
#define PRES_ARENA_OBJECT(name_) total += NS_ARENA_SIZES_FIELD(name_);
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
FOR_EACH_SIZE(DECL_SIZE)
|
||||
|
||||
#define FRAME_ID(classname, ...) size_t NS_ARENA_SIZES_FIELD(classname);
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
#define PRES_ARENA_OBJECT(name_) size_t NS_ARENA_SIZES_FIELD(name_);
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) PRES_ARENA_OBJECT(name_)
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
|
||||
// Present just to absorb the trailing comma in the constructor.
|
||||
int dummy;
|
||||
|
||||
#undef FOR_EACH_SIZE
|
||||
};
|
||||
|
||||
class nsWindowSizes {
|
||||
|
@ -14,12 +14,9 @@
|
||||
namespace mozilla {
|
||||
|
||||
enum ArenaObjectID {
|
||||
eArenaObjectID_DummyBeforeFirstObjectID = nsQueryFrame::NON_FRAME_MARKER - 1,
|
||||
|
||||
#define PRES_ARENA_OBJECT(name_) eArenaObjectID_##name_,
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
|
||||
eArenaObjectID_COUNT
|
||||
};
|
||||
|
||||
|
@ -10650,8 +10650,7 @@ PresShell* PresShell::GetRootPresShell() {
|
||||
|
||||
void PresShell::AddSizeOfIncludingThis(nsWindowSizes& aSizes) const {
|
||||
MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
|
||||
mFrameArena.AddSizeOfExcludingThis(aSizes,
|
||||
&nsWindowSizes::mLayoutPresShellSize);
|
||||
mFrameArena.AddSizeOfExcludingThis(aSizes, Arena::ArenaKind::PresShell);
|
||||
aSizes.mLayoutPresShellSize += mallocSizeOf(this);
|
||||
if (mCaret) {
|
||||
aSizes.mLayoutPresShellSize += mCaret->SizeOfIncludingThis(mallocSizeOf);
|
||||
|
@ -257,26 +257,26 @@ class PresShell final : public nsStubDocumentObserver,
|
||||
* on out-of-memory.
|
||||
*/
|
||||
void* AllocateFrame(nsQueryFrame::FrameIID aID, size_t aSize) {
|
||||
void* result = mFrameArena.AllocateByFrameID(aID, aSize);
|
||||
RecordAlloc(result);
|
||||
return result;
|
||||
#define FRAME_ID(classname, ...) \
|
||||
static_assert(size_t(nsQueryFrame::FrameIID::classname##_id) == \
|
||||
size_t(eArenaObjectID_##classname), \
|
||||
"");
|
||||
#define ABSTRACT_FRAME_ID(classname) \
|
||||
static_assert(size_t(nsQueryFrame::FrameIID::classname##_id) == \
|
||||
size_t(eArenaObjectID_##classname), \
|
||||
"");
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
return AllocateByObjectID(ArenaObjectID(size_t(aID)), aSize);
|
||||
}
|
||||
|
||||
void FreeFrame(nsQueryFrame::FrameIID aID, void* aPtr) {
|
||||
RecordFree(aPtr);
|
||||
if (!mIsDestroying) {
|
||||
mFrameArena.FreeByFrameID(aID, aPtr);
|
||||
}
|
||||
return FreeByObjectID(ArenaObjectID(size_t(aID)), aPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for allocating other types of objects (not frames). Separate free
|
||||
* lists are maintained for each type (aID), which must always correspond to
|
||||
* the same aSize value. AllocateByObjectID is infallible and will abort on
|
||||
* out-of-memory.
|
||||
*/
|
||||
void* AllocateByObjectID(ArenaObjectID aID, size_t aSize) {
|
||||
void* result = mFrameArena.AllocateByObjectID(aID, aSize);
|
||||
void* result = mFrameArena.Allocate(aID, aSize);
|
||||
RecordAlloc(result);
|
||||
return result;
|
||||
}
|
||||
@ -284,7 +284,7 @@ class PresShell final : public nsStubDocumentObserver,
|
||||
void FreeByObjectID(ArenaObjectID aID, void* aPtr) {
|
||||
RecordFree(aPtr);
|
||||
if (!mIsDestroying) {
|
||||
mFrameArena.FreeByObjectID(aID, aPtr);
|
||||
mFrameArena.Free(aID, aPtr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2953,7 +2953,8 @@ class PresShell final : public nsStubDocumentObserver,
|
||||
// The focus information needed for async keyboard scrolling
|
||||
FocusTarget mAPZFocusTarget;
|
||||
|
||||
nsPresArena<8192> mFrameArena;
|
||||
using Arena = nsPresArena<8192, ArenaObjectID, eArenaObjectID_COUNT>;
|
||||
Arena mFrameArena;
|
||||
|
||||
Maybe<nsPoint> mVisualViewportOffset;
|
||||
|
||||
|
@ -22,8 +22,8 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
template <size_t ArenaSize>
|
||||
nsPresArena<ArenaSize>::~nsPresArena<ArenaSize>() {
|
||||
template <size_t ArenaSize, typename ObjectId, size_t ObjectIdCount>
|
||||
nsPresArena<ArenaSize, ObjectId, ObjectIdCount>::~nsPresArena() {
|
||||
#if defined(MOZ_HAVE_MEM_CHECKS)
|
||||
for (FreeList* entry = mFreeLists; entry != ArrayEnd(mFreeLists); ++entry) {
|
||||
nsTArray<void*>::index_type len;
|
||||
@ -36,16 +36,17 @@ nsPresArena<ArenaSize>::~nsPresArena<ArenaSize>() {
|
||||
#endif
|
||||
}
|
||||
|
||||
template <size_t ArenaSize>
|
||||
void* nsPresArena<ArenaSize>::Allocate(uint32_t aCode, size_t aSize) {
|
||||
template <size_t ArenaSize, typename ObjectId, size_t ObjectIdCount>
|
||||
void* nsPresArena<ArenaSize, ObjectId, ObjectIdCount>::Allocate(ObjectId aCode,
|
||||
size_t aSize) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aSize > 0, "PresArena cannot allocate zero bytes");
|
||||
MOZ_ASSERT(aCode < ArrayLength(mFreeLists));
|
||||
MOZ_ASSERT(size_t(aCode) < ArrayLength(mFreeLists));
|
||||
|
||||
// We only hand out aligned sizes
|
||||
aSize = mPool.AlignedSize(aSize);
|
||||
|
||||
FreeList* list = &mFreeLists[aCode];
|
||||
FreeList* list = &mFreeLists[size_t(aCode)];
|
||||
|
||||
nsTArray<void*>::index_type len = list->mEntries.Length();
|
||||
if (list->mEntrySize == 0) {
|
||||
@ -100,13 +101,14 @@ void* nsPresArena<ArenaSize>::Allocate(uint32_t aCode, size_t aSize) {
|
||||
return mPool.Allocate(aSize);
|
||||
}
|
||||
|
||||
template <size_t ArenaSize>
|
||||
void nsPresArena<ArenaSize>::Free(uint32_t aCode, void* aPtr) {
|
||||
template <size_t ArenaSize, typename ObjectId, size_t ObjectIdCount>
|
||||
void nsPresArena<ArenaSize, ObjectId, ObjectIdCount>::Free(ObjectId aCode,
|
||||
void* aPtr) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(aCode < ArrayLength(mFreeLists));
|
||||
MOZ_ASSERT(size_t(aCode) < ArrayLength(mFreeLists));
|
||||
|
||||
// Try to recycle this entry.
|
||||
FreeList* list = &mFreeLists[aCode];
|
||||
FreeList* list = &mFreeLists[size_t(aCode)];
|
||||
MOZ_ASSERT(list->mEntrySize > 0, "object of this type was never allocated");
|
||||
|
||||
mozWritePoison(aPtr, list->mEntrySize);
|
||||
@ -115,9 +117,9 @@ void nsPresArena<ArenaSize>::Free(uint32_t aCode, void* aPtr) {
|
||||
list->mEntries.AppendElement(aPtr);
|
||||
}
|
||||
|
||||
template <size_t ArenaSize>
|
||||
void nsPresArena<ArenaSize>::AddSizeOfExcludingThis(
|
||||
nsWindowSizes& aSizes, size_t nsWindowSizes::*aArenaSize) const {
|
||||
template <size_t ArenaSize, typename ObjectId, size_t ObjectIdCount>
|
||||
void nsPresArena<ArenaSize, ObjectId, ObjectIdCount>::AddSizeOfExcludingThis(
|
||||
nsWindowSizes& aSizes, ArenaKind aKind) const {
|
||||
// We do a complicated dance here because we want to measure the
|
||||
// space taken up by the different kinds of objects in the arena,
|
||||
// but we don't have pointers to those objects. And even if we did,
|
||||
@ -143,29 +145,43 @@ void nsPresArena<ArenaSize>::AddSizeOfExcludingThis(
|
||||
// total size of objects allocated with a given ID.
|
||||
size_t totalSize = entry->mEntrySize * entry->mEntriesEverAllocated;
|
||||
|
||||
switch (entry - mFreeLists) {
|
||||
#define FRAME_ID(classname, ...) \
|
||||
case nsQueryFrame::classname##_id: \
|
||||
aSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(classname) += totalSize; \
|
||||
if (aKind == ArenaKind::PresShell) {
|
||||
switch (entry - mFreeLists) {
|
||||
#define PRES_ARENA_OBJECT(name_) \
|
||||
case eArenaObjectID_##name_: \
|
||||
aSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_) += totalSize; \
|
||||
break;
|
||||
#define ABSTRACT_FRAME_ID(...)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
case eArenaObjectID_nsLineBox:
|
||||
aSizes.mArenaSizes.mLineBoxes += totalSize;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
#include "nsPresArenaObjectList.h"
|
||||
#undef PRES_ARENA_OBJECT
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown arena object type");
|
||||
}
|
||||
} else {
|
||||
MOZ_ASSERT(aKind == ArenaKind::DisplayList);
|
||||
switch (DisplayListArenaObjectId(entry - mFreeLists)) {
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) \
|
||||
case DisplayListArenaObjectId::name_: \
|
||||
aSizes.mArenaSizes.NS_ARENA_SIZES_FIELD(name_) += totalSize; \
|
||||
break;
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unknown display item arena type");
|
||||
}
|
||||
}
|
||||
|
||||
totalSizeInFreeLists += totalSize;
|
||||
}
|
||||
|
||||
aSizes.*aArenaSize += mallocSize - totalSizeInFreeLists;
|
||||
auto& field = aKind == ArenaKind::PresShell
|
||||
? aSizes.mLayoutPresShellSize
|
||||
: aSizes.mLayoutRetainedDisplayListSize;
|
||||
|
||||
field += mallocSize - totalSizeInFreeLists;
|
||||
}
|
||||
|
||||
// Explicitly instantiate templates for the used nsPresArena allocator sizes.
|
||||
// This is needed because nsPresArena definition is split across multiple files.
|
||||
template class nsPresArena<8192>;
|
||||
template class nsPresArena<32768>;
|
||||
template class nsPresArena<8192, ArenaObjectID, eArenaObjectID_COUNT>;
|
||||
template class nsPresArena<32768, DisplayListArenaObjectId,
|
||||
size_t(DisplayListArenaObjectId::COUNT)>;
|
||||
|
@ -24,51 +24,30 @@
|
||||
|
||||
class nsWindowSizes;
|
||||
|
||||
template <size_t ArenaSize>
|
||||
template <size_t ArenaSize, typename ObjectId, size_t ObjectIdCount>
|
||||
class nsPresArena {
|
||||
public:
|
||||
nsPresArena() = default;
|
||||
~nsPresArena();
|
||||
|
||||
/**
|
||||
* Pool allocation with recycler lists indexed by frame-type ID.
|
||||
* Every aID must always be used with the same object size, aSize.
|
||||
*/
|
||||
void* AllocateByFrameID(nsQueryFrame::FrameIID aID, size_t aSize) {
|
||||
return Allocate(aID, aSize);
|
||||
}
|
||||
void FreeByFrameID(nsQueryFrame::FrameIID aID, void* aPtr) {
|
||||
Free(aID, aPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pool allocation with recycler lists indexed by object-type ID (see above).
|
||||
* Every aID must always be used with the same object size, aSize.
|
||||
*/
|
||||
void* AllocateByObjectID(mozilla::ArenaObjectID aID, size_t aSize) {
|
||||
return Allocate(aID, aSize);
|
||||
}
|
||||
void FreeByObjectID(mozilla::ArenaObjectID aID, void* aPtr) {
|
||||
Free(aID, aPtr);
|
||||
}
|
||||
|
||||
void* AllocateByCustomID(uint32_t aID, size_t aSize) {
|
||||
return Allocate(aID, aSize);
|
||||
}
|
||||
void FreeByCustomID(uint32_t aID, void* ptr) { Free(aID, ptr); }
|
||||
void* Allocate(ObjectId aCode, size_t aSize);
|
||||
void Free(ObjectId aCode, void* aPtr);
|
||||
|
||||
enum class ArenaKind { PresShell, DisplayList };
|
||||
/**
|
||||
* Increment nsWindowSizes with sizes of interesting objects allocated in this
|
||||
* arena, and put the general unclassified size in `aArenaSize`.
|
||||
* arena, and put the general unclassified size in the relevant field
|
||||
* depending on the arena size.
|
||||
*/
|
||||
void AddSizeOfExcludingThis(nsWindowSizes&,
|
||||
size_t nsWindowSizes::*aArenaSize) const;
|
||||
void AddSizeOfExcludingThis(nsWindowSizes&, ArenaKind) const;
|
||||
|
||||
void Check() { mPool.Check(); }
|
||||
|
||||
private:
|
||||
void* Allocate(uint32_t aCode, size_t aSize);
|
||||
void Free(uint32_t aCode, void* aPtr);
|
||||
|
||||
class FreeList {
|
||||
public:
|
||||
@ -83,7 +62,7 @@ class nsPresArena {
|
||||
}
|
||||
};
|
||||
|
||||
FreeList mFreeLists[mozilla::eArenaObjectID_COUNT];
|
||||
FreeList mFreeLists[ObjectIdCount];
|
||||
mozilla::ArenaAllocator<ArenaSize, 8> mPool;
|
||||
};
|
||||
|
||||
|
@ -8,7 +8,14 @@
|
||||
preprocessing */
|
||||
|
||||
// These are objects that can be stored in the pres arena
|
||||
|
||||
//
|
||||
// FIXME(emilio): Including abstract frame classes in the arena is a bit
|
||||
// wasteful, but it simplifies the allocation code.
|
||||
#define FRAME_ID(classname, ...) PRES_ARENA_OBJECT(classname)
|
||||
#define ABSTRACT_FRAME_ID(classname) PRES_ARENA_OBJECT(classname)
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
PRES_ARENA_OBJECT(nsLineBox)
|
||||
PRES_ARENA_OBJECT(DisplayItemData)
|
||||
PRES_ARENA_OBJECT(nsFrameList)
|
||||
|
@ -69,11 +69,6 @@ class nsQueryFrame {
|
||||
#include "mozilla/FrameIdList.h"
|
||||
#undef FRAME_ID
|
||||
#undef ABSTRACT_FRAME_ID
|
||||
|
||||
// This marker allows mozilla::ArenaObjectID to "extend" this enum
|
||||
// with additional sequential values for use in nsPresArena and
|
||||
// PresShell::{Allocate,Free}ByObjectId
|
||||
NON_FRAME_MARKER
|
||||
};
|
||||
|
||||
// A strict subset of FrameIID above for frame classes that we instantiate.
|
||||
|
@ -20,6 +20,7 @@ EXPORTS += [
|
||||
'nsDisplayItemTypes.h',
|
||||
'nsDisplayItemTypesList.h',
|
||||
'nsDisplayList.h',
|
||||
'nsDisplayListArenaTypes.h',
|
||||
'nsDisplayListInvalidation.h',
|
||||
'nsImageRenderer.h',
|
||||
'RetainedDisplayListBuilder.h',
|
||||
|
@ -1805,7 +1805,7 @@ void nsDisplayListBuilder::FreeClipChains() {
|
||||
|
||||
mClipDeduplicator.erase(*indirect);
|
||||
(*indirect)->DisplayItemClipChain::~DisplayItemClipChain();
|
||||
Destroy(DisplayItemType::TYPE_ZERO, *indirect);
|
||||
Destroy(DisplayListArenaObjectId::CLIPCHAIN, *indirect);
|
||||
|
||||
*indirect = next;
|
||||
} else {
|
||||
@ -1926,23 +1926,6 @@ void nsDisplayListBuilder::MarkPreserve3DFramesForDisplayList(
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gDisplayItemSizes[static_cast<uint32_t>(DisplayItemType::TYPE_MAX)] = {
|
||||
0};
|
||||
|
||||
void* nsDisplayListBuilder::Allocate(size_t aSize, DisplayItemType aType) {
|
||||
size_t roundedUpSize = RoundUpPow2(aSize);
|
||||
uint_fast8_t type = FloorLog2Size(roundedUpSize);
|
||||
|
||||
MOZ_RELEASE_ASSERT(gDisplayItemSizes[static_cast<uint32_t>(aType)] == type ||
|
||||
gDisplayItemSizes[static_cast<uint32_t>(aType)] == 0);
|
||||
gDisplayItemSizes[static_cast<uint32_t>(aType)] = type;
|
||||
return mPool.AllocateByCustomID(type, roundedUpSize);
|
||||
}
|
||||
|
||||
void nsDisplayListBuilder::Destroy(DisplayItemType aType, void* aPtr) {
|
||||
mPool.FreeByCustomID(gDisplayItemSizes[static_cast<uint32_t>(aType)], aPtr);
|
||||
}
|
||||
|
||||
ActiveScrolledRoot* nsDisplayListBuilder::AllocateActiveScrolledRoot(
|
||||
const ActiveScrolledRoot* aParent, nsIScrollableFrame* aScrollableFrame) {
|
||||
RefPtr<ActiveScrolledRoot> asr = ActiveScrolledRoot::CreateASRForFrame(
|
||||
@ -1955,7 +1938,8 @@ const DisplayItemClipChain* nsDisplayListBuilder::AllocateDisplayItemClipChain(
|
||||
const DisplayItemClip& aClip, const ActiveScrolledRoot* aASR,
|
||||
const DisplayItemClipChain* aParent) {
|
||||
MOZ_ASSERT(!(aParent && aParent->mOnStack));
|
||||
void* p = Allocate(sizeof(DisplayItemClipChain), DisplayItemType::TYPE_ZERO);
|
||||
void* p = Allocate(sizeof(DisplayItemClipChain),
|
||||
DisplayListArenaObjectId::CLIPCHAIN);
|
||||
DisplayItemClipChain* c = new (KnownNotNull, p)
|
||||
DisplayItemClipChain(aClip, aASR, aParent, mFirstClipChainToDestroy);
|
||||
#ifdef DEBUG
|
||||
@ -1969,7 +1953,7 @@ const DisplayItemClipChain* nsDisplayListBuilder::AllocateDisplayItemClipChain(
|
||||
// collapse into the same clip chain object, because clip chains do not keep
|
||||
// track of the reference frame that they were created in.
|
||||
c->DisplayItemClipChain::~DisplayItemClipChain();
|
||||
Destroy(DisplayItemType::TYPE_ZERO, c);
|
||||
Destroy(DisplayListArenaObjectId::CLIPCHAIN, c);
|
||||
return *(result.first);
|
||||
}
|
||||
mFirstClipChainToDestroy = c;
|
||||
@ -2361,8 +2345,7 @@ void nsDisplayTransform::AddSizeOfExcludingThis(nsWindowSizes& aSizes) const {
|
||||
}
|
||||
|
||||
void nsDisplayListBuilder::AddSizeOfExcludingThis(nsWindowSizes& aSizes) const {
|
||||
mPool.AddSizeOfExcludingThis(aSizes,
|
||||
&nsWindowSizes::mLayoutRetainedDisplayListSize);
|
||||
mPool.AddSizeOfExcludingThis(aSizes, Arena::ArenaKind::DisplayList);
|
||||
|
||||
size_t n = 0;
|
||||
MallocSizeOf mallocSizeOf = aSizes.mState.mMallocSizeOf;
|
||||
|
@ -91,6 +91,14 @@ class DisplayListBuilder;
|
||||
namespace dom {
|
||||
class Selection;
|
||||
} // namespace dom
|
||||
|
||||
enum class DisplayListArenaObjectId {
|
||||
#define DISPLAY_LIST_ARENA_OBJECT(name_) name_,
|
||||
#include "nsDisplayListArenaTypes.h"
|
||||
#undef DISPLAY_LIST_ARENA_OBJECT
|
||||
COUNT
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/*
|
||||
@ -1048,12 +1056,33 @@ class nsDisplayListBuilder {
|
||||
|
||||
/**
|
||||
* Allocate memory in our arena. It will only be freed when this display list
|
||||
* builder is destroyed. This memory holds nsDisplayItems. nsDisplayItem
|
||||
* destructors are called as soon as the item is no longer used.
|
||||
* builder is destroyed. This memory holds nsDisplayItems and
|
||||
* DisplayItemClipChain objects.
|
||||
*
|
||||
* Destructors are called as soon as the item is no longer used.
|
||||
*/
|
||||
void* Allocate(size_t aSize, DisplayItemType aType);
|
||||
void* Allocate(size_t aSize, mozilla::DisplayListArenaObjectId aId) {
|
||||
return mPool.Allocate(aId, aSize);
|
||||
}
|
||||
void* Allocate(size_t aSize, DisplayItemType aType) {
|
||||
static_assert(size_t(DisplayItemType::TYPE_ZERO) ==
|
||||
size_t(mozilla::DisplayListArenaObjectId::CLIPCHAIN),
|
||||
"");
|
||||
#define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) \
|
||||
static_assert(size_t(DisplayItemType::TYPE_##name_) == \
|
||||
size_t(mozilla::DisplayListArenaObjectId::name_), \
|
||||
"");
|
||||
#include "nsDisplayItemTypesList.h"
|
||||
#undef DECLARE_DISPLAY_ITEM_TYPE
|
||||
return Allocate(aSize, mozilla::DisplayListArenaObjectId(size_t(aType)));
|
||||
}
|
||||
|
||||
void Destroy(DisplayItemType aType, void* aPtr);
|
||||
void Destroy(mozilla::DisplayListArenaObjectId aId, void* aPtr) {
|
||||
return mPool.Free(aId, aPtr);
|
||||
}
|
||||
void Destroy(DisplayItemType aType, void* aPtr) {
|
||||
return Destroy(mozilla::DisplayListArenaObjectId(size_t(aType)), aPtr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate a new ActiveScrolledRoot in the arena. Will be cleaned up
|
||||
@ -1858,7 +1887,10 @@ class nsDisplayListBuilder {
|
||||
|
||||
nsIFrame* const mReferenceFrame;
|
||||
nsIFrame* mIgnoreScrollFrame;
|
||||
nsPresArena<32768> mPool;
|
||||
|
||||
using Arena = nsPresArena<32768, mozilla::DisplayListArenaObjectId,
|
||||
size_t(mozilla::DisplayListArenaObjectId::COUNT)>;
|
||||
Arena mPool;
|
||||
|
||||
AutoTArray<PresShellState, 8> mPresShellStates;
|
||||
AutoTArray<nsIFrame*, 400> mFramesMarkedForDisplay;
|
||||
|
13
layout/painting/nsDisplayListArenaTypes.h
Normal file
13
layout/painting/nsDisplayListArenaTypes.h
Normal file
@ -0,0 +1,13 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* a list of all types that can be allocated in the display list's nsPresArena,
|
||||
for preprocessing */
|
||||
|
||||
DISPLAY_LIST_ARENA_OBJECT(CLIPCHAIN)
|
||||
#define DECLARE_DISPLAY_ITEM_TYPE(name_, ...) DISPLAY_LIST_ARENA_OBJECT(name_)
|
||||
#include "nsDisplayItemTypesList.h"
|
||||
#undef DECLARE_DISPLAY_ITEM_TYPE
|
Loading…
Reference in New Issue
Block a user