diff --git a/mps/code/arenavm.c b/mps/code/arenavm.c index 129556595f5..63d546f14df 100644 --- a/mps/code/arenavm.c +++ b/mps/code/arenavm.c @@ -1215,12 +1215,12 @@ static Bool pageDescIsMapped(VMChunk vmChunk, Index pi) * free. */ -static int pageType(VMChunk vmChunk, Index pi) +static unsigned pageType(VMChunk vmChunk, Index pi) { Chunk chunk = VMChunk2Chunk(vmChunk); if (pageDescIsMapped(vmChunk, pi)) return PageType(&chunk->pageTable[pi]); - return PageTypeFree; + 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) == PageTypeSpare); + AVER(PageType(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]) == PageTypeFree) + PageType(&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]) == PageTypeFree) + PageType(&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]) != PageTypeFree) + PageType(&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) != PageTypeFree) + pageType(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]) == PageTypeSpare) { + while(i < limitIndex && PageType(&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]) == PageTypeFree); - while (i < limitIndex && PageType(&chunk->pageTable[i]) == PageTypeFree) { + AVER(PageType(&chunk->pageTable[i]) == PageStateFREE); + while (i < limitIndex && PageType(&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) == PageTypeSpare); + AVER(PageType(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) == PageTypeSpare); + pageType(vmChunk, limitPage) == PageStateSPARE); while (purged < size && basePage > 0 && - pageType(vmChunk, basePage - 1) == PageTypeSpare) { + pageType(vmChunk, basePage - 1) == PageStateSPARE) { --basePage; sparePageRelease(vmChunk, basePage); PageInit(chunk, basePage); @@ -1667,8 +1667,8 @@ static void VMFree(Addr base, Size size, Pool pool) AVER(TractPool(tract) == pool); TractFinish(tract); - PagePool(page) = NULL; - PageType(page) = PageTypeSpare; + PageSetPool(page, NULL); + PageSetType(page, PageStateSPARE); /* We must init the page's spare ring because it is a union with the tract and will contain junk. */ RingInit(PageSpareRing(page)); diff --git a/mps/code/tract.c b/mps/code/tract.c index 6e4797d1fc3..1c068201cf4 100644 --- a/mps/code/tract.c +++ b/mps/code/tract.c @@ -48,7 +48,7 @@ void TractInit(Tract tract, Pool pool, Addr base) AVER(tract != NULL); AVERT(Pool, pool); - tract->pool = pool; + tract->pool.pool = pool; tract->base = base; tract->p = NULL; tract->white = TraceSetEMPTY; @@ -67,7 +67,7 @@ void TractFinish(Tract tract) /* Check that there's no segment - and hence no shielding. */ AVER(!TractHasSeg(tract)); - tract->pool = NULL; + tract->pool.pool = NULL; } @@ -628,8 +628,8 @@ void PageInit(Chunk chunk, Index pi) AVER(pi < chunk->pages); BTRes(chunk->allocTable, pi); - PagePool(&chunk->pageTable[pi]) = NULL; - PageType(&chunk->pageTable[pi]) = PageTypeFree; + PageSetPool(&chunk->pageTable[pi], NULL); + PageSetType(&chunk->pageTable[pi], PageStateFREE); RingInit(PageSpareRing(&chunk->pageTable[pi])); return; } diff --git a/mps/code/tract.h b/mps/code/tract.h index 3fda531a518..8c459765b96 100644 --- a/mps/code/tract.h +++ b/mps/code/tract.h @@ -13,6 +13,35 @@ #include "bt.h" +/* Page states + * + * .states: Pages (hence PageStructs 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 + * PagePool()->pool == pool + * spare + * these pages are mapped + * BTGet(allocTable, i) == 0 + * PageType() == PageStateSPARE + * PagePool() == NULL + * free + * these pages are not mapped + * BTGet(allocTable, i) == 0 + * 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 + */ + +#define PageStateALLOC 0 +#define PageStateSPARE 1 +#define PageStateFREE 2 +#define PageStateWIDTH 2 /* bitfield width */ + + /* TractStruct -- tract structure * * .tract: Tracts represent the grains of memory allocation from @@ -22,8 +51,13 @@ * as type Bool. See . */ +typedef union TractPoolUnion { + Pool pool; + unsigned state : PageStateWIDTH; /* see .states */ +} TractPoolUnion; + typedef struct TractStruct { /* Tract structure */ - Pool pool; /* MUST BE FIRST ( pool) */ + TractPoolUnion 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 */ @@ -35,7 +69,7 @@ extern Addr (TractBase)(Tract tract); #define TractBase(tract) ((tract)->base) extern Addr TractLimit(Tract tract); -#define TractPool(tract) ((tract)->pool) +#define TractPool(tract) ((tract)->pool.pool) #define TractP(tract) ((tract)->p) #define TractSetP(tract, pp) ((void)((tract)->p = (pp))) #define TractHasSeg(tract) ((Bool)(tract)->hasSeg) @@ -71,67 +105,43 @@ extern void TractFinish(Tract tract); * * .page: The "pool" field must be the first field of the "tail" * field of this union. See . - * - * .states: Pages (hence PageStructs that describe them) can be in - * one of 3 states: - * allocated (to a pool as tracts) - * allocated pages are mapped - * BTGet(allocTable, i) == 1 - * PageRest()->pool == pool - * spare - * these pages are mapped - * BTGet(allocTable, i) == 0 - * PageRest()->pool == NULL - * PageRest()->type == PageTypeSpare - * free - * these pages are not mapped - * BTGet(allocTable, i) == 0 - * PTE may itself be unmapped, but when it is (use pageTableMapped - * to determine whether page occupied by page table is mapped): - * PageRest()->pool == NULL - * PageRest()->type == PageTypeFree */ -enum {PageTypeSpare=1, PageTypeFree}; - typedef struct PageStruct { /* page structure */ union PageStructUnion { + TractPoolUnion pool; TractStruct tractStruct; /* allocated tract */ struct { - Pool pool; /* NULL, must be first field (.page) */ - int type; /* see .states */ + TractPoolUnion pool; /* MUST BE FIRST ( pool) */ RingStruct spareRing; } rest; /* other (non-allocated) page */ } the; } PageStruct; -/* PageTract -- tract descriptor of an allocated page */ - -#define PageTract(page) (&(page)->the.tractStruct) - -/* PageOfTract -- VM page descriptor from arena tract */ - -#define PageOfTract(tract) PARENT(PageStruct, the, PARENT(union PageStructUnion, tractStruct, (tract))) - -/* PagePool -- pool field of a page */ - -#define PagePool(page) ((page)->the.rest.pool) - -/* PageIsAllocated -- is a page allocated? - * - * See . - */ - -#define PageIsAllocated(page) ((page)->the.rest.pool != NULL) - -/* PageType -- type of page */ - -#define PageType(page) ((page)->the.rest.type) - -#define PageSpareRing(page) (&(page)->the.rest.spareRing) +#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 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 PageSetPool(page, _pool) \ + BEGIN \ + PageStruct *_page = (page); \ + _page->the.pool.pool = (_pool); \ + AVER(PageType(_page) == PageStateALLOC); \ + END + +#define PageSetType(page, _state) \ + BEGIN \ + PageStruct *_page = (page); \ + AVER(PagePool(_page) == NULL); \ + _page->the.pool.state = (_state); \ + END + /* Chunks */