diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c
index 63d546f14df..fb55019ff3c 100644
--- a/mps/code/arenavm.c
+++ b/mps/code/arenavm.c
@@ -687,7 +687,7 @@ static Size VMArenaReserved(Arena arena)
*/
#define tablePageBaseIndex(chunk, tablePage) \
(AddrOffset((Addr)(chunk)->pageTable, (tablePage)) \
- / sizeof(PageStruct))
+ / sizeof(PageUnion))
/* tablePageWholeBaseIndex
@@ -697,8 +697,8 @@ static Size VMArenaReserved(Arena arena)
*/
#define tablePageWholeBaseIndex(chunk, tablePage) \
(AddrOffset((Addr)(chunk)->pageTable, \
- AddrAdd((tablePage), sizeof(PageStruct)-1)) \
- / sizeof(PageStruct))
+ AddrAdd((tablePage), sizeof(PageUnion)-1)) \
+ / sizeof(PageUnion))
/* tablePageLimitIndex -- index of the first page descriptor falling
@@ -709,7 +709,7 @@ static Size VMArenaReserved(Arena arena)
#define tablePageLimitIndex(chunk, tablePage) \
((AddrOffset((Addr)(chunk)->pageTable, (tablePage)) \
+ ChunkPageSize(chunk) - 1) \
- / sizeof(PageStruct) \
+ / sizeof(PageUnion) \
+ 1)
/* tablePageWholeLimitIndex
@@ -720,14 +720,14 @@ static Size VMArenaReserved(Arena arena)
#define tablePageWholeLimitIndex(chunk, tablePage) \
((AddrOffset((Addr)(chunk)->pageTable, (tablePage)) \
+ ChunkPageSize(chunk)) \
- / sizeof(PageStruct))
+ / sizeof(PageUnion))
/* tablePagesUsed
*
* Takes a range of pages identified by [pageBase, pageLimit), and
* returns the pages occupied by the page table which store the
- * PageStruct descriptors for those pages.
+ * PageUnion descriptors for those pages.
*/
static void tablePagesUsed(Index *tableBaseReturn, Index *tableLimitReturn,
Chunk chunk, Index pageBase, Index pageLimit)
@@ -1194,32 +1194,32 @@ static Bool pageDescIsMapped(VMChunk vmChunk, Index pi)
AVER(pi < chunk->pages);
- /* Note that unless the pi'th PageStruct crosses a page boundary */
+ /* Note that unless the pi'th PageUnion crosses a page boundary */
/* Base and Limit will differ by exactly 1. */
/* They will differ by at most 2 assuming that */
- /* sizeof(PageStruct) <= ChunkPageSize(chunk) (!) */
+ /* sizeof(PageUnion) <= ChunkPageSize(chunk) (!) */
tablePagesUsed(&pageTableBaseIndex, &pageTableLimitIndex, chunk, pi, pi+1);
/* using unsigned arithmetic overflow to use just one comparison */
AVER(pageTableLimitIndex - pageTableBaseIndex - 1 < 2);
- /* We can examine the PageStruct descriptor iff both table pages */
+ /* We can examine the page descriptor iff both table pages */
/* are mapped. */
return BTGet(vmChunk->pageTableMapped, pageTableBaseIndex) &&
BTGet(vmChunk->pageTableMapped, pageTableLimitIndex - 1);
}
-/* pageType -- determine page type
+/* pageState -- determine page state, even if unmapped
*
* Parts of the page table may be unmapped if their corresponding pages are
* free.
*/
-static unsigned pageType(VMChunk vmChunk, Index pi)
+static unsigned pageState(VMChunk vmChunk, Index pi)
{
Chunk chunk = VMChunk2Chunk(vmChunk);
if (pageDescIsMapped(vmChunk, pi))
- return PageType(&chunk->pageTable[pi]);
+ return PageState(&chunk->pageTable[pi]);
return PageStateFREE;
}
@@ -1235,7 +1235,7 @@ static void sparePageRelease(VMChunk vmChunk, Index pi)
Arena arena = ChunkArena(chunk);
Page page = &chunk->pageTable[pi];
- AVER(PageType(page) == PageStateSPARE);
+ AVER(PageState(page) == PageStateSPARE);
AVER(arena->spareCommitted >= ChunkPageSize(chunk));
arena->spareCommitted -= ChunkPageSize(chunk);
@@ -1272,14 +1272,14 @@ static void tablePagesUnmap(VMChunk vmChunk, Index basePage, Index limitPage)
beginning of the table. */
while (basePage > 0 &&
pageDescIsMapped(vmChunk, basePage) &&
- PageType(&chunk->pageTable[basePage]) == PageStateFREE)
+ PageState(&chunk->pageTable[basePage]) == PageStateFREE)
--basePage;
/* Raise limitPage until we reach a descriptor we can't unmap, or the end
of the table. */
while (limitPage < chunk->pages &&
pageDescIsMapped(vmChunk, limitPage) &&
- PageType(&chunk->pageTable[limitPage]) == PageStateFREE)
+ PageState(&chunk->pageTable[limitPage]) == PageStateFREE)
++limitPage;
/* Calculate the range of pages in the page table. */
@@ -1289,14 +1289,14 @@ static void tablePagesUnmap(VMChunk vmChunk, Index basePage, Index limitPage)
/* If we can't unmap the base page, step up. */
if (!pageDescIsMapped(vmChunk, basePage) ||
- PageType(&chunk->pageTable[basePage]) != PageStateFREE)
+ PageState(&chunk->pageTable[basePage]) != PageStateFREE)
base = AddrAdd(base, chunk->pageSize);
/* If that leaves any pages, then if the limit page contains a desciptor
we can't unmap, step down. Note, limit is the base of the page table
page *after* the one containing the desc for limitPage. */
if (base < limit) {
if (limitPage < chunk->pages &&
- pageType(vmChunk, limitPage) != PageStateFREE)
+ pageState(vmChunk, limitPage) != PageStateFREE)
limit = AddrSub(limit, chunk->pageSize);
/* If that leaves any pages, unmap them. */
if (base < limit) {
@@ -1334,7 +1334,7 @@ static Res pagesMarkAllocated(VMArena vmArena, VMChunk vmChunk,
Addr freeBase;
/* Allocate a run of spare pages. */
- while(i < limitIndex && PageType(&chunk->pageTable[i]) == PageStateSPARE) {
+ while(i < limitIndex && PageState(&chunk->pageTable[i]) == PageStateSPARE) {
sparePageRelease(vmChunk, i);
PageAlloc(chunk, i, pool);
++i;
@@ -1345,8 +1345,8 @@ static Res pagesMarkAllocated(VMArena vmArena, VMChunk vmChunk,
/* Allocate a run of free pages. */
freeBase = PageIndexBase(chunk, i);
- AVER(PageType(&chunk->pageTable[i]) == PageStateFREE);
- while (i < limitIndex && PageType(&chunk->pageTable[i]) == PageStateFREE) {
+ AVER(PageState(&chunk->pageTable[i]) == PageStateFREE);
+ while (i < limitIndex && PageState(&chunk->pageTable[i]) == PageStateFREE) {
PageAlloc(chunk, i, pool);
++i;
}
@@ -1518,7 +1518,7 @@ static Size chunkUnmapAroundPage(Chunk chunk, Size size, Page page)
AVERT(Chunk, chunk);
vmChunk = Chunk2VMChunk(chunk);
AVERT(VMChunk, vmChunk);
- AVER(PageType(page) == PageStateSPARE);
+ AVER(PageState(page) == PageStateSPARE);
/* size is arbitrary */
pageSize = ChunkPageSize(chunk);
@@ -1537,10 +1537,10 @@ static Size chunkUnmapAroundPage(Chunk chunk, Size size, Page page)
purged += pageSize;
} while (purged < size &&
limitPage < chunk->pages &&
- pageType(vmChunk, limitPage) == PageStateSPARE);
+ pageState(vmChunk, limitPage) == PageStateSPARE);
while (purged < size &&
basePage > 0 &&
- pageType(vmChunk, basePage - 1) == PageStateSPARE) {
+ pageState(vmChunk, basePage - 1) == PageStateSPARE) {
--basePage;
sparePageRelease(vmChunk, basePage);
PageInit(chunk, basePage);
diff --git a/mps/code/mpmtypes.h b/mps/code/mpmtypes.h
index 7f035c1c792..131447ed065 100644
--- a/mps/code/mpmtypes.h
+++ b/mps/code/mpmtypes.h
@@ -88,7 +88,7 @@ typedef struct mps_chain_s *Chain; /* */
typedef struct TractStruct *Tract; /* */
typedef struct ChunkStruct *Chunk; /* */
typedef struct ChunkCacheEntryStruct *ChunkCacheEntry; /* */
-typedef struct PageStruct *Page; /* */
+typedef union PageUnion *Page; /* */
typedef struct SegStruct *Seg; /* */
typedef struct GCSegStruct *GCSeg; /* */
typedef struct SegClassStruct *SegClass; /* */
diff --git a/mps/code/tract.c b/mps/code/tract.c
index 1c068201cf4..b87421d6870 100644
--- a/mps/code/tract.c
+++ b/mps/code/tract.c
@@ -159,7 +159,7 @@ Res ChunkInit(Chunk chunk, Arena arena,
{
Size size;
Count pages;
- PageStruct *pageTable;
+ Page pageTable;
Shift pageShift;
Size pageTableSize;
void *p;
@@ -192,7 +192,7 @@ Res ChunkInit(Chunk chunk, Arena arena,
goto failAllocTable;
chunk->allocTable = p;
- pageTableSize = SizeAlignUp(pages * sizeof(PageStruct), pageSize);
+ pageTableSize = SizeAlignUp(pages * sizeof(PageUnion), pageSize);
chunk->pageTablePages = pageTableSize >> pageShift;
res = (arena->class->chunkInit)(chunk, boot);
@@ -597,7 +597,7 @@ Bool TractNext(Tract *tractReturn, Arena arena, Addr addr)
/* PageAlloc
*
- * Sets up the PageStruct for an allocated page to turn it into a Tract.
+ * Sets up the page descriptor for an allocated page to turn it into a Tract.
*/
void PageAlloc(Chunk chunk, Index pi, Pool pool)
diff --git a/mps/code/tract.h b/mps/code/tract.h
index 8c459765b96..9cf59f48d20 100644
--- a/mps/code/tract.h
+++ b/mps/code/tract.h
@@ -15,17 +15,17 @@
/* Page states
*
- * .states: Pages (hence PageStructs that describe them) can be in
+ * .states: Pages (hence PageUnions that describe them) can be in
* one of 3 states:
* allocated (to a pool as tracts)
* allocated pages are mapped
* BTGet(allocTable, i) == 1
- * PageType() == PageStateALLOC
+ * PageState() == PageStateALLOC
* PagePool()->pool == pool
* spare
* these pages are mapped
* BTGet(allocTable, i) == 0
- * PageType() == PageStateSPARE
+ * PageState() == PageStateSPARE
* PagePool() == NULL
* free
* these pages are not mapped
@@ -33,7 +33,7 @@
* PTE may itself be unmapped, but when it is (use pageTableMapped
* to determine whether page occupied by page table is mapped):
* PagePool() == NULL
- * PageType() == PageStateFREE
+ * PageState() == PageStateFREE
*/
#define PageStateALLOC 0
@@ -41,6 +41,12 @@
#define PageStateFREE 2
#define PageStateWIDTH 2 /* bitfield width */
+typedef union PagePoolUnion {
+ unsigned state : PageStateWIDTH; /* see .states */
+ Pool pool;
+} PagePoolUnion;
+
+
/* TractStruct -- tract structure
*
@@ -51,17 +57,12 @@
* as type Bool. See .
*/
-typedef union TractPoolUnion {
- Pool pool;
- unsigned state : PageStateWIDTH; /* see .states */
-} TractPoolUnion;
-
typedef struct TractStruct { /* Tract structure */
- TractPoolUnion pool; /* MUST BE FIRST ( pool) */
+ PagePoolUnion pool; /* MUST BE FIRST ( pool) */
void *p; /* pointer for use of owning pool */
Addr base; /* Base address of the tract */
TraceSet white : TraceLIMIT; /* traces for which tract is white */
- unsigned int hasSeg : 1; /* does tract have a seg in p? See .bool */
+ unsigned hasSeg : 1; /* does tract have a seg in p? See .bool */
} TractStruct;
@@ -97,9 +98,9 @@ extern void TractFinish(Tract tract);
(TractSetHasSeg(tract, FALSE), TractSetP(tract, NULL))
-/* PageStruct -- Page structure
+/* PageUnion -- page descriptor
*
- * .page-table: The page table (defined as a PageStruct array)
+ * .page-table: The page table (defined as a PageUnion array)
* is central to the design of the arena.
* See .*.
*
@@ -107,39 +108,38 @@ extern void TractFinish(Tract tract);
* field of this union. See .
*/
-typedef struct PageStruct { /* page structure */
- union PageStructUnion {
- TractPoolUnion pool;
- TractStruct tractStruct; /* allocated tract */
- struct {
- TractPoolUnion pool; /* MUST BE FIRST ( pool) */
- RingStruct spareRing;
- } rest; /* other (non-allocated) page */
- } the;
-} PageStruct;
+typedef struct PageSpareStruct {
+ PagePoolUnion pool; /* spare tract, pool.state == PoolStateSPARE */
+ RingStruct ring; /* link in arena spare ring, LRU order */
+} PageSpareStruct;
+
+typedef union PageUnion { /* page structure */
+ PagePoolUnion pool; /* pool.state is the discriminator */
+ TractStruct alloc; /* allocated tract, pool.state == PoolStateALLOC */
+ PageSpareStruct spare; /* spare page, pool.state == PoolStateSPARE */
+} PageUnion;
-#define PageTract(page) (&(page)->the.tractStruct)
-#define PageOfTract(tract) \
- PARENT(PageStruct, the, PARENT(union PageStructUnion, tractStruct, (tract)))
-#define PagePool(page) RVALUE((page)->the.pool.pool)
+#define PageTract(page) (&(page)->alloc)
+#define PageOfTract(tract) PARENT(PageUnion, alloc, tract)
+#define PagePool(page) RVALUE((page)->pool.pool)
#define PageIsAllocated(page) RVALUE(PagePool(page) != NULL)
-#define PageType(page) RVALUE((page)->the.pool.state)
-#define PageSpareRing(page) RVALUE(&(page)->the.rest.spareRing)
-#define PageOfSpareRing(node) RING_ELT(Page, the.rest.spareRing, node)
+#define PageState(page) RVALUE((page)->pool.state)
+#define PageSpareRing(page) RVALUE(&(page)->spare.ring)
+#define PageOfSpareRing(node) PARENT(PageUnion, spare, RING_ELT(PageSpare, ring, node))
#define PageSetPool(page, _pool) \
BEGIN \
- PageStruct *_page = (page); \
- _page->the.pool.pool = (_pool); \
- AVER(PageType(_page) == PageStateALLOC); \
+ Page _page = (page); \
+ _page->pool.pool = (_pool); \
+ AVER(PageState(_page) == PageStateALLOC); \
END
#define PageSetType(page, _state) \
BEGIN \
- PageStruct *_page = (page); \
+ Page _page = (page); \
AVER(PagePool(_page) == NULL); \
- _page->the.pool.state = (_state); \
+ _page->pool.state = (_state); \
END
@@ -160,7 +160,7 @@ typedef struct ChunkStruct {
Index allocBase; /* index of first page allocatable to clients */
Index pages; /* index of the page after the last allocatable page */
BT allocTable; /* page allocation table */
- PageStruct* pageTable; /* the page table */
+ Page pageTable; /* the page table */
Count pageTablePages; /* number of pages occupied by page table */
} ChunkStruct;