Bug 1850746 - Part 5: Factor out conversion between arena and page indexes r=sfink

This also adds an assertion that the first arena is on a page boundary which is
required for decommit to work correctly.

Differential Revision: https://phabricator.services.mozilla.com/D220414
This commit is contained in:
Jon Coppeard 2024-09-06 15:32:35 +00:00
Родитель 049c5b2513
Коммит ee9156bab2
4 изменённых файлов: 26 добавлений и 18 удалений

Просмотреть файл

@ -524,7 +524,7 @@ void ArenaChunk::commitOnePage(GCRuntime* gc) {
decommittedPages[pageIndex] = false;
for (size_t i = 0; i < ArenasPerPage; i++) {
size_t arenaIndex = pageIndex * ArenasPerPage + i;
size_t arenaIndex = pageToArenaIndex(pageIndex) + i;
MOZ_ASSERT(!freeCommittedArenas[arenaIndex]);
freeCommittedArenas[arenaIndex] = true;
++info.numArenasFreeCommitted;

Просмотреть файл

@ -94,7 +94,7 @@ const uint8_t Arena::ThingsPerArena[] = {
bool Arena::allocated() const {
size_t arenaIndex = ArenaChunk::arenaIndex(this);
size_t pageIndex = arenaIndex / ArenasPerPage;
size_t pageIndex = ArenaChunk::arenaToPageIndex(arenaIndex);
bool result = !chunk()->decommittedPages[pageIndex] &&
!chunk()->freeCommittedArenas[arenaIndex] &&
IsValidAllocKind(allocKind);
@ -321,7 +321,7 @@ inline bool ArenaChunk::canDecommitPage(size_t pageIndex) const {
return false;
}
size_t arenaIndex = pageIndex * ArenasPerPage;
size_t arenaIndex = pageToArenaIndex(pageIndex);
for (size_t i = 0; i < ArenasPerPage; i++) {
if (!freeCommittedArenas[arenaIndex + i]) {
return false;
@ -374,7 +374,7 @@ bool ArenaChunk::decommitOneFreePage(GCRuntime* gc, size_t pageIndex,
// Temporarily mark the page as allocated while we decommit.
for (size_t i = 0; i < ArenasPerPage; i++) {
size_t arenaIndex = pageIndex * ArenasPerPage + i;
size_t arenaIndex = pageToArenaIndex(pageIndex) + i;
MOZ_ASSERT(freeCommittedArenas[arenaIndex]);
freeCommittedArenas[arenaIndex] = false;
}
@ -397,7 +397,7 @@ bool ArenaChunk::decommitOneFreePage(GCRuntime* gc, size_t pageIndex,
decommittedPages[pageIndex] = true;
} else {
for (size_t i = 0; i < ArenasPerPage; i++) {
size_t arenaIndex = pageIndex * ArenasPerPage + i;
size_t arenaIndex = pageToArenaIndex(pageIndex) + i;
MOZ_ASSERT(!freeCommittedArenas[arenaIndex]);
freeCommittedArenas[arenaIndex] = true;
}
@ -430,7 +430,7 @@ void ArenaChunk::decommitFreeArenasWithoutUnlocking(const AutoLockGC& lock) {
decommittedPages[i] = true;
for (size_t j = 0; j < ArenasPerPage; ++j) {
size_t arenaIndex = i * ArenasPerPage + j;
size_t arenaIndex = pageToArenaIndex(i) + j;
MOZ_ASSERT(freeCommittedArenas[arenaIndex]);
freeCommittedArenas[arenaIndex] = false;
}
@ -636,7 +636,8 @@ void ArenaChunk::verify() const {
MOZ_ASSERT(freeCommittedCount == info.numArenasFreeCommitted);
for (size_t i = 0; i < ArenasPerChunk; ++i) {
MOZ_ASSERT(!(decommittedPages[pageIndex(i)] && freeCommittedArenas[i]));
MOZ_ASSERT(
!(decommittedPages[arenaToPageIndex(i)] && freeCommittedArenas[i]));
}
}

Просмотреть файл

@ -491,6 +491,20 @@ class ArenaChunk : public ArenaChunkBase {
return (offset - offsetof(ArenaChunk, arenas)) >> ArenaShift;
}
static size_t pageIndex(const Arena* arena) {
return arenaToPageIndex(arenaIndex(arena));
}
static size_t arenaToPageIndex(size_t arenaIndex) {
static_assert((offsetof(ArenaChunk, arenas) % PageSize) == 0,
"First arena should be on a page boundary");
return arenaIndex / ArenasPerPage;
}
static size_t pageToArenaIndex(size_t pageIndex) {
return pageIndex * ArenasPerPage;
}
explicit ArenaChunk(JSRuntime* runtime) : ArenaChunkBase(runtime) {}
uintptr_t address() const {
@ -549,16 +563,8 @@ class ArenaChunk : public ArenaChunkBase {
// build.
bool isPageFree(const Arena* arena) const;
// Get the page index of the arena.
size_t pageIndex(const Arena* arena) const {
return pageIndex(arenaIndex(arena));
}
size_t pageIndex(size_t arenaIndex) const {
return arenaIndex / ArenasPerPage;
}
Arena* pageAddress(size_t pageIndex) {
return &arenas[pageIndex * ArenasPerPage];
void* pageAddress(size_t pageIndex) {
return &arenas[pageToArenaIndex(pageIndex)];
}
};

Просмотреть файл

@ -692,7 +692,8 @@ void js::gc::MarkingValidator::validate() {
ChunkMarkBitmap* incBitmap = &chunk->markBits;
for (size_t i = 0; i < ArenasPerChunk; i++) {
if (chunk->decommittedPages[chunk->pageIndex(i)]) {
size_t pageIndex = ArenaChunk::arenaToPageIndex(i);
if (chunk->decommittedPages[pageIndex]) {
continue;
}
Arena* arena = &chunk->arenas[i];