Skip to content
This repository has been archived by the owner on Oct 12, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1107 from rainers/fullcollect_refactor
Browse files Browse the repository at this point in the history
refactor GC: split fullcollect into separate functions
  • Loading branch information
MartinNowak committed Jan 20, 2015
2 parents ce6edc5 + b74cc55 commit 4bd360d
Showing 1 changed file with 92 additions and 64 deletions.
156 changes: 92 additions & 64 deletions src/gc/gc.d
Original file line number Diff line number Diff line change
Expand Up @@ -2516,29 +2516,11 @@ struct Gcx
goto Lagain;
}


/**
* Return number of full pages free'd.
*/
size_t fullcollect() nothrow
// collection step 1: prepare freebits and mark bits
void prepare() nothrow
{
size_t n;
Pool* pool;
MonoTime start, stop, begin;

if (GC.config.profile)
{
begin = start = currTime;
}

debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n");
//printf("\tpool address range = %p .. %p\n", minAddr, maxAddr);

if (running)
onInvalidMemoryOperationError();
running = 1;

thread_suspendAll();

for (n = 0; n < npools; n++)
{
Expand Down Expand Up @@ -2570,14 +2552,11 @@ struct Gcx
pool.mark.copy(&pool.freebits);
}
}
}

if (GC.config.profile)
{
stop = currTime;
prepTime += (stop - start);
start = stop;
}

// collection step 2: mark roots and heap
void markAll() nothrow
{
if (!noStack)
{
debug(COLLECT_PRINTF) printf("\tscan stacks.\n");
Expand All @@ -2601,30 +2580,19 @@ struct Gcx
mark(range.pbot, range.ptop);
}
//log--;
}

debug(COLLECT_PRINTF) printf("\tscan heap\n");

thread_processGCMarks(&isMarked);
thread_resumeAll();

if (GC.config.profile)
{
stop = currTime;
markTime += (stop - start);
Duration pause = stop - begin;
if (pause > maxPauseTime)
maxPauseTime = pause;
start = stop;
}

// collection step 3: free all unreferenced objects
size_t sweep() nothrow
{
// Free up everything not marked
debug(COLLECT_PRINTF) printf("\tfree'ing\n");
size_t freedpages = 0;
size_t freed = 0;
for (n = 0; n < npools; n++)
{ size_t pn;

pool = pooltable[n];
for (size_t n = 0; n < npools; n++)
{
size_t pn;
Pool* pool = pooltable[n];

if(pool.isLargeObject)
{
Expand Down Expand Up @@ -2741,24 +2709,27 @@ struct Gcx
}
}

if (GC.config.profile)
{
stop = currTime;
sweepTime += (stop - start);
start = stop;
}
debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools);
return freedpages;
}

// collection step 4: recover pages with no live objects, rebuild free lists
size_t recover() nothrow
{
// Zero buckets
bucket[] = null;

// Free complete pages, rebuild free list
debug(COLLECT_PRINTF) printf("\tfree complete pages\n");
size_t recoveredpages = 0;
for (n = 0; n < npools; n++)
{ size_t pn;
for (size_t n = 0; n < npools; n++)
{
size_t pn;
Pool* pool = pooltable[n];

if(pool.isLargeObject)
continue;

pool = pooltable[n];
if(pool.isLargeObject) continue;
for (pn = 0; pn < pool.npages; pn++)
{
Bins bin = cast(Bins)pool.pagetable[pn];
Expand All @@ -2775,7 +2746,8 @@ struct Gcx

biti = bitbase;
for (biti = bitbase; biti < bittop; biti += bitstride)
{ if (!pool.freebits.test(biti))
{
if (!pool.freebits.test(biti))
goto Lnotfree;
}
pool.pagetable[pn] = B_FREE;
Expand All @@ -2784,14 +2756,13 @@ struct Gcx
recoveredpages++;
continue;

Lnotfree:
Lnotfree:
p = pool.baseAddr + pn * PAGESIZE;
for (u = 0; u < PAGESIZE; u += size)
{ biti = bitbase + u / 16;
if (pool.freebits.test(biti))
{ List *list;

list = cast(List *)(p + u);
{
List *list = cast(List *)(p + u);
if (list.next != bucket[bin]) // avoid unnecessary writes
list.next = bucket[bin];
list.pool = pool;
Expand All @@ -2802,16 +2773,73 @@ struct Gcx
}
}

debug(COLLECT_PRINTF) printf("\trecovered pages = %d\n", recoveredpages);
return recoveredpages;
}

/**
* Return number of full pages free'd.
*/
size_t fullcollect() nothrow
{
MonoTime start, stop, begin;

if (GC.config.profile)
{
begin = start = currTime;
}

debug(COLLECT_PRINTF) printf("Gcx.fullcollect()\n");
//printf("\tpool address range = %p .. %p\n", minAddr, maxAddr);

if (running)
onInvalidMemoryOperationError();
running = 1;

thread_suspendAll();

prepare();

if (GC.config.profile)
{
stop = currTime;
prepTime += (stop - start);
start = stop;
}

markAll();

thread_processGCMarks(&isMarked);
thread_resumeAll();

if (GC.config.profile)
{
stop = currTime;
markTime += (stop - start);
Duration pause = stop - begin;
if (pause > maxPauseTime)
maxPauseTime = pause;
start = stop;
}

size_t freedpages = sweep();

if (GC.config.profile)
{
stop = currTime;
sweepTime += (stop - start);
start = stop;
}

size_t recoveredpages = recover();

if (GC.config.profile)
{
stop = currTime;
recoverTime += (stop - start);
++numCollections;
}

debug(COLLECT_PRINTF) printf("\trecovered pages = %d\n", recoveredpages);
debug(COLLECT_PRINTF) printf("\tfree'd %u bytes, %u pages from %u pools\n", freed, freedpages, npools);

running = 0; // only clear on success

return freedpages + recoveredpages;
Expand Down

0 comments on commit 4bd360d

Please sign in to comment.