X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2Fsm%2FScav.c;h=732ad15927470283ee1523ef670d4c4401093c20;hb=1b3d6042138d884841df3bc530b022dc13c5f296;hp=f61d6b7a61d8bd35c6bef2fa41e5b1e5ffe4940a;hpb=b339c8b1d0f239031802555b454062e9430ec8bb;p=ghc-hetmet.git diff --git a/rts/sm/Scav.c b/rts/sm/Scav.c index f61d6b7..732ad15 100644 --- a/rts/sm/Scav.c +++ b/rts/sm/Scav.c @@ -25,6 +25,7 @@ #include "Trace.h" #include "LdvProfile.h" #include "Sanity.h" +#include "Capability.h" static void scavenge_stack (StgPtr p, StgPtr stack_end); @@ -36,7 +37,8 @@ static void scavenge_large_bitmap (StgPtr p, # define evacuate(a) evacuate1(a) # define recordMutableGen_GC(a,b) recordMutableGen(a,b) # define scavenge_loop(a) scavenge_loop1(a) -# define scavenge_mutable_list(g) scavenge_mutable_list1(g) +# define scavenge_mutable_list(bd,g) scavenge_mutable_list1(bd,g) +# define scavenge_capability_mut_lists(cap) scavenge_capability_mut_Lists1(cap) #endif /* ----------------------------------------------------------------------------- @@ -67,6 +69,8 @@ scavengeTSO (StgTSO *tso) return; } + debugTrace(DEBUG_gc,"scavenging thread %d",(int)tso->id); + saved_eager = gct->eager_promotion; gct->eager_promotion = rtsFalse; @@ -140,7 +144,7 @@ scavenge_arg_block (StgFunInfoTable *fun_info, StgClosure **args) return p; } -STATIC_INLINE StgPtr +STATIC_INLINE GNUC_ATTR_HOT StgPtr scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size) { StgPtr p; @@ -179,7 +183,7 @@ scavenge_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size) return p; } -STATIC_INLINE StgPtr +STATIC_INLINE GNUC_ATTR_HOT StgPtr scavenge_PAP (StgPAP *pap) { evacuate(&pap->fun); @@ -230,7 +234,7 @@ scavenge_large_srt_bitmap( StgLargeSRT *large_srt ) * srt field in the info table. That's ok, because we'll * never dereference it. */ -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void scavenge_srt (StgClosure **srt, nat srt_bitmap) { nat bitmap; @@ -270,7 +274,7 @@ scavenge_srt (StgClosure **srt, nat srt_bitmap) } -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void scavenge_thunk_srt(const StgInfoTable *info) { StgThunkInfoTable *thunk_info; @@ -281,7 +285,7 @@ scavenge_thunk_srt(const StgInfoTable *info) scavenge_srt((StgClosure **)GET_SRT(thunk_info), thunk_info->i.srt_bitmap); } -STATIC_INLINE void +STATIC_INLINE GNUC_ATTR_HOT void scavenge_fun_srt(const StgInfoTable *info) { StgFunInfoTable *fun_info; @@ -304,7 +308,7 @@ scavenge_fun_srt(const StgInfoTable *info) idea. -------------------------------------------------------------------------- */ -static void +static GNUC_ATTR_HOT void scavenge_block (bdescr *bd) { StgPtr p, q; @@ -504,8 +508,6 @@ scavenge_block (bdescr *bd) break; case CAF_BLACKHOLE: - case SE_CAF_BLACKHOLE: - case SE_BLACKHOLE: case BLACKHOLE: p += BLACKHOLE_sizeW(); break; @@ -694,7 +696,7 @@ scavenge_block (bdescr *bd) if (gct->failed_to_evac) { gct->failed_to_evac = rtsFalse; if (bd->gen_no > 0) { - recordMutableGen_GC((StgClosure *)q, &generations[bd->gen_no]); + recordMutableGen_GC((StgClosure *)q, bd->gen_no); } } } @@ -745,7 +747,7 @@ linear_scan: info = get_itbl((StgClosure *)p); q = p; - switch (((volatile StgWord *)info)[1] & 0xffff) { + switch (info->type) { case MVAR_CLEAN: case MVAR_DIRTY: @@ -881,8 +883,6 @@ linear_scan: } case CAF_BLACKHOLE: - case SE_CAF_BLACKHOLE: - case SE_BLACKHOLE: case BLACKHOLE: case ARR_WORDS: break; @@ -1051,7 +1051,7 @@ linear_scan: if (gct->failed_to_evac) { gct->failed_to_evac = rtsFalse; if (gct->evac_step) { - recordMutableGen_GC((StgClosure *)q, gct->evac_step->gen); + recordMutableGen_GC((StgClosure *)q, gct->evac_step->gen_no); } } @@ -1197,8 +1197,6 @@ scavenge_one(StgPtr p) } case CAF_BLACKHOLE: - case SE_CAF_BLACKHOLE: - case SE_BLACKHOLE: case BLACKHOLE: break; @@ -1425,13 +1423,10 @@ scavenge_one(StgPtr p) -------------------------------------------------------------------------- */ void -scavenge_mutable_list(generation *gen) +scavenge_mutable_list(bdescr *bd, generation *gen) { - bdescr *bd; StgPtr p, q; - bd = gen->saved_mut_list; - gct->evac_step = &gen->steps[0]; for (; bd != NULL; bd = bd->link) { for (q = bd->start; q < bd->free; q++) { @@ -1462,12 +1457,12 @@ scavenge_mutable_list(generation *gen) // definitely doesn't point into a young generation. // Clean objects don't need to be scavenged. Some clean // objects (MUT_VAR_CLEAN) are not kept on the mutable - // list at all; others, such as MUT_ARR_PTRS_CLEAN and - // TSO, are always on the mutable list. + // list at all; others, such as MUT_ARR_PTRS_CLEAN + // are always on the mutable list. // switch (get_itbl((StgClosure *)p)->type) { case MUT_ARR_PTRS_CLEAN: - recordMutableGen_GC((StgClosure *)p,gen); + recordMutableGen_GC((StgClosure *)p,gen->no); continue; case TSO: { StgTSO *tso = (StgTSO *)p; @@ -1478,7 +1473,7 @@ scavenge_mutable_list(generation *gen) scavenge_TSO_link(tso); if (gct->failed_to_evac) { - recordMutableGen_GC((StgClosure *)p,gen); + recordMutableGen_GC((StgClosure *)p,gen->no); gct->failed_to_evac = rtsFalse; } else { tso->flags &= ~TSO_LINK_DIRTY; @@ -1493,14 +1488,28 @@ scavenge_mutable_list(generation *gen) if (scavenge_one(p)) { // didn't manage to promote everything, so put the // object back on the list. - recordMutableGen_GC((StgClosure *)p,gen); + recordMutableGen_GC((StgClosure *)p,gen->no); } } } +} + +void +scavenge_capability_mut_lists (Capability *cap) +{ + nat g; - // free the old mut_list - freeChain_sync(gen->saved_mut_list); - gen->saved_mut_list = NULL; + /* Mutable lists from each generation > N + * we want to *scavenge* these roots, not evacuate them: they're not + * going to move in this GC. + * Also do them in reverse generation order, for the usual reason: + * namely to reduce the likelihood of spurious old->new pointers. + */ + for (g = RtsFlags.GcFlags.generations-1; g > N; g--) { + scavenge_mutable_list(cap->saved_mut_lists[g], &generations[g]); + freeChain_sync(cap->saved_mut_lists[g]); + cap->saved_mut_lists[g] = NULL; + } } /* ----------------------------------------------------------------------------- @@ -1566,7 +1575,7 @@ scavenge_static(void) */ if (gct->failed_to_evac) { gct->failed_to_evac = rtsFalse; - recordMutableGen_GC((StgClosure *)p,oldest_gen); + recordMutableGen_GC((StgClosure *)p,oldest_gen->no); } break; } @@ -1686,24 +1695,34 @@ scavenge_stack(StgPtr p, StgPtr stack_end) // the indirection into an IND_PERM, so that evacuate will // copy the indirection into the old generation instead of // discarding it. + // + // Note [upd-black-hole] + // One slight hiccup is that the THUNK_SELECTOR machinery can + // overwrite the updatee with an IND. In parallel GC, this + // could even be happening concurrently, so we can't check for + // the IND. Fortunately if we assume that blackholing is + // happening (either lazy or eager), then we can be sure that + // the updatee is never a THUNK_SELECTOR and we're ok. + // NB. this is a new invariant: blackholing is not optional. { nat type; const StgInfoTable *i; + StgClosure *updatee; - i = ((StgUpdateFrame *)p)->updatee->header.info; + updatee = ((StgUpdateFrame *)p)->updatee; + i = updatee->header.info; if (!IS_FORWARDING_PTR(i)) { - type = get_itbl(((StgUpdateFrame *)p)->updatee)->type; + type = get_itbl(updatee)->type; if (type == IND) { - ((StgUpdateFrame *)p)->updatee->header.info = - (StgInfoTable *)&stg_IND_PERM_info; + updatee->header.info = &stg_IND_PERM_info; } else if (type == IND_OLDGEN) { - ((StgUpdateFrame *)p)->updatee->header.info = - (StgInfoTable *)&stg_IND_OLDGEN_PERM_info; + updatee->header.info = &stg_IND_OLDGEN_PERM_info; } - evacuate(&((StgUpdateFrame *)p)->updatee); - p += sizeofW(StgUpdateFrame); - continue; } + evacuate(&((StgUpdateFrame *)p)->updatee); + ASSERT(GET_CLOSURE_TAG(((StgUpdateFrame *)p)->updatee) == 0); + p += sizeofW(StgUpdateFrame); + continue; } // small bitmap (< 32 entries, or 64 on a 64-bit machine) @@ -1830,7 +1849,7 @@ scavenge_large (step_workspace *ws) p = bd->start; if (scavenge_one(p)) { if (ws->step->gen_no > 0) { - recordMutableGen_GC((StgClosure *)p, ws->step->gen); + recordMutableGen_GC((StgClosure *)p, ws->step->gen_no); } }