#include "RtsFlags.h"
#include "RtsUtils.h"
#include "Apply.h"
+#include "OSThreads.h"
#include "Storage.h"
#include "LdvProfile.h"
#include "Updates.h"
bitmap_size = stp->n_blocks * BLOCK_SIZE / (sizeof(W_)*BITS_PER_BYTE);
if (bitmap_size > 0) {
- bitmap_bdescr = allocGroup((nat)BLOCK_ROUND_UP(bitmap_size)
+ bitmap_bdescr = allocGroup((lnat)BLOCK_ROUND_UP(bitmap_size)
/ BLOCK_SIZE);
stp->bitmap = bitmap_bdescr;
bitmap = bitmap_bdescr->start;
STATIC_INLINE void
upd_evacuee(StgClosure *p, StgClosure *dest)
{
- // Source object must be in from-space:
- ASSERT((Bdescr((P_)p)->flags & BF_EVACUATED) == 0);
// not true: (ToDo: perhaps it should be)
// ASSERT(Bdescr((P_)dest)->flags & BF_EVACUATED);
SET_INFO(p, &stg_EVACUATED_info);
REGPARM1 static StgClosure *
evacuate(StgClosure *q)
{
+#if defined(PAR)
StgClosure *to;
+#endif
bdescr *bd = NULL;
step *stp;
const StgInfoTable *info;
return q;
}
+ /* Object is not already evacuated. */
+ ASSERT((bd->flags & BF_EVACUATED) == 0);
+
stp = bd->step->to;
}
#ifdef DEBUG
case BLACKHOLE:
return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),stp);
- case BLACKHOLE_BQ:
- to = copy(q,BLACKHOLE_sizeW(),stp);
- return to;
-
case THUNK_SELECTOR:
{
StgClosure *p;
}
#if defined(PAR)
- case RBH: // cf. BLACKHOLE_BQ
+ case RBH:
{
//StgInfoTable *rip = get_closure_info(q, &size, &ptrs, &nonptrs, &vhs, str);
to = copy(q,BLACKHOLE_sizeW(),stp);
// check that we don't recurse too much, re-using the
// depth bound also used in evacuate().
- thunk_selector_depth++;
- if (thunk_selector_depth > MAX_THUNK_SELECTOR_DEPTH) {
+ if (thunk_selector_depth >= MAX_THUNK_SELECTOR_DEPTH) {
break;
}
+ thunk_selector_depth++;
val = eval_thunk_selector(info->layout.selector_offset,
(StgSelector *)selectee);
case SE_CAF_BLACKHOLE:
case SE_BLACKHOLE:
case BLACKHOLE:
- case BLACKHOLE_BQ:
#if defined(PAR)
case RBH:
case BLOCKED_FETCH:
p = (StgPtr)args;
switch (fun_info->f.fun_type) {
case ARG_GEN:
- bitmap = BITMAP_BITS(fun_info->f.bitmap);
- size = BITMAP_SIZE(fun_info->f.bitmap);
+ bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
+ size = BITMAP_SIZE(fun_info->f.b.bitmap);
goto small_bitmap;
case ARG_GEN_BIG:
size = GET_FUN_LARGE_BITMAP(fun_info)->size;
switch (fun_info->f.fun_type) {
case ARG_GEN:
- bitmap = BITMAP_BITS(fun_info->f.bitmap);
+ bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
goto small_bitmap;
case ARG_GEN_BIG:
scavenge_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
p += BLACKHOLE_sizeW();
break;
- case BLACKHOLE_BQ:
- {
- StgBlockingQueue *bh = (StgBlockingQueue *)p;
- bh->blocking_queue =
- (StgTSO *)evacuate((StgClosure *)bh->blocking_queue);
- failed_to_evac = rtsTrue;
- p += BLACKHOLE_sizeW();
- break;
- }
-
case THUNK_SELECTOR:
{
StgSelector *s = (StgSelector *)p;
}
#if defined(PAR)
- case RBH: // cf. BLACKHOLE_BQ
+ case RBH:
{
#if 0
nat size, ptrs, nonptrs, vhs;
p += sizeofW(StgFetchMe);
break; // nothing to do in this case
- case FETCH_ME_BQ: // cf. BLACKHOLE_BQ
+ case FETCH_ME_BQ:
{
StgFetchMeBlockingQueue *fmbq = (StgFetchMeBlockingQueue *)p;
(StgClosure *)fmbq->blocking_queue =
case ARR_WORDS:
break;
- case BLACKHOLE_BQ:
- {
- StgBlockingQueue *bh = (StgBlockingQueue *)p;
- bh->blocking_queue =
- (StgTSO *)evacuate((StgClosure *)bh->blocking_queue);
- failed_to_evac = rtsTrue;
- break;
- }
-
case THUNK_SELECTOR:
{
StgSelector *s = (StgSelector *)p;
}
#if defined(PAR)
- case RBH: // cf. BLACKHOLE_BQ
+ case RBH:
{
#if 0
nat size, ptrs, nonptrs, vhs;
case FETCH_ME:
break; // nothing to do in this case
- case FETCH_ME_BQ: // cf. BLACKHOLE_BQ
+ case FETCH_ME_BQ:
{
StgFetchMeBlockingQueue *fmbq = (StgFetchMeBlockingQueue *)p;
(StgClosure *)fmbq->blocking_queue =
p, info_type((StgClosure *)p)));
break;
}
-#endif // PAR
+#endif /* PAR */
case TVAR_WAIT_QUEUE:
{
case BLACKHOLE:
break;
- case BLACKHOLE_BQ:
- {
- StgBlockingQueue *bh = (StgBlockingQueue *)p;
- evac_gen = 0; // repeatedly mutable
- bh->blocking_queue =
- (StgTSO *)evacuate((StgClosure *)bh->blocking_queue);
- failed_to_evac = rtsTrue;
- break;
- }
-
case THUNK_SELECTOR:
{
StgSelector *s = (StgSelector *)p;
}
#if defined(PAR)
- case RBH: // cf. BLACKHOLE_BQ
+ case RBH:
{
#if 0
nat size, ptrs, nonptrs, vhs;
case FETCH_ME:
break; // nothing to do in this case
- case FETCH_ME_BQ: // cf. BLACKHOLE_BQ
+ case FETCH_ME_BQ:
{
StgFetchMeBlockingQueue *fmbq = (StgFetchMeBlockingQueue *)p;
(StgClosure *)fmbq->blocking_queue =
case IND_OLDGEN:
case IND_OLDGEN_PERM:
case IND_STATIC:
- /* Try to pull the indirectee into this generation, so we can
- * remove the indirection from the mutable list.
- */
- ((StgInd *)p)->indirectee = evacuate(((StgInd *)p)->indirectee);
-
+ {
+ /* Careful here: a THUNK can be on the mutable list because
+ * it contains pointers to young gen objects. If such a thunk
+ * is updated, the IND_OLDGEN will be added to the mutable
+ * list again, and we'll scavenge it twice. evacuate()
+ * doesn't check whether the object has already been
+ * evacuated, so we perform that check here.
+ */
+ StgClosure *q = ((StgInd *)p)->indirectee;
+ if (HEAP_ALLOCED(q) && Bdescr((StgPtr)q)->flags & BF_EVACUATED) {
+ break;
+ }
+ ((StgInd *)p)->indirectee = evacuate(q);
+ }
+
#if 0 && defined(DEBUG)
if (RtsFlags.DebugFlags.gc)
/* Debugging code to print out the size of the thing we just
{
StgIndStatic *c;
- for (c = (StgIndStatic *)caf_list; c != NULL;
+ for (c = (StgIndStatic *)revertible_caf_list; c != NULL;
c = (StgIndStatic *)c->static_link)
{
SET_INFO(c, c->saved_info);
c->saved_info = NULL;
// could, but not necessary: c->static_link = NULL;
}
- caf_list = NULL;
+ revertible_caf_list = NULL;
}
void
{
evac(&c->indirectee);
}
+ for (c = (StgIndStatic *)revertible_caf_list; c != NULL;
+ c = (StgIndStatic *)c->static_link)
+ {
+ evac(&c->indirectee);
+ }
}
/* -----------------------------------------------------------------------------
{
StgClosure *frame;
StgRetInfoTable *info;
- StgBlockingQueue *bh;
+ StgClosure *bh;
StgPtr stack_end;
stack_end = &tso->stack[tso->stack_size];
switch (info->i.type) {
case UPDATE_FRAME:
- bh = (StgBlockingQueue *)((StgUpdateFrame *)frame)->updatee;
+ bh = ((StgUpdateFrame *)frame)->updatee;
/* if the thunk is already blackholed, it means we've also
* already blackholed the rest of the thunks on this stack,
return;
}
- if (bh->header.info != &stg_BLACKHOLE_BQ_info &&
- bh->header.info != &stg_CAF_BLACKHOLE_info) {
+ if (bh->header.info != &stg_CAF_BLACKHOLE_info) {
#if (!defined(LAZY_BLACKHOLING)) && defined(DEBUG)
debugBelch("Unexpected lazy BHing required at 0x%04x",(int)bh);
#endif
* screw us up if we don't check.
*/
if (upd->updatee != updatee && !closure_IND(upd->updatee)) {
- // this wakes the threads up
UPD_IND_NOLOCK(upd->updatee, updatee);
}
// single update frame, or the topmost update frame in a series
else {
- StgBlockingQueue *bh = (StgBlockingQueue *)upd->updatee;
+ StgClosure *bh = upd->updatee;
// Do lazy black-holing
if (bh->header.info != &stg_BLACKHOLE_info &&
- bh->header.info != &stg_BLACKHOLE_BQ_info &&
bh->header.info != &stg_CAF_BLACKHOLE_info) {
#if (!defined(LAZY_BLACKHOLING)) && defined(DEBUG)
debugBelch("Unexpected lazy BHing required at 0x%04x",(int)bh);
}
-#endif // DEBUG
+#endif /* DEBUG */