1 /* -----------------------------------------------------------------------------
2 * $Id: GC.c,v 1.16 1999/01/19 17:22:55 simonm Exp $
4 * Two-space garbage collector
6 * ---------------------------------------------------------------------------*/
12 #include "StoragePriv.h"
15 #include "SchedAPI.h" /* for ReverCAFs prototype */
18 #include "BlockAlloc.h"
20 #include "DebugProf.h"
26 /* STATIC OBJECT LIST.
29 * We maintain a linked list of static objects that are still live.
30 * The requirements for this list are:
32 * - we need to scan the list while adding to it, in order to
33 * scavenge all the static objects (in the same way that
34 * breadth-first scavenging works for dynamic objects).
36 * - we need to be able to tell whether an object is already on
37 * the list, to break loops.
39 * Each static object has a "static link field", which we use for
40 * linking objects on to the list. We use a stack-type list, consing
41 * objects on the front as they are added (this means that the
42 * scavenge phase is depth-first, not breadth-first, but that
45 * A separate list is kept for objects that have been scavenged
46 * already - this is so that we can zero all the marks afterwards.
48 * An object is on the list if its static link field is non-zero; this
49 * means that we have to mark the end of the list with '1', not NULL.
51 * Extra notes for generational GC:
53 * Each generation has a static object list associated with it. When
54 * collecting generations up to N, we treat the static object lists
55 * from generations > N as roots.
57 * We build up a static object list while collecting generations 0..N,
58 * which is then appended to the static object list of generation N+1.
60 StgClosure* static_objects; /* live static objects */
61 StgClosure* scavenged_static_objects; /* static objects scavenged so far */
63 /* N is the oldest generation being collected, where the generations
64 * are numbered starting at 0. A major GC (indicated by the major_gc
65 * flag) is when we're collecting all generations. We only attempt to
66 * deal with static objects and GC CAFs when doing a major GC.
69 static rtsBool major_gc;
71 /* Youngest generation that objects should be evacuated to in
72 * evacuate(). (Logically an argument to evacuate, but it's static
73 * a lot of the time so we optimise it into a global variable).
79 static StgWeak *old_weak_ptr_list; /* also pending finaliser list */
80 static rtsBool weak_done; /* all done for this pass */
82 /* Flag indicating failure to evacuate an object to the desired
85 static rtsBool failed_to_evac;
87 /* Old to-space (used for two-space collector only)
91 /* -----------------------------------------------------------------------------
92 Static function declarations
93 -------------------------------------------------------------------------- */
95 static StgClosure *evacuate(StgClosure *q);
96 static void zeroStaticObjectList(StgClosure* first_static);
97 static rtsBool traverse_weak_ptr_list(void);
98 static void zeroMutableList(StgMutClosure *first);
99 static void revertDeadCAFs(void);
101 static void scavenge_stack(StgPtr p, StgPtr stack_end);
102 static void scavenge_large(step *step);
103 static void scavenge(step *step);
104 static void scavenge_static(void);
105 static StgMutClosure *scavenge_mutable_list(StgMutClosure *p, nat gen);
108 static void gcCAFs(void);
111 /* -----------------------------------------------------------------------------
114 For garbage collecting generation N (and all younger generations):
116 - follow all pointers in the root set. the root set includes all
117 mutable objects in all steps in all generations.
119 - for each pointer, evacuate the object it points to into either
120 + to-space in the next higher step in that generation, if one exists,
121 + if the object's generation == N, then evacuate it to the next
122 generation if one exists, or else to-space in the current
124 + if the object's generation < N, then evacuate it to to-space
125 in the next generation.
127 - repeatedly scavenge to-space from each step in each generation
128 being collected until no more objects can be evacuated.
130 - free from-space in each step, and set from-space = to-space.
132 -------------------------------------------------------------------------- */
134 void GarbageCollect(void (*get_roots)(void))
138 lnat live, allocated, collected = 0;
142 CostCentreStack *prev_CCS;
145 /* tell the stats department that we've started a GC */
148 /* attribute any costs to CCS_GC */
154 /* We might have been called from Haskell land by _ccall_GC, in
155 * which case we need to call threadPaused() because the scheduler
156 * won't have done it.
158 if (CurrentTSO) { threadPaused(CurrentTSO); }
160 /* Approximate how much we allocated: number of blocks in the
161 * nursery + blocks allocated via allocate() - unused nusery blocks.
162 * This leaves a little slop at the end of each block, and doesn't
163 * take into account large objects (ToDo).
165 allocated = (nursery_blocks * BLOCK_SIZE_W) + allocated_bytes();
166 for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
167 allocated -= BLOCK_SIZE_W;
170 /* Figure out which generation to collect
173 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
174 if (generations[g].steps[0].n_blocks >= generations[g].max_blocks) {
178 major_gc = (N == RtsFlags.GcFlags.generations-1);
180 /* check stack sanity *before* GC (ToDo: check all threads) */
181 /*IF_DEBUG(sanity, checkTSO(MainTSO,0)); */
182 IF_DEBUG(sanity, checkFreeListSanity());
184 /* Initialise the static object lists
186 static_objects = END_OF_STATIC_LIST;
187 scavenged_static_objects = END_OF_STATIC_LIST;
189 /* zero the mutable list for the oldest generation (see comment by
190 * zeroMutableList below).
193 zeroMutableList(generations[RtsFlags.GcFlags.generations-1].mut_list);
196 /* Save the old to-space if we're doing a two-space collection
198 if (RtsFlags.GcFlags.generations == 1) {
199 old_to_space = g0s0->to_space;
200 g0s0->to_space = NULL;
203 /* Initialise to-space in all the generations/steps that we're
206 for (g = 0; g <= N; g++) {
207 generations[g].mut_list = END_MUT_LIST;
209 for (s = 0; s < generations[g].n_steps; s++) {
211 /* generation 0, step 0 doesn't need to-space */
212 if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) {
216 /* Get a free block for to-space. Extra blocks will be chained on
220 step = &generations[g].steps[s];
221 ASSERT(step->gen->no == g);
222 ASSERT(step->hp ? Bdescr(step->hp)->step == step : rtsTrue);
223 bd->gen = &generations[g];
226 bd->evacuated = 1; /* it's a to-space block */
227 step->hp = bd->start;
228 step->hpLim = step->hp + BLOCK_SIZE_W;
231 step->to_blocks = 1; /* ???? */
232 step->scan = bd->start;
234 step->new_large_objects = NULL;
235 step->scavenged_large_objects = NULL;
236 /* mark the large objects as not evacuated yet */
237 for (bd = step->large_objects; bd; bd = bd->link) {
243 /* make sure the older generations have at least one block to
244 * allocate into (this makes things easier for copy(), see below.
246 for (g = N+1; g < RtsFlags.GcFlags.generations; g++) {
247 for (s = 0; s < generations[g].n_steps; s++) {
248 step = &generations[g].steps[s];
249 if (step->hp_bd == NULL) {
251 bd->gen = &generations[g];
254 bd->evacuated = 0; /* *not* a to-space block */
255 step->hp = bd->start;
256 step->hpLim = step->hp + BLOCK_SIZE_W;
261 /* Set the scan pointer for older generations: remember we
262 * still have to scavenge objects that have been promoted. */
263 step->scan = step->hp;
264 step->scan_bd = step->hp_bd;
265 step->to_space = NULL;
267 step->new_large_objects = NULL;
268 step->scavenged_large_objects = NULL;
272 /* -----------------------------------------------------------------------
273 * follow all the roots that we know about:
274 * - mutable lists from each generation > N
275 * we want to *scavenge* these roots, not evacuate them: they're not
276 * going to move in this GC.
277 * Also: do them in reverse generation order. This is because we
278 * often want to promote objects that are pointed to by older
279 * generations early, so we don't have to repeatedly copy them.
280 * Doing the generations in reverse order ensures that we don't end
281 * up in the situation where we want to evac an object to gen 3 and
282 * it has already been evaced to gen 2.
285 StgMutClosure *tmp, **pp;
286 for (g = N+1; g < RtsFlags.GcFlags.generations; g++) {
287 generations[g].saved_mut_list = generations[g].mut_list;
288 generations[g].mut_list = END_MUT_LIST;
291 for (g = RtsFlags.GcFlags.generations-1; g > N; g--) {
292 tmp = scavenge_mutable_list(generations[g].saved_mut_list, g);
293 pp = &generations[g].mut_list;
294 while (*pp != END_MUT_LIST) {
295 pp = &(*pp)->mut_link;
301 /* follow all the roots that the application knows about.
306 /* And don't forget to mark the TSO if we got here direct from
309 CurrentTSO = (StgTSO *)MarkRoot((StgClosure *)CurrentTSO);
312 /* Mark the weak pointer list, and prepare to detect dead weak
316 old_weak_ptr_list = weak_ptr_list;
317 weak_ptr_list = NULL;
318 weak_done = rtsFalse;
322 /* ToDo: To fix the caf leak, we need to make the commented out
323 * parts of this code do something sensible - as described in
326 extern void markHugsObjects(void);
328 /* ToDo: This (undefined) function should contain the scavenge
329 * loop immediately below this block of code - but I'm not sure
330 * enough of the details to do this myself.
332 scavengeEverything();
333 /* revert dead CAFs and update enteredCAFs list */
338 /* This will keep the CAFs and the attached BCOs alive
339 * but the values will have been reverted
341 scavengeEverything();
346 /* -------------------------------------------------------------------------
347 * Repeatedly scavenge all the areas we know about until there's no
348 * more scavenging to be done.
355 /* scavenge static objects */
356 if (major_gc && static_objects != END_OF_STATIC_LIST) {
360 /* When scavenging the older generations: Objects may have been
361 * evacuated from generations <= N into older generations, and we
362 * need to scavenge these objects. We're going to try to ensure that
363 * any evacuations that occur move the objects into at least the
364 * same generation as the object being scavenged, otherwise we
365 * have to create new entries on the mutable list for the older
369 /* scavenge each step in generations 0..maxgen */
372 for (gen = RtsFlags.GcFlags.generations-1; gen >= 0; gen--) {
373 for (s = 0; s < generations[gen].n_steps; s++) {
374 step = &generations[gen].steps[s];
376 if (step->hp_bd != step->scan_bd || step->scan < step->hp) {
380 if (step->new_large_objects != NULL) {
381 scavenge_large(step);
387 if (flag) { goto loop; }
389 /* must be last... */
390 if (traverse_weak_ptr_list()) { /* returns rtsTrue if evaced something */
395 /* Set the maximum blocks for the oldest generation, based on twice
396 * the amount of live data now, adjusted to fit the maximum heap
399 * This is an approximation, since in the worst case we'll need
400 * twice the amount of live data plus whatever space the other
403 if (RtsFlags.GcFlags.generations > 1) {
405 oldest_gen->max_blocks =
406 stg_max(oldest_gen->steps[0].to_blocks * RtsFlags.GcFlags.oldGenFactor,
407 RtsFlags.GcFlags.minOldGenSize);
408 if (oldest_gen->max_blocks > RtsFlags.GcFlags.maxHeapSize / 2) {
409 oldest_gen->max_blocks = RtsFlags.GcFlags.maxHeapSize / 2;
410 if (((int)oldest_gen->max_blocks -
411 (int)oldest_gen->steps[0].to_blocks) <
412 (RtsFlags.GcFlags.pcFreeHeap *
413 RtsFlags.GcFlags.maxHeapSize / 200)) {
418 /* For a two-space collector, we need to resize the nursery. */
420 /* set up a new nursery. Allocate a nursery size based on a
421 * function of the amount of live data (currently a factor of 2,
422 * should be configurable (ToDo)). Use the blocks from the old
423 * nursery if possible, freeing up any left over blocks.
425 * If we get near the maximum heap size, then adjust our nursery
426 * size accordingly. If the nursery is the same size as the live
427 * data (L), then we need 3L bytes. We can reduce the size of the
428 * nursery to bring the required memory down near 2L bytes.
430 * A normal 2-space collector would need 4L bytes to give the same
431 * performance we get from 3L bytes, reducing to the same
432 * performance at 2L bytes.
434 nat blocks = g0s0->to_blocks;
436 if ( blocks * 4 > RtsFlags.GcFlags.maxHeapSize ) {
437 int adjusted_blocks; /* signed on purpose */
440 adjusted_blocks = (RtsFlags.GcFlags.maxHeapSize - 2 * blocks);
441 IF_DEBUG(gc, fprintf(stderr, "Near maximum heap size of 0x%x blocks, blocks = %d, adjusted to %d\n", RtsFlags.GcFlags.maxHeapSize, blocks, adjusted_blocks));
442 pc_free = adjusted_blocks * 100 / RtsFlags.GcFlags.maxHeapSize;
443 if (pc_free < RtsFlags.GcFlags.pcFreeHeap) /* might even be < 0 */ {
446 blocks = adjusted_blocks;
450 if (blocks < RtsFlags.GcFlags.minAllocAreaSize) {
451 blocks = RtsFlags.GcFlags.minAllocAreaSize;
455 if (nursery_blocks < blocks) {
456 IF_DEBUG(gc, fprintf(stderr, "Increasing size of nursery to %d blocks\n",
458 g0s0->blocks = allocNursery(g0s0->blocks, blocks-nursery_blocks);
462 IF_DEBUG(gc, fprintf(stderr, "Decreasing size of nursery to %d blocks\n",
464 for (bd = g0s0->blocks; nursery_blocks > blocks; nursery_blocks--) {
472 g0s0->n_blocks = nursery_blocks = blocks;
475 /* run through all the generations/steps and tidy up
477 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
480 generations[g].collections++; /* for stats */
483 for (s = 0; s < generations[g].n_steps; s++) {
485 step = &generations[g].steps[s];
487 if (!(g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1)) {
488 /* Tidy the end of the to-space chains */
489 step->hp_bd->free = step->hp;
490 step->hp_bd->link = NULL;
493 /* for generations we collected... */
496 collected += step->n_blocks * BLOCK_SIZE_W; /* for stats */
498 /* free old memory and shift to-space into from-space for all
499 * the collected steps (except the allocation area). These
500 * freed blocks will probaby be quickly recycled.
502 if (!(g == 0 && s == 0)) {
503 freeChain(step->blocks);
504 step->blocks = step->to_space;
505 step->n_blocks = step->to_blocks;
506 step->to_space = NULL;
508 for (bd = step->blocks; bd != NULL; bd = bd->link) {
509 bd->evacuated = 0; /* now from-space */
513 /* LARGE OBJECTS. The current live large objects are chained on
514 * scavenged_large, having been moved during garbage
515 * collection from large_objects. Any objects left on
516 * large_objects list are therefore dead, so we free them here.
518 for (bd = step->large_objects; bd != NULL; bd = next) {
523 for (bd = step->scavenged_large_objects; bd != NULL; bd = bd->link) {
526 step->large_objects = step->scavenged_large_objects;
528 /* Set the maximum blocks for this generation, interpolating
529 * between the maximum size of the oldest and youngest
532 * max_blocks = alloc_area_size +
533 * (oldgen_max_blocks - alloc_area_size) * G
534 * -----------------------------------------
538 generations[g].max_blocks =
539 RtsFlags.GcFlags.minAllocAreaSize +
540 (((oldest_gen->max_blocks - RtsFlags.GcFlags.minAllocAreaSize) * g)
541 / (RtsFlags.GcFlags.generations-1));
544 /* for older generations... */
547 /* For older generations, we need to append the
548 * scavenged_large_object list (i.e. large objects that have been
549 * promoted during this GC) to the large_object list for that step.
551 for (bd = step->scavenged_large_objects; bd; bd = next) {
554 dbl_link_onto(bd, &step->large_objects);
557 /* add the new blocks we promoted during this GC */
558 step->n_blocks += step->to_blocks;
563 /* Two-space collector:
564 * Free the old to-space, and estimate the amount of live data.
566 if (RtsFlags.GcFlags.generations == 1) {
567 if (old_to_space != NULL) {
568 freeChain(old_to_space);
570 for (bd = g0s0->to_space; bd != NULL; bd = bd->link) {
571 bd->evacuated = 0; /* now from-space */
573 live = g0s0->to_blocks * BLOCK_SIZE_W +
574 ((lnat)g0s0->hp_bd->free - (lnat)g0s0->hp_bd->start) / sizeof(W_);
576 /* Generational collector:
577 * estimate the amount of live data.
581 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
582 for (s = 0; s < generations[g].n_steps; s++) {
583 /* approximate amount of live data (doesn't take into account slop
584 * at end of each block). ToDo: this more accurately.
586 if (g == 0 && s == 0) { continue; }
587 step = &generations[g].steps[s];
588 live += step->n_blocks * BLOCK_SIZE_W +
589 ((lnat)step->hp_bd->free -(lnat)step->hp_bd->start) / sizeof(W_);
594 /* revert dead CAFs and update enteredCAFs list */
597 /* mark the garbage collected CAFs as dead */
599 if (major_gc) { gcCAFs(); }
602 /* zero the scavenged static object list */
604 zeroStaticObjectList(scavenged_static_objects);
609 for (bd = g0s0->blocks; bd; bd = bd->link) {
610 bd->free = bd->start;
611 ASSERT(bd->gen == g0);
612 ASSERT(bd->step == g0s0);
614 current_nursery = g0s0->blocks;
616 /* Free the small objects allocated via allocate(), since this will
617 * all have been copied into G0S1 now.
619 if (small_alloc_list != NULL) {
620 freeChain(small_alloc_list);
622 small_alloc_list = NULL;
624 alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
626 /* start any pending finalisers */
627 scheduleFinalisers(old_weak_ptr_list);
629 /* check sanity after GC */
631 if (RtsFlags.GcFlags.generations == 1) {
632 IF_DEBUG(sanity, checkHeap(g0s0->to_space, NULL));
633 IF_DEBUG(sanity, checkChain(g0s0->large_objects));
636 for (g = 0; g <= N; g++) {
637 for (s = 0; s < generations[g].n_steps; s++) {
638 if (g == 0 && s == 0) { continue; }
639 IF_DEBUG(sanity, checkHeap(generations[g].steps[s].blocks, NULL));
642 for (g = N+1; g < RtsFlags.GcFlags.generations; g++) {
643 for (s = 0; s < generations[g].n_steps; s++) {
644 IF_DEBUG(sanity, checkHeap(generations[g].steps[s].blocks,
645 generations[g].steps[s].blocks->start));
646 IF_DEBUG(sanity, checkChain(generations[g].steps[s].large_objects));
649 IF_DEBUG(sanity, checkFreeListSanity());
653 IF_DEBUG(gc, stat_describe_gens());
656 /* symbol-table based profiling */
657 /* heapCensus(to_space); */ /* ToDo */
660 /* restore enclosing cost centre */
665 /* check for memory leaks if sanity checking is on */
666 IF_DEBUG(sanity, memInventory());
668 /* ok, GC over: tell the stats department what happened. */
669 stat_endGC(allocated, collected, live, N);
672 /* -----------------------------------------------------------------------------
675 traverse_weak_ptr_list is called possibly many times during garbage
676 collection. It returns a flag indicating whether it did any work
677 (i.e. called evacuate on any live pointers).
679 Invariant: traverse_weak_ptr_list is called when the heap is in an
680 idempotent state. That means that there are no pending
681 evacuate/scavenge operations. This invariant helps the weak
682 pointer code decide which weak pointers are dead - if there are no
683 new live weak pointers, then all the currently unreachable ones are
686 For generational GC: we just don't try to finalise weak pointers in
687 older generations than the one we're collecting. This could
688 probably be optimised by keeping per-generation lists of weak
689 pointers, but for a few weak pointers this scheme will work.
690 -------------------------------------------------------------------------- */
693 traverse_weak_ptr_list(void)
695 StgWeak *w, **last_w, *next_w;
697 const StgInfoTable *info;
698 rtsBool flag = rtsFalse;
700 if (weak_done) { return rtsFalse; }
702 /* doesn't matter where we evacuate values/finalisers to, since
703 * these pointers are treated as roots (iff the keys are alive).
707 last_w = &old_weak_ptr_list;
708 for (w = old_weak_ptr_list; w; w = next_w) {
711 /* ignore weak pointers in older generations */
712 if (!LOOKS_LIKE_STATIC(target) && Bdescr((P_)target)->gen->no > N) {
713 IF_DEBUG(weak, fprintf(stderr,"Weak pointer still alive (in old gen) at %p\n", w));
714 /* remove this weak ptr from the old_weak_ptr list */
716 /* and put it on the new weak ptr list */
718 w->link = weak_ptr_list;
724 info = get_itbl(target);
725 switch (info->type) {
730 case IND_OLDGEN: /* rely on compatible layout with StgInd */
731 case IND_OLDGEN_PERM:
732 /* follow indirections */
733 target = ((StgInd *)target)->indirectee;
737 /* If key is alive, evacuate value and finaliser and
738 * place weak ptr on new weak ptr list.
740 IF_DEBUG(weak, fprintf(stderr,"Weak pointer still alive at %p\n", w));
741 w->key = ((StgEvacuated *)target)->evacuee;
742 w->value = evacuate(w->value);
743 w->finaliser = evacuate(w->finaliser);
745 /* remove this weak ptr from the old_weak_ptr list */
748 /* and put it on the new weak ptr list */
750 w->link = weak_ptr_list;
755 default: /* key is dead */
762 /* If we didn't make any changes, then we can go round and kill all
763 * the dead weak pointers. The old_weak_ptr list is used as a list
764 * of pending finalisers later on.
766 if (flag == rtsFalse) {
767 for (w = old_weak_ptr_list; w; w = w->link) {
768 w->value = evacuate(w->value);
769 w->finaliser = evacuate(w->finaliser);
778 MarkRoot(StgClosure *root)
780 root = evacuate(root);
784 static inline void addBlock(step *step)
786 bdescr *bd = allocBlock();
790 if (step->gen->no <= N) {
796 step->hp_bd->free = step->hp;
797 step->hp_bd->link = bd;
798 step->hp = bd->start;
799 step->hpLim = step->hp + BLOCK_SIZE_W;
804 static __inline__ StgClosure *
805 copy(StgClosure *src, nat size, bdescr *bd)
810 /* Find out where we're going, using the handy "to" pointer in
811 * the step of the source object. If it turns out we need to
812 * evacuate to an older generation, adjust it here (see comment
816 if (step->gen->no < evac_gen) {
817 step = &generations[evac_gen].steps[0];
820 /* chain a new block onto the to-space for the destination step if
823 if (step->hp + size >= step->hpLim) {
829 for(to = dest, from = (P_)src; size>0; --size) {
832 return (StgClosure *)dest;
835 /* Special version of copy() for when we only want to copy the info
836 * pointer of an object, but reserve some padding after it. This is
837 * used to optimise evacuation of BLACKHOLEs.
840 static __inline__ StgClosure *
841 copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, bdescr *bd)
847 if (step->gen->no < evac_gen) {
848 step = &generations[evac_gen].steps[0];
851 if (step->hp + size_to_reserve >= step->hpLim) {
856 step->hp += size_to_reserve;
857 for(to = dest, from = (P_)src; size_to_copy>0; --size_to_copy) {
861 return (StgClosure *)dest;
864 static __inline__ void
865 upd_evacuee(StgClosure *p, StgClosure *dest)
867 StgEvacuated *q = (StgEvacuated *)p;
869 SET_INFO(q,&EVACUATED_info);
873 /* -----------------------------------------------------------------------------
874 Evacuate a mutable object
876 If we evacuate a mutable object to an old generation, cons the
877 object onto the older generation's mutable list.
878 -------------------------------------------------------------------------- */
881 evacuate_mutable(StgMutClosure *c)
886 if (bd->gen->no > 0) {
887 c->mut_link = bd->gen->mut_list;
888 bd->gen->mut_list = c;
892 /* -----------------------------------------------------------------------------
893 Evacuate a large object
895 This just consists of removing the object from the (doubly-linked)
896 large_alloc_list, and linking it on to the (singly-linked)
897 new_large_objects list, from where it will be scavenged later.
899 Convention: bd->evacuated is /= 0 for a large object that has been
900 evacuated, or 0 otherwise.
901 -------------------------------------------------------------------------- */
904 evacuate_large(StgPtr p, rtsBool mutable)
906 bdescr *bd = Bdescr(p);
909 /* should point to the beginning of the block */
910 ASSERT(((W_)p & BLOCK_MASK) == 0);
912 /* already evacuated? */
914 /* Don't forget to set the failed_to_evac flag if we didn't get
915 * the desired destination (see comments in evacuate()).
917 if (bd->gen->no < evac_gen) {
918 failed_to_evac = rtsTrue;
924 /* remove from large_object list */
926 bd->back->link = bd->link;
927 } else { /* first object in the list */
928 step->large_objects = bd->link;
931 bd->link->back = bd->back;
934 /* link it on to the evacuated large object list of the destination step
937 if (step->gen->no < evac_gen) {
938 step = &generations[evac_gen].steps[0];
943 bd->link = step->new_large_objects;
944 step->new_large_objects = bd;
948 evacuate_mutable((StgMutClosure *)p);
952 /* -----------------------------------------------------------------------------
953 Adding a MUT_CONS to an older generation.
955 This is necessary from time to time when we end up with an
956 old-to-new generation pointer in a non-mutable object. We defer
957 the promotion until the next GC.
958 -------------------------------------------------------------------------- */
961 mkMutCons(StgClosure *ptr, generation *gen)
966 step = &gen->steps[0];
968 /* chain a new block onto the to-space for the destination step if
971 if (step->hp + sizeofW(StgIndOldGen) >= step->hpLim) {
975 q = (StgMutVar *)step->hp;
976 step->hp += sizeofW(StgMutVar);
978 SET_HDR(q,&MUT_CONS_info,CCS_GC);
980 evacuate_mutable((StgMutClosure *)q);
982 return (StgClosure *)q;
985 /* -----------------------------------------------------------------------------
988 This is called (eventually) for every live object in the system.
990 The caller to evacuate specifies a desired generation in the
991 evac_gen global variable. The following conditions apply to
992 evacuating an object which resides in generation M when we're
993 collecting up to generation N
997 else evac to step->to
999 if M < evac_gen evac to evac_gen, step 0
1001 if the object is already evacuated, then we check which generation
1004 if M >= evac_gen do nothing
1005 if M < evac_gen set failed_to_evac flag to indicate that we
1006 didn't manage to evacuate this object into evac_gen.
1008 -------------------------------------------------------------------------- */
1012 evacuate(StgClosure *q)
1016 const StgInfoTable *info;
1019 if (!LOOKS_LIKE_STATIC(q)) {
1021 if (bd->gen->no > N) {
1022 /* Can't evacuate this object, because it's in a generation
1023 * older than the ones we're collecting. Let's hope that it's
1024 * in evac_gen or older, or we will have to make an IND_OLDGEN object.
1026 if (bd->gen->no < evac_gen) {
1028 failed_to_evac = rtsTrue;
1034 /* make sure the info pointer is into text space */
1035 ASSERT(q && (LOOKS_LIKE_GHC_INFO(GET_INFO(q))
1036 || IS_HUGS_CONSTR_INFO(GET_INFO(q))));
1039 switch (info -> type) {
1042 to = copy(q,bco_sizeW(stgCast(StgBCO*,q)),bd);
1048 to = copy(q,sizeW_fromITBL(info),bd);
1050 evacuate_mutable((StgMutClosure *)to);
1057 case IND_OLDGEN_PERM:
1062 to = copy(q,sizeW_fromITBL(info),bd);
1068 to = copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),bd);
1073 to = copy(q,BLACKHOLE_sizeW(),bd);
1075 evacuate_mutable((StgMutClosure *)to);
1078 case THUNK_SELECTOR:
1080 const StgInfoTable* selectee_info;
1081 StgClosure* selectee = ((StgSelector*)q)->selectee;
1084 selectee_info = get_itbl(selectee);
1085 switch (selectee_info->type) {
1089 StgNat32 offset = info->layout.selector_offset;
1091 /* check that the size is in range */
1093 (StgNat32)(selectee_info->layout.payload.ptrs +
1094 selectee_info->layout.payload.nptrs));
1096 /* perform the selection! */
1097 q = selectee->payload[offset];
1099 /* if we're already in to-space, there's no need to continue
1100 * with the evacuation, just update the source address with
1101 * a pointer to the (evacuated) constructor field.
1103 if (IS_USER_PTR(q)) {
1104 bdescr *bd = Bdescr((P_)q);
1105 if (bd->evacuated) {
1106 if (bd->gen->no < evac_gen) {
1107 failed_to_evac = rtsTrue;
1113 /* otherwise, carry on and evacuate this constructor field,
1114 * (but not the constructor itself)
1123 case IND_OLDGEN_PERM:
1124 selectee = stgCast(StgInd *,selectee)->indirectee;
1128 selectee = stgCast(StgCAF *,selectee)->value;
1132 selectee = stgCast(StgEvacuated*,selectee)->evacuee;
1137 case THUNK_SELECTOR:
1138 /* aargh - do recursively???? */
1143 /* not evaluated yet */
1147 barf("evacuate: THUNK_SELECTOR: strange selectee");
1150 to = copy(q,THUNK_SELECTOR_sizeW(),bd);
1156 /* follow chains of indirections, don't evacuate them */
1157 q = ((StgInd*)q)->indirectee;
1160 /* ToDo: optimise STATIC_LINK for known cases.
1161 - FUN_STATIC : payload[0]
1162 - THUNK_STATIC : payload[1]
1163 - IND_STATIC : payload[1]
1167 if (info->srt_len == 0) { /* small optimisation */
1173 /* don't want to evacuate these, but we do want to follow pointers
1174 * from SRTs - see scavenge_static.
1177 /* put the object on the static list, if necessary.
1179 if (major_gc && STATIC_LINK(info,(StgClosure *)q) == NULL) {
1180 STATIC_LINK(info,(StgClosure *)q) = static_objects;
1181 static_objects = (StgClosure *)q;
1185 case CONSTR_INTLIKE:
1186 case CONSTR_CHARLIKE:
1187 case CONSTR_NOCAF_STATIC:
1188 /* no need to put these on the static linked list, they don't need
1203 /* shouldn't see these */
1204 barf("evacuate: stack frame\n");
1208 /* these are special - the payload is a copy of a chunk of stack,
1210 to = copy(q,pap_sizeW(stgCast(StgPAP*,q)),bd);
1215 /* Already evacuated, just return the forwarding address.
1216 * HOWEVER: if the requested destination generation (evac_gen) is
1217 * older than the actual generation (because the object was
1218 * already evacuated to a younger generation) then we have to
1219 * set the failed_to_evac flag to indicate that we couldn't
1220 * manage to promote the object to the desired generation.
1222 if (evac_gen > 0) { /* optimisation */
1223 StgClosure *p = ((StgEvacuated*)q)->evacuee;
1224 if (Bdescr((P_)p)->gen->no < evac_gen) {
1225 /* fprintf(stderr,"evac failed!\n");*/
1226 failed_to_evac = rtsTrue;
1229 return ((StgEvacuated*)q)->evacuee;
1234 nat size = arr_words_sizeW(stgCast(StgArrWords*,q));
1236 if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1237 evacuate_large((P_)q, rtsFalse);
1240 /* just copy the block */
1241 to = copy(q,size,bd);
1248 case MUT_ARR_PTRS_FROZEN:
1250 nat size = mut_arr_ptrs_sizeW(stgCast(StgMutArrPtrs*,q));
1252 if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1253 evacuate_large((P_)q, info->type == MUT_ARR_PTRS);
1256 /* just copy the block */
1257 to = copy(q,size,bd);
1259 if (info->type == MUT_ARR_PTRS) {
1260 evacuate_mutable((StgMutClosure *)to);
1268 StgTSO *tso = stgCast(StgTSO *,q);
1269 nat size = tso_sizeW(tso);
1272 /* Large TSOs don't get moved, so no relocation is required.
1274 if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1275 evacuate_large((P_)q, rtsTrue);
1278 /* To evacuate a small TSO, we need to relocate the update frame
1282 StgTSO *new_tso = (StgTSO *)copy((StgClosure *)tso,tso_sizeW(tso),bd);
1284 diff = (StgPtr)new_tso - (StgPtr)tso; /* In *words* */
1286 /* relocate the stack pointers... */
1287 new_tso->su = (StgUpdateFrame *) ((StgPtr)new_tso->su + diff);
1288 new_tso->sp = (StgPtr)new_tso->sp + diff;
1289 new_tso->splim = (StgPtr)new_tso->splim + diff;
1291 relocate_TSO(tso, new_tso);
1292 upd_evacuee(q,(StgClosure *)new_tso);
1294 evacuate_mutable((StgMutClosure *)new_tso);
1295 return (StgClosure *)new_tso;
1301 fprintf(stderr,"evacuate: unimplemented/strange closure type\n");
1305 barf("evacuate: strange closure type");
1311 /* -----------------------------------------------------------------------------
1312 relocate_TSO is called just after a TSO has been copied from src to
1313 dest. It adjusts the update frame list for the new location.
1314 -------------------------------------------------------------------------- */
1317 relocate_TSO(StgTSO *src, StgTSO *dest)
1324 diff = (StgPtr)dest->sp - (StgPtr)src->sp; /* In *words* */
1328 while ((P_)su < dest->stack + dest->stack_size) {
1329 switch (get_itbl(su)->type) {
1331 /* GCC actually manages to common up these three cases! */
1334 su->link = (StgUpdateFrame *) ((StgPtr)su->link + diff);
1339 cf = (StgCatchFrame *)su;
1340 cf->link = (StgUpdateFrame *) ((StgPtr)cf->link + diff);
1345 sf = (StgSeqFrame *)su;
1346 sf->link = (StgUpdateFrame *) ((StgPtr)sf->link + diff);
1355 barf("relocate_TSO");
1364 scavenge_srt(const StgInfoTable *info)
1366 StgClosure **srt, **srt_end;
1368 /* evacuate the SRT. If srt_len is zero, then there isn't an
1369 * srt field in the info table. That's ok, because we'll
1370 * never dereference it.
1372 srt = stgCast(StgClosure **,info->srt);
1373 srt_end = srt + info->srt_len;
1374 for (; srt < srt_end; srt++) {
1379 /* -----------------------------------------------------------------------------
1380 Scavenge a given step until there are no more objects in this step
1383 evac_gen is set by the caller to be either zero (for a step in a
1384 generation < N) or G where G is the generation of the step being
1387 We sometimes temporarily change evac_gen back to zero if we're
1388 scavenging a mutable object where early promotion isn't such a good
1390 -------------------------------------------------------------------------- */
1394 scavenge(step *step)
1397 const StgInfoTable *info;
1399 nat saved_evac_gen = evac_gen; /* used for temporarily changing evac_gen */
1404 failed_to_evac = rtsFalse;
1406 /* scavenge phase - standard breadth-first scavenging of the
1410 while (bd != step->hp_bd || p < step->hp) {
1412 /* If we're at the end of this block, move on to the next block */
1413 if (bd != step->hp_bd && p == bd->free) {
1419 q = p; /* save ptr to object */
1421 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO((StgClosure *)p))
1422 || IS_HUGS_CONSTR_INFO(GET_INFO((StgClosure *)p))));
1424 info = get_itbl((StgClosure *)p);
1425 switch (info -> type) {
1429 StgBCO* bco = stgCast(StgBCO*,p);
1431 for (i = 0; i < bco->n_ptrs; i++) {
1432 bcoConstCPtr(bco,i) = evacuate(bcoConstCPtr(bco,i));
1434 p += bco_sizeW(bco);
1439 /* treat MVars specially, because we don't want to evacuate the
1440 * mut_link field in the middle of the closure.
1443 StgMVar *mvar = ((StgMVar *)p);
1445 (StgClosure *)mvar->head = evacuate((StgClosure *)mvar->head);
1446 (StgClosure *)mvar->tail = evacuate((StgClosure *)mvar->tail);
1447 (StgClosure *)mvar->value = evacuate((StgClosure *)mvar->value);
1448 p += sizeofW(StgMVar);
1449 evac_gen = saved_evac_gen;
1462 case IND_OLDGEN_PERM:
1468 end = (P_)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1469 for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
1470 (StgClosure *)*p = evacuate((StgClosure *)*p);
1472 p += info->layout.payload.nptrs;
1477 /* ignore MUT_CONSs */
1478 if (((StgMutVar *)p)->header.info != &MUT_CONS_info) {
1480 ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
1481 evac_gen = saved_evac_gen;
1483 p += sizeofW(StgMutVar);
1488 p += BLACKHOLE_sizeW();
1493 StgBlockingQueue *bh = (StgBlockingQueue *)p;
1494 (StgClosure *)bh->blocking_queue =
1495 evacuate((StgClosure *)bh->blocking_queue);
1496 if (failed_to_evac) {
1497 failed_to_evac = rtsFalse;
1498 evacuate_mutable((StgMutClosure *)bh);
1500 p += BLACKHOLE_sizeW();
1504 case THUNK_SELECTOR:
1506 StgSelector *s = (StgSelector *)p;
1507 s->selectee = evacuate(s->selectee);
1508 p += THUNK_SELECTOR_sizeW();
1514 barf("scavenge:IND???\n");
1516 case CONSTR_INTLIKE:
1517 case CONSTR_CHARLIKE:
1519 case CONSTR_NOCAF_STATIC:
1523 /* Shouldn't see a static object here. */
1524 barf("scavenge: STATIC object\n");
1536 /* Shouldn't see stack frames here. */
1537 barf("scavenge: stack frame\n");
1539 case AP_UPD: /* same as PAPs */
1541 /* Treat a PAP just like a section of stack, not forgetting to
1542 * evacuate the function pointer too...
1545 StgPAP* pap = stgCast(StgPAP*,p);
1547 pap->fun = evacuate(pap->fun);
1548 scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1549 p += pap_sizeW(pap);
1555 /* nothing to follow */
1556 p += arr_words_sizeW(stgCast(StgArrWords*,p));
1560 /* follow everything */
1564 evac_gen = 0; /* repeatedly mutable */
1565 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1566 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1567 (StgClosure *)*p = evacuate((StgClosure *)*p);
1569 evac_gen = saved_evac_gen;
1573 case MUT_ARR_PTRS_FROZEN:
1574 /* follow everything */
1576 StgPtr start = p, next;
1578 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1579 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1580 (StgClosure *)*p = evacuate((StgClosure *)*p);
1582 if (failed_to_evac) {
1583 /* we can do this easier... */
1584 evacuate_mutable((StgMutClosure *)start);
1585 failed_to_evac = rtsFalse;
1596 /* chase the link field for any TSOs on the same queue */
1597 (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
1598 /* scavenge this thread's stack */
1599 scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
1600 evac_gen = saved_evac_gen;
1601 p += tso_sizeW(tso);
1608 barf("scavenge: unimplemented/strange closure type\n");
1614 /* If we didn't manage to promote all the objects pointed to by
1615 * the current object, then we have to designate this object as
1616 * mutable (because it contains old-to-new generation pointers).
1618 if (failed_to_evac) {
1619 mkMutCons((StgClosure *)q, &generations[evac_gen]);
1620 failed_to_evac = rtsFalse;
1628 /* -----------------------------------------------------------------------------
1629 Scavenge one object.
1631 This is used for objects that are temporarily marked as mutable
1632 because they contain old-to-new generation pointers. Only certain
1633 objects can have this property.
1634 -------------------------------------------------------------------------- */
1636 scavenge_one(StgPtr p)
1641 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO((StgClosure *)p))
1642 || IS_HUGS_CONSTR_INFO(GET_INFO((StgClosure *)p))));
1644 info = get_itbl((StgClosure *)p);
1646 switch (info -> type) {
1654 case IND_OLDGEN_PERM:
1660 end = (P_)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1661 for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
1662 (StgClosure *)*p = evacuate((StgClosure *)*p);
1671 case THUNK_SELECTOR:
1673 StgSelector *s = (StgSelector *)p;
1674 s->selectee = evacuate(s->selectee);
1678 case AP_UPD: /* same as PAPs */
1680 /* Treat a PAP just like a section of stack, not forgetting to
1681 * evacuate the function pointer too...
1684 StgPAP* pap = stgCast(StgPAP*,p);
1686 pap->fun = evacuate(pap->fun);
1687 scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1692 /* This might happen if for instance a MUT_CONS was pointing to a
1693 * THUNK which has since been updated. The IND_OLDGEN will
1694 * be on the mutable list anyway, so we don't need to do anything
1700 barf("scavenge_one: strange object");
1703 no_luck = failed_to_evac;
1704 failed_to_evac = rtsFalse;
1709 /* -----------------------------------------------------------------------------
1710 Scavenging mutable lists.
1712 We treat the mutable list of each generation > N (i.e. all the
1713 generations older than the one being collected) as roots. We also
1714 remove non-mutable objects from the mutable list at this point.
1715 -------------------------------------------------------------------------- */
1717 static StgMutClosure *
1718 scavenge_mutable_list(StgMutClosure *p, nat gen)
1721 StgMutClosure *start;
1722 StgMutClosure **prev;
1729 failed_to_evac = rtsFalse;
1731 for (; p != END_MUT_LIST; p = *prev) {
1733 /* make sure the info pointer is into text space */
1734 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1735 || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1738 switch(info->type) {
1740 case MUT_ARR_PTRS_FROZEN:
1741 /* remove this guy from the mutable list, but follow the ptrs
1742 * anyway (and make sure they get promoted to this gen).
1747 end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1749 for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
1750 (StgClosure *)*q = evacuate((StgClosure *)*q);
1754 if (failed_to_evac) {
1755 failed_to_evac = rtsFalse;
1756 prev = &p->mut_link;
1758 *prev = p->mut_link;
1764 /* follow everything */
1765 prev = &p->mut_link;
1769 end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1770 for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
1771 (StgClosure *)*q = evacuate((StgClosure *)*q);
1777 /* MUT_CONS is a kind of MUT_VAR, except that we try to remove
1778 * it from the mutable list if possible by promoting whatever it
1781 if (p->header.info == &MUT_CONS_info) {
1783 if (scavenge_one((P_)((StgMutVar *)p)->var) == rtsTrue) {
1784 /* didn't manage to promote everything, so leave the
1785 * MUT_CONS on the list.
1787 prev = &p->mut_link;
1789 *prev = p->mut_link;
1793 ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
1794 prev = &p->mut_link;
1800 StgMVar *mvar = (StgMVar *)p;
1801 (StgClosure *)mvar->head = evacuate((StgClosure *)mvar->head);
1802 (StgClosure *)mvar->tail = evacuate((StgClosure *)mvar->tail);
1803 (StgClosure *)mvar->value = evacuate((StgClosure *)mvar->value);
1804 prev = &p->mut_link;
1809 /* follow ptrs and remove this from the mutable list */
1811 StgTSO *tso = (StgTSO *)p;
1813 /* Don't bother scavenging if this thread is dead
1815 if (!(tso->whatNext == ThreadComplete ||
1816 tso->whatNext == ThreadKilled)) {
1817 /* Don't need to chase the link field for any TSOs on the
1818 * same queue. Just scavenge this thread's stack
1820 scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
1823 /* Don't take this TSO off the mutable list - it might still
1824 * point to some younger objects (because we set evac_gen to 0
1827 prev = &tso->mut_link;
1832 case IND_OLDGEN_PERM:
1834 /* Try to pull the indirectee into this generation, so we can
1835 * remove the indirection from the mutable list.
1838 ((StgIndOldGen *)p)->indirectee =
1839 evacuate(((StgIndOldGen *)p)->indirectee);
1842 if (failed_to_evac) {
1843 failed_to_evac = rtsFalse;
1844 prev = &p->mut_link;
1846 *prev = p->mut_link;
1847 /* the mut_link field of an IND_STATIC is overloaded as the
1848 * static link field too (it just so happens that we don't need
1849 * both at the same time), so we need to NULL it out when
1850 * removing this object from the mutable list because the static
1851 * link fields are all assumed to be NULL before doing a major
1860 StgBlockingQueue *bh = (StgBlockingQueue *)p;
1861 (StgClosure *)bh->blocking_queue =
1862 evacuate((StgClosure *)bh->blocking_queue);
1863 prev = &p->mut_link;
1868 /* shouldn't have anything else on the mutables list */
1869 barf("scavenge_mutable_object: non-mutable object?");
1876 scavenge_static(void)
1878 StgClosure* p = static_objects;
1879 const StgInfoTable *info;
1881 /* Always evacuate straight to the oldest generation for static
1883 evac_gen = oldest_gen->no;
1885 /* keep going until we've scavenged all the objects on the linked
1887 while (p != END_OF_STATIC_LIST) {
1891 /* make sure the info pointer is into text space */
1892 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1893 || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1895 /* Take this object *off* the static_objects list,
1896 * and put it on the scavenged_static_objects list.
1898 static_objects = STATIC_LINK(info,p);
1899 STATIC_LINK(info,p) = scavenged_static_objects;
1900 scavenged_static_objects = p;
1902 switch (info -> type) {
1906 StgInd *ind = (StgInd *)p;
1907 ind->indirectee = evacuate(ind->indirectee);
1909 /* might fail to evacuate it, in which case we have to pop it
1910 * back on the mutable list (and take it off the
1911 * scavenged_static list because the static link and mut link
1912 * pointers are one and the same).
1914 if (failed_to_evac) {
1915 failed_to_evac = rtsFalse;
1916 scavenged_static_objects = STATIC_LINK(info,p);
1917 ((StgMutClosure *)ind)->mut_link = oldest_gen->mut_list;
1918 oldest_gen->mut_list = (StgMutClosure *)ind;
1932 next = (P_)p->payload + info->layout.payload.ptrs;
1933 /* evacuate the pointers */
1934 for (q = (P_)p->payload; q < next; q++) {
1935 (StgClosure *)*q = evacuate((StgClosure *)*q);
1941 barf("scavenge_static");
1944 ASSERT(failed_to_evac == rtsFalse);
1946 /* get the next static object from the list. Remeber, there might
1947 * be more stuff on this list now that we've done some evacuating!
1948 * (static_objects is a global)
1954 /* -----------------------------------------------------------------------------
1955 scavenge_stack walks over a section of stack and evacuates all the
1956 objects pointed to by it. We can use the same code for walking
1957 PAPs, since these are just sections of copied stack.
1958 -------------------------------------------------------------------------- */
1961 scavenge_stack(StgPtr p, StgPtr stack_end)
1964 const StgInfoTable* info;
1968 * Each time around this loop, we are looking at a chunk of stack
1969 * that starts with either a pending argument section or an
1970 * activation record.
1973 while (p < stack_end) {
1974 q = *stgCast(StgPtr*,p);
1976 /* If we've got a tag, skip over that many words on the stack */
1977 if (IS_ARG_TAG(stgCast(StgWord,q))) {
1982 /* Is q a pointer to a closure?
1984 if (! LOOKS_LIKE_GHC_INFO(q)) {
1987 if (LOOKS_LIKE_STATIC(q)) { /* Is it a static closure? */
1988 ASSERT(closure_STATIC(stgCast(StgClosure*,q)));
1990 /* otherwise, must be a pointer into the allocation space.
1994 (StgClosure *)*p = evacuate((StgClosure *)q);
2000 * Otherwise, q must be the info pointer of an activation
2001 * record. All activation records have 'bitmap' style layout
2004 info = get_itbl(stgCast(StgClosure*,p));
2006 switch (info->type) {
2008 /* Dynamic bitmap: the mask is stored on the stack */
2010 bitmap = stgCast(StgRetDyn*,p)->liveness;
2011 p = &payloadWord(stgCast(StgRetDyn*,p),0);
2014 /* probably a slow-entry point return address: */
2020 /* Specialised code for update frames, since they're so common.
2021 * We *know* the updatee points to a BLACKHOLE, CAF_BLACKHOLE,
2022 * or BLACKHOLE_BQ, so just inline the code to evacuate it here.
2026 StgUpdateFrame *frame = (StgUpdateFrame *)p;
2028 StgClosureType type = get_itbl(frame->updatee)->type;
2030 p += sizeofW(StgUpdateFrame);
2031 if (type == EVACUATED) {
2032 frame->updatee = evacuate(frame->updatee);
2035 bdescr *bd = Bdescr((P_)frame->updatee);
2036 if (bd->gen->no > N) {
2037 if (bd->gen->no < evac_gen) {
2038 failed_to_evac = rtsTrue;
2045 to = copyPart(frame->updatee, BLACKHOLE_sizeW(),
2046 sizeofW(StgHeader), bd);
2047 upd_evacuee(frame->updatee,to);
2048 frame->updatee = to;
2051 to = copy(frame->updatee, BLACKHOLE_sizeW(), bd);
2052 upd_evacuee(frame->updatee,to);
2053 frame->updatee = to;
2054 evacuate_mutable((StgMutClosure *)to);
2057 barf("scavenge_stack: UPDATE_FRAME updatee");
2062 /* small bitmap (< 32 entries, or 64 on a 64-bit machine) */
2069 bitmap = info->layout.bitmap;
2072 while (bitmap != 0) {
2073 if ((bitmap & 1) == 0) {
2074 (StgClosure *)*p = evacuate((StgClosure *)*p);
2077 bitmap = bitmap >> 1;
2084 /* large bitmap (> 32 entries) */
2089 StgLargeBitmap *large_bitmap;
2092 large_bitmap = info->layout.large_bitmap;
2095 for (i=0; i<large_bitmap->size; i++) {
2096 bitmap = large_bitmap->bitmap[i];
2097 q = p + sizeof(W_) * 8;
2098 while (bitmap != 0) {
2099 if ((bitmap & 1) == 0) {
2100 (StgClosure *)*p = evacuate((StgClosure *)*p);
2103 bitmap = bitmap >> 1;
2105 if (i+1 < large_bitmap->size) {
2107 (StgClosure *)*p = evacuate((StgClosure *)*p);
2113 /* and don't forget to follow the SRT */
2118 barf("scavenge_stack: weird activation record found on stack.\n");
2123 /*-----------------------------------------------------------------------------
2124 scavenge the large object list.
2126 evac_gen set by caller; similar games played with evac_gen as with
2127 scavenge() - see comment at the top of scavenge(). Most large
2128 objects are (repeatedly) mutable, so most of the time evac_gen will
2130 --------------------------------------------------------------------------- */
2133 scavenge_large(step *step)
2137 const StgInfoTable* info;
2138 nat saved_evac_gen = evac_gen; /* used for temporarily changing evac_gen */
2140 evac_gen = 0; /* most objects are mutable */
2141 bd = step->new_large_objects;
2143 for (; bd != NULL; bd = step->new_large_objects) {
2145 /* take this object *off* the large objects list and put it on
2146 * the scavenged large objects list. This is so that we can
2147 * treat new_large_objects as a stack and push new objects on
2148 * the front when evacuating.
2150 step->new_large_objects = bd->link;
2151 dbl_link_onto(bd, &step->scavenged_large_objects);
2154 info = get_itbl(stgCast(StgClosure*,p));
2156 switch (info->type) {
2158 /* only certain objects can be "large"... */
2162 /* nothing to follow */
2166 /* follow everything */
2170 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2171 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
2172 (StgClosure *)*p = evacuate((StgClosure *)*p);
2177 case MUT_ARR_PTRS_FROZEN:
2178 /* follow everything */
2180 StgPtr start = p, next;
2182 evac_gen = saved_evac_gen; /* not really mutable */
2183 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2184 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
2185 (StgClosure *)*p = evacuate((StgClosure *)*p);
2188 if (failed_to_evac) {
2189 evacuate_mutable((StgMutClosure *)start);
2196 StgBCO* bco = stgCast(StgBCO*,p);
2198 evac_gen = saved_evac_gen;
2199 for (i = 0; i < bco->n_ptrs; i++) {
2200 bcoConstCPtr(bco,i) = evacuate(bcoConstCPtr(bco,i));
2211 /* chase the link field for any TSOs on the same queue */
2212 (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
2213 /* scavenge this thread's stack */
2214 scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
2219 barf("scavenge_large: unknown/strange object");
2225 zeroStaticObjectList(StgClosure* first_static)
2229 const StgInfoTable *info;
2231 for (p = first_static; p != END_OF_STATIC_LIST; p = link) {
2233 link = STATIC_LINK(info, p);
2234 STATIC_LINK(info,p) = NULL;
2238 /* This function is only needed because we share the mutable link
2239 * field with the static link field in an IND_STATIC, so we have to
2240 * zero the mut_link field before doing a major GC, which needs the
2241 * static link field.
2243 * It doesn't do any harm to zero all the mutable link fields on the
2247 zeroMutableList(StgMutClosure *first)
2249 StgMutClosure *next, *c;
2251 for (c = first; c != END_MUT_LIST; c = next) {
2257 /* -----------------------------------------------------------------------------
2259 -------------------------------------------------------------------------- */
2261 void RevertCAFs(void)
2263 while (enteredCAFs != END_CAF_LIST) {
2264 StgCAF* caf = enteredCAFs;
2266 enteredCAFs = caf->link;
2267 ASSERT(get_itbl(caf)->type == CAF_ENTERED);
2268 SET_INFO(caf,&CAF_UNENTERED_info);
2269 caf->value = stgCast(StgClosure*,0xdeadbeef);
2270 caf->link = stgCast(StgCAF*,0xdeadbeef);
2274 void revertDeadCAFs(void)
2276 StgCAF* caf = enteredCAFs;
2277 enteredCAFs = END_CAF_LIST;
2278 while (caf != END_CAF_LIST) {
2279 StgCAF* next = caf->link;
2281 switch(GET_INFO(caf)->type) {
2284 /* This object has been evacuated, it must be live. */
2285 StgCAF* new = stgCast(StgCAF*,stgCast(StgEvacuated*,caf)->evacuee);
2286 new->link = enteredCAFs;
2292 SET_INFO(caf,&CAF_UNENTERED_info);
2293 caf->value = stgCast(StgClosure*,0xdeadbeef);
2294 caf->link = stgCast(StgCAF*,0xdeadbeef);
2298 barf("revertDeadCAFs: enteredCAFs list corrupted");
2304 /* -----------------------------------------------------------------------------
2305 Sanity code for CAF garbage collection.
2307 With DEBUG turned on, we manage a CAF list in addition to the SRT
2308 mechanism. After GC, we run down the CAF list and blackhole any
2309 CAFs which have been garbage collected. This means we get an error
2310 whenever the program tries to enter a garbage collected CAF.
2312 Any garbage collected CAFs are taken off the CAF list at the same
2314 -------------------------------------------------------------------------- */
2322 const StgInfoTable *info;
2333 ASSERT(info->type == IND_STATIC);
2335 if (STATIC_LINK(info,p) == NULL) {
2336 IF_DEBUG(gccafs, fprintf(stderr, "CAF gc'd at 0x%04x\n", (int)p));
2338 SET_INFO(p,&BLACKHOLE_info);
2339 p = STATIC_LINK2(info,p);
2343 pp = &STATIC_LINK2(info,p);
2350 /* fprintf(stderr, "%d CAFs live\n", i); */
2354 /* -----------------------------------------------------------------------------
2357 Whenever a thread returns to the scheduler after possibly doing
2358 some work, we have to run down the stack and black-hole all the
2359 closures referred to by update frames.
2360 -------------------------------------------------------------------------- */
2363 threadLazyBlackHole(StgTSO *tso)
2365 StgUpdateFrame *update_frame;
2366 StgBlockingQueue *bh;
2369 stack_end = &tso->stack[tso->stack_size];
2370 update_frame = tso->su;
2373 switch (get_itbl(update_frame)->type) {
2376 update_frame = stgCast(StgCatchFrame*,update_frame)->link;
2380 bh = (StgBlockingQueue *)update_frame->updatee;
2382 /* if the thunk is already blackholed, it means we've also
2383 * already blackholed the rest of the thunks on this stack,
2384 * so we can stop early.
2387 /* Don't for now: when we enter a CAF, we create a black hole on
2388 * the heap and make the update frame point to it. Thus the
2389 * above optimisation doesn't apply.
2391 if (bh->header.info != &BLACKHOLE_info
2392 && bh->header.info != &BLACKHOLE_BQ_info
2393 && bh->header.info != &CAF_BLACKHOLE_info) {
2394 SET_INFO(bh,&BLACKHOLE_info);
2397 update_frame = update_frame->link;
2401 update_frame = stgCast(StgSeqFrame*,update_frame)->link;
2407 barf("threadPaused");
2412 /* -----------------------------------------------------------------------------
2415 * Code largely pinched from old RTS, then hacked to bits. We also do
2416 * lazy black holing here.
2418 * -------------------------------------------------------------------------- */
2421 threadSqueezeStack(StgTSO *tso)
2423 lnat displacement = 0;
2424 StgUpdateFrame *frame;
2425 StgUpdateFrame *next_frame; /* Temporally next */
2426 StgUpdateFrame *prev_frame; /* Temporally previous */
2428 rtsBool prev_was_update_frame;
2430 bottom = &(tso->stack[tso->stack_size]);
2433 /* There must be at least one frame, namely the STOP_FRAME.
2435 ASSERT((P_)frame < bottom);
2437 /* Walk down the stack, reversing the links between frames so that
2438 * we can walk back up as we squeeze from the bottom. Note that
2439 * next_frame and prev_frame refer to next and previous as they were
2440 * added to the stack, rather than the way we see them in this
2441 * walk. (It makes the next loop less confusing.)
2443 * Could stop if we find an update frame pointing to a black hole,
2444 * but see comment in threadLazyBlackHole().
2448 while ((P_)frame < bottom - 1) { /* bottom - 1 is the STOP_FRAME */
2449 prev_frame = frame->link;
2450 frame->link = next_frame;
2455 /* Now, we're at the bottom. Frame points to the lowest update
2456 * frame on the stack, and its link actually points to the frame
2457 * above. We have to walk back up the stack, squeezing out empty
2458 * update frames and turning the pointers back around on the way
2461 * The bottom-most frame (the STOP_FRAME) has not been altered, and
2462 * we never want to eliminate it anyway. Just walk one step up
2463 * before starting to squeeze. When you get to the topmost frame,
2464 * remember that there are still some words above it that might have
2471 prev_was_update_frame = (get_itbl(prev_frame)->type == UPDATE_FRAME);
2474 * Loop through all of the frames (everything except the very
2475 * bottom). Things are complicated by the fact that we have
2476 * CATCH_FRAMEs and SEQ_FRAMEs interspersed with the update frames.
2477 * We can only squeeze when there are two consecutive UPDATE_FRAMEs.
2479 while (frame != NULL) {
2481 StgPtr frame_bottom = (P_)frame + sizeofW(StgUpdateFrame);
2482 rtsBool is_update_frame;
2484 next_frame = frame->link;
2485 is_update_frame = (get_itbl(frame)->type == UPDATE_FRAME);
2488 * 1. both the previous and current frame are update frames
2489 * 2. the current frame is empty
2491 if (prev_was_update_frame && is_update_frame &&
2492 (P_)prev_frame == frame_bottom + displacement) {
2494 /* Now squeeze out the current frame */
2495 StgClosure *updatee_keep = prev_frame->updatee;
2496 StgClosure *updatee_bypass = frame->updatee;
2499 fprintf(stderr, "squeezing frame at %p\n", frame);
2502 /* Deal with blocking queues. If both updatees have blocked
2503 * threads, then we should merge the queues into the update
2504 * frame that we're keeping.
2506 * Alternatively, we could just wake them up: they'll just go
2507 * straight to sleep on the proper blackhole! This is less code
2508 * and probably less bug prone, although it's probably much
2511 #if 0 /* do it properly... */
2512 if (GET_INFO(updatee_bypass) == BLACKHOLE_BQ_info) {
2513 /* Sigh. It has one. Don't lose those threads! */
2514 if (GET_INFO(updatee_keep) == BLACKHOLE_BQ_info) {
2515 /* Urgh. Two queues. Merge them. */
2516 P_ keep_tso = ((StgBlockingQueue *)updatee_keep)->blocking_queue;
2518 while (keep_tso->link != END_TSO_QUEUE) {
2519 keep_tso = keep_tso->link;
2521 keep_tso->link = ((StgBlockingQueue *)updatee_bypass)->blocking_queue;
2524 /* For simplicity, just swap the BQ for the BH */
2525 P_ temp = updatee_keep;
2527 updatee_keep = updatee_bypass;
2528 updatee_bypass = temp;
2530 /* Record the swap in the kept frame (below) */
2531 prev_frame->updatee = updatee_keep;
2536 TICK_UPD_SQUEEZED();
2537 UPD_IND(updatee_bypass, updatee_keep); /* this wakes the threads up */
2539 sp = (P_)frame - 1; /* sp = stuff to slide */
2540 displacement += sizeofW(StgUpdateFrame);
2543 /* No squeeze for this frame */
2544 sp = frame_bottom - 1; /* Keep the current frame */
2546 /* Do lazy black-holing.
2548 if (is_update_frame) {
2549 StgBlockingQueue *bh = (StgBlockingQueue *)frame->updatee;
2550 if (bh->header.info != &BLACKHOLE_info
2551 && bh->header.info != &BLACKHOLE_BQ_info
2552 && bh->header.info != &CAF_BLACKHOLE_info
2554 SET_INFO(bh,&BLACKHOLE_info);
2558 /* Fix the link in the current frame (should point to the frame below) */
2559 frame->link = prev_frame;
2560 prev_was_update_frame = is_update_frame;
2563 /* Now slide all words from sp up to the next frame */
2565 if (displacement > 0) {
2566 P_ next_frame_bottom;
2568 if (next_frame != NULL)
2569 next_frame_bottom = (P_)next_frame + sizeofW(StgUpdateFrame);
2571 next_frame_bottom = tso->sp - 1;
2574 fprintf(stderr, "sliding [%p, %p] by %ld\n", sp, next_frame_bottom,
2578 while (sp >= next_frame_bottom) {
2579 sp[displacement] = *sp;
2583 (P_)prev_frame = (P_)frame + displacement;
2587 tso->sp += displacement;
2588 tso->su = prev_frame;
2591 /* -----------------------------------------------------------------------------
2594 * We have to prepare for GC - this means doing lazy black holing
2595 * here. We also take the opportunity to do stack squeezing if it's
2597 * -------------------------------------------------------------------------- */
2600 threadPaused(StgTSO *tso)
2602 if ( RtsFlags.GcFlags.squeezeUpdFrames == rtsTrue )
2603 threadSqueezeStack(tso); /* does black holing too */
2605 threadLazyBlackHole(tso);