/* -----------------------------------------------------------------------------
- * $Id: GC.c,v 1.161 2003/10/22 15:00:59 simonmar Exp $
+ * $Id: GC.c,v 1.164 2003/11/26 12:14:26 simonmar Exp $
*
* (c) The GHC Team 1998-2003
*
static bdescr *oldgen_scan_bd;
static StgPtr oldgen_scan;
-static inline rtsBool
+STATIC_INLINE rtsBool
mark_stack_empty(void)
{
return mark_sp == mark_stack;
}
-static inline rtsBool
+STATIC_INLINE rtsBool
mark_stack_full(void)
{
return mark_sp >= mark_splim;
}
-static inline void
+STATIC_INLINE void
reset_mark_stack(void)
{
mark_sp = mark_stack;
}
-static inline void
+STATIC_INLINE void
push_mark_stack(StgPtr p)
{
*mark_sp++ = p;
}
-static inline StgPtr
+STATIC_INLINE StgPtr
pop_mark_stack(void)
{
return *--mark_sp;
// onto the front of the now-compacted existing blocks.
for (bd = stp->to_blocks; bd != NULL; bd = bd->link) {
bd->flags &= ~BF_EVACUATED; // now from-space
+ bd->flags |= BF_COMPACTED; // compacted next time
}
// tack the new blocks on the end of the existing blocks
if (stp->blocks == NULL) {
default:
barf("traverse_weak_ptr_list");
+ return rtsTrue;
}
}
}
// check the mark bit for compacted steps
- if (bd->step->is_compacted && is_marked((P_)p,bd)) {
+ if ((bd->flags & BF_COMPACTED) && is_marked((P_)p,bd)) {
return p;
}
*root = evacuate(*root);
}
-static __inline__ void
+STATIC_INLINE void
upd_evacuee(StgClosure *p, StgClosure *dest)
{
// Source object must be in from-space:
}
-static __inline__ StgClosure *
+STATIC_INLINE StgClosure *
copy(StgClosure *src, nat size, step *stp)
{
P_ to, from, dest;
-------------------------------------------------------------------------- */
-static inline void
+STATIC_INLINE void
evacuate_large(StgPtr p)
{
bdescr *bd = Bdescr(p);
/* If the object is in a step that we're compacting, then we
* need to use an alternative evacuate procedure.
*/
- if (bd->step->is_compacted) {
+ if (bd->flags & BF_COMPACTED) {
if (!is_marked((P_)q,bd)) {
mark((P_)q,bd);
if (mark_stack_full()) {
StgInfoTable *info;
const StgInfoTable *info_ptr;
StgClosure *selectee;
+ bdescr *bd;
selectee = p->selectee;
// eval_thunk_selector(). There are various ways this could
// happen:
//
- // - following an IND_STATIC
+ // 1. 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).
+ // 2. 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.
+ // 3. compacting GC again: if we're looking at a constructor in
+ // the compacted generation, it might point directly to objects
+ // in to-space. We must bale out here, otherwise doing the selection
+ // will result in a to-space pointer being returned.
+ //
+ // (1) is dealt with using a BF_EVACUATED test on the
+ // selectee. (2) and (3): we can tell if we're looking at an
+ // object in the compacted generation that might point to
+ // to-space objects by testing that (a) it is BF_COMPACTED, (b)
+ // the compacted generation is being collected, and (c) the
+ // object is marked. Only a marked object may have pointers that
+ // point to to-space objects, because that happens when
+ // scavenging.
//
+ bd = Bdescr((StgPtr)selectee);
if (HEAP_ALLOCED(selectee) &&
- Bdescr((StgPtr)selectee)->flags & BF_EVACUATED) {
+ ((bd->flags & BF_EVACUATED)
+ || ((bd->flags & BF_COMPACTED) &&
+ bd->gen_no <= N &&
+ is_marked((P_)selectee,bd)))) {
goto bale_out;
}
* srt field in the info table. That's ok, because we'll
* never dereference it.
*/
-static inline void
+STATIC_INLINE void
scavenge_srt (StgClosure **srt, nat srt_bitmap)
{
nat bitmap;
}
-static inline void
+STATIC_INLINE void
scavenge_thunk_srt(const StgInfoTable *info)
{
StgThunkInfoTable *thunk_info;
scavenge_srt((StgClosure **)thunk_info->srt, thunk_info->i.srt_bitmap);
}
-static inline void
+STATIC_INLINE void
scavenge_fun_srt(const StgInfoTable *info)
{
StgFunInfoTable *fun_info;
scavenge_srt((StgClosure **)fun_info->srt, fun_info->i.srt_bitmap);
}
-static inline void
+STATIC_INLINE void
scavenge_ret_srt(const StgInfoTable *info)
{
StgRetInfoTable *ret_info;
in PAPs.
-------------------------------------------------------------------------- */
-static inline StgPtr
+STATIC_INLINE StgPtr
scavenge_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
{
StgPtr p;
return p;
}
-static inline StgPtr
+STATIC_INLINE StgPtr
scavenge_PAP (StgPAP *pap)
{
StgPtr p;
{
StgPtr next;
+ // Set the mut_link field to NULL, so that we will put this
+ // array back on the mutable list if it is subsequently thawed
+ // by unsafeThaw#.
+ ((StgMutArrPtrs*)p)->mut_link = NULL;
+
next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
(StgClosure *)*p = evacuate((StgClosure *)*p);
// false, but that breaks some assumptions (eg. every
// closure on the mutable list is supposed to have the MUT
// flag set, and MUT_ARR_PTRS_FROZEN doesn't).
-
- // Set the mut_link field to NULL, so that we will put this
- // array back on the mutable list if it is subsequently thawed
- // by unsafeThaw#.
- ((StgMutArrPtrs*)p)->mut_link = NULL;
break;
}
{
StgPtr next;
- next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
- for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
- (StgClosure *)*p = evacuate((StgClosure *)*p);
- }
// Set the mut_link field to NULL, so that we will put this
// array on the mutable list if it is subsequently thawed
// by unsafeThaw#.
((StgMutArrPtrs*)p)->mut_link = NULL;
+
+ next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
+ for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
+ (StgClosure *)*p = evacuate((StgClosure *)*p);
+ }
break;
}
// follow everything
StgPtr next;
- next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
- for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
- (StgClosure *)*p = evacuate((StgClosure *)*p);
- }
// Set the mut_link field to NULL, so that we will put this
// array on the mutable list if it is subsequently thawed
// by unsafeThaw#.
((StgMutArrPtrs*)p)->mut_link = NULL;
+
+ next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
+ for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
+ (StgClosure *)*p = evacuate((StgClosure *)*p);
+ }
break;
}
}
}
-static inline StgPtr
+STATIC_INLINE StgPtr
scavenge_small_bitmap (StgPtr p, nat size, StgWord bitmap)
{
while (size > 0) {
void *gap_start, *next_gap_start, *gap_end;
nat chunk_size;
- next_gap_start = (void *)gap + sizeof(StgUpdateFrame);
+ next_gap_start = (void *)((unsigned char*)gap + sizeof(StgUpdateFrame));
sp = next_gap_start;
while ((StgPtr)gap > tso->sp) {
// we're working in *bytes* now...
gap_start = next_gap_start;
- gap_end = gap_start - gap->gap_size * sizeof(W_);
+ gap_end = (void*) ((unsigned char*)gap_start - gap->gap_size * sizeof(W_));
gap = gap->next_gap;
- next_gap_start = (void *)gap + sizeof(StgUpdateFrame);
+ next_gap_start = (void *)((unsigned char*)gap + sizeof(StgUpdateFrame));
- chunk_size = gap_end - next_gap_start;
- sp -= chunk_size;
+ chunk_size = (unsigned char*)gap_end - (unsigned char*)next_gap_start;
+ (unsigned char*)sp -= chunk_size;
memmove(sp, next_gap_start, chunk_size);
}
fputc('\n', stderr);
}
-static inline rtsBool
+STATIC_INLINE rtsBool
maybeLarge(StgClosure *closure)
{
StgInfoTable *info = get_itbl(closure);