1
/* -----------------------------------------------------------------------------
3
* (c) The GHC Team 2001-2008
5
* Compacting garbage collector
7
* Documentation on the architecture of the Garbage Collector can be
8
* found in the online commentary:
10
* http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC
12
* ---------------------------------------------------------------------------*/
14
#include "PosixSource.h"
19
#include "BlockAlloc.h"
29
// Turn off inlining when debugging - it obfuscates things
32
# define STATIC_INLINE static
35
/* ----------------------------------------------------------------------------
36
Threading / unthreading pointers.
38
The basic idea here is to chain together all the fields pointing at
39
a particular object, with the root of the chain in the object's
40
info table field. The original contents of the info pointer goes
41
at the end of the chain.
43
Adding a new field to the chain is a matter of swapping the
44
contents of the field with the contents of the object's info table
47
To unthread the chain, we walk down it updating all the fields on
48
the chain with the new location of the object. We stop when we
49
reach the info pointer at the end.
51
The main difficulty here is that we need to be able to identify the
52
info pointer at the end of the chain. We can't use the low bits of
53
the pointer for this; they are already being used for
54
pointer-tagging. What's more, we need to retain the
55
pointer-tagging tag bits on each pointer during the
56
threading/unthreading process.
58
Our solution is as follows:
59
- an info pointer (chain length zero) is identified by having tag 0
60
- in a threaded chain of length > 0:
61
- the pointer-tagging tag bits are attached to the info pointer
62
- the first entry in the chain has tag 1
63
- second and subsequent entries in the chain have tag 2
65
This exploits the fact that the tag on each pointer to a given
66
closure is normally the same (if they are not the same, then
67
presumably the tag is not essential and it therefore doesn't matter
68
if we throw away some of the tags).
69
------------------------------------------------------------------------- */
72
thread (StgClosure **p)
80
q = (StgPtr)UNTAG_CLOSURE(q0);
82
// It doesn't look like a closure at the moment, because the info
83
// ptr is possibly threaded:
84
// ASSERT(LOOKS_LIKE_CLOSURE_PTR(q));
86
if (HEAP_ALLOCED(q)) {
89
if (bd->flags & BF_MARKED)
92
switch (GET_CLOSURE_TAG((StgClosure *)iptr))
95
// this is the info pointer; we are creating a new chain.
96
// save the original tag at the end of the chain.
97
*p = (StgClosure *)((StgWord)iptr + GET_CLOSURE_TAG(q0));
102
// this is a chain of length 1 or more
103
*p = (StgClosure *)iptr;
112
thread_root (void *user STG_UNUSED, StgClosure **p)
117
// This version of thread() takes a (void *), used to circumvent
118
// warnings from gcc about pointer punning and strict aliasing.
119
STATIC_INLINE void thread_ (void *p) { thread((StgClosure **)p); }
122
unthread( StgPtr p, StgWord free )
129
switch (GET_CLOSURE_TAG((StgClosure *)q))
132
// nothing to do; the chain is length zero
136
r = *q0; // r is the info ptr, tagged with the pointer-tag
138
*p = (StgWord)UNTAG_CLOSURE((StgClosure *)r);
151
// Traverse a threaded chain and pull out the info pointer at the end.
152
// The info pointer is also tagged with the appropriate pointer tag
153
// for this closure, which should be attached to the pointer
154
// subsequently passed to unthread().
155
STATIC_INLINE StgWord
156
get_threaded_info( StgPtr p )
160
q = (W_)GET_INFO(UNTAG_CLOSURE((StgClosure *)p));
163
switch (GET_CLOSURE_TAG((StgClosure *)q))
166
ASSERT(LOOKS_LIKE_INFO_PTR(q));
170
StgWord r = *(StgPtr)(q-1);
171
ASSERT(LOOKS_LIKE_INFO_PTR((StgWord)UNTAG_CLOSURE((StgClosure *)r)));
178
barf("get_threaded_info");
182
// A word-aligned memmove will be faster for small objects than libc's or gcc's.
183
// Remember, the two regions *might* overlap, but: to <= from.
185
move(StgPtr to, StgPtr from, nat size)
187
for(; size > 0; --size) {
193
thread_static( StgClosure* p )
195
const StgInfoTable *info;
197
// keep going until we've threaded all the objects on the linked
199
while (p != END_OF_STATIC_LIST) {
202
switch (info->type) {
205
thread(&((StgInd *)p)->indirectee);
206
p = *IND_STATIC_LINK(p);
210
p = *THUNK_STATIC_LINK(p);
213
p = *FUN_STATIC_LINK(p);
216
p = *STATIC_LINK(info,p);
220
barf("thread_static: strange closure %d", (int)(info->type));
227
thread_large_bitmap( StgPtr p, StgLargeBitmap *large_bitmap, nat size )
233
bitmap = large_bitmap->bitmap[b];
234
for (i = 0; i < size; ) {
235
if ((bitmap & 1) == 0) {
236
thread((StgClosure **)p);
240
if (i % BITS_IN(W_) == 0) {
242
bitmap = large_bitmap->bitmap[b];
244
bitmap = bitmap >> 1;
250
thread_arg_block (StgFunInfoTable *fun_info, StgClosure **args)
257
switch (fun_info->f.fun_type) {
259
bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
260
size = BITMAP_SIZE(fun_info->f.b.bitmap);
263
size = GET_FUN_LARGE_BITMAP(fun_info)->size;
264
thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
268
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
269
size = BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);
272
if ((bitmap & 1) == 0) {
273
thread((StgClosure **)p);
276
bitmap = bitmap >> 1;
285
thread_stack(StgPtr p, StgPtr stack_end)
287
const StgRetInfoTable* info;
291
// highly similar to scavenge_stack, but we do pointer threading here.
293
while (p < stack_end) {
295
// *p must be the info pointer of an activation
296
// record. All activation records have 'bitmap' style layout
299
info = get_ret_itbl((StgClosure *)p);
301
switch (info->i.type) {
303
// Dynamic bitmap: the mask is stored on the stack
307
dyn = ((StgRetDyn *)p)->liveness;
309
// traverse the bitmap first
310
bitmap = RET_DYN_LIVENESS(dyn);
311
p = (P_)&((StgRetDyn *)p)->payload[0];
312
size = RET_DYN_BITMAP_SIZE;
314
if ((bitmap & 1) == 0) {
315
thread((StgClosure **)p);
318
bitmap = bitmap >> 1;
322
// skip over the non-ptr words
323
p += RET_DYN_NONPTRS(dyn) + RET_DYN_NONPTR_REGS_SIZE;
325
// follow the ptr words
326
for (size = RET_DYN_PTRS(dyn); size > 0; size--) {
327
thread((StgClosure **)p);
333
// small bitmap (<= 32 entries, or 64 on a 64-bit machine)
334
case CATCH_RETRY_FRAME:
335
case CATCH_STM_FRAME:
336
case ATOMICALLY_FRAME:
341
bitmap = BITMAP_BITS(info->i.layout.bitmap);
342
size = BITMAP_SIZE(info->i.layout.bitmap);
344
// NOTE: the payload starts immediately after the info-ptr, we
345
// don't have an StgHeader in the same sense as a heap closure.
347
if ((bitmap & 1) == 0) {
348
thread((StgClosure **)p);
351
bitmap = bitmap >> 1;
362
thread((StgClosure **)p);
364
size = BCO_BITMAP_SIZE(bco);
365
thread_large_bitmap(p, BCO_BITMAP(bco), size);
370
// large bitmap (> 32 entries, or 64 on a 64-bit machine)
373
size = GET_LARGE_BITMAP(&info->i)->size;
374
thread_large_bitmap(p, GET_LARGE_BITMAP(&info->i), size);
380
StgRetFun *ret_fun = (StgRetFun *)p;
381
StgFunInfoTable *fun_info;
383
fun_info = FUN_INFO_PTR_TO_STRUCT(UNTAG_CLOSURE((StgClosure *)
384
get_threaded_info((StgPtr)ret_fun->fun)));
385
// *before* threading it!
386
thread(&ret_fun->fun);
387
p = thread_arg_block(fun_info, ret_fun->payload);
392
barf("thread_stack: weird activation record found on stack: %d",
393
(int)(info->i.type));
399
thread_PAP_payload (StgClosure *fun, StgClosure **payload, StgWord size)
403
StgFunInfoTable *fun_info;
405
fun_info = FUN_INFO_PTR_TO_STRUCT(UNTAG_CLOSURE((StgClosure *)
406
get_threaded_info((StgPtr)fun)));
407
ASSERT(fun_info->i.type != PAP);
411
switch (fun_info->f.fun_type) {
413
bitmap = BITMAP_BITS(fun_info->f.b.bitmap);
416
thread_large_bitmap(p, GET_FUN_LARGE_BITMAP(fun_info), size);
420
thread_large_bitmap((StgPtr)payload, BCO_BITMAP(fun), size);
424
bitmap = BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);
427
if ((bitmap & 1) == 0) {
428
thread((StgClosure **)p);
431
bitmap = bitmap >> 1;
441
thread_PAP (StgPAP *pap)
444
p = thread_PAP_payload(pap->fun, pap->payload, pap->n_args);
450
thread_AP (StgAP *ap)
453
p = thread_PAP_payload(ap->fun, ap->payload, ap->n_args);
459
thread_AP_STACK (StgAP_STACK *ap)
462
thread_stack((P_)ap->payload, (P_)ap->payload + ap->size);
463
return (P_)ap + sizeofW(StgAP_STACK) + ap->size;
467
thread_TSO (StgTSO *tso)
469
thread_(&tso->_link);
470
thread_(&tso->global_link);
472
if ( tso->why_blocked == BlockedOnMVar
473
|| tso->why_blocked == BlockedOnBlackHole
474
|| tso->why_blocked == BlockedOnMsgThrowTo
476
thread_(&tso->block_info.closure);
478
thread_(&tso->blocked_exceptions);
483
thread_stack(tso->sp, &(tso->stack[tso->stack_size]));
484
return (StgPtr)tso + tso_sizeW(tso);
489
update_fwd_large( bdescr *bd )
492
const StgInfoTable* info;
494
for (; bd != NULL; bd = bd->link) {
496
// nothing to do in a pinned block; it might not even have an object
498
if (bd->flags & BF_PINNED) continue;
501
info = get_itbl((StgClosure *)p);
503
switch (info->type) {
509
case MUT_ARR_PTRS_CLEAN:
510
case MUT_ARR_PTRS_DIRTY:
511
case MUT_ARR_PTRS_FROZEN:
512
case MUT_ARR_PTRS_FROZEN0:
517
a = (StgMutArrPtrs*)p;
518
for (p = (P_)a->payload; p < (P_)&a->payload[a->ptrs]; p++) {
519
thread((StgClosure **)p);
525
thread_TSO((StgTSO *)p);
529
thread_AP_STACK((StgAP_STACK *)p);
533
thread_PAP((StgPAP *)p);
539
StgTRecChunk *tc = (StgTRecChunk *)p;
540
TRecEntry *e = &(tc -> entries[0]);
541
thread_(&tc->prev_chunk);
542
for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
544
thread(&e->expected_value);
545
thread(&e->new_value);
551
barf("update_fwd_large: unknown/strange object %d", (int)(info->type));
556
// ToDo: too big to inline
557
static /* STATIC_INLINE */ StgPtr
558
thread_obj (StgInfoTable *info, StgPtr p)
560
switch (info->type) {
562
return p + sizeofW(StgThunk) + 1;
566
return p + sizeofW(StgHeader) + 1;
570
thread(&((StgClosure *)p)->payload[0]);
571
return p + sizeofW(StgHeader) + 1;
574
thread(&((StgThunk *)p)->payload[0]);
575
return p + sizeofW(StgThunk) + 1;
578
return p + sizeofW(StgThunk) + 2;
582
return p + sizeofW(StgHeader) + 2;
585
thread(&((StgThunk *)p)->payload[0]);
586
return p + sizeofW(StgThunk) + 2;
590
thread(&((StgClosure *)p)->payload[0]);
591
return p + sizeofW(StgHeader) + 2;
594
thread(&((StgThunk *)p)->payload[0]);
595
thread(&((StgThunk *)p)->payload[1]);
596
return p + sizeofW(StgThunk) + 2;
600
thread(&((StgClosure *)p)->payload[0]);
601
thread(&((StgClosure *)p)->payload[1]);
602
return p + sizeofW(StgHeader) + 2;
605
StgBCO *bco = (StgBCO *)p;
606
thread_(&bco->instrs);
607
thread_(&bco->literals);
609
return p + bco_sizeW(bco);
616
end = (P_)((StgThunk *)p)->payload +
617
info->layout.payload.ptrs;
618
for (p = (P_)((StgThunk *)p)->payload; p < end; p++) {
619
thread((StgClosure **)p);
621
return p + info->layout.payload.nptrs;
635
end = (P_)((StgClosure *)p)->payload +
636
info->layout.payload.ptrs;
637
for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
638
thread((StgClosure **)p);
640
return p + info->layout.payload.nptrs;
645
StgWeak *w = (StgWeak *)p;
646
thread(&w->cfinalizer);
649
thread(&w->finalizer);
650
if (w->link != NULL) {
653
return p + sizeofW(StgWeak);
659
StgMVar *mvar = (StgMVar *)p;
660
thread_(&mvar->head);
661
thread_(&mvar->tail);
662
thread(&mvar->value);
663
return p + sizeofW(StgMVar);
668
thread(&((StgInd *)p)->indirectee);
669
return p + sizeofW(StgInd);
673
StgSelector *s = (StgSelector *)p;
674
thread(&s->selectee);
675
return p + THUNK_SELECTOR_sizeW();
679
return thread_AP_STACK((StgAP_STACK *)p);
682
return thread_PAP((StgPAP *)p);
685
return thread_AP((StgAP *)p);
688
return p + arr_words_sizeW((StgArrWords *)p);
690
case MUT_ARR_PTRS_CLEAN:
691
case MUT_ARR_PTRS_DIRTY:
692
case MUT_ARR_PTRS_FROZEN:
693
case MUT_ARR_PTRS_FROZEN0:
698
a = (StgMutArrPtrs *)p;
699
for (p = (P_)a->payload; p < (P_)&a->payload[a->ptrs]; p++) {
700
thread((StgClosure **)p);
703
return (StgPtr)a + mut_arr_ptrs_sizeW(a);
707
return thread_TSO((StgTSO *)p);
712
StgTRecChunk *tc = (StgTRecChunk *)p;
713
TRecEntry *e = &(tc -> entries[0]);
714
thread_(&tc->prev_chunk);
715
for (i = 0; i < tc -> next_entry_idx; i ++, e++ ) {
717
thread(&e->expected_value);
718
thread(&e->new_value);
720
return p + sizeofW(StgTRecChunk);
724
barf("update_fwd: unknown/strange object %d", (int)(info->type));
730
update_fwd( bdescr *blocks )
738
// cycle through all the blocks in the step
739
for (; bd != NULL; bd = bd->link) {
742
// linearly scan the objects in this block
743
while (p < bd->free) {
744
ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));
745
info = get_itbl((StgClosure *)p);
746
p = thread_obj(info, p);
752
update_fwd_compact( bdescr *blocks )
758
bdescr *bd, *free_bd;
765
free = free_bd->start;
767
// cycle through all the blocks in the step
768
for (; bd != NULL; bd = bd->link) {
771
while (p < bd->free ) {
773
while ( p < bd->free && !is_marked(p,bd) ) {
782
m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord))));
783
m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1));
785
while ( p < bd->free ) {
790
if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) {
798
// Problem: we need to know the destination for this cell
799
// in order to unthread its info pointer. But we can't
800
// know the destination without the size, because we may
801
// spill into the next block. So we have to run down the
802
// threaded list and get the info ptr first.
804
// ToDo: one possible avenue of attack is to use the fact
805
// that if (p&BLOCK_MASK) >= (free&BLOCK_MASK), then we
806
// definitely have enough room. Also see bug #1147.
807
iptr = get_threaded_info(p);
808
info = INFO_PTR_TO_STRUCT(UNTAG_CLOSURE((StgClosure *)iptr));
812
p = thread_obj(info, p);
815
if (free + size > free_bd->start + BLOCK_SIZE_W) {
816
// set the next bit in the bitmap to indicate that
817
// this object needs to be pushed into the next
818
// block. This saves us having to run down the
819
// threaded info pointer list twice during the next pass.
821
free_bd = free_bd->link;
822
free = free_bd->start;
824
ASSERT(!is_marked(q+1,bd));
827
unthread(q,(StgWord)free + GET_CLOSURE_TAG((StgClosure *)iptr));
837
update_bkwd_compact( generation *gen )
843
bdescr *bd, *free_bd;
845
nat size, free_blocks;
848
bd = free_bd = gen->old_blocks;
849
free = free_bd->start;
852
// cycle through all the blocks in the step
853
for (; bd != NULL; bd = bd->link) {
856
while (p < bd->free ) {
858
while ( p < bd->free && !is_marked(p,bd) ) {
867
m = * ((StgPtr)bd->u.bitmap + ((p - bd->start) / (BITS_IN(StgWord))));
868
m >>= ((p - bd->start) & (BITS_IN(StgWord) - 1));
870
while ( p < bd->free ) {
875
if (((StgWord)p & (sizeof(W_) * BITS_IN(StgWord))) == 0) {
883
if (is_marked(p+1,bd)) {
884
// don't forget to update the free ptr in the block desc.
885
free_bd->free = free;
886
free_bd = free_bd->link;
887
free = free_bd->start;
891
iptr = get_threaded_info(p);
892
unthread(p, (StgWord)free + GET_CLOSURE_TAG((StgClosure *)iptr));
893
ASSERT(LOOKS_LIKE_INFO_PTR((StgWord)((StgClosure *)p)->header.info));
894
info = get_itbl((StgClosure *)p);
895
size = closure_sizeW_((StgClosure *)p,info);
902
if (info->type == TSO) {
903
move_TSO((StgTSO *)p, (StgTSO *)free);
914
// free the remaining blocks and count what's left.
915
free_bd->free = free;
916
if (free_bd->link != NULL) {
917
freeChain(free_bd->link);
918
free_bd->link = NULL;
925
compact(StgClosure *static_objects)
930
// 1. thread the roots
931
markCapabilities((evac_fn)thread_root, NULL);
933
// the weak pointer lists...
934
if (weak_ptr_list != NULL) {
935
thread((void *)&weak_ptr_list);
937
if (old_weak_ptr_list != NULL) {
938
thread((void *)&old_weak_ptr_list); // tmp
942
for (g = 1; g < RtsFlags.GcFlags.generations; g++) {
946
for (bd = generations[g].mut_list; bd != NULL; bd = bd->link) {
947
for (p = bd->start; p < bd->free; p++) {
948
thread((StgClosure **)p);
951
for (n = 0; n < n_capabilities; n++) {
952
for (bd = capabilities[n].mut_lists[g];
953
bd != NULL; bd = bd->link) {
954
for (p = bd->start; p < bd->free; p++) {
955
thread((StgClosure **)p);
961
// the global thread list
962
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
963
thread((void *)&generations[g].threads);
966
// any threads resurrected during this GC
967
thread((void *)&resurrected_threads);
973
for (task = all_tasks; task != NULL; task = task->all_link) {
974
for (incall = task->incall; incall != NULL;
975
incall = incall->prev_stack) {
977
thread_(&incall->tso);
983
// the static objects
984
thread_static(static_objects /* ToDo: ok? */);
986
// the stable pointer table
987
threadStablePtrTable((evac_fn)thread_root, NULL);
989
// the CAF list (used by GHCi)
990
markCAFs((evac_fn)thread_root, NULL);
992
// 2. update forward ptrs
993
for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
994
gen = &generations[g];
995
debugTrace(DEBUG_gc, "update_fwd: %d", g);
997
update_fwd(gen->blocks);
998
update_fwd_large(gen->scavenged_large_objects);
999
if (g == RtsFlags.GcFlags.generations-1 && gen->old_blocks != NULL) {
1000
debugTrace(DEBUG_gc, "update_fwd: %d (compact)", g);
1001
update_fwd_compact(gen->old_blocks);
1005
// 3. update backward ptrs
1007
if (gen->old_blocks != NULL) {
1008
blocks = update_bkwd_compact(gen);
1009
debugTrace(DEBUG_gc,
1010
"update_bkwd: %d (compact, old: %d blocks, now %d blocks)",
1011
gen->no, gen->n_old_blocks, blocks);
1012
gen->n_old_blocks = blocks;