Showing with 36 additions and 31 deletions.
  1. +36 −31 src/gc/gc.d
67 changes: 36 additions & 31 deletions src/gc/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -2024,7 +2024,7 @@ struct Gcx
//debug(PRINTF) printf("\t\tbiti = x%x\n", biti);

pcache = cast(size_t)p & ~cast(size_t)(PAGESIZE-1);

// For the NO_INTERIOR attribute. This tracks whether
// the pointer is an interior pointer or points to the
// base address of a block.
Expand Down Expand Up @@ -2217,6 +2217,7 @@ struct Gcx
memset(p, 0xF3, PAGESIZE);
}
}
pool.largestFree = pool.freepages; // invalidate
}
}
}
Expand Down Expand Up @@ -2614,6 +2615,7 @@ struct Pool
// page in this pool is, so that if a lot of pages towards the beginning
// are occupied, we can bypass them in O(1).
size_t searchStart;
size_t largestFree; // upper limit for largest free chunk in large object pool

void initialize(size_t npages, bool isLargeObject) nothrow
{
Expand Down Expand Up @@ -2669,6 +2671,8 @@ struct Pool

this.npages = npages;
this.freepages = npages;
this.searchStart = 0;
this.largestFree = npages;
}


Expand Down Expand Up @@ -2911,43 +2915,42 @@ struct LargeObjectPool
*/
size_t allocPages(size_t n) nothrow
{
if(freepages < n) return OPFAIL;
size_t i;
size_t n2;
if(largestFree < n || searchStart + n > npages)
return OPFAIL;

//debug(PRINTF) printf("Pool::allocPages(n = %d)\n", n);
n2 = n;
for (i = searchStart; i < npages; i++)
size_t largest = 0;
if (pagetable[searchStart] == B_PAGEPLUS)
{
if (pagetable[i] == B_FREE)
{
if(pagetable[searchStart] < B_FREE)
{
searchStart = i;
}

if (--n2 == 0)
{ //debug(PRINTF) printf("\texisting pn = %d\n", i - n + 1);
return i - n + 1;
}
}
else
{
n2 = n;
if(pagetable[i] == B_PAGE)
{
// Then we have the offset information. We can skip a
// whole bunch of stuff.
i += bPageOffsets[i] - 1;
}
}
searchStart -= bPageOffsets[searchStart]; // jump to B_PAGE
searchStart += bPageOffsets[searchStart];
}
while (searchStart < npages && pagetable[searchStart] == B_PAGE)
searchStart += bPageOffsets[searchStart];

if(pagetable[searchStart] < B_FREE)
for (size_t i = searchStart; i < npages; )
{
searchStart = npages;
assert(pagetable[i] == B_FREE);
size_t p = 1;
while (p < n && pagetable[i + p] == B_FREE)
p++;

if (p == n)
return i;

if (p > largest)
largest = p;

i += p;
while(i < npages && pagetable[i] == B_PAGE)
{
// we have the size information, so we skip a whole bunch of pages.
i += bPageOffsets[i];
}
}

// not enough free pages found, remember largest free chunk
largestFree = largest;
return OPFAIL;
}

Expand All @@ -2957,7 +2960,8 @@ struct LargeObjectPool
void freePages(size_t pagenum, size_t npages) nothrow
{
//memset(&pagetable[pagenum], B_FREE, npages);
if(pagenum < searchStart) searchStart = pagenum;
if(pagenum < searchStart)
searchStart = pagenum;

for(size_t i = pagenum; i < npages + pagenum; i++)
{
Expand All @@ -2968,6 +2972,7 @@ struct LargeObjectPool

pagetable[i] = B_FREE;
}
largestFree = freepages; // invalidate
}

/**
Expand Down