X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FGCCompact.c;fp=rts%2FGCCompact.c;h=0000000000000000000000000000000000000000;hb=ab0e778ccfde61aed4c22679b24d175fc6cc9bf3;hp=da3c7a7c6200077f1defcc18b0d5b31832a23349;hpb=2246c514eade324d70058ba3135dc0c51ee9353b;p=ghc-hetmet.git diff --git a/rts/GCCompact.c b/rts/GCCompact.c deleted file mode 100644 index da3c7a7..0000000 --- a/rts/GCCompact.c +++ /dev/null @@ -1,974 +0,0 @@ -/* ----------------------------------------------------------------------------- - * - * (c) The GHC Team 2001 - * - * Compacting garbage collector - * - * ---------------------------------------------------------------------------*/ - -#include "PosixSource.h" -#include "Rts.h" -#include "RtsUtils.h" -#include "RtsFlags.h" -#include "OSThreads.h" -#include "Storage.h" -#include "BlockAlloc.h" -#include "MBlock.h" -#include "GCCompact.h" -#include "Schedule.h" -#include "Apply.h" -#include "Trace.h" - -// Turn off inlining when debugging - it obfuscates things -#ifdef DEBUG -# undef STATIC_INLINE -# define STATIC_INLINE static -#endif - -/* ----------------------------------------------------------------------------- - Threading / unthreading pointers. - - The basic idea here is to chain together all the fields pointing at - a particular object, with the root of the chain in the object's - info table field. The original contents of the info pointer goes - at the end of the chain. - - Adding a new field to the chain is a matter of swapping the - contents of the field with the contents of the object's info table - field. - - To unthread the chain, we walk down it updating all the fields on - the chain with the new location of the object. We stop when we - reach the info pointer at the end. - - We use a trick to identify the info pointer: when swapping pointers - for threading, we set the low bit of the original pointer, with the - result that all the pointers in the chain have their low bits set - except for the info pointer. - -------------------------------------------------------------------------- */ - -STATIC_INLINE void -thread (StgClosure **p) -{ - StgPtr q = *(StgPtr *)p; - bdescr *bd; - - // It doesn't look like a closure at the moment, because the info - // ptr is possibly threaded: - // ASSERT(LOOKS_LIKE_CLOSURE_PTR(q)); - - if (HEAP_ALLOCED(q)) { - bd = Bdescr(q); - // a handy way to discover whether the ptr is into the - // compacted area of the old gen, is that the EVACUATED flag - // is zero (it's non-zero for all the other areas of live - // memory). - if ((bd->flags & BF_EVACUATED) == 0) { - - *(StgPtr)p = (StgWord)*q; - *q = (StgWord)p + 1; // set the low bit - } - } -} - -// This version of thread() takes a (void *), used to circumvent -// warnings from gcc about pointer punning and strict aliasing. -STATIC_INLINE void thread_ (void *p) { thread((StgClosure **)p); } - -STATIC_INLINE void -unthread( StgPtr p, StgPtr free ) -{ - StgWord q = *p, r; - - while ((q & 1) != 0) { - q -= 1; // unset the low bit again - r = *((StgPtr)q); - *((StgPtr)q) = (StgWord)free; - q = r; - } - *p = q; -} - -STATIC_INLINE StgInfoTable * -get_threaded_info( StgPtr p ) -{ - StgPtr q = (P_)GET_INFO((StgClosure *)p); - - while (((StgWord)q & 1) != 0) { - q = (P_)*((StgPtr)((StgWord)q-1)); - } - - ASSERT(LOOKS_LIKE_INFO_PTR(q)); - return INFO_PTR_TO_STRUCT((StgInfoTable *)q); -} - -// A word-aligned memmove will be faster for small objects than libc's or gcc's. -// Remember, the two regions *might* overlap, but: to <= from. -STATIC_INLINE void -move(StgPtr to, StgPtr from, nat size) -{ - for(; size > 0; --size) { - *to++ = *from++; - } -} - -static void -thread_static( StgClosure* p ) -{ - const StgInfoTable *info; - - // keep going until we've threaded all the objects on the linked - // list... - while (p != END_OF_STATIC_LIST) { - - info = get_itbl(p); - switch (info->type) { - - case IND_STATIC: - thread(&((StgInd *)p)->indirectee); - p = *IND_STATIC_LINK(p); - continue; - - case THUNK_STATIC: - p = *THUNK_STATIC_LINK(p); - continue; - case FUN_STATIC: - p = *FUN_STATIC_LINK(p); - continue; - case CONSTR_STATIC: - p = *STATIC_LINK(info,p); - continue; - - default: - barf("thread_static: strange closure %d", (int)(info->type)); - } - - } -} - -STATIC_INLINE void -thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, nat size ) -{ - nat i, b; - StgWord bitmap; - - b = 0; - bitmap = large_bitmap->bitmap[b]; - for (i = 0; i < size; ) { - if ((bitmap & 1) == 0) { - thread((StgClosure **)p); - } - i++; - p++; - if (i % BITS_IN(W_) == 0) { - b++; - bitmap = large_bitmap->bitmap[b]; - } else { - bitmap = bitmap >> 1; - } - } -} - -STATIC_INLINE StgPtr -thread_arg_block (StgFunInfoTable *fun_info, StgClosure **args) -{ - StgPtr p; - StgWord bitmap; - nat size; - - p = (StgPtr)args; - switch (fun_info->f.fun_type) { - case ARG_GEN: - 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; - thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size); - p += size; - break; - default: - bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); - size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]); - small_bitmap: - while (size > 0) { - if ((bitmap & 1) == 0) { - thread((StgClosure **)p); - } - p++; - bitmap = bitmap >> 1; - size--; - } - break; - } - return p; -} - -static void -thread_stack(StgPtr p, StgPtr stack_end) -{ - const StgRetInfoTable* info; - StgWord bitmap; - nat size; - - // highly similar to scavenge_stack, but we do pointer threading here. - - while (p < stack_end) { - - // *p must be the info pointer of an activation - // record. All activation records have 'bitmap' style layout - // info. - // - info = get_ret_itbl((StgClosure *)p); - - switch (info->i.type) { - - // Dynamic bitmap: the mask is stored on the stack - case RET_DYN: - { - StgWord dyn; - dyn = ((StgRetDyn *)p)->liveness; - - // traverse the bitmap first - bitmap = RET_DYN_LIVENESS(dyn); - p = (P_)&((StgRetDyn *)p)->payload[0]; - size = RET_DYN_BITMAP_SIZE; - while (size > 0) { - if ((bitmap & 1) == 0) { - thread((StgClosure **)p); - } - p++; - bitmap = bitmap >> 1; - size--; - } - - // skip over the non-ptr words - p += RET_DYN_NONPTRS(dyn) + RET_DYN_NONPTR_REGS_SIZE; - - // follow the ptr words - for (size = RET_DYN_PTRS(dyn); size > 0; size--) { - thread((StgClosure **)p); - p++; - } - continue; - } - - // small bitmap (<= 32 entries, or 64 on a 64-bit machine) - case CATCH_RETRY_FRAME: - case CATCH_STM_FRAME: - case ATOMICALLY_FRAME: - case UPDATE_FRAME: - case STOP_FRAME: - case CATCH_FRAME: - case RET_SMALL: - case RET_VEC_SMALL: - bitmap = BITMAP_BITS(info->i.layout.bitmap); - size = BITMAP_SIZE(info->i.layout.bitmap); - p++; - // NOTE: the payload starts immediately after the info-ptr, we - // don't have an StgHeader in the same sense as a heap closure. - while (size > 0) { - if ((bitmap & 1) == 0) { - thread((StgClosure **)p); - } - p++; - bitmap = bitmap >> 1; - size--; - } - continue; - - case RET_BCO: { - StgBCO *bco; - nat size; - - p++; - bco = (StgBCO *)*p; - thread((StgClosure **)p); - p++; - size = BCO_BITMAP_SIZE(bco); - thread_large_bitmap(p, BCO_BITMAP(bco), size); - p += size; - continue; - } - - // large bitmap (> 32 entries, or 64 on a 64-bit machine) - case RET_BIG: - case RET_VEC_BIG: - p++; - size = GET_LARGE_BITMAP(&info->i)->size; - thread_large_bitmap(p, GET_LARGE_BITMAP(&info->i), size); - p += size; - continue; - - case RET_FUN: - { - StgRetFun *ret_fun = (StgRetFun *)p; - StgFunInfoTable *fun_info; - - fun_info = itbl_to_fun_itbl( - get_threaded_info((StgPtr)ret_fun->fun)); - // *before* threading it! - thread(&ret_fun->fun); - p = thread_arg_block(fun_info, ret_fun->payload); - continue; - } - - default: - barf("thread_stack: weird activation record found on stack: %d", - (int)(info->i.type)); - } - } -} - -STATIC_INLINE StgPtr -thread_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size) -{ - StgPtr p; - StgWord bitmap; - StgFunInfoTable *fun_info; - - fun_info = itbl_to_fun_itbl(get_threaded_info((StgPtr)fun)); - ASSERT(fun_info->i.type != PAP); - - p = (StgPtr)payload; - - switch (fun_info->f.fun_type) { - case ARG_GEN: - bitmap = BITMAP_BITS(fun_info->f.b.bitmap); - goto small_bitmap; - case ARG_GEN_BIG: - thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size); - p += size; - break; - case ARG_BCO: - thread_large_bitmap((StgPtr)payload, BCO_BITMAP(fun), size); - p += size; - break; - default: - bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]); - small_bitmap: - while (size > 0) { - if ((bitmap & 1) == 0) { - thread((StgClosure **)p); - } - p++; - bitmap = bitmap >> 1; - size--; - } - break; - } - - return p; -} - -STATIC_INLINE StgPtr -thread_PAP (StgPAP *pap) -{ - StgPtr p; - p = thread_PAP_payload(pap->fun, pap->payload, pap->n_args); - thread(&pap->fun); - return p; -} - -STATIC_INLINE StgPtr -thread_AP (StgAP *ap) -{ - StgPtr p; - p = thread_PAP_payload(ap->fun, ap->payload, ap->n_args); - thread(&ap->fun); - return p; -} - -STATIC_INLINE StgPtr -thread_AP_STACK (StgAP_STACK *ap) -{ - thread(&ap->fun); - thread_stack((P_)ap->payload, (P_)ap->payload + ap->size); - return (P_)ap + sizeofW(StgAP_STACK) + ap->size; -} - -static StgPtr -thread_TSO (StgTSO *tso) -{ - thread_(&tso->link); - thread_(&tso->global_link); - - if ( tso->why_blocked == BlockedOnMVar - || tso->why_blocked == BlockedOnBlackHole - || tso->why_blocked == BlockedOnException -#if defined(PAR) - || tso->why_blocked == BlockedOnGA - || tso->why_blocked == BlockedOnGA_NoSend -#endif - ) { - thread_(&tso->block_info.closure); - } - thread_(&tso->blocked_exceptions); - - thread_(&tso->trec); - - thread_stack(tso->sp, &(tso->stack[tso->stack_size])); - return (StgPtr)tso + tso_sizeW(tso); -} - - -static void -update_fwd_large( bdescr *bd ) -{ - StgPtr p; - const StgInfoTable* info; - - for (; bd != NULL; bd = bd->link) { - - p = bd->start; - info = get_itbl((StgClosure *)p); - - switch (info->type) { - - case ARR_WORDS: - // nothing to follow - continue; - - case MUT_ARR_PTRS_CLEAN: - case MUT_ARR_PTRS_DIRTY: - case MUT_ARR_PTRS_FROZEN: - case MUT_ARR_PTRS_FROZEN0: - // follow everything - { - StgPtr next; - - next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p); - for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) { - thread((StgClosure **)p); - } - continue; - } - - case TSO: - thread_TSO((StgTSO *)p); - continue; - - case AP_STACK: - thread_AP_STACK((StgAP_STACK *)p); - continue; - - case PAP: - thread_PAP((StgPAP *)p); - continue; - - case TREC_CHUNK: - { - StgWord i; - StgTRecChunk *tc = (StgTRecChunk *)p; - TRecEntry *e = &(tc -> entries[0]); - thread_(&tc->prev_chunk); - for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) { - thread_(&e->tvar); - thread(&e->expected_value); - thread(&e->new_value); - } - continue; - } - - default: - barf("update_fwd_large: unknown/strange object %d", (int)(info->type)); - } - } -} - -STATIC_INLINE StgPtr -thread_obj (StgInfoTable *info, StgPtr p) -{ - switch (info->type) { - case THUNK_0_1: - return p + sizeofW(StgThunk) + 1; - - case FUN_0_1: - case CONSTR_0_1: - return p + sizeofW(StgHeader) + 1; - - case FUN_1_0: - case CONSTR_1_0: - thread(&((StgClosure *)p)->payload[0]); - return p + sizeofW(StgHeader) + 1; - - case THUNK_1_0: - thread(&((StgThunk *)p)->payload[0]); - return p + sizeofW(StgThunk) + 1; - - case THUNK_0_2: - return p + sizeofW(StgThunk) + 2; - - case FUN_0_2: - case CONSTR_0_2: - return p + sizeofW(StgHeader) + 2; - - case THUNK_1_1: - thread(&((StgThunk *)p)->payload[0]); - return p + sizeofW(StgThunk) + 2; - - case FUN_1_1: - case CONSTR_1_1: - thread(&((StgClosure *)p)->payload[0]); - return p + sizeofW(StgHeader) + 2; - - case THUNK_2_0: - thread(&((StgThunk *)p)->payload[0]); - thread(&((StgThunk *)p)->payload[1]); - return p + sizeofW(StgThunk) + 2; - - case FUN_2_0: - case CONSTR_2_0: - thread(&((StgClosure *)p)->payload[0]); - thread(&((StgClosure *)p)->payload[1]); - return p + sizeofW(StgHeader) + 2; - - case BCO: { - StgBCO *bco = (StgBCO *)p; - thread_(&bco->instrs); - thread_(&bco->literals); - thread_(&bco->ptrs); - thread_(&bco->itbls); - return p + bco_sizeW(bco); - } - - case THUNK: - { - StgPtr end; - - end = (P_)((StgThunk *)p)->payload + - info->layout.payload.ptrs; - for (p = (P_)((StgThunk *)p)->payload; p < end; p++) { - thread((StgClosure **)p); - } - return p + info->layout.payload.nptrs; - } - - case FUN: - case CONSTR: - case STABLE_NAME: - case IND_PERM: - case MUT_VAR_CLEAN: - case MUT_VAR_DIRTY: - case CAF_BLACKHOLE: - case SE_CAF_BLACKHOLE: - case SE_BLACKHOLE: - case BLACKHOLE: - { - StgPtr end; - - end = (P_)((StgClosure *)p)->payload + - info->layout.payload.ptrs; - for (p = (P_)((StgClosure *)p)->payload; p < end; p++) { - thread((StgClosure **)p); - } - return p + info->layout.payload.nptrs; - } - - case WEAK: - { - StgWeak *w = (StgWeak *)p; - thread(&w->key); - thread(&w->value); - thread(&w->finalizer); - if (w->link != NULL) { - thread_(&w->link); - } - return p + sizeofW(StgWeak); - } - - case MVAR: - { - StgMVar *mvar = (StgMVar *)p; - thread_(&mvar->head); - thread_(&mvar->tail); - thread(&mvar->value); - return p + sizeofW(StgMVar); - } - - case IND_OLDGEN: - case IND_OLDGEN_PERM: - thread(&((StgInd *)p)->indirectee); - return p + sizeofW(StgInd); - - case THUNK_SELECTOR: - { - StgSelector *s = (StgSelector *)p; - thread(&s->selectee); - return p + THUNK_SELECTOR_sizeW(); - } - - case AP_STACK: - return thread_AP_STACK((StgAP_STACK *)p); - - case PAP: - return thread_PAP((StgPAP *)p); - - case AP: - return thread_AP((StgAP *)p); - - case ARR_WORDS: - return p + arr_words_sizeW((StgArrWords *)p); - - case MUT_ARR_PTRS_CLEAN: - case MUT_ARR_PTRS_DIRTY: - case MUT_ARR_PTRS_FROZEN: - case MUT_ARR_PTRS_FROZEN0: - // follow everything - { - StgPtr next; - - next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p); - for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) { - thread((StgClosure **)p); - } - return p; - } - - case TSO: - return thread_TSO((StgTSO *)p); - - case TVAR_WATCH_QUEUE: - { - StgTVarWatchQueue *wq = (StgTVarWatchQueue *)p; - thread_(&wq->closure); - thread_(&wq->next_queue_entry); - thread_(&wq->prev_queue_entry); - return p + sizeofW(StgTVarWatchQueue); - } - - case TVAR: - { - StgTVar *tvar = (StgTVar *)p; - thread((void *)&tvar->current_value); - thread((void *)&tvar->first_watch_queue_entry); - return p + sizeofW(StgTVar); - } - - case TREC_HEADER: - { - StgTRecHeader *trec = (StgTRecHeader *)p; - thread_(&trec->enclosing_trec); - thread_(&trec->current_chunk); - thread_(&trec->invariants_to_check); - return p + sizeofW(StgTRecHeader); - } - - case TREC_CHUNK: - { - StgWord i; - StgTRecChunk *tc = (StgTRecChunk *)p; - TRecEntry *e = &(tc -> entries[0]); - thread_(&tc->prev_chunk); - for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) { - thread_(&e->tvar); - thread(&e->expected_value); - thread(&e->new_value); - } - return p + sizeofW(StgTRecChunk); - } - - case ATOMIC_INVARIANT: - { - StgAtomicInvariant *invariant = (StgAtomicInvariant *)p; - thread_(&invariant->code); - thread_(&invariant->last_execution); - return p + sizeofW(StgAtomicInvariant); - } - - case INVARIANT_CHECK_QUEUE: - { - StgInvariantCheckQueue *queue = (StgInvariantCheckQueue *)p; - thread_(&queue->invariant); - thread_(&queue->my_execution); - thread_(&queue->next_queue_entry); - return p + sizeofW(StgInvariantCheckQueue); - } - - default: - barf("update_fwd: unknown/strange object %d", (int)(info->type)); - return NULL; - } -} - -static void -update_fwd( bdescr *blocks ) -{ - StgPtr p; - bdescr *bd; - StgInfoTable *info; - - bd = blocks; - -#if defined(PAR) - barf("update_fwd: ToDo"); -#endif - - // cycle through all the blocks in the step - for (; bd != NULL; bd = bd->link) { - p = bd->start; - - // linearly scan the objects in this block - while (p < bd->free) { - ASSERT(LOOKS_LIKE_CLOSURE_PTR(p)); - info = get_itbl((StgClosure *)p); - p = thread_obj(info, p); - } - } -} - -static void -update_fwd_compact( bdescr *blocks ) -{ - StgPtr p, q, free; -#if 0 - StgWord m; -#endif - bdescr *bd, *free_bd; - StgInfoTable *info; - nat size; - - bd = blocks; - free_bd = blocks; - free = free_bd->start; - -#if defined(PAR) - barf("update_fwd: ToDo"); -#endif - - // cycle through all the blocks in the step - for (; bd != NULL; bd = bd->link) { - p = bd->start; - - while (p < bd->free ) { - - while ( p < bd->free && !is_marked(p,bd) ) { - p++; - } - if (p >= bd->free) { - break; - } - -#if 0 - next: - m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord)))); - m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1)); - - while ( p < bd->free ) { - - if ((m & 1) == 0) { - m >>= 1; - p++; - if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) { - goto next; - } else { - continue; - } - } -#endif - - // Problem: we need to know the destination for this cell - // in order to unthread its info pointer. But we can't - // know the destination without the size, because we may - // spill into the next block. So we have to run down the - // threaded list and get the info ptr first. - info = get_threaded_info(p); - - q = p; - - p = thread_obj(info, p); - - size = p - q; - if (free + size > free_bd->start + BLOCK_SIZE_W) { - // unset the next bit in the bitmap to indicate that - // this object needs to be pushed into the next - // block. This saves us having to run down the - // threaded info pointer list twice during the next pass. - unmark(q+1,bd); - free_bd = free_bd->link; - free = free_bd->start; - } else { - ASSERT(is_marked(q+1,bd)); - } - - unthread(q,free); - free += size; -#if 0 - goto next; -#endif - } - } -} - -static nat -update_bkwd_compact( step *stp ) -{ - StgPtr p, free; -#if 0 - StgWord m; -#endif - bdescr *bd, *free_bd; - StgInfoTable *info; - nat size, free_blocks; - - bd = free_bd = stp->old_blocks; - free = free_bd->start; - free_blocks = 1; - -#if defined(PAR) - barf("update_bkwd: ToDo"); -#endif - - // cycle through all the blocks in the step - for (; bd != NULL; bd = bd->link) { - p = bd->start; - - while (p < bd->free ) { - - while ( p < bd->free && !is_marked(p,bd) ) { - p++; - } - if (p >= bd->free) { - break; - } - -#if 0 - next: - m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord)))); - m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1)); - - while ( p < bd->free ) { - - if ((m & 1) == 0) { - m >>= 1; - p++; - if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) { - goto next; - } else { - continue; - } - } -#endif - - if (!is_marked(p+1,bd)) { - // don't forget to update the free ptr in the block desc. - free_bd->free = free; - free_bd = free_bd->link; - free = free_bd->start; - free_blocks++; - } - - unthread(p,free); - ASSERT(LOOKS_LIKE_INFO_PTR(((StgClosure *)p)->header.info)); - info = get_itbl((StgClosure *)p); - size = closure_sizeW_((StgClosure *)p,info); - - if (free != p) { - move(free,p,size); - } - - // relocate TSOs - if (info->type == TSO) { - move_TSO((StgTSO *)p, (StgTSO *)free); - } - - free += size; - p += size; -#if 0 - goto next; -#endif - } - } - - // free the remaining blocks and count what's left. - free_bd->free = free; - if (free_bd->link != NULL) { - freeChain(free_bd->link); - free_bd->link = NULL; - } - - return free_blocks; -} - -void -compact( void (*get_roots)(evac_fn) ) -{ - nat g, s, blocks; - step *stp; - - // 1. thread the roots - get_roots((evac_fn)thread); - - // the weak pointer lists... - if (weak_ptr_list != NULL) { - thread((void *)&weak_ptr_list); - } - if (old_weak_ptr_list != NULL) { - thread((void *)&old_weak_ptr_list); // tmp - } - - // mutable lists - for (g = 1; g < RtsFlags.GcFlags.generations; g++) { - bdescr *bd; - StgPtr p; - for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) { - for (p = bd->start; p < bd->free; p++) { - thread((StgClosure **)p); - } - } - } - - // the global thread list - thread((void *)&all_threads); - - // any threads resurrected during this GC - thread((void *)&resurrected_threads); - - // the task list - { - Task *task; - for (task = all_tasks; task != NULL; task = task->all_link) { - if (task->tso) { - thread_(&task->tso); - } - } - } - - // the static objects - thread_static(scavenged_static_objects); - - // the stable pointer table - threadStablePtrTable((evac_fn)thread); - - // the CAF list (used by GHCi) - markCAFs((evac_fn)thread); - - // 2. update forward ptrs - for (g = 0; g < RtsFlags.GcFlags.generations; g++) { - for (s = 0; s < generations[g].n_steps; s++) { - if (g==0 && s ==0) continue; - stp = &generations[g].steps[s]; - debugTrace(DEBUG_gc, "update_fwd: %d.%d", - stp->gen->no, stp->no); - - update_fwd(stp->blocks); - update_fwd_large(stp->scavenged_large_objects); - if (g == RtsFlags.GcFlags.generations-1 && stp->old_blocks != NULL) { - debugTrace(DEBUG_gc, "update_fwd: %d.%d (compact)", - stp->gen->no, stp->no); - update_fwd_compact(stp->old_blocks); - } - } - } - - // 3. update backward ptrs - stp = &oldest_gen->steps[0]; - if (stp->old_blocks != NULL) { - blocks = update_bkwd_compact(stp); - debugTrace(DEBUG_gc, - "update_bkwd: %d.%d (compact, old: %d blocks, now %d blocks)", - stp->gen->no, stp->no, - stp->n_old_blocks, blocks); - stp->n_old_blocks = blocks; - } -}