/* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.148 2003/03/19 18:41:18 sof Exp $
+ * $Id: GC.c,v 1.153 2003/04/01 15:05:13 sof Exp $
*
* (c) The GHC Team 1998-2003
*
static bdescr * gc_alloc_block ( step *stp );
static void mark_root ( StgClosure **root );
-static StgClosure * evacuate ( StgClosure *q );
+
+// Use a register argument for evacuate, if available.
+#if __GNUC__ >= 2
+static StgClosure * evacuate (StgClosure *q) __attribute__((regparm(1)));
+#else
+static StgClosure * evacuate (StgClosure *q);
+#endif
+
static void zero_static_object_list ( StgClosure* first_static );
static void zero_mutable_list ( StgMutClosure *first );
Now, Now));
#endif
-#ifndef mingw32_TARGET_OS
+#if defined(RTS_USER_SIGNALS)
// block signals
blockUserSignals();
#endif
// ok, GC over: tell the stats department what happened.
stat_endGC(allocated, collected, live, copied, N);
-#ifndef mingw32_TARGET_OS
+#if defined(RTS_USER_SIGNALS)
// unblock signals again
unblockUserSignals();
#endif
case WEAK:
case FOREIGN:
case STABLE_NAME:
- case BCO:
return copy(q,sizeW_fromITBL(info),stp);
+ case BCO:
+ return copy(q,bco_sizeW((StgBCO *)q),stp);
+
case CAF_BLACKHOLE:
case SE_CAF_BLACKHOLE:
case SE_BLACKHOLE:
selector_loop:
+ // We don't want to end up in to-space, because this causes
+ // problems when the GC later tries to evacuate the result of
+ // eval_thunk_selector(). There are various ways this could
+ // happen:
+ //
+ // - following an IND_STATIC
+ //
+ // - when the old generation is compacted, the mark phase updates
+ // from-space pointers to be to-space pointers, and we can't
+ // reliably tell which we're following (eg. from an IND_STATIC).
+ //
+ // So we use the block-descriptor test to find out if we're in
+ // to-space.
+ //
+ if (HEAP_ALLOCED(selectee) &&
+ Bdescr((StgPtr)selectee)->flags & BF_EVACUATED) {
+ goto bale_out;
+ }
+
info = get_itbl(selectee);
switch (info->type) {
case CONSTR:
ASSERT(field < (StgWord32)(info->layout.payload.ptrs +
info->layout.payload.nptrs));
+ // ToDo: shouldn't we test whether this pointer is in
+ // to-space?
return selectee->payload[field];
case IND:
case IND_PERM:
case IND_OLDGEN:
case IND_OLDGEN_PERM:
+ case IND_STATIC:
selectee = ((StgInd *)selectee)->indirectee;
goto selector_loop;
// leaks by evaluating this selector thunk anyhow.
break;
- case IND_STATIC:
- // We can't easily tell whether the indirectee is into
- // from or to-space, so just bail out here.
- break;
-
case THUNK_SELECTOR:
{
StgClosure *val;
(int)(info->type));
}
+bale_out:
// We didn't manage to evaluate this thunk; restore the old info pointer
SET_INFO(p, info_ptr);
return NULL;
case WEAK:
case FOREIGN:
case STABLE_NAME:
- case BCO:
{
StgPtr end;
break;
}
+ case BCO: {
+ StgBCO *bco = (StgBCO *)p;
+ (StgClosure *)bco->instrs = evacuate((StgClosure *)bco->instrs);
+ (StgClosure *)bco->literals = evacuate((StgClosure *)bco->literals);
+ (StgClosure *)bco->ptrs = evacuate((StgClosure *)bco->ptrs);
+ (StgClosure *)bco->itbls = evacuate((StgClosure *)bco->itbls);
+ p += bco_sizeW(bco);
+ break;
+ }
+
case IND_PERM:
if (stp->gen->no != 0) {
#ifdef PROFILING
case WEAK:
case FOREIGN:
case STABLE_NAME:
- case BCO:
{
StgPtr end;
break;
}
+ case BCO: {
+ StgBCO *bco = (StgBCO *)p;
+ (StgClosure *)bco->instrs = evacuate((StgClosure *)bco->instrs);
+ (StgClosure *)bco->literals = evacuate((StgClosure *)bco->literals);
+ (StgClosure *)bco->ptrs = evacuate((StgClosure *)bco->ptrs);
+ (StgClosure *)bco->itbls = evacuate((StgClosure *)bco->itbls);
+ break;
+ }
+
case IND_PERM:
// don't need to do anything here: the only possible case
// is that we're in a 1-space compacting collector, with