1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-24 06:20:43 -08:00

Merge branch/2016-04-11/job003998.

Copied from Perforce
 Change: 191388
 ServerID: perforce.ravenbrook.com
This commit is contained in:
Gareth Rees 2016-04-20 17:56:59 +01:00
commit ffcd3f0b7b
4 changed files with 92 additions and 38 deletions

View file

@ -954,6 +954,7 @@ Res ArenaFreeLandInsert(Arena arena, Addr base, Addr limit)
Res res;
AVERT(Arena, arena);
AVER(base < limit);
RangeInit(&range, base, limit);
res = arenaFreeLandInsertExtend(&oldRange, arena, &range);

View file

@ -308,8 +308,7 @@ static Res VMChunkCreate(Chunk *chunkReturn, VMArena vmArena, Size size)
if (res != ResOK)
goto failBootInit;
/* Allocate and map the descriptor. */
/* See <design/arena/>.@@@@ */
/* .overhead.chunk-struct: Allocate and map the chunk structure. */
res = BootAlloc(&p, boot, sizeof(VMChunkStruct), MPS_PF_ALIGN);
if (res != ResOK)
goto failChunkAlloc;
@ -361,11 +360,13 @@ static Res VMChunkInit(Chunk chunk, BootBlock boot)
vmChunk = Chunk2VMChunk(chunk);
AVERT(BootBlock, boot);
/* .overhead.sa-mapped: Chunk overhead for sparse array 'mapped' table. */
res = BootAlloc(&p, boot, BTSize(chunk->pages), MPS_PF_ALIGN);
if (res != ResOK)
goto failSaMapped;
saMapped = p;
/* .overhead.sa-pages: Chunk overhead for sparse array 'pages' table. */
res = BootAlloc(&p, boot, BTSize(chunk->pageTablePages), MPS_PF_ALIGN);
if (res != ResOK)
goto failSaPages;
@ -373,8 +374,8 @@ static Res VMChunkInit(Chunk chunk, BootBlock boot)
overheadLimit = AddrAdd(chunk->base, (Size)BootAllocated(boot));
/* Put the page table as late as possible, as in VM systems we don't want */
/* to map it. */
/* .overhead.page-table: Put the page table as late as possible, as
* in VM systems we don't want to map it. */
res = BootAlloc(&p, boot, chunk->pageTablePages << chunk->pageShift, chunk->pageSize);
if (res != ResOK)
goto failAllocPageTable;
@ -491,6 +492,64 @@ static void vmArenaTrivContracted(Arena arena, Addr base, Size size)
}
/* vmArenaChunkSize -- compute chunk size
*
* Compute the size of the smallest chunk that has size bytes of usable
* address space (that is, after all overheads are accounted for).
*
* If successful, update *chunkSizeReturn with the computed chunk size
* and return ResOK. If size is too large for a chunk, leave
* *chunkSizeReturn unchanged and return ResRESOURCE.
*/
static Res vmArenaChunkSize(Size *chunkSizeReturn, VMArena vmArena, Size size)
{
Size grainSize; /* Arena grain size. */
Shift grainShift; /* The corresponding Shift. */
Count pages; /* Number of usable pages in chunk. */
Size pageTableSize; /* Size of the page table. */
Count pageTablePages; /* Number of pages in the page table. */
Size chunkSize; /* Size of the chunk. */
Size overhead; /* Total overheads for the chunk. */
AVER(chunkSizeReturn != NULL);
AVERT(VMArena, vmArena);
AVER(size > 0);
grainSize = ArenaGrainSize(VMArena2Arena(vmArena));
grainShift = SizeLog2(grainSize);
overhead = 0;
do {
chunkSize = size + overhead;
/* See .overhead.chunk-struct. */
overhead = SizeAlignUp(sizeof(VMChunkStruct), MPS_PF_ALIGN);
/* See <code/tract.c#overhead.pages>, */
pages = chunkSize >> grainShift;
overhead += SizeAlignUp(BTSize(pages), MPS_PF_ALIGN);
/* See .overhead.sa-mapped. */
overhead += SizeAlignUp(BTSize(pages), MPS_PF_ALIGN);
/* See .overhead.sa-pages. */
pageTableSize = SizeAlignUp(pages * sizeof(PageUnion), grainSize);
pageTablePages = pageTableSize >> grainShift;
overhead += SizeAlignUp(BTSize(pageTablePages), MPS_PF_ALIGN);
/* See .overhead.page-table. */
overhead = SizeAlignUp(overhead, grainSize);
overhead += SizeAlignUp(pageTableSize, grainSize);
if (SizeMAX - overhead < size)
return ResRESOURCE;
} while (chunkSize < size + overhead);
*chunkSizeReturn = chunkSize;
return ResOK;
}
/* VMArenaInit -- create and initialize the VM arena
*
* .arena.init: Once the arena has been allocated, we call ArenaInit
@ -589,6 +648,19 @@ static Res VMArenaInit(Arena *arenaReturn, ArenaClass class, ArgList args)
if (res != ResOK)
goto failChunkCreate;
#if defined(AVER_AND_CHECK_ALL)
/* Check that the computation of the chunk size in vmArenaChunkSize
* was correct, now that we have the actual chunk for comparison. */
{
Size usableSize, computedChunkSize;
usableSize = AddrOffset(PageIndexBase(chunk, chunk->allocBase),
chunk->limit);
res = vmArenaChunkSize(&computedChunkSize, vmArena, usableSize);
AVER(res == ResOK);
AVER(computedChunkSize == ChunkSize(chunk));
}
#endif
/* .zoneshift: Set the zone shift to divide the chunk into the same */
/* number of stripes as will fit into a reference set (the number of */
/* bits in a word). Fail if the chunk is so small stripes are smaller */
@ -655,42 +727,16 @@ static void VMArenaFinish(Arena arena)
}
/* vmArenaChunkSize -- choose chunk size for arena extension
*
* .vmchunk.overhead: This code still lacks a proper estimate of
* the overhead required by a vmChunk for chunkStruct, page tables
* etc. For now, estimate it as 10%. RHSK 2007-12-21
*/
static Size vmArenaChunkSize(VMArena vmArena, Size size)
{
Size fraction = 10; /* 10% -- see .vmchunk.overhead */
Size chunkSize;
Size chunkOverhead;
/* 1: use extendBy, if it is big enough for size + overhead */
chunkSize = vmArena->extendBy;
chunkOverhead = chunkSize / fraction;
if(chunkSize > size && (chunkSize - size) >= chunkOverhead)
return chunkSize;
/* 2: use size + overhead (unless it overflows SizeMAX) */
chunkOverhead = size / (fraction - 1);
if((SizeMAX - size) >= chunkOverhead)
return size + chunkOverhead;
/* 3: use SizeMAX */
return SizeMAX;
}
/* VMArenaGrow -- Extend the arena by making a new chunk
*
* The size arg specifies how much we wish to allocate after the extension.
* size specifies how much we wish to allocate after the extension.
* pref specifies the preference for the location of the allocation.
*/
static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
{
Chunk newChunk;
Size chunkSize;
Size chunkMin;
Res res;
VMArena vmArena;
@ -702,7 +748,10 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
AVERT(LocusPref, pref);
UNUSED(pref);
chunkSize = vmArenaChunkSize(vmArena, size);
res = vmArenaChunkSize(&chunkMin, vmArena, size);
if (res != ResOK)
return res;
chunkSize = vmArena->extendBy;
EVENT3(vmArenaExtendStart, size, chunkSize,
ArenaReserved(VMArena2Arena(vmArena)));
@ -711,7 +760,6 @@ static Res VMArenaGrow(Arena arena, LocusPref pref, Size size)
{
unsigned fidelity = 8; /* max fraction of addr-space we may 'waste' */
Size chunkHalf;
Size chunkMin = 4 * 1024; /* typical single page */
Size sliceSize;
if (vmArena->extendMin > chunkMin)

View file

@ -198,6 +198,7 @@ Res LandInsert(Range rangeReturn, Land land, Range range)
AVERT(Land, land);
AVERT(Range, range);
AVER(RangeIsAligned(range, land->alignment));
AVER(!RangeIsEmpty(range));
landEnter(land);
res = (*land->class->insert)(rangeReturn, land, range);

View file

@ -174,6 +174,7 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
Count pages;
Shift pageShift;
Size pageTableSize;
Addr allocBase;
void *p;
Res res;
@ -196,6 +197,7 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
chunk->reserved = reserved;
size = ChunkSize(chunk);
/* .overhead.pages: Chunk overhead for the page allocation table. */
chunk->pages = pages = size >> pageShift;
res = BootAlloc(&p, boot, (size_t)BTSize(pages), MPS_PF_ALIGN);
if (res != ResOK)
@ -219,12 +221,14 @@ Res ChunkInit(Chunk chunk, Arena arena, Addr base, Addr limit, Size reserved,
/* Init allocTable after class init, because it might be mapped there. */
BTResRange(chunk->allocTable, 0, pages);
/* Check that there is some usable address space remaining in the chunk. */
allocBase = PageIndexBase(chunk, chunk->allocBase);
AVER(allocBase < chunk->limit);
/* Add the chunk's free address space to the arena's freeLand, so that
we can allocate from it. */
if (arena->hasFreeLand) {
res = ArenaFreeLandInsert(arena,
PageIndexBase(chunk, chunk->allocBase),
chunk->limit);
res = ArenaFreeLandInsert(arena, allocBase, chunk->limit);
if (res != ResOK)
goto failLandInsert;
}