1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 2001
5 * Compacting garbage collector
7 * ---------------------------------------------------------------------------*/
9 #include "PosixSource.h"
13 #include "OSThreads.h"
15 #include "BlockAlloc.h"
17 #include "GCCompact.h"
22 // Turn off inlining when debugging - it obfuscates things
25 # define STATIC_INLINE static
28 /* -----------------------------------------------------------------------------
29 Threading / unthreading pointers.
31 The basic idea here is to chain together all the fields pointing at
32 a particular object, with the root of the chain in the object's
33 info table field. The original contents of the info pointer goes
34 at the end of the chain.
36 Adding a new field to the chain is a matter of swapping the
37 contents of the field with the contents of the object's info table
40 To unthread the chain, we walk down it updating all the fields on
41 the chain with the new location of the object. We stop when we
42 reach the info pointer at the end.
44 We use a trick to identify the info pointer: when swapping pointers
45 for threading, we set the low bit of the original pointer, with the
46 result that all the pointers in the chain have their low bits set
47 except for the info pointer.
48 -------------------------------------------------------------------------- */
51 thread (StgClosure **p)
53 StgPtr q = *(StgPtr *)p;
56 // It doesn't look like a closure at the moment, because the info
57 // ptr is possibly threaded:
58 // ASSERT(LOOKS_LIKE_CLOSURE_PTR(q));
60 if (HEAP_ALLOCED(q)) {
62 // a handy way to discover whether the ptr is into the
63 // compacted area of the old gen, is that the EVACUATED flag
64 // is zero (it's non-zero for all the other areas of live
66 if ((bd->flags & BF_EVACUATED) == 0) {
68 *(StgPtr)p = (StgWord)*q;
69 *q = (StgWord)p + 1; // set the low bit
74 // This version of thread() takes a (void *), used to circumvent
75 // warnings from gcc about pointer punning and strict aliasing.
76 STATIC_INLINE void thread_ (void *p) { thread((StgClosure **)p); }
79 unthread( StgPtr p, StgPtr free )
83 while ((q & 1) != 0) {
84 q -= 1; // unset the low bit again
86 *((StgPtr)q) = (StgWord)free;
92 STATIC_INLINE StgInfoTable *
93 get_threaded_info( StgPtr p )
95 StgPtr q = (P_)GET_INFO((StgClosure *)p);
97 while (((StgWord)q & 1) != 0) {
98 q = (P_)*((StgPtr)((StgWord)q-1));
101 ASSERT(LOOKS_LIKE_INFO_PTR(q));
102 return INFO_PTR_TO_STRUCT((StgInfoTable *)q);
105 // A word-aligned memmove will be faster for small objects than libc's or gcc's.
106 // Remember, the two regions *might* overlap, but: to <= from.
108 move(StgPtr to, StgPtr from, nat size)
110 for(; size > 0; --size) {
116 thread_static( StgClosure* p )
118 const StgInfoTable *info;
120 // keep going until we've threaded all the objects on the linked
122 while (p != END_OF_STATIC_LIST) {
125 switch (info->type) {
128 thread(&((StgInd *)p)->indirectee);
129 p = *IND_STATIC_LINK(p);
133 p = *THUNK_STATIC_LINK(p);
136 p = *FUN_STATIC_LINK(p);
139 p = *STATIC_LINK(info,p);
143 barf("thread_static: strange closure %d", (int)(info->type));
150 thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, nat size )
156 bitmap = large_bitmap->bitmap[b];
157 for (i = 0; i < size; ) {
158 if ((bitmap & 1) == 0) {
159 thread((StgClosure **)p);
163 if (i % BITS_IN(W_) == 0) {
165 bitmap = large_bitmap->bitmap[b];
167 bitmap = bitmap >> 1;
173 thread_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
180 switch (fun_info->f.fun_type) {
182 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
183 size = BITMAP_SIZE(fun_info->f.b.bitmap);
186 size = GET_FUN_LARGE_BITMAP(fun_info)->size;
187 thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
191 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
192 size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
195 if ((bitmap & 1) == 0) {
196 thread((StgClosure **)p);
199 bitmap = bitmap >> 1;
208 thread_stack(StgPtr p, StgPtr stack_end)
210 const StgRetInfoTable* info;
214 // highly similar to scavenge_stack, but we do pointer threading here.
216 while (p < stack_end) {
218 // *p must be the info pointer of an activation
219 // record. All activation records have 'bitmap' style layout
222 info = get_ret_itbl((StgClosure *)p);
224 switch (info->i.type) {
226 // Dynamic bitmap: the mask is stored on the stack
230 dyn = ((StgRetDyn *)p)->liveness;
232 // traverse the bitmap first
233 bitmap = RET_DYN_LIVENESS(dyn);
234 p = (P_)&((StgRetDyn *)p)->payload[0];
235 size = RET_DYN_BITMAP_SIZE;
237 if ((bitmap & 1) == 0) {
238 thread((StgClosure **)p);
241 bitmap = bitmap >> 1;
245 // skip over the non-ptr words
246 p += RET_DYN_NONPTRS(dyn) + RET_DYN_NONPTR_REGS_SIZE;
248 // follow the ptr words
249 for (size = RET_DYN_PTRS(dyn); size > 0; size--) {
250 thread((StgClosure **)p);
256 // small bitmap (<= 32 entries, or 64 on a 64-bit machine)
257 case CATCH_RETRY_FRAME:
258 case CATCH_STM_FRAME:
259 case ATOMICALLY_FRAME:
265 bitmap = BITMAP_BITS(info->i.layout.bitmap);
266 size = BITMAP_SIZE(info->i.layout.bitmap);
268 // NOTE: the payload starts immediately after the info-ptr, we
269 // don't have an StgHeader in the same sense as a heap closure.
271 if ((bitmap & 1) == 0) {
272 thread((StgClosure **)p);
275 bitmap = bitmap >> 1;
286 thread((StgClosure **)p);
288 size = BCO_BITMAP_SIZE(bco);
289 thread_large_bitmap(p, BCO_BITMAP(bco), size);
294 // large bitmap (> 32 entries, or 64 on a 64-bit machine)
298 size = GET_LARGE_BITMAP(&info->i)->size;
299 thread_large_bitmap(p, GET_LARGE_BITMAP(&info->i), size);
305 StgRetFun *ret_fun = (StgRetFun *)p;
306 StgFunInfoTable *fun_info;
308 fun_info = itbl_to_fun_itbl(
309 get_threaded_info((StgPtr)ret_fun->fun));
310 // *before* threading it!
311 thread(&ret_fun->fun);
312 p = thread_arg_block(fun_info, ret_fun->payload);
317 barf("thread_stack: weird activation record found on stack: %d",
318 (int)(info->i.type));
324 thread_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)
328 StgFunInfoTable *fun_info;
330 fun_info = itbl_to_fun_itbl(get_threaded_info((StgPtr)fun));
331 ASSERT(fun_info->i.type != PAP);
335 switch (fun_info->f.fun_type) {
337 bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
340 thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
344 thread_large_bitmap((StgPtr)payload, BCO_BITMAP(fun), size);
348 bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
351 if ((bitmap & 1) == 0) {
352 thread((StgClosure **)p);
355 bitmap = bitmap >> 1;
365 thread_PAP (StgPAP *pap)
368 p = thread_PAP_payload(pap->fun, pap->payload, pap->n_args);
374 thread_AP (StgAP *ap)
377 p = thread_PAP_payload(ap->fun, ap->payload, ap->n_args);
383 thread_AP_STACK (StgAP_STACK *ap)
386 thread_stack((P_)ap->payload, (P_)ap->payload + ap->size);
387 return (P_)ap + sizeofW(StgAP_STACK) + ap->size;
391 thread_TSO (StgTSO *tso)
394 thread_(&tso->global_link);
396 if ( tso->why_blocked == BlockedOnMVar
397 || tso->why_blocked == BlockedOnBlackHole
398 || tso->why_blocked == BlockedOnException
400 || tso->why_blocked == BlockedOnGA
401 || tso->why_blocked == BlockedOnGA_NoSend
404 thread_(&tso->block_info.closure);
406 if ( tso->blocked_exceptions != NULL ) {
407 thread_(&tso->blocked_exceptions);
412 thread_stack(tso->sp, &(tso->stack[tso->stack_size]));
413 return (StgPtr)tso + tso_sizeW(tso);
418 update_fwd_large( bdescr *bd )
421 const StgInfoTable* info;
423 for (; bd != NULL; bd = bd->link) {
426 info = get_itbl((StgClosure *)p);
428 switch (info->type) {
434 case MUT_ARR_PTRS_CLEAN:
435 case MUT_ARR_PTRS_DIRTY:
436 case MUT_ARR_PTRS_FROZEN:
437 case MUT_ARR_PTRS_FROZEN0:
442 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
443 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
444 thread((StgClosure **)p);
450 thread_TSO((StgTSO *)p);
454 thread_AP_STACK((StgAP_STACK *)p);
458 thread_PAP((StgPAP *)p);
464 StgTRecChunk *tc = (StgTRecChunk *)p;
465 TRecEntry *e = &(tc -> entries[0]);
466 thread_(&tc->prev_chunk);
467 for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
469 thread(&e->expected_value);
470 thread(&e->new_value);
476 barf("update_fwd_large: unknown/strange object %d", (int)(info->type));
482 thread_obj (StgInfoTable *info, StgPtr p)
484 switch (info->type) {
486 return p + sizeofW(StgThunk) + 1;
490 return p + sizeofW(StgHeader) + 1;
494 thread(&((StgClosure *)p)->payload[0]);
495 return p + sizeofW(StgHeader) + 1;
498 thread(&((StgThunk *)p)->payload[0]);
499 return p + sizeofW(StgThunk) + 1;
502 return p + sizeofW(StgThunk) + 2;
506 return p + sizeofW(StgHeader) + 2;
509 thread(&((StgThunk *)p)->payload[0]);
510 return p + sizeofW(StgThunk) + 2;
514 thread(&((StgClosure *)p)->payload[0]);
515 return p + sizeofW(StgHeader) + 2;
518 thread(&((StgThunk *)p)->payload[0]);
519 thread(&((StgThunk *)p)->payload[1]);
520 return p + sizeofW(StgThunk) + 2;
524 thread(&((StgClosure *)p)->payload[0]);
525 thread(&((StgClosure *)p)->payload[1]);
526 return p + sizeofW(StgHeader) + 2;
529 StgBCO *bco = (StgBCO *)p;
530 thread_(&bco->instrs);
531 thread_(&bco->literals);
533 thread_(&bco->itbls);
534 return p + bco_sizeW(bco);
541 end = (P_)((StgThunk *)p)->payload +
542 info->layout.payload.ptrs;
543 for (p = (P_)((StgThunk *)p)->payload; p < end; p++) {
544 thread((StgClosure **)p);
546 return p + info->layout.payload.nptrs;
556 case SE_CAF_BLACKHOLE:
562 end = (P_)((StgClosure *)p)->payload +
563 info->layout.payload.ptrs;
564 for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
565 thread((StgClosure **)p);
567 return p + info->layout.payload.nptrs;
572 StgWeak *w = (StgWeak *)p;
575 thread(&w->finalizer);
576 if (w->link != NULL) {
579 return p + sizeofW(StgWeak);
584 StgMVar *mvar = (StgMVar *)p;
585 thread_(&mvar->head);
586 thread_(&mvar->tail);
587 thread(&mvar->value);
588 return p + sizeofW(StgMVar);
592 case IND_OLDGEN_PERM:
593 thread(&((StgInd *)p)->indirectee);
594 return p + sizeofW(StgInd);
598 StgSelector *s = (StgSelector *)p;
599 thread(&s->selectee);
600 return p + THUNK_SELECTOR_sizeW();
604 return thread_AP_STACK((StgAP_STACK *)p);
607 return thread_PAP((StgPAP *)p);
610 return thread_AP((StgAP *)p);
613 return p + arr_words_sizeW((StgArrWords *)p);
615 case MUT_ARR_PTRS_CLEAN:
616 case MUT_ARR_PTRS_DIRTY:
617 case MUT_ARR_PTRS_FROZEN:
618 case MUT_ARR_PTRS_FROZEN0:
623 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
624 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
625 thread((StgClosure **)p);
631 return thread_TSO((StgTSO *)p);
633 case TVAR_WAIT_QUEUE:
635 StgTVarWaitQueue *wq = (StgTVarWaitQueue *)p;
636 thread_(&wq->waiting_tso);
637 thread_(&wq->next_queue_entry);
638 thread_(&wq->prev_queue_entry);
639 return p + sizeofW(StgTVarWaitQueue);
644 StgTVar *tvar = (StgTVar *)p;
645 thread((void *)&tvar->current_value);
646 thread((void *)&tvar->first_wait_queue_entry);
647 return p + sizeofW(StgTVar);
652 StgTRecHeader *trec = (StgTRecHeader *)p;
653 thread_(&trec->enclosing_trec);
654 thread_(&trec->current_chunk);
655 return p + sizeofW(StgTRecHeader);
661 StgTRecChunk *tc = (StgTRecChunk *)p;
662 TRecEntry *e = &(tc -> entries[0]);
663 thread_(&tc->prev_chunk);
664 for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
666 thread(&e->expected_value);
667 thread(&e->new_value);
669 return p + sizeofW(StgTRecChunk);
673 barf("update_fwd: unknown/strange object %d", (int)(info->type));
679 update_fwd( bdescr *blocks )
688 barf("update_fwd: ToDo");
691 // cycle through all the blocks in the step
692 for (; bd != NULL; bd = bd->link) {
695 // linearly scan the objects in this block
696 while (p < bd->free) {
697 ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
698 info = get_itbl((StgClosure *)p);
699 p = thread_obj(info, p);
705 update_fwd_compact( bdescr *blocks )
711 bdescr *bd, *free_bd;
717 free = free_bd->start;
720 barf("update_fwd: ToDo");
723 // cycle through all the blocks in the step
724 for (; bd != NULL; bd = bd->link) {
727 while (p < bd->free ) {
729 while ( p < bd->free && !is_marked(p,bd) ) {
738 m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord))));
739 m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1));
741 while ( p < bd->free ) {
746 if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) {
754 // Problem: we need to know the destination for this cell
755 // in order to unthread its info pointer. But we can't
756 // know the destination without the size, because we may
757 // spill into the next block. So we have to run down the
758 // threaded list and get the info ptr first.
759 info = get_threaded_info(p);
763 p = thread_obj(info, p);
766 if (free + size > free_bd->start + BLOCK_SIZE_W) {
767 // unset the next bit in the bitmap to indicate that
768 // this object needs to be pushed into the next
769 // block. This saves us having to run down the
770 // threaded info pointer list twice during the next pass.
772 free_bd = free_bd->link;
773 free = free_bd->start;
775 ASSERT(is_marked(q+1,bd));
788 update_bkwd_compact( step *stp )
794 bdescr *bd, *free_bd;
796 nat size, free_blocks;
798 bd = free_bd = stp->old_blocks;
799 free = free_bd->start;
803 barf("update_bkwd: ToDo");
806 // cycle through all the blocks in the step
807 for (; bd != NULL; bd = bd->link) {
810 while (p < bd->free ) {
812 while ( p < bd->free && !is_marked(p,bd) ) {
821 m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord))));
822 m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1));
824 while ( p < bd->free ) {
829 if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) {
837 if (!is_marked(p+1,bd)) {
838 // don't forget to update the free ptr in the block desc.
839 free_bd->free = free;
840 free_bd = free_bd->link;
841 free = free_bd->start;
846 ASSERT(LOOKS_LIKE_INFO_PTR(((StgClosure *)p)->header.info));
847 info = get_itbl((StgClosure *)p);
848 size = closure_sizeW_((StgClosure *)p,info);
855 if (info->type == TSO) {
856 move_TSO((StgTSO *)p, (StgTSO *)free);
867 // free the remaining blocks and count what's left.
868 free_bd->free = free;
869 if (free_bd->link != NULL) {
870 freeChain(free_bd->link);
871 free_bd->link = NULL;
878 compact( void (*get_roots)(evac_fn) )
883 // 1. thread the roots
884 get_roots((evac_fn)thread);
886 // the weak pointer lists...
887 if (weak_ptr_list != NULL) {
888 thread((void *)&weak_ptr_list);
890 if (old_weak_ptr_list != NULL) {
891 thread((void *)&old_weak_ptr_list); // tmp
895 for (g = 1; g < RtsFlags.GcFlags.generations; g++) {
898 for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) {
899 for (p = bd->start; p < bd->free; p++) {
900 thread((StgClosure **)p);
905 // the global thread list
906 thread((void *)&all_threads);
908 // any threads resurrected during this GC
909 thread((void *)&resurrected_threads);
914 for (task = all_tasks; task != NULL; task = task->all_link) {
921 // the static objects
922 thread_static(scavenged_static_objects);
924 // the stable pointer table
925 threadStablePtrTable((evac_fn)thread);
927 // the CAF list (used by GHCi)
928 markCAFs((evac_fn)thread);
930 // 2. update forward ptrs
931 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
932 for (s = 0; s < generations[g].n_steps; s++) {
933 if (g==0 && s ==0) continue;
934 stp = &generations[g].steps[s];
935 debugTrace(DEBUG_gc, "update_fwd: %d.%d",
936 stp->gen->no, stp->no);
938 update_fwd(stp->blocks);
939 update_fwd_large(stp->scavenged_large_objects);
940 if (g == RtsFlags.GcFlags.generations-1 && stp->old_blocks != NULL) {
941 debugTrace(DEBUG_gc, "update_fwd: %d.%d (compact)",
942 stp->gen->no, stp->no);
943 update_fwd_compact(stp->old_blocks);
948 // 3. update backward ptrs
949 stp = &oldest_gen->steps[0];
950 if (stp->old_blocks != NULL) {
951 blocks = update_bkwd_compact(stp);
953 "update_bkwd: %d.%d (compact, old: %d blocks, now %d blocks)",
954 stp->gen->no, stp->no,
955 stp->n_old_blocks, blocks);
956 stp->n_old_blocks = blocks;