-/* -----------------------------------------------------------------------------
+/* -----------------------------------------------------------------------*-c-*-
*
* (c) The GHC Team 1998-2006
*
*
* ---------------------------------------------------------------------------*/
-// This file is #included into Scav.c, twice: firstly with MINOR_GC
+// This file is #included into Scav.c, twice: firstly with PARALLEL_GC
// defined, the second time without.
-#ifdef MINOR_GC
-#define scavenge_block(a,b) scavenge_block0(a,b)
-#define evacuate(a) evacuate0(a)
+#ifndef PARALLEL_GC
+#define scavenge_block(a) scavenge_block1(a)
+#define evacuate(a) evacuate1(a)
+#define recordMutableGen_GC(a,b) recordMutableGen(a,b)
#else
#undef scavenge_block
#undef evacuate
+#undef recordMutableGen_GC
#endif
-static void scavenge_block (bdescr *bd, StgPtr scan);
+static void scavenge_block (bdescr *bd);
/* -----------------------------------------------------------------------------
Scavenge a block from the given scan pointer up to bd->free.
-------------------------------------------------------------------------- */
static void
-scavenge_block (bdescr *bd, StgPtr scan)
+scavenge_block (bdescr *bd)
{
StgPtr p, q;
StgInfoTable *info;
step *saved_evac_step;
+ rtsBool saved_eager_promotion;
+ step_workspace *ws;
- p = scan;
+ p = bd->u.scan;
debugTrace(DEBUG_gc, "scavenging block %p (gen %d, step %d) @ %p",
- bd->start, bd->gen_no, bd->step->no, scan);
+ bd->start, bd->gen_no, bd->step->no, p);
gct->evac_step = bd->step;
saved_evac_step = gct->evac_step;
+ saved_eager_promotion = gct->eager_promotion;
gct->failed_to_evac = rtsFalse;
+ ws = &gct->steps[bd->step->abs_no];
+
// we might be evacuating into the very object that we're
// scavenging, so we have to check the real bd->free pointer each
// time around the loop.
- while (p < bd->free) {
+ while (p < bd->free || (bd == ws->todo_bd && p < ws->todo_free)) {
ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
info = get_itbl((StgClosure *)p);
case MVAR_CLEAN:
case MVAR_DIRTY:
{
- rtsBool saved_eager_promotion = gct->eager_promotion;
-
StgMVar *mvar = ((StgMVar *)p);
gct->eager_promotion = rtsFalse;
evacuate((StgClosure **)&mvar->head);
}
case FUN_2_0:
-#ifndef MINOR_GC
scavenge_fun_srt(info);
-#endif
evacuate(&((StgClosure *)p)->payload[1]);
evacuate(&((StgClosure *)p)->payload[0]);
p += sizeofW(StgHeader) + 2;
break;
case THUNK_2_0:
-#ifndef MINOR_GC
scavenge_thunk_srt(info);
-#endif
evacuate(&((StgThunk *)p)->payload[1]);
evacuate(&((StgThunk *)p)->payload[0]);
p += sizeofW(StgThunk) + 2;
break;
case THUNK_1_0:
-#ifndef MINOR_GC
scavenge_thunk_srt(info);
-#endif
evacuate(&((StgThunk *)p)->payload[0]);
p += sizeofW(StgThunk) + 1;
break;
case FUN_1_0:
-#ifndef MINOR_GC
scavenge_fun_srt(info);
-#endif
case CONSTR_1_0:
evacuate(&((StgClosure *)p)->payload[0]);
p += sizeofW(StgHeader) + 1;
break;
case THUNK_0_1:
-#ifndef MINOR_GC
scavenge_thunk_srt(info);
-#endif
p += sizeofW(StgThunk) + 1;
break;
case FUN_0_1:
-#ifndef MINOR_GC
scavenge_fun_srt(info);
-#endif
case CONSTR_0_1:
p += sizeofW(StgHeader) + 1;
break;
case THUNK_0_2:
-#ifndef MINOR_GC
scavenge_thunk_srt(info);
-#endif
p += sizeofW(StgThunk) + 2;
break;
case FUN_0_2:
-#ifndef MINOR_GC
scavenge_fun_srt(info);
-#endif
case CONSTR_0_2:
p += sizeofW(StgHeader) + 2;
break;
case THUNK_1_1:
-#ifndef MINOR_GC
scavenge_thunk_srt(info);
-#endif
evacuate(&((StgThunk *)p)->payload[0]);
p += sizeofW(StgThunk) + 2;
break;
case FUN_1_1:
-#ifndef MINOR_GC
scavenge_fun_srt(info);
-#endif
case CONSTR_1_1:
evacuate(&((StgClosure *)p)->payload[0]);
p += sizeofW(StgHeader) + 2;
break;
case FUN:
-#ifndef MINOR_GC
scavenge_fun_srt(info);
-#endif
goto gen_obj;
case THUNK:
{
StgPtr end;
-#ifndef MINOR_GC
scavenge_thunk_srt(info);
-#endif
end = (P_)((StgThunk *)p)->payload + info->layout.payload.ptrs;
for (p = (P_)((StgThunk *)p)->payload; p < end; p++) {
evacuate((StgClosure **)p);
break;
case MUT_VAR_CLEAN:
- case MUT_VAR_DIRTY: {
- rtsBool saved_eager_promotion = gct->eager_promotion;
-
+ case MUT_VAR_DIRTY:
gct->eager_promotion = rtsFalse;
evacuate(&((StgMutVar *)p)->var);
gct->eager_promotion = saved_eager_promotion;
}
p += sizeofW(StgMutVar);
break;
- }
case CAF_BLACKHOLE:
case SE_CAF_BLACKHOLE:
// follow everything
{
StgPtr next;
- rtsBool saved_eager;
// We don't eagerly promote objects pointed to by a mutable
// array, but if we find the array only points to objects in
// the same or an older generation, we mark it "clean" and
// avoid traversing it during minor GCs.
- saved_eager = gct->eager_promotion;
gct->eager_promotion = rtsFalse;
next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
evacuate((StgClosure **)p);
}
- gct->eager_promotion = saved_eager;
+ gct->eager_promotion = saved_eager_promotion;
if (gct->failed_to_evac) {
((StgClosure *)q)->header.info = &stg_MUT_ARR_PTRS_DIRTY_info;
case TSO:
{
StgTSO *tso = (StgTSO *)p;
- rtsBool saved_eager = gct->eager_promotion;
gct->eager_promotion = rtsFalse;
scavengeTSO(tso);
- gct->eager_promotion = saved_eager;
+ gct->eager_promotion = saved_eager_promotion;
if (gct->failed_to_evac) {
tso->flags |= TSO_DIRTY;
}
}
- debugTrace(DEBUG_gc, " scavenged %ld bytes", (bd->free - scan) * sizeof(W_));
+ if (p > bd->free) {
+ bd->free = p;
+ }
+
+ debugTrace(DEBUG_gc, " scavenged %ld bytes",
+ (unsigned long)((bd->free - bd->u.scan) * sizeof(W_)));
+
+ // update stats: this is a block that has been copied & scavenged
+ gct->copied += bd->free - bd->u.scan;
+
+ bd->u.scan = bd->free;
}
+
+#undef scavenge_block
+#undef evacuate
+#undef recordMutableGen_GC