X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FGC.c;h=05728ca3eaa73ea80360d7e94cfd23488b129d97;hb=d4e0cee2445d9845bb7b0a0687bad84ff32bac28;hp=d35d83b6679f995f40716bf88b0d20fd120b721b;hpb=c046089ef9722a733396759b87fd24bae37e70d9;p=ghc-hetmet.git diff --git a/ghc/rts/GC.c b/ghc/rts/GC.c index d35d83b..05728ca 100644 --- a/ghc/rts/GC.c +++ b/ghc/rts/GC.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: GC.c,v 1.38 1999/02/23 15:45:06 simonm Exp $ + * $Id: GC.c,v 1.57 1999/03/26 10:29:04 simonm Exp $ * * (c) The GHC Team 1998-1999 * @@ -100,21 +100,23 @@ lnat g0s0_pcnt_kept = 30; /* percentage of g0s0 live at last minor GC */ Static function declarations -------------------------------------------------------------------------- */ -static StgClosure *evacuate(StgClosure *q); -static void zeroStaticObjectList(StgClosure* first_static); -static rtsBool traverse_weak_ptr_list(void); -static void zeroMutableList(StgMutClosure *first); -static void revertDeadCAFs(void); +static StgClosure * evacuate ( StgClosure *q ); +static void zero_static_object_list ( StgClosure* first_static ); +static void zero_mutable_list ( StgMutClosure *first ); +static void revert_dead_CAFs ( void ); -static void scavenge_stack(StgPtr p, StgPtr stack_end); -static void scavenge_large(step *step); -static void scavenge(step *step); -static void scavenge_static(void); -static void scavenge_mutable_list(generation *g); -static void scavenge_mut_once_list(generation *g); +static rtsBool traverse_weak_ptr_list ( void ); +static void cleanup_weak_ptr_list ( StgWeak **list ); + +static void scavenge_stack ( StgPtr p, StgPtr stack_end ); +static void scavenge_large ( step *step ); +static void scavenge ( step *step ); +static void scavenge_static ( void ); +static void scavenge_mutable_list ( generation *g ); +static void scavenge_mut_once_list ( generation *g ); #ifdef DEBUG -static void gcCAFs(void); +static void gcCAFs ( void ); #endif /* ----------------------------------------------------------------------------- @@ -175,6 +177,10 @@ void GarbageCollect(void (*get_roots)(void)) for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) { allocated -= BLOCK_SIZE_W; } + if (current_nursery->free < current_nursery->start + BLOCK_SIZE_W) { + allocated -= (current_nursery->start + BLOCK_SIZE_W) + - current_nursery->free; + } /* Figure out which generation to collect */ @@ -196,10 +202,10 @@ void GarbageCollect(void (*get_roots)(void)) scavenged_static_objects = END_OF_STATIC_LIST; /* zero the mutable list for the oldest generation (see comment by - * zeroMutableList below). + * zero_mutable_list below). */ if (major_gc) { - zeroMutableList(generations[RtsFlags.GcFlags.generations-1].mut_once_list); + zero_mutable_list(generations[RtsFlags.GcFlags.generations-1].mut_once_list); } /* Save the old to-space if we're doing a two-space collection @@ -337,7 +343,6 @@ void GarbageCollect(void (*get_roots)(void)) /* Mark the weak pointer list, and prepare to detect dead weak * pointers. */ - markWeakList(); old_weak_ptr_list = weak_ptr_list; weak_ptr_list = NULL; weak_done = rtsFalse; @@ -353,22 +358,7 @@ void GarbageCollect(void (*get_roots)(void)) * the CAF document. */ extern void markHugsObjects(void); -#if 0 - /* ToDo: This (undefined) function should contain the scavenge - * loop immediately below this block of code - but I'm not sure - * enough of the details to do this myself. - */ - scavengeEverything(); - /* revert dead CAFs and update enteredCAFs list */ - revertDeadCAFs(); -#endif markHugsObjects(); -#if 0 - /* This will keep the CAFs and the attached BCOs alive - * but the values will have been reverted - */ - scavengeEverything(); -#endif } #endif @@ -427,10 +417,18 @@ void GarbageCollect(void (*get_roots)(void)) } } - /* Now see which stable names are still alive + /* Final traversal of the weak pointer list (see comment by + * cleanUpWeakPtrList below). + */ + cleanup_weak_ptr_list(&weak_ptr_list); + + /* Now see which stable names are still alive. */ gcStablePtrTable(major_gc); + /* revert dead CAFs and update enteredCAFs list */ + revert_dead_CAFs(); + /* Set the maximum blocks for the oldest generation, based on twice * the amount of live data now, adjusted to fit the maximum heap * size if necessary. @@ -561,6 +559,8 @@ void GarbageCollect(void (*get_roots)(void)) } small_alloc_list = NULL; alloc_blocks = 0; + alloc_Hp = NULL; + alloc_HpLim = NULL; alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize; /* Two-space collector: @@ -657,17 +657,14 @@ void GarbageCollect(void (*get_roots)(void)) } } - /* revert dead CAFs and update enteredCAFs list */ - revertDeadCAFs(); - - /* mark the garbage collected CAFs as dead */ + /* mark the garbage collected CAFs as dead */ #ifdef DEBUG if (major_gc) { gcCAFs(); } #endif /* zero the scavenged static object list */ if (major_gc) { - zeroStaticObjectList(scavenged_static_objects); + zero_static_object_list(scavenged_static_objects); } /* Reset the nursery @@ -676,6 +673,7 @@ void GarbageCollect(void (*get_roots)(void)) bd->free = bd->start; ASSERT(bd->gen == g0); ASSERT(bd->step == g0s0); + IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE)); } current_nursery = g0s0->blocks; @@ -742,6 +740,27 @@ traverse_weak_ptr_list(void) last_w = &old_weak_ptr_list; for (w = old_weak_ptr_list; w; w = next_w) { + /* First, this weak pointer might have been evacuated. If so, + * remove the forwarding pointer from the weak_ptr_list. + */ + if (get_itbl(w)->type == EVACUATED) { + w = (StgWeak *)((StgEvacuated *)w)->evacuee; + *last_w = w; + } + + /* There might be a DEAD_WEAK on the list if finalizeWeak# was + * called on a live weak pointer object. Just remove it. + */ + if (w->header.info == &DEAD_WEAK_info) { + next_w = ((StgDeadWeak *)w)->link; + *last_w = next_w; + continue; + } + + ASSERT(get_itbl(w)->type == WEAK); + + /* Now, check whether the key is reachable. + */ if ((new = isAlive(w->key))) { w->key = new; /* evacuate the value and finalizer */ @@ -769,8 +788,8 @@ traverse_weak_ptr_list(void) * of pending finalizers later on. */ if (flag == rtsFalse) { + cleanup_weak_ptr_list(&old_weak_ptr_list); for (w = old_weak_ptr_list; w; w = w->link) { - w->value = evacuate(w->value); w->finalizer = evacuate(w->finalizer); } weak_done = rtsTrue; @@ -780,6 +799,39 @@ traverse_weak_ptr_list(void) } /* ----------------------------------------------------------------------------- + After GC, the live weak pointer list may have forwarding pointers + on it, because a weak pointer object was evacuated after being + moved to the live weak pointer list. We remove those forwarding + pointers here. + + Also, we don't consider weak pointer objects to be reachable, but + we must nevertheless consider them to be "live" and retain them. + Therefore any weak pointer objects which haven't as yet been + evacuated need to be evacuated now. + -------------------------------------------------------------------------- */ + +static void +cleanup_weak_ptr_list ( StgWeak **list ) +{ + StgWeak *w, **last_w; + + last_w = list; + for (w = *list; w; w = w->link) { + + if (get_itbl(w)->type == EVACUATED) { + w = (StgWeak *)((StgEvacuated *)w)->evacuee; + *last_w = w; + } + + if (Bdescr((P_)w)->evacuated == 0) { + (StgClosure *)w = evacuate((StgClosure *)w); + *last_w = w; + } + last_w = &(w->link); + } +} + +/* ----------------------------------------------------------------------------- isAlive determines whether the given closure is still alive (after a garbage collection) or not. It returns the new address of the closure if it is alive, or NULL otherwise. @@ -853,6 +905,13 @@ static void addBlock(step *step) new_blocks++; } +static __inline__ void +upd_evacuee(StgClosure *p, StgClosure *dest) +{ + p->header.info = &EVACUATED_info; + ((StgEvacuated *)p)->evacuee = dest; +} + static __inline__ StgClosure * copy(StgClosure *src, nat size, step *step) { @@ -865,7 +924,11 @@ copy(StgClosure *src, nat size, step *step) * by evacuate()). */ if (step->gen->no < evac_gen) { +#ifdef NO_EAGER_PROMOTION + failed_to_evac = rtsTrue; +#else step = &generations[evac_gen].steps[0]; +#endif } /* chain a new block onto the to-space for the destination step if @@ -881,6 +944,7 @@ copy(StgClosure *src, nat size, step *step) dest = step->hp; step->hp = to; + upd_evacuee(src,(StgClosure *)dest); return (StgClosure *)dest; } @@ -896,7 +960,11 @@ copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *step) TICK_GC_WORDS_COPIED(size_to_copy); if (step->gen->no < evac_gen) { +#ifdef NO_EAGER_PROMOTION + failed_to_evac = rtsTrue; +#else step = &generations[evac_gen].steps[0]; +#endif } if (step->hp + size_to_reserve >= step->hpLim) { @@ -909,18 +977,10 @@ copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *step) dest = step->hp; step->hp += size_to_reserve; + upd_evacuee(src,(StgClosure *)dest); return (StgClosure *)dest; } -static __inline__ void -upd_evacuee(StgClosure *p, StgClosure *dest) -{ - StgEvacuated *q = (StgEvacuated *)p; - - SET_INFO(q,&EVACUATED_info); - q->evacuee = dest; -} - /* ----------------------------------------------------------------------------- Evacuate a large object @@ -968,7 +1028,11 @@ evacuate_large(StgPtr p, rtsBool mutable) */ step = bd->step->to; if (step->gen->no < evac_gen) { +#ifdef NO_EAGER_PROMOTION + failed_to_evac = rtsTrue; +#else step = &generations[evac_gen].steps[0]; +#endif } bd->step = step; @@ -1050,7 +1114,7 @@ evacuate(StgClosure *q) const StgInfoTable *info; loop: - if (!LOOKS_LIKE_STATIC(q)) { + if (HEAP_ALLOCED(q)) { bd = Bdescr((P_)q); if (bd->gen->no > N) { /* Can't evacuate this object, because it's in a generation @@ -1075,46 +1139,42 @@ loop: switch (info -> type) { case BCO: - to = copy(q,bco_sizeW(stgCast(StgBCO*,q)),step); - upd_evacuee(q,to); - return to; + return copy(q,bco_sizeW(stgCast(StgBCO*,q)),step); case MUT_VAR: ASSERT(q->header.info != &MUT_CONS_info); case MVAR: to = copy(q,sizeW_fromITBL(info),step); - upd_evacuee(q,to); recordMutable((StgMutClosure *)to); return to; - case STABLE_NAME: - stable_ptr_table[((StgStableName *)q)->sn].keep = rtsTrue; - to = copy(q,sizeofW(StgStableName),step); - upd_evacuee(q,to); - return to; - case FUN_1_0: case FUN_0_1: case CONSTR_1_0: case CONSTR_0_1: - to = copy(q,sizeofW(StgHeader)+1,step); - upd_evacuee(q,to); - return to; + return copy(q,sizeofW(StgHeader)+1,step); case THUNK_1_0: /* here because of MIN_UPD_SIZE */ case THUNK_0_1: - case FUN_1_1: - case FUN_0_2: - case FUN_2_0: case THUNK_1_1: case THUNK_0_2: case THUNK_2_0: +#ifdef NO_PROMOTE_THUNKS + if (bd->gen->no == 0 && + bd->step->no != 0 && + bd->step->no == bd->gen->n_steps-1) { + step = bd->step; + } +#endif + return copy(q,sizeofW(StgHeader)+2,step); + + case FUN_1_1: + case FUN_0_2: + case FUN_2_0: case CONSTR_1_1: case CONSTR_0_2: case CONSTR_2_0: - to = copy(q,sizeofW(StgHeader)+2,step); - upd_evacuee(q,to); - return to; + return copy(q,sizeofW(StgHeader)+2,step); case FUN: case THUNK: @@ -1125,19 +1185,15 @@ loop: case CAF_ENTERED: case WEAK: case FOREIGN: - to = copy(q,sizeW_fromITBL(info),step); - upd_evacuee(q,to); - return to; + case STABLE_NAME: + return copy(q,sizeW_fromITBL(info),step); case CAF_BLACKHOLE: case BLACKHOLE: - to = copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step); - upd_evacuee(q,to); - return to; + return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step); case BLACKHOLE_BQ: to = copy(q,BLACKHOLE_sizeW(),step); - upd_evacuee(q,to); recordMutable((StgMutClosure *)to); return to; @@ -1157,11 +1213,11 @@ loop: case CONSTR_0_2: case CONSTR_STATIC: { - StgNat32 offset = info->layout.selector_offset; + StgWord32 offset = info->layout.selector_offset; /* check that the size is in range */ ASSERT(offset < - (StgNat32)(selectee_info->layout.payload.ptrs + + (StgWord32)(selectee_info->layout.payload.ptrs + selectee_info->layout.payload.nptrs)); /* perform the selection! */ @@ -1171,7 +1227,7 @@ loop: * with the evacuation, just update the source address with * a pointer to the (evacuated) constructor field. */ - if (IS_USER_PTR(q)) { + if (HEAP_ALLOCED(q)) { bdescr *bd = Bdescr((P_)q); if (bd->evacuated) { if (bd->gen->no < evac_gen) { @@ -1224,9 +1280,7 @@ loop: barf("evacuate: THUNK_SELECTOR: strange selectee"); } } - to = copy(q,THUNK_SELECTOR_sizeW(),step); - upd_evacuee(q,to); - return to; + return copy(q,THUNK_SELECTOR_sizeW(),step); case IND: case IND_OLDGEN: @@ -1234,30 +1288,35 @@ loop: q = ((StgInd*)q)->indirectee; goto loop; - /* ToDo: optimise STATIC_LINK for known cases. - - FUN_STATIC : payload[0] - - THUNK_STATIC : payload[1] - - IND_STATIC : payload[1] - */ case THUNK_STATIC: + if (info->srt_len > 0 && major_gc && + THUNK_STATIC_LINK((StgClosure *)q) == NULL) { + THUNK_STATIC_LINK((StgClosure *)q) = static_objects; + static_objects = (StgClosure *)q; + } + return q; + case FUN_STATIC: - if (info->srt_len == 0) { /* small optimisation */ - return q; + if (info->srt_len > 0 && major_gc && + FUN_STATIC_LINK((StgClosure *)q) == NULL) { + FUN_STATIC_LINK((StgClosure *)q) = static_objects; + static_objects = (StgClosure *)q; } - /* fall through */ - case CONSTR_STATIC: + return q; + case IND_STATIC: - /* don't want to evacuate these, but we do want to follow pointers - * from SRTs - see scavenge_static. - */ + if (major_gc && IND_STATIC_LINK((StgClosure *)q) == NULL) { + IND_STATIC_LINK((StgClosure *)q) = static_objects; + static_objects = (StgClosure *)q; + } + return q; - /* put the object on the static list, if necessary. - */ + case CONSTR_STATIC: if (major_gc && STATIC_LINK(info,(StgClosure *)q) == NULL) { STATIC_LINK(info,(StgClosure *)q) = static_objects; static_objects = (StgClosure *)q; } - /* fall through */ + return q; case CONSTR_INTLIKE: case CONSTR_CHARLIKE: @@ -1284,9 +1343,7 @@ loop: case PAP: /* these are special - the payload is a copy of a chunk of stack, tagging and all. */ - to = copy(q,pap_sizeW(stgCast(StgPAP*,q)),step); - upd_evacuee(q,to); - return to; + return copy(q,pap_sizeW(stgCast(StgPAP*,q)),step); case EVACUATED: /* Already evacuated, just return the forwarding address. @@ -1315,9 +1372,7 @@ loop: return q; } else { /* just copy the block */ - to = copy(q,size,step); - upd_evacuee(q,to); - return to; + return copy(q,size,step); } } @@ -1332,7 +1387,6 @@ loop: } else { /* just copy the block */ to = copy(q,size,step); - upd_evacuee(q,to); if (info->type == MUT_ARR_PTRS) { recordMutable((StgMutClosure *)to); } @@ -1366,7 +1420,6 @@ loop: new_tso->splim = (StgPtr)new_tso->splim + diff; relocate_TSO(tso, new_tso); - upd_evacuee(q,(StgClosure *)new_tso); recordMutable((StgMutClosure *)new_tso); return (StgClosure *)new_tso; @@ -1449,7 +1502,24 @@ scavenge_srt(const StgInfoTable *info) srt = stgCast(StgClosure **,info->srt); srt_end = srt + info->srt_len; for (; srt < srt_end; srt++) { - evacuate(*srt); + /* Special-case to handle references to closures hiding out in DLLs, since + double indirections required to get at those. The code generator knows + which is which when generating the SRT, so it stores the (indirect) + reference to the DLL closure in the table by first adding one to it. + We check for this here, and undo the addition before evacuating it. + + If the SRT entry hasn't got bit 0 set, the SRT entry points to a + closure that's fixed at link-time, and no extra magic is required. + */ +#ifdef HAVE_WIN32_DLL_SUPPORT + if ( stgCast(unsigned long,*srt) & 0x1 ) { + evacuate(*stgCast(StgClosure**,(stgCast(unsigned long, *srt) & ~0x1))); + } else { + evacuate(*srt); + } +#else + evacuate(*srt); +#endif } } @@ -1584,10 +1654,6 @@ scavenge(step *step) case WEAK: case FOREIGN: case STABLE_NAME: - case IND_PERM: - case IND_OLDGEN_PERM: - case CAF_UNENTERED: - case CAF_ENTERED: { StgPtr end; @@ -1599,6 +1665,52 @@ scavenge(step *step) break; } + case IND_PERM: + if (step->gen->no != 0) { + SET_INFO(((StgClosure *)p), &IND_OLDGEN_PERM_info); + } + /* fall through */ + case IND_OLDGEN_PERM: + ((StgIndOldGen *)p)->indirectee = + evacuate(((StgIndOldGen *)p)->indirectee); + if (failed_to_evac) { + failed_to_evac = rtsFalse; + recordOldToNewPtrs((StgMutClosure *)p); + } + p += sizeofW(StgIndOldGen); + break; + + case CAF_UNENTERED: + { + StgCAF *caf = (StgCAF *)p; + + caf->body = evacuate(caf->body); + if (failed_to_evac) { + failed_to_evac = rtsFalse; + recordOldToNewPtrs((StgMutClosure *)p); + } else { + caf->mut_link = NULL; + } + p += sizeofW(StgCAF); + break; + } + + case CAF_ENTERED: + { + StgCAF *caf = (StgCAF *)p; + + caf->body = evacuate(caf->body); + caf->value = evacuate(caf->value); + if (failed_to_evac) { + failed_to_evac = rtsFalse; + recordOldToNewPtrs((StgMutClosure *)p); + } else { + caf->mut_link = NULL; + } + p += sizeofW(StgCAF); + break; + } + case MUT_VAR: /* ignore MUT_CONSs */ if (((StgMutVar *)p)->header.info != &MUT_CONS_info) { @@ -1720,6 +1832,9 @@ scavenge(step *step) evac_gen = 0; /* chase the link field for any TSOs on the same queue */ (StgClosure *)tso->link = evacuate((StgClosure *)tso->link); + if (tso->blocked_on) { + tso->blocked_on = evacuate(tso->blocked_on); + } /* scavenge this thread's stack */ scavenge_stack(tso->sp, &(tso->stack[tso->stack_size])); evac_gen = saved_evac_gen; @@ -1793,7 +1908,6 @@ scavenge_one(StgClosure *p) case IND_PERM: case IND_OLDGEN_PERM: case CAF_UNENTERED: - case CAF_ENTERED: { StgPtr q, end; @@ -1946,6 +2060,35 @@ scavenge_mut_once_list(generation *gen) } continue; + case CAF_ENTERED: + { + StgCAF *caf = (StgCAF *)p; + caf->body = evacuate(caf->body); + caf->value = evacuate(caf->value); + if (failed_to_evac) { + failed_to_evac = rtsFalse; + p->mut_link = new_list; + new_list = p; + } else { + p->mut_link = NULL; + } + } + continue; + + case CAF_UNENTERED: + { + StgCAF *caf = (StgCAF *)p; + caf->body = evacuate(caf->body); + if (failed_to_evac) { + failed_to_evac = rtsFalse; + p->mut_link = new_list; + new_list = p; + } else { + p->mut_link = NULL; + } + } + continue; + default: /* shouldn't have anything else on the mutables list */ barf("scavenge_mut_once_list: strange object?"); @@ -2036,19 +2179,14 @@ scavenge_mutable_list(generation *gen) } case TSO: - /* follow ptrs and remove this from the mutable list */ { StgTSO *tso = (StgTSO *)p; - /* Don't bother scavenging if this thread is dead - */ - if (!(tso->whatNext == ThreadComplete || - tso->whatNext == ThreadKilled)) { - /* Don't need to chase the link field for any TSOs on the - * same queue. Just scavenge this thread's stack - */ - scavenge_stack(tso->sp, &(tso->stack[tso->stack_size])); + (StgClosure *)tso->link = evacuate((StgClosure *)tso->link); + if (tso->blocked_on) { + tso->blocked_on = evacuate(tso->blocked_on); } + scavenge_stack(tso->sp, &(tso->stack[tso->stack_size])); /* Don't take this TSO off the mutable list - it might still * point to some younger objects (because we set evac_gen to 0 @@ -2166,7 +2304,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end) { StgPtr q; const StgInfoTable* info; - StgNat32 bitmap; + StgWord32 bitmap; /* * Each time around this loop, we are looking at a chunk of stack @@ -2175,24 +2313,23 @@ scavenge_stack(StgPtr p, StgPtr stack_end) */ while (p < stack_end) { - q = *stgCast(StgPtr*,p); + q = *(P_ *)p; /* If we've got a tag, skip over that many words on the stack */ - if (IS_ARG_TAG(stgCast(StgWord,q))) { + if (IS_ARG_TAG((W_)q)) { p += ARG_SIZE(q); p++; continue; } /* Is q a pointer to a closure? */ - if (! LOOKS_LIKE_GHC_INFO(q)) { + if (! LOOKS_LIKE_GHC_INFO(q)) { #ifdef DEBUG - if (LOOKS_LIKE_STATIC(q)) { /* Is it a static closure? */ + if ( 0 && LOOKS_LIKE_STATIC_CLOSURE(q) ) { /* Is it a static closure? */ ASSERT(closure_STATIC(stgCast(StgClosure*,q))); - } - /* otherwise, must be a pointer into the allocation space. - */ + } + /* otherwise, must be a pointer into the allocation space. */ #endif (StgClosure *)*p = evacuate((StgClosure *)q); @@ -2205,14 +2342,14 @@ scavenge_stack(StgPtr p, StgPtr stack_end) * record. All activation records have 'bitmap' style layout * info. */ - info = get_itbl(stgCast(StgClosure*,p)); + info = get_itbl((StgClosure *)p); switch (info->type) { /* Dynamic bitmap: the mask is stored on the stack */ case RET_DYN: - bitmap = stgCast(StgRetDyn*,p)->liveness; - p = &payloadWord(stgCast(StgRetDyn*,p),0); + bitmap = ((StgRetDyn *)p)->liveness; + p = (P_)&((StgRetDyn *)p)->payload[0]; goto small_bitmap; /* probably a slow-entry point return address: */ @@ -2229,7 +2366,7 @@ scavenge_stack(StgPtr p, StgPtr stack_end) { StgUpdateFrame *frame = (StgUpdateFrame *)p; StgClosure *to; - StgClosureType type = get_itbl(frame->updatee)->type; + nat type = get_itbl(frame->updatee)->type; p += sizeofW(StgUpdateFrame); if (type == EVACUATED) { @@ -2244,18 +2381,24 @@ scavenge_stack(StgPtr p, StgPtr stack_end) } continue; } - step = bd->step->to; + + /* Don't promote blackholes */ + step = bd->step; + if (!(step->gen->no == 0 && + step->no != 0 && + step->no == step->gen->n_steps-1)) { + step = step->to; + } + switch (type) { case BLACKHOLE: case CAF_BLACKHOLE: to = copyPart(frame->updatee, BLACKHOLE_sizeW(), sizeofW(StgHeader), step); - upd_evacuee(frame->updatee,to); frame->updatee = to; continue; case BLACKHOLE_BQ: to = copy(frame->updatee, BLACKHOLE_sizeW(), step); - upd_evacuee(frame->updatee,to); frame->updatee = to; recordMutable((StgMutClosure *)to); continue; @@ -2415,6 +2558,9 @@ scavenge_large(step *step) tso = (StgTSO *)p; /* chase the link field for any TSOs on the same queue */ (StgClosure *)tso->link = evacuate((StgClosure *)tso->link); + if (tso->blocked_on) { + tso->blocked_on = evacuate(tso->blocked_on); + } /* scavenge this thread's stack */ scavenge_stack(tso->sp, &(tso->stack[tso->stack_size])); continue; @@ -2427,7 +2573,7 @@ scavenge_large(step *step) } static void -zeroStaticObjectList(StgClosure* first_static) +zero_static_object_list(StgClosure* first_static) { StgClosure* p; StgClosure* link; @@ -2449,7 +2595,7 @@ zeroStaticObjectList(StgClosure* first_static) * mutable list. */ static void -zeroMutableList(StgMutClosure *first) +zero_mutable_list( StgMutClosure *first ) { StgMutClosure *next, *c; @@ -2474,35 +2620,27 @@ void RevertCAFs(void) caf->value = stgCast(StgClosure*,0xdeadbeef); caf->link = stgCast(StgCAF*,0xdeadbeef); } + enteredCAFs = END_CAF_LIST; } -void revertDeadCAFs(void) +void revert_dead_CAFs(void) { StgCAF* caf = enteredCAFs; enteredCAFs = END_CAF_LIST; while (caf != END_CAF_LIST) { - StgCAF* next = caf->link; - - switch(GET_INFO(caf)->type) { - case EVACUATED: - { - /* This object has been evacuated, it must be live. */ - StgCAF* new = stgCast(StgCAF*,stgCast(StgEvacuated*,caf)->evacuee); - new->link = enteredCAFs; - enteredCAFs = new; - break; - } - case CAF_ENTERED: - { - SET_INFO(caf,&CAF_UNENTERED_info); - caf->value = stgCast(StgClosure*,0xdeadbeef); - caf->link = stgCast(StgCAF*,0xdeadbeef); - break; - } - default: - barf("revertDeadCAFs: enteredCAFs list corrupted"); - } - caf = next; + StgCAF *next, *new; + next = caf->link; + new = (StgCAF*)isAlive((StgClosure*)caf); + if (new) { + new->link = enteredCAFs; + enteredCAFs = new; + } else { + ASSERT(0); + SET_INFO(caf,&CAF_UNENTERED_info); + caf->value = (StgClosure*)0xdeadbeef; + caf->link = (StgCAF*)0xdeadbeef; + } + caf = next; } } @@ -2651,7 +2789,8 @@ threadSqueezeStack(StgTSO *tso) */ next_frame = NULL; - while ((P_)frame < bottom - 1) { /* bottom - 1 is the STOP_FRAME */ + /* bottom - sizeof(StgStopFrame) is the STOP_FRAME */ + while ((P_)frame < bottom - sizeofW(StgStopFrame)) { prev_frame = frame->link; frame->link = next_frame; next_frame = frame;