* evacuate to an older generation, adjust it here (see comment
* by evacuate()).
*/
- if (stp->gen_no < gct->evac_gen) {
+ if (stp < gct->evac_step) {
if (gct->eager_promotion) {
- stp = &generations[gct->evac_gen].steps[0];
+ stp = gct->evac_step;
} else {
gct->failed_to_evac = rtsTrue;
}
* evacuate to an older generation, adjust it here (see comment
* by evacuate()).
*/
- if (stp->gen_no < gct->evac_gen) {
+ if (stp < gct->evac_step) {
if (gct->eager_promotion) {
- stp = &generations[gct->evac_gen].steps[0];
+ stp = gct->evac_step;
} else {
gct->failed_to_evac = rtsTrue;
}
} while (info == (W_)&stg_WHITEHOLE_info);
if (info == (W_)&stg_EVACUATED_info) {
src->header.info = (const StgInfoTable *)info;
- return evacuate(src); // does the failed_to_evac stuff
+ return evacuate(p); // does the failed_to_evac stuff
}
#else
info = (W_)src->header.info;
} while (info == (W_)&stg_WHITEHOLE_info);
if (info == (W_)&stg_EVACUATED_info) {
src->header.info = (const StgInfoTable *)info;
- return evacuate(src); // does the failed_to_evac stuff
+ return evacuate(p); // does the failed_to_evac stuff
}
#else
info = (W_)src->header.info;
src->header.info = &stg_EVACUATED_info;
#endif
-
+
to = alloc_for_copy_noscav(size,stp);
tagged_to = (StgPtr)TAG_CLOSURE(tag,(StgClosure*)to);
*p = (StgClosure *)tagged_to;
} while (info == (W_)&stg_WHITEHOLE_info);
if (info == (W_)&stg_EVACUATED_info) {
src->header.info = (const StgInfoTable *)info;
- return evacuate(src); // does the failed_to_evac stuff
+ return evacuate(p); // does the failed_to_evac stuff
}
#else
info = (W_)src->header.info;
/* Don't forget to set the gct->failed_to_evac flag if we didn't get
* the desired destination (see comments in evacuate()).
*/
- if (bd->gen_no < gct->evac_gen) {
+ if (bd->step < gct->evac_step) {
gct->failed_to_evac = rtsTrue;
TICK_GC_FAILED_PROMOTION();
}
/* link it on to the evacuated large object list of the destination step
*/
stp = bd->step->to;
- if (stp->gen_no < gct->evac_gen) {
+ if (stp < gct->evac_step) {
if (gct->eager_promotion) {
- stp = &generations[gct->evac_gen].steps[0];
+ stp = gct->evac_step;
} else {
gct->failed_to_evac = rtsTrue;
}
This is called (eventually) for every live object in the system.
The caller to evacuate specifies a desired generation in the
- gct->evac_gen thread-lock variable. The following conditions apply to
+ gct->evac_step thread-local variable. The following conditions apply to
evacuating an object which resides in generation M when we're
collecting up to generation N
- if M >= gct->evac_gen
+ if M >= gct->evac_step
if M > N do nothing
else evac to step->to
- if M < gct->evac_gen evac to gct->evac_gen, step 0
+ if M < gct->evac_step evac to gct->evac_step, step 0
if the object is already evacuated, then we check which generation
it now resides in.
- if M >= gct->evac_gen do nothing
- if M < gct->evac_gen set gct->failed_to_evac flag to indicate that we
- didn't manage to evacuate this object into gct->evac_gen.
+ if M >= gct->evac_step do nothing
+ if M < gct->evac_step set gct->failed_to_evac flag to indicate that we
+ didn't manage to evacuate this object into gct->evac_step.
OPTIMISATION NOTES:
if (bd->gen_no > N) {
/* Can't evacuate this object, because it's in a generation
* older than the ones we're collecting. Let's hope that it's
- * in gct->evac_gen or older, or we will have to arrange to track
+ * in gct->evac_step or older, or we will have to arrange to track
* this pointer using the mutable list.
*/
- if (bd->gen_no < gct->evac_gen) {
+ if (bd->step < gct->evac_step) {
// nope
gct->failed_to_evac = rtsTrue;
TICK_GC_FAILED_PROMOTION();
* object twice, for example).
*/
if (bd->flags & BF_EVACUATED) {
- if (bd->gen_no < gct->evac_gen) {
+ if (bd->step < gct->evac_step) {
gct->failed_to_evac = rtsTrue;
TICK_GC_FAILED_PROMOTION();
}
case EVACUATED:
/* Already evacuated, just return the forwarding address.
- * HOWEVER: if the requested destination generation (gct->evac_gen) is
+ * HOWEVER: if the requested destination generation (gct->evac_step) is
* older than the actual generation (because the object was
* already evacuated to a younger generation) then we have to
* set the gct->failed_to_evac flag to indicate that we couldn't
{
StgClosure *e = ((StgEvacuated*)q)->evacuee;
*p = e;
- if (gct->evac_gen > 0 && stp->gen_no < gct->evac_gen) { // optimisation
- if (HEAP_ALLOCED(e) && Bdescr((P_)e)->gen_no < gct->evac_gen) {
+ if (stp < gct->evac_step) { // optimisation
+ if (HEAP_ALLOCED(e) && Bdescr((P_)e)->step < gct->evac_step) {
gct->failed_to_evac = rtsTrue;
TICK_GC_FAILED_PROMOTION();
}
/* -----------------------------------------------------------------------------
Scavenge a block from the given scan pointer up to bd->free.
- evac_gen is set by the caller to be either zero (for a step in a
+ evac_step is set by the caller to be either zero (for a step in a
generation < N) or G where G is the generation of the step being
scavenged.
- We sometimes temporarily change evac_gen back to zero if we're
+ We sometimes temporarily change evac_step back to zero if we're
scavenging a mutable object where eager promotion isn't such a good
idea.
-------------------------------------------------------------------------- */
{
StgPtr p, q;
StgInfoTable *info;
- nat saved_evac_gen;
+ step *saved_evac_step;
p = scan;
debugTrace(DEBUG_gc, "scavenging block %p (gen %d, step %d) @ %p",
bd->start, bd->gen_no, bd->step->no, scan);
- gct->evac_gen = bd->gen_no;
- saved_evac_gen = gct->evac_gen;
+ gct->evac_step = bd->step;
+ saved_evac_step = gct->evac_step;
gct->failed_to_evac = rtsFalse;
// we might be evacuating into the very object that we're
case TVAR_WATCH_QUEUE:
{
StgTVarWatchQueue *wq = ((StgTVarWatchQueue *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&wq->closure);
evacuate((StgClosure **)&wq->next_queue_entry);
evacuate((StgClosure **)&wq->prev_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
p += sizeofW(StgTVarWatchQueue);
break;
case TVAR:
{
StgTVar *tvar = ((StgTVar *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&tvar->current_value);
evacuate((StgClosure **)&tvar->first_watch_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
p += sizeofW(StgTVar);
break;
case TREC_HEADER:
{
StgTRecHeader *trec = ((StgTRecHeader *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&trec->enclosing_trec);
evacuate((StgClosure **)&trec->current_chunk);
evacuate((StgClosure **)&trec->invariants_to_check);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
p += sizeofW(StgTRecHeader);
break;
StgWord i;
StgTRecChunk *tc = ((StgTRecChunk *) p);
TRecEntry *e = &(tc -> entries[0]);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&tc->prev_chunk);
for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
evacuate((StgClosure **)&e->tvar);
evacuate((StgClosure **)&e->expected_value);
evacuate((StgClosure **)&e->new_value);
}
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
p += sizeofW(StgTRecChunk);
break;
case ATOMIC_INVARIANT:
{
StgAtomicInvariant *invariant = ((StgAtomicInvariant *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate(&invariant->code);
evacuate((StgClosure **)&invariant->last_execution);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
p += sizeofW(StgAtomicInvariant);
break;
case INVARIANT_CHECK_QUEUE:
{
StgInvariantCheckQueue *queue = ((StgInvariantCheckQueue *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&queue->invariant);
evacuate((StgClosure **)&queue->my_execution);
evacuate((StgClosure **)&queue->next_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
p += sizeofW(StgInvariantCheckQueue);
break;
{
StgPtr p, q;
StgInfoTable *info;
- nat saved_evac_gen;
+ step *saved_evac_step;
- gct->evac_gen = oldest_gen->no;
- saved_evac_gen = gct->evac_gen;
+ gct->evac_step = &oldest_gen->steps[0];
+ saved_evac_step = gct->evac_step;
linear_scan:
while (!mark_stack_empty()) {
case TVAR_WATCH_QUEUE:
{
StgTVarWatchQueue *wq = ((StgTVarWatchQueue *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&wq->closure);
evacuate((StgClosure **)&wq->next_queue_entry);
evacuate((StgClosure **)&wq->prev_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case TVAR:
{
StgTVar *tvar = ((StgTVar *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&tvar->current_value);
evacuate((StgClosure **)&tvar->first_watch_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
StgWord i;
StgTRecChunk *tc = ((StgTRecChunk *) p);
TRecEntry *e = &(tc -> entries[0]);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&tc->prev_chunk);
for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
evacuate((StgClosure **)&e->tvar);
evacuate((StgClosure **)&e->expected_value);
evacuate((StgClosure **)&e->new_value);
}
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case TREC_HEADER:
{
StgTRecHeader *trec = ((StgTRecHeader *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&trec->enclosing_trec);
evacuate((StgClosure **)&trec->current_chunk);
evacuate((StgClosure **)&trec->invariants_to_check);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case ATOMIC_INVARIANT:
{
StgAtomicInvariant *invariant = ((StgAtomicInvariant *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate(&invariant->code);
evacuate((StgClosure **)&invariant->last_execution);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case INVARIANT_CHECK_QUEUE:
{
StgInvariantCheckQueue *queue = ((StgInvariantCheckQueue *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&queue->invariant);
evacuate((StgClosure **)&queue->my_execution);
evacuate((StgClosure **)&queue->next_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
if (gct->failed_to_evac) {
gct->failed_to_evac = rtsFalse;
- if (gct->evac_gen > 0) {
- recordMutableGen_GC((StgClosure *)q, &generations[gct->evac_gen]);
+ if (gct->evac_step) {
+ recordMutableGen_GC((StgClosure *)q, gct->evac_step->gen);
}
}
scavenge_one(StgPtr p)
{
const StgInfoTable *info;
- nat saved_evac_gen = gct->evac_gen;
+ step *saved_evac_step = gct->evac_step;
rtsBool no_luck;
ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
case TVAR_WATCH_QUEUE:
{
StgTVarWatchQueue *wq = ((StgTVarWatchQueue *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&wq->closure);
evacuate((StgClosure **)&wq->next_queue_entry);
evacuate((StgClosure **)&wq->prev_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case TVAR:
{
StgTVar *tvar = ((StgTVar *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&tvar->current_value);
evacuate((StgClosure **)&tvar->first_watch_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case TREC_HEADER:
{
StgTRecHeader *trec = ((StgTRecHeader *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&trec->enclosing_trec);
evacuate((StgClosure **)&trec->current_chunk);
evacuate((StgClosure **)&trec->invariants_to_check);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
StgWord i;
StgTRecChunk *tc = ((StgTRecChunk *) p);
TRecEntry *e = &(tc -> entries[0]);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&tc->prev_chunk);
for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
evacuate((StgClosure **)&e->tvar);
evacuate((StgClosure **)&e->expected_value);
evacuate((StgClosure **)&e->new_value);
}
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case ATOMIC_INVARIANT:
{
StgAtomicInvariant *invariant = ((StgAtomicInvariant *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate(&invariant->code);
evacuate((StgClosure **)&invariant->last_execution);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
case INVARIANT_CHECK_QUEUE:
{
StgInvariantCheckQueue *queue = ((StgInvariantCheckQueue *) p);
- gct->evac_gen = 0;
+ gct->evac_step = 0;
evacuate((StgClosure **)&queue->invariant);
evacuate((StgClosure **)&queue->my_execution);
evacuate((StgClosure **)&queue->next_queue_entry);
- gct->evac_gen = saved_evac_gen;
+ gct->evac_step = saved_evac_step;
gct->failed_to_evac = rtsTrue; // mutable
break;
}
bd = gen->saved_mut_list;
- gct->evac_gen = gen->no;
+ gct->evac_step = &gen->steps[0];
for (; bd != NULL; bd = bd->link) {
for (q = bd->start; q < bd->free; q++) {
p = (StgPtr)*q;
/* Always evacuate straight to the oldest generation for static
* objects */
- gct->evac_gen = oldest_gen->no;
+ gct->evac_step = &oldest_gen->steps[0];
/* keep going until we've scavenged all the objects on the linked
list... */
/*-----------------------------------------------------------------------------
scavenge the large object list.
- evac_gen set by caller; similar games played with evac_gen as with
+ evac_step set by caller; similar games played with evac_step as with
scavenge() - see comment at the top of scavenge(). Most large
- objects are (repeatedly) mutable, so most of the time evac_gen will
+ objects are (repeatedly) mutable, so most of the time evac_step will
be zero.
--------------------------------------------------------------------------- */
bdescr *bd;
StgPtr p;
- gct->evac_gen = ws->stp->gen_no;
+ gct->evac_step = ws->stp;
bd = ws->todo_large_objects;