1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 2001
5 * Compacting garbage collector
7 * ---------------------------------------------------------------------------*/
9 #include "PosixSource.h"
13 #include "OSThreads.h"
16 #include "BlockAlloc.h"
24 // Turn off inlining when debugging - it obfuscates things
27 # define STATIC_INLINE static
30 /* -----------------------------------------------------------------------------
31 Threading / unthreading pointers.
33 The basic idea here is to chain together all the fields pointing at
34 a particular object, with the root of the chain in the object's
35 info table field. The original contents of the info pointer goes
36 at the end of the chain.
38 Adding a new field to the chain is a matter of swapping the
39 contents of the field with the contents of the object's info table
42 To unthread the chain, we walk down it updating all the fields on
43 the chain with the new location of the object. We stop when we
44 reach the info pointer at the end.
46 We use a trick to identify the info pointer: when swapping pointers
47 for threading, we set the low bit of the original pointer, with the
48 result that all the pointers in the chain have their low bits set
49 except for the info pointer.
50 -------------------------------------------------------------------------- */
53 thread (StgClosure **p)
55 StgPtr q = *(StgPtr *)p;
58 // It doesn't look like a closure at the moment, because the info
59 // ptr is possibly threaded:
60 // ASSERT(LOOKS_LIKE_CLOSURE_PTR(q));
62 if (HEAP_ALLOCED(q)) {
64 // a handy way to discover whether the ptr is into the
65 // compacted area of the old gen, is that the EVACUATED flag
66 // is zero (it's non-zero for all the other areas of live
68 if ((bd->flags & BF_EVACUATED) == 0) {
70 *(StgPtr)p = (StgWord)*q;
71 *q = (StgWord)p + 1; // set the low bit
76 // This version of thread() takes a (void *), used to circumvent
77 // warnings from gcc about pointer punning and strict aliasing.
78 STATIC_INLINE void thread_ (void *p) { thread((StgClosure **)p); }
81 unthread( StgPtr p, StgPtr free )
85 while ((q & 1) != 0) {
86 q -= 1; // unset the low bit again
88 *((StgPtr)q) = (StgWord)free;
94 STATIC_INLINE StgInfoTable *
95 get_threaded_info( StgPtr p )
97 StgPtr q = (P_)GET_INFO((StgClosure *)p);
99 while (((StgWord)q & 1) != 0) {
100 q = (P_)*((StgPtr)((StgWord)q-1));
103 ASSERT(LOOKS_LIKE_INFO_PTR(q));
104 return INFO_PTR_TO_STRUCT((StgInfoTable *)q);
107 // A word-aligned memmove will be faster for small objects than libc's or gcc's.
108 // Remember, the two regions *might* overlap, but: to <= from.
110 move(StgPtr to, StgPtr from, nat size)
112 for(; size > 0; --size) {
118 thread_static( StgClosure* p )
120 const StgInfoTable *info;
122 // keep going until we've threaded all the objects on the linked
124 while (p != END_OF_STATIC_LIST) {
127 switch (info->type) {
130 thread(&((StgInd *)p)->indirectee);
131 p = *IND_STATIC_LINK(p);
135 p = *THUNK_STATIC_LINK(p);
138 p = *FUN_STATIC_LINK(p);
141 p = *STATIC_LINK(info,p);
145 barf("thread_static: strange closure %d", (int)(info->type));
152 thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, nat size )
158 bitmap = large_bitmap->bitmap[b];
159 for (i = 0; i < size; ) {
160 if ((bitmap & 1) == 0) {
161 thread((StgClosure **)p);
165 if (i % BITS_IN(W_) == 0) {
167 bitmap = large_bitmap->bitmap[b];
169 bitmap = bitmap >> 1;
175 thread_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
182 switch (fun_info->f.fun_type) {
184 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
185 size = BITMAP_SIZE(fun_info->f.b.bitmap);
188 size = GET_FUN_LARGE_BITMAP(fun_info)->size;
189 thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
193 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
194 size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
197 if ((bitmap & 1) == 0) {
198 thread((StgClosure **)p);
201 bitmap = bitmap >> 1;
210 thread_stack(StgPtr p, StgPtr stack_end)
212 const StgRetInfoTable* info;
216 // highly similar to scavenge_stack, but we do pointer threading here.
218 while (p < stack_end) {
220 // *p must be the info pointer of an activation
221 // record. All activation records have 'bitmap' style layout
224 info = get_ret_itbl((StgClosure *)p);
226 switch (info->i.type) {
228 // Dynamic bitmap: the mask is stored on the stack
232 dyn = ((StgRetDyn *)p)->liveness;
234 // traverse the bitmap first
235 bitmap = RET_DYN_LIVENESS(dyn);
236 p = (P_)&((StgRetDyn *)p)->payload[0];
237 size = RET_DYN_BITMAP_SIZE;
239 if ((bitmap & 1) == 0) {
240 thread((StgClosure **)p);
243 bitmap = bitmap >> 1;
247 // skip over the non-ptr words
248 p += RET_DYN_NONPTRS(dyn) + RET_DYN_NONPTR_REGS_SIZE;
250 // follow the ptr words
251 for (size = RET_DYN_PTRS(dyn); size > 0; size--) {
252 thread((StgClosure **)p);
258 // small bitmap (<= 32 entries, or 64 on a 64-bit machine)
259 case CATCH_RETRY_FRAME:
260 case CATCH_STM_FRAME:
261 case ATOMICALLY_FRAME:
267 bitmap = BITMAP_BITS(info->i.layout.bitmap);
268 size = BITMAP_SIZE(info->i.layout.bitmap);
270 // NOTE: the payload starts immediately after the info-ptr, we
271 // don't have an StgHeader in the same sense as a heap closure.
273 if ((bitmap & 1) == 0) {
274 thread((StgClosure **)p);
277 bitmap = bitmap >> 1;
288 thread((StgClosure **)p);
290 size = BCO_BITMAP_SIZE(bco);
291 thread_large_bitmap(p, BCO_BITMAP(bco), size);
296 // large bitmap (> 32 entries, or 64 on a 64-bit machine)
300 size = GET_LARGE_BITMAP(&info->i)->size;
301 thread_large_bitmap(p, GET_LARGE_BITMAP(&info->i), size);
307 StgRetFun *ret_fun = (StgRetFun *)p;
308 StgFunInfoTable *fun_info;
310 fun_info = itbl_to_fun_itbl(
311 get_threaded_info((StgPtr)ret_fun->fun));
312 // *before* threading it!
313 thread(&ret_fun->fun);
314 p = thread_arg_block(fun_info, ret_fun->payload);
319 barf("thread_stack: weird activation record found on stack: %d",
320 (int)(info->i.type));
326 thread_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)
330 StgFunInfoTable *fun_info;
332 fun_info = itbl_to_fun_itbl(get_threaded_info((StgPtr)fun));
333 ASSERT(fun_info->i.type != PAP);
337 switch (fun_info->f.fun_type) {
339 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
342 thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
346 thread_large_bitmap((StgPtr)payload, BCO_BITMAP(fun), size);
350 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
353 if ((bitmap & 1) == 0) {
354 thread((StgClosure **)p);
357 bitmap = bitmap >> 1;
367 thread_PAP (StgPAP *pap)
370 p = thread_PAP_payload(pap->fun, pap->payload, pap->n_args);
376 thread_AP (StgAP *ap)
379 p = thread_PAP_payload(ap->fun, ap->payload, ap->n_args);
385 thread_AP_STACK (StgAP_STACK *ap)
388 thread_stack((P_)ap->payload, (P_)ap->payload + ap->size);
389 return (P_)ap + sizeofW(StgAP_STACK) + ap->size;
393 thread_TSO (StgTSO *tso)
396 thread_(&tso->global_link);
398 if ( tso->why_blocked == BlockedOnMVar
399 || tso->why_blocked == BlockedOnBlackHole
400 || tso->why_blocked == BlockedOnException
402 thread_(&tso->block_info.closure);
404 thread_(&tso->blocked_exceptions);
408 thread_stack(tso->sp, &(tso->stack[tso->stack_size]));
409 return (StgPtr)tso + tso_sizeW(tso);
414 update_fwd_large( bdescr *bd )
417 const StgInfoTable* info;
419 for (; bd != NULL; bd = bd->link) {
422 info = get_itbl((StgClosure *)p);
424 switch (info->type) {
430 case MUT_ARR_PTRS_CLEAN:
431 case MUT_ARR_PTRS_DIRTY:
432 case MUT_ARR_PTRS_FROZEN:
433 case MUT_ARR_PTRS_FROZEN0:
438 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
439 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
440 thread((StgClosure **)p);
446 thread_TSO((StgTSO *)p);
450 thread_AP_STACK((StgAP_STACK *)p);
454 thread_PAP((StgPAP *)p);
460 StgTRecChunk *tc = (StgTRecChunk *)p;
461 TRecEntry *e = &(tc -> entries[0]);
462 thread_(&tc->prev_chunk);
463 for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
465 thread(&e->expected_value);
466 thread(&e->new_value);
472 barf("update_fwd_large: unknown/strange object %d", (int)(info->type));
477 // ToDo: too big to inline
478 static /* STATIC_INLINE */ StgPtr
479 thread_obj (StgInfoTable *info, StgPtr p)
481 switch (info->type) {
483 return p + sizeofW(StgThunk) + 1;
487 return p + sizeofW(StgHeader) + 1;
491 thread(&((StgClosure *)p)->payload[0]);
492 return p + sizeofW(StgHeader) + 1;
495 thread(&((StgThunk *)p)->payload[0]);
496 return p + sizeofW(StgThunk) + 1;
499 return p + sizeofW(StgThunk) + 2;
503 return p + sizeofW(StgHeader) + 2;
506 thread(&((StgThunk *)p)->payload[0]);
507 return p + sizeofW(StgThunk) + 2;
511 thread(&((StgClosure *)p)->payload[0]);
512 return p + sizeofW(StgHeader) + 2;
515 thread(&((StgThunk *)p)->payload[0]);
516 thread(&((StgThunk *)p)->payload[1]);
517 return p + sizeofW(StgThunk) + 2;
521 thread(&((StgClosure *)p)->payload[0]);
522 thread(&((StgClosure *)p)->payload[1]);
523 return p + sizeofW(StgHeader) + 2;
526 StgBCO *bco = (StgBCO *)p;
527 thread_(&bco->instrs);
528 thread_(&bco->literals);
530 thread_(&bco->itbls);
531 return p + bco_sizeW(bco);
538 end = (P_)((StgThunk *)p)->payload +
539 info->layout.payload.ptrs;
540 for (p = (P_)((StgThunk *)p)->payload; p < end; p++) {
541 thread((StgClosure **)p);
543 return p + info->layout.payload.nptrs;
553 case SE_CAF_BLACKHOLE:
559 end = (P_)((StgClosure *)p)->payload +
560 info->layout.payload.ptrs;
561 for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
562 thread((StgClosure **)p);
564 return p + info->layout.payload.nptrs;
569 StgWeak *w = (StgWeak *)p;
572 thread(&w->finalizer);
573 if (w->link != NULL) {
576 return p + sizeofW(StgWeak);
581 StgMVar *mvar = (StgMVar *)p;
582 thread_(&mvar->head);
583 thread_(&mvar->tail);
584 thread(&mvar->value);
585 return p + sizeofW(StgMVar);
589 case IND_OLDGEN_PERM:
590 thread(&((StgInd *)p)->indirectee);
591 return p + sizeofW(StgInd);
595 StgSelector *s = (StgSelector *)p;
596 thread(&s->selectee);
597 return p + THUNK_SELECTOR_sizeW();
601 return thread_AP_STACK((StgAP_STACK *)p);
604 return thread_PAP((StgPAP *)p);
607 return thread_AP((StgAP *)p);
610 return p + arr_words_sizeW((StgArrWords *)p);
612 case MUT_ARR_PTRS_CLEAN:
613 case MUT_ARR_PTRS_DIRTY:
614 case MUT_ARR_PTRS_FROZEN:
615 case MUT_ARR_PTRS_FROZEN0:
620 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
621 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
622 thread((StgClosure **)p);
628 return thread_TSO((StgTSO *)p);
630 case TVAR_WATCH_QUEUE:
632 StgTVarWatchQueue *wq = (StgTVarWatchQueue *)p;
633 thread_(&wq->closure);
634 thread_(&wq->next_queue_entry);
635 thread_(&wq->prev_queue_entry);
636 return p + sizeofW(StgTVarWatchQueue);
641 StgTVar *tvar = (StgTVar *)p;
642 thread((void *)&tvar->current_value);
643 thread((void *)&tvar->first_watch_queue_entry);
644 return p + sizeofW(StgTVar);
649 StgTRecHeader *trec = (StgTRecHeader *)p;
650 thread_(&trec->enclosing_trec);
651 thread_(&trec->current_chunk);
652 thread_(&trec->invariants_to_check);
653 return p + sizeofW(StgTRecHeader);
659 StgTRecChunk *tc = (StgTRecChunk *)p;
660 TRecEntry *e = &(tc -> entries[0]);
661 thread_(&tc->prev_chunk);
662 for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
664 thread(&e->expected_value);
665 thread(&e->new_value);
667 return p + sizeofW(StgTRecChunk);
670 case ATOMIC_INVARIANT:
672 StgAtomicInvariant *invariant = (StgAtomicInvariant *)p;
673 thread_(&invariant->code);
674 thread_(&invariant->last_execution);
675 return p + sizeofW(StgAtomicInvariant);
678 case INVARIANT_CHECK_QUEUE:
680 StgInvariantCheckQueue *queue = (StgInvariantCheckQueue *)p;
681 thread_(&queue->invariant);
682 thread_(&queue->my_execution);
683 thread_(&queue->next_queue_entry);
684 return p + sizeofW(StgInvariantCheckQueue);
688 barf("update_fwd: unknown/strange object %d", (int)(info->type));
694 update_fwd( bdescr *blocks )
702 // cycle through all the blocks in the step
703 for (; bd != NULL; bd = bd->link) {
706 // linearly scan the objects in this block
707 while (p < bd->free) {
708 ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
709 info = get_itbl((StgClosure *)p);
710 p = thread_obj(info, p);
716 update_fwd_compact( bdescr *blocks )
722 bdescr *bd, *free_bd;
728 free = free_bd->start;
730 // cycle through all the blocks in the step
731 for (; bd != NULL; bd = bd->link) {
734 while (p < bd->free ) {
736 while ( p < bd->free && !is_marked(p,bd) ) {
745 m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord))));
746 m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1));
748 while ( p < bd->free ) {
753 if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) {
761 // Problem: we need to know the destination for this cell
762 // in order to unthread its info pointer. But we can't
763 // know the destination without the size, because we may
764 // spill into the next block. So we have to run down the
765 // threaded list and get the info ptr first.
766 info = get_threaded_info(p);
770 p = thread_obj(info, p);
773 if (free + size > free_bd->start + BLOCK_SIZE_W) {
774 // unset the next bit in the bitmap to indicate that
775 // this object needs to be pushed into the next
776 // block. This saves us having to run down the
777 // threaded info pointer list twice during the next pass.
779 free_bd = free_bd->link;
780 free = free_bd->start;
782 ASSERT(is_marked(q+1,bd));
795 update_bkwd_compact( step *stp )
801 bdescr *bd, *free_bd;
803 nat size, free_blocks;
805 bd = free_bd = stp->old_blocks;
806 free = free_bd->start;
809 // cycle through all the blocks in the step
810 for (; bd != NULL; bd = bd->link) {
813 while (p < bd->free ) {
815 while ( p < bd->free && !is_marked(p,bd) ) {
824 m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord))));
825 m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1));
827 while ( p < bd->free ) {
832 if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) {
840 if (!is_marked(p+1,bd)) {
841 // don't forget to update the free ptr in the block desc.
842 free_bd->free = free;
843 free_bd = free_bd->link;
844 free = free_bd->start;
849 ASSERT(LOOKS_LIKE_INFO_PTR(((StgClosure *)p)->header.info));
850 info = get_itbl((StgClosure *)p);
851 size = closure_sizeW_((StgClosure *)p,info);
858 if (info->type == TSO) {
859 move_TSO((StgTSO *)p, (StgTSO *)free);
870 // free the remaining blocks and count what's left.
871 free_bd->free = free;
872 if (free_bd->link != NULL) {
873 freeChain(free_bd->link);
874 free_bd->link = NULL;
886 // 1. thread the roots
887 GetRoots((evac_fn)thread);
889 // the weak pointer lists...
890 if (weak_ptr_list != NULL) {
891 thread((void *)&weak_ptr_list);
893 if (old_weak_ptr_list != NULL) {
894 thread((void *)&old_weak_ptr_list); // tmp
898 for (g = 1; g < RtsFlags.GcFlags.generations; g++) {
901 for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) {
902 for (p = bd->start; p < bd->free; p++) {
903 thread((StgClosure **)p);
908 // the global thread list
909 thread((void *)&all_threads);
911 // any threads resurrected during this GC
912 thread((void *)&resurrected_threads);
917 for (task = all_tasks; task != NULL; task = task->all_link) {
924 // the static objects
925 thread_static(scavenged_static_objects);
927 // the stable pointer table
928 threadStablePtrTable((evac_fn)thread);
930 // the CAF list (used by GHCi)
931 markCAFs((evac_fn)thread);
933 // 2. update forward ptrs
934 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
935 for (s = 0; s < generations[g].n_steps; s++) {
936 if (g==0 && s ==0) continue;
937 stp = &generations[g].steps[s];
938 debugTrace(DEBUG_gc, "update_fwd: %d.%d",
939 stp->gen->no, stp->no);
941 update_fwd(stp->blocks);
942 update_fwd_large(stp->scavenged_large_objects);
943 if (g == RtsFlags.GcFlags.generations-1 && stp->old_blocks != NULL) {
944 debugTrace(DEBUG_gc, "update_fwd: %d.%d (compact)",
945 stp->gen->no, stp->no);
946 update_fwd_compact(stp->old_blocks);
951 // 3. update backward ptrs
952 stp = &oldest_gen->steps[0];
953 if (stp->old_blocks != NULL) {
954 blocks = update_bkwd_compact(stp);
956 "update_bkwd: %d.%d (compact, old: %d blocks, now %d blocks)",
957 stp->gen->no, stp->no,
958 stp->n_old_blocks, blocks);
959 stp->n_old_blocks = blocks;