1 /* -----------------------------------------------------------------------------
2 * $Id: GC.c,v 1.42 1999/02/25 17:52:33 simonm Exp $
4 * (c) The GHC Team 1998-1999
6 * Generational garbage collector
8 * ---------------------------------------------------------------------------*/
14 #include "StoragePriv.h"
17 #include "SchedAPI.h" /* for ReverCAFs prototype */
20 #include "BlockAlloc.h"
22 #include "DebugProf.h"
25 #include "StablePriv.h"
29 /* STATIC OBJECT LIST.
32 * We maintain a linked list of static objects that are still live.
33 * The requirements for this list are:
35 * - we need to scan the list while adding to it, in order to
36 * scavenge all the static objects (in the same way that
37 * breadth-first scavenging works for dynamic objects).
39 * - we need to be able to tell whether an object is already on
40 * the list, to break loops.
42 * Each static object has a "static link field", which we use for
43 * linking objects on to the list. We use a stack-type list, consing
44 * objects on the front as they are added (this means that the
45 * scavenge phase is depth-first, not breadth-first, but that
48 * A separate list is kept for objects that have been scavenged
49 * already - this is so that we can zero all the marks afterwards.
51 * An object is on the list if its static link field is non-zero; this
52 * means that we have to mark the end of the list with '1', not NULL.
54 * Extra notes for generational GC:
56 * Each generation has a static object list associated with it. When
57 * collecting generations up to N, we treat the static object lists
58 * from generations > N as roots.
60 * We build up a static object list while collecting generations 0..N,
61 * which is then appended to the static object list of generation N+1.
63 StgClosure* static_objects; /* live static objects */
64 StgClosure* scavenged_static_objects; /* static objects scavenged so far */
66 /* N is the oldest generation being collected, where the generations
67 * are numbered starting at 0. A major GC (indicated by the major_gc
68 * flag) is when we're collecting all generations. We only attempt to
69 * deal with static objects and GC CAFs when doing a major GC.
72 static rtsBool major_gc;
74 /* Youngest generation that objects should be evacuated to in
75 * evacuate(). (Logically an argument to evacuate, but it's static
76 * a lot of the time so we optimise it into a global variable).
82 static StgWeak *old_weak_ptr_list; /* also pending finaliser list */
83 static rtsBool weak_done; /* all done for this pass */
85 /* Flag indicating failure to evacuate an object to the desired
88 static rtsBool failed_to_evac;
90 /* Old to-space (used for two-space collector only)
94 /* Data used for allocation area sizing.
96 lnat new_blocks; /* blocks allocated during this GC */
97 lnat g0s0_pcnt_kept = 30; /* percentage of g0s0 live at last minor GC */
99 /* -----------------------------------------------------------------------------
100 Static function declarations
101 -------------------------------------------------------------------------- */
103 static StgClosure *evacuate(StgClosure *q);
104 static void zeroStaticObjectList(StgClosure* first_static);
105 static rtsBool traverse_weak_ptr_list(void);
106 static void zeroMutableList(StgMutClosure *first);
107 static void revertDeadCAFs(void);
109 static void scavenge_stack(StgPtr p, StgPtr stack_end);
110 static void scavenge_large(step *step);
111 static void scavenge(step *step);
112 static void scavenge_static(void);
113 static void scavenge_mutable_list(generation *g);
114 static void scavenge_mut_once_list(generation *g);
117 static void gcCAFs(void);
120 /* -----------------------------------------------------------------------------
123 For garbage collecting generation N (and all younger generations):
125 - follow all pointers in the root set. the root set includes all
126 mutable objects in all steps in all generations.
128 - for each pointer, evacuate the object it points to into either
129 + to-space in the next higher step in that generation, if one exists,
130 + if the object's generation == N, then evacuate it to the next
131 generation if one exists, or else to-space in the current
133 + if the object's generation < N, then evacuate it to to-space
134 in the next generation.
136 - repeatedly scavenge to-space from each step in each generation
137 being collected until no more objects can be evacuated.
139 - free from-space in each step, and set from-space = to-space.
141 -------------------------------------------------------------------------- */
143 void GarbageCollect(void (*get_roots)(void))
147 lnat live, allocated, collected = 0, copied = 0;
151 CostCentreStack *prev_CCS;
154 /* tell the stats department that we've started a GC */
157 /* attribute any costs to CCS_GC */
163 /* We might have been called from Haskell land by _ccall_GC, in
164 * which case we need to call threadPaused() because the scheduler
165 * won't have done it.
167 if (CurrentTSO) { threadPaused(CurrentTSO); }
169 /* Approximate how much we allocated: number of blocks in the
170 * nursery + blocks allocated via allocate() - unused nusery blocks.
171 * This leaves a little slop at the end of each block, and doesn't
172 * take into account large objects (ToDo).
174 allocated = (nursery_blocks * BLOCK_SIZE_W) + allocated_bytes();
175 for ( bd = current_nursery->link; bd != NULL; bd = bd->link ) {
176 allocated -= BLOCK_SIZE_W;
179 /* Figure out which generation to collect
182 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
183 if (generations[g].steps[0].n_blocks >= generations[g].max_blocks) {
187 major_gc = (N == RtsFlags.GcFlags.generations-1);
189 /* check stack sanity *before* GC (ToDo: check all threads) */
190 /*IF_DEBUG(sanity, checkTSO(MainTSO,0)); */
191 IF_DEBUG(sanity, checkFreeListSanity());
193 /* Initialise the static object lists
195 static_objects = END_OF_STATIC_LIST;
196 scavenged_static_objects = END_OF_STATIC_LIST;
198 /* zero the mutable list for the oldest generation (see comment by
199 * zeroMutableList below).
202 zeroMutableList(generations[RtsFlags.GcFlags.generations-1].mut_once_list);
205 /* Save the old to-space if we're doing a two-space collection
207 if (RtsFlags.GcFlags.generations == 1) {
208 old_to_space = g0s0->to_space;
209 g0s0->to_space = NULL;
212 /* Keep a count of how many new blocks we allocated during this GC
213 * (used for resizing the allocation area, later).
217 /* Initialise to-space in all the generations/steps that we're
220 for (g = 0; g <= N; g++) {
221 generations[g].mut_once_list = END_MUT_LIST;
222 generations[g].mut_list = END_MUT_LIST;
224 for (s = 0; s < generations[g].n_steps; s++) {
226 /* generation 0, step 0 doesn't need to-space */
227 if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) {
231 /* Get a free block for to-space. Extra blocks will be chained on
235 step = &generations[g].steps[s];
236 ASSERT(step->gen->no == g);
237 ASSERT(step->hp ? Bdescr(step->hp)->step == step : rtsTrue);
238 bd->gen = &generations[g];
241 bd->evacuated = 1; /* it's a to-space block */
242 step->hp = bd->start;
243 step->hpLim = step->hp + BLOCK_SIZE_W;
247 step->scan = bd->start;
249 step->new_large_objects = NULL;
250 step->scavenged_large_objects = NULL;
252 /* mark the large objects as not evacuated yet */
253 for (bd = step->large_objects; bd; bd = bd->link) {
259 /* make sure the older generations have at least one block to
260 * allocate into (this makes things easier for copy(), see below.
262 for (g = N+1; g < RtsFlags.GcFlags.generations; g++) {
263 for (s = 0; s < generations[g].n_steps; s++) {
264 step = &generations[g].steps[s];
265 if (step->hp_bd == NULL) {
267 bd->gen = &generations[g];
270 bd->evacuated = 0; /* *not* a to-space block */
271 step->hp = bd->start;
272 step->hpLim = step->hp + BLOCK_SIZE_W;
278 /* Set the scan pointer for older generations: remember we
279 * still have to scavenge objects that have been promoted. */
280 step->scan = step->hp;
281 step->scan_bd = step->hp_bd;
282 step->to_space = NULL;
284 step->new_large_objects = NULL;
285 step->scavenged_large_objects = NULL;
289 /* -----------------------------------------------------------------------
290 * follow all the roots that we know about:
291 * - mutable lists from each generation > N
292 * we want to *scavenge* these roots, not evacuate them: they're not
293 * going to move in this GC.
294 * Also: do them in reverse generation order. This is because we
295 * often want to promote objects that are pointed to by older
296 * generations early, so we don't have to repeatedly copy them.
297 * Doing the generations in reverse order ensures that we don't end
298 * up in the situation where we want to evac an object to gen 3 and
299 * it has already been evaced to gen 2.
303 for (g = RtsFlags.GcFlags.generations-1; g > N; g--) {
304 generations[g].saved_mut_list = generations[g].mut_list;
305 generations[g].mut_list = END_MUT_LIST;
308 /* Do the mut-once lists first */
309 for (g = RtsFlags.GcFlags.generations-1; g > N; g--) {
310 scavenge_mut_once_list(&generations[g]);
312 for (st = generations[g].n_steps-1; st >= 0; st--) {
313 scavenge(&generations[g].steps[st]);
317 for (g = RtsFlags.GcFlags.generations-1; g > N; g--) {
318 scavenge_mutable_list(&generations[g]);
320 for (st = generations[g].n_steps-1; st >= 0; st--) {
321 scavenge(&generations[g].steps[st]);
326 /* follow all the roots that the application knows about.
331 /* And don't forget to mark the TSO if we got here direct from
334 CurrentTSO = (StgTSO *)MarkRoot((StgClosure *)CurrentTSO);
337 /* Mark the weak pointer list, and prepare to detect dead weak
341 old_weak_ptr_list = weak_ptr_list;
342 weak_ptr_list = NULL;
343 weak_done = rtsFalse;
345 /* Mark the stable pointer table.
347 markStablePtrTable(major_gc);
351 /* ToDo: To fix the caf leak, we need to make the commented out
352 * parts of this code do something sensible - as described in
355 extern void markHugsObjects(void);
357 /* ToDo: This (undefined) function should contain the scavenge
358 * loop immediately below this block of code - but I'm not sure
359 * enough of the details to do this myself.
361 scavengeEverything();
362 /* revert dead CAFs and update enteredCAFs list */
367 /* This will keep the CAFs and the attached BCOs alive
368 * but the values will have been reverted
370 scavengeEverything();
375 /* -------------------------------------------------------------------------
376 * Repeatedly scavenge all the areas we know about until there's no
377 * more scavenging to be done.
384 /* scavenge static objects */
385 if (major_gc && static_objects != END_OF_STATIC_LIST) {
389 /* When scavenging the older generations: Objects may have been
390 * evacuated from generations <= N into older generations, and we
391 * need to scavenge these objects. We're going to try to ensure that
392 * any evacuations that occur move the objects into at least the
393 * same generation as the object being scavenged, otherwise we
394 * have to create new entries on the mutable list for the older
398 /* scavenge each step in generations 0..maxgen */
402 for (gen = RtsFlags.GcFlags.generations-1; gen >= 0; gen--) {
403 for (st = generations[gen].n_steps-1; st >= 0 ; st--) {
404 if (gen == 0 && st == 0 && RtsFlags.GcFlags.generations > 1) {
407 step = &generations[gen].steps[st];
409 if (step->hp_bd != step->scan_bd || step->scan < step->hp) {
414 if (step->new_large_objects != NULL) {
415 scavenge_large(step);
422 if (flag) { goto loop; }
424 /* must be last... */
425 if (traverse_weak_ptr_list()) { /* returns rtsTrue if evaced something */
430 /* Now see which stable names are still alive
432 gcStablePtrTable(major_gc);
434 /* Set the maximum blocks for the oldest generation, based on twice
435 * the amount of live data now, adjusted to fit the maximum heap
438 * This is an approximation, since in the worst case we'll need
439 * twice the amount of live data plus whatever space the other
442 if (RtsFlags.GcFlags.generations > 1) {
444 oldest_gen->max_blocks =
445 stg_max(oldest_gen->steps[0].to_blocks * RtsFlags.GcFlags.oldGenFactor,
446 RtsFlags.GcFlags.minOldGenSize);
447 if (oldest_gen->max_blocks > RtsFlags.GcFlags.maxHeapSize / 2) {
448 oldest_gen->max_blocks = RtsFlags.GcFlags.maxHeapSize / 2;
449 if (((int)oldest_gen->max_blocks -
450 (int)oldest_gen->steps[0].to_blocks) <
451 (RtsFlags.GcFlags.pcFreeHeap *
452 RtsFlags.GcFlags.maxHeapSize / 200)) {
459 /* run through all the generations/steps and tidy up
461 copied = new_blocks * BLOCK_SIZE_W;
462 for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
465 generations[g].collections++; /* for stats */
468 for (s = 0; s < generations[g].n_steps; s++) {
470 step = &generations[g].steps[s];
472 if (!(g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1)) {
473 /* Tidy the end of the to-space chains */
474 step->hp_bd->free = step->hp;
475 step->hp_bd->link = NULL;
476 /* stats information: how much we copied */
478 copied -= step->hp_bd->start + BLOCK_SIZE_W -
483 /* for generations we collected... */
486 collected += step->n_blocks * BLOCK_SIZE_W; /* for stats */
488 /* free old memory and shift to-space into from-space for all
489 * the collected steps (except the allocation area). These
490 * freed blocks will probaby be quickly recycled.
492 if (!(g == 0 && s == 0)) {
493 freeChain(step->blocks);
494 step->blocks = step->to_space;
495 step->n_blocks = step->to_blocks;
496 step->to_space = NULL;
498 for (bd = step->blocks; bd != NULL; bd = bd->link) {
499 bd->evacuated = 0; /* now from-space */
503 /* LARGE OBJECTS. The current live large objects are chained on
504 * scavenged_large, having been moved during garbage
505 * collection from large_objects. Any objects left on
506 * large_objects list are therefore dead, so we free them here.
508 for (bd = step->large_objects; bd != NULL; bd = next) {
513 for (bd = step->scavenged_large_objects; bd != NULL; bd = bd->link) {
516 step->large_objects = step->scavenged_large_objects;
518 /* Set the maximum blocks for this generation, interpolating
519 * between the maximum size of the oldest and youngest
522 * max_blocks = oldgen_max_blocks * G
523 * ----------------------
528 generations[g].max_blocks = (oldest_gen->max_blocks * g)
529 / (RtsFlags.GcFlags.generations-1);
531 generations[g].max_blocks = oldest_gen->max_blocks;
534 /* for older generations... */
537 /* For older generations, we need to append the
538 * scavenged_large_object list (i.e. large objects that have been
539 * promoted during this GC) to the large_object list for that step.
541 for (bd = step->scavenged_large_objects; bd; bd = next) {
544 dbl_link_onto(bd, &step->large_objects);
547 /* add the new blocks we promoted during this GC */
548 step->n_blocks += step->to_blocks;
553 /* Guess the amount of live data for stats. */
556 /* Free the small objects allocated via allocate(), since this will
557 * all have been copied into G0S1 now.
559 if (small_alloc_list != NULL) {
560 freeChain(small_alloc_list);
562 small_alloc_list = NULL;
566 alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
568 /* Two-space collector:
569 * Free the old to-space, and estimate the amount of live data.
571 if (RtsFlags.GcFlags.generations == 1) {
574 if (old_to_space != NULL) {
575 freeChain(old_to_space);
577 for (bd = g0s0->to_space; bd != NULL; bd = bd->link) {
578 bd->evacuated = 0; /* now from-space */
581 /* For a two-space collector, we need to resize the nursery. */
583 /* set up a new nursery. Allocate a nursery size based on a
584 * function of the amount of live data (currently a factor of 2,
585 * should be configurable (ToDo)). Use the blocks from the old
586 * nursery if possible, freeing up any left over blocks.
588 * If we get near the maximum heap size, then adjust our nursery
589 * size accordingly. If the nursery is the same size as the live
590 * data (L), then we need 3L bytes. We can reduce the size of the
591 * nursery to bring the required memory down near 2L bytes.
593 * A normal 2-space collector would need 4L bytes to give the same
594 * performance we get from 3L bytes, reducing to the same
595 * performance at 2L bytes.
597 blocks = g0s0->to_blocks;
599 if ( blocks * RtsFlags.GcFlags.oldGenFactor * 2 >
600 RtsFlags.GcFlags.maxHeapSize ) {
601 int adjusted_blocks; /* signed on purpose */
604 adjusted_blocks = (RtsFlags.GcFlags.maxHeapSize - 2 * blocks);
605 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));
606 pc_free = adjusted_blocks * 100 / RtsFlags.GcFlags.maxHeapSize;
607 if (pc_free < RtsFlags.GcFlags.pcFreeHeap) /* might even be < 0 */ {
610 blocks = adjusted_blocks;
613 blocks *= RtsFlags.GcFlags.oldGenFactor;
614 if (blocks < RtsFlags.GcFlags.minAllocAreaSize) {
615 blocks = RtsFlags.GcFlags.minAllocAreaSize;
618 resizeNursery(blocks);
621 /* Generational collector:
622 * If the user has given us a suggested heap size, adjust our
623 * allocation area to make best use of the memory available.
626 if (RtsFlags.GcFlags.heapSizeSuggestion) {
628 nat needed = calcNeeded(); /* approx blocks needed at next GC */
630 /* Guess how much will be live in generation 0 step 0 next time.
631 * A good approximation is the obtained by finding the
632 * percentage of g0s0 that was live at the last minor GC.
635 g0s0_pcnt_kept = (new_blocks * 100) / g0s0->n_blocks;
638 /* Estimate a size for the allocation area based on the
639 * information available. We might end up going slightly under
640 * or over the suggested heap size, but we should be pretty
643 * Formula: suggested - needed
644 * ----------------------------
645 * 1 + g0s0_pcnt_kept/100
647 * where 'needed' is the amount of memory needed at the next
648 * collection for collecting all steps except g0s0.
651 (((int)RtsFlags.GcFlags.heapSizeSuggestion - (int)needed) * 100) /
652 (100 + (int)g0s0_pcnt_kept);
654 if (blocks < (int)RtsFlags.GcFlags.minAllocAreaSize) {
655 blocks = RtsFlags.GcFlags.minAllocAreaSize;
658 resizeNursery((nat)blocks);
662 /* revert dead CAFs and update enteredCAFs list */
665 /* mark the garbage collected CAFs as dead */
667 if (major_gc) { gcCAFs(); }
670 /* zero the scavenged static object list */
672 zeroStaticObjectList(scavenged_static_objects);
677 for (bd = g0s0->blocks; bd; bd = bd->link) {
678 bd->free = bd->start;
679 ASSERT(bd->gen == g0);
680 ASSERT(bd->step == g0s0);
681 IF_DEBUG(sanity,memset(bd->start, 0xaa, BLOCK_SIZE));
683 current_nursery = g0s0->blocks;
685 /* start any pending finalizers */
686 scheduleFinalizers(old_weak_ptr_list);
688 /* check sanity after GC */
689 IF_DEBUG(sanity, checkSanity(N));
691 /* extra GC trace info */
692 IF_DEBUG(gc, stat_describe_gens());
695 /* symbol-table based profiling */
696 /* heapCensus(to_space); */ /* ToDo */
699 /* restore enclosing cost centre */
704 /* check for memory leaks if sanity checking is on */
705 IF_DEBUG(sanity, memInventory());
707 /* ok, GC over: tell the stats department what happened. */
708 stat_endGC(allocated, collected, live, copied, N);
711 /* -----------------------------------------------------------------------------
714 traverse_weak_ptr_list is called possibly many times during garbage
715 collection. It returns a flag indicating whether it did any work
716 (i.e. called evacuate on any live pointers).
718 Invariant: traverse_weak_ptr_list is called when the heap is in an
719 idempotent state. That means that there are no pending
720 evacuate/scavenge operations. This invariant helps the weak
721 pointer code decide which weak pointers are dead - if there are no
722 new live weak pointers, then all the currently unreachable ones are
725 For generational GC: we just don't try to finalize weak pointers in
726 older generations than the one we're collecting. This could
727 probably be optimised by keeping per-generation lists of weak
728 pointers, but for a few weak pointers this scheme will work.
729 -------------------------------------------------------------------------- */
732 traverse_weak_ptr_list(void)
734 StgWeak *w, **last_w, *next_w;
736 rtsBool flag = rtsFalse;
738 if (weak_done) { return rtsFalse; }
740 /* doesn't matter where we evacuate values/finalizers to, since
741 * these pointers are treated as roots (iff the keys are alive).
745 last_w = &old_weak_ptr_list;
746 for (w = old_weak_ptr_list; w; w = next_w) {
748 if ((new = isAlive(w->key))) {
750 /* evacuate the value and finalizer */
751 w->value = evacuate(w->value);
752 w->finalizer = evacuate(w->finalizer);
753 /* remove this weak ptr from the old_weak_ptr list */
755 /* and put it on the new weak ptr list */
757 w->link = weak_ptr_list;
760 IF_DEBUG(weak, fprintf(stderr,"Weak pointer still alive at %p -> %p\n", w, w->key));
770 /* If we didn't make any changes, then we can go round and kill all
771 * the dead weak pointers. The old_weak_ptr list is used as a list
772 * of pending finalizers later on.
774 if (flag == rtsFalse) {
775 for (w = old_weak_ptr_list; w; w = w->link) {
776 w->value = evacuate(w->value);
777 w->finalizer = evacuate(w->finalizer);
785 /* -----------------------------------------------------------------------------
786 isAlive determines whether the given closure is still alive (after
787 a garbage collection) or not. It returns the new address of the
788 closure if it is alive, or NULL otherwise.
789 -------------------------------------------------------------------------- */
792 isAlive(StgClosure *p)
800 /* ToDo: for static closures, check the static link field.
801 * Problem here is that we sometimes don't set the link field, eg.
802 * for static closures with an empty SRT or CONSTR_STATIC_NOCAFs.
805 /* ignore closures in generations that we're not collecting. */
806 if (LOOKS_LIKE_STATIC(p) || Bdescr((P_)p)->gen->no > N) {
810 switch (info->type) {
815 case IND_OLDGEN: /* rely on compatible layout with StgInd */
816 case IND_OLDGEN_PERM:
817 /* follow indirections */
818 p = ((StgInd *)p)->indirectee;
823 return ((StgEvacuated *)p)->evacuee;
833 MarkRoot(StgClosure *root)
835 return evacuate(root);
838 static void addBlock(step *step)
840 bdescr *bd = allocBlock();
844 if (step->gen->no <= N) {
850 step->hp_bd->free = step->hp;
851 step->hp_bd->link = bd;
852 step->hp = bd->start;
853 step->hpLim = step->hp + BLOCK_SIZE_W;
859 static __inline__ void
860 upd_evacuee(StgClosure *p, StgClosure *dest)
862 p->header.info = &EVACUATED_info;
863 ((StgEvacuated *)p)->evacuee = dest;
866 static __inline__ StgClosure *
867 copy(StgClosure *src, nat size, step *step)
871 TICK_GC_WORDS_COPIED(size);
872 /* Find out where we're going, using the handy "to" pointer in
873 * the step of the source object. If it turns out we need to
874 * evacuate to an older generation, adjust it here (see comment
877 if (step->gen->no < evac_gen) {
878 #ifdef NO_EAGER_PROMOTION
879 failed_to_evac = rtsTrue;
881 step = &generations[evac_gen].steps[0];
885 /* chain a new block onto the to-space for the destination step if
888 if (step->hp + size >= step->hpLim) {
892 for(to = step->hp, from = (P_)src; size>0; --size) {
898 upd_evacuee(src,(StgClosure *)dest);
899 return (StgClosure *)dest;
902 /* Special version of copy() for when we only want to copy the info
903 * pointer of an object, but reserve some padding after it. This is
904 * used to optimise evacuation of BLACKHOLEs.
907 static __inline__ StgClosure *
908 copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *step)
912 TICK_GC_WORDS_COPIED(size_to_copy);
913 if (step->gen->no < evac_gen) {
914 #ifdef NO_EAGER_PROMOTION
915 failed_to_evac = rtsTrue;
917 step = &generations[evac_gen].steps[0];
921 if (step->hp + size_to_reserve >= step->hpLim) {
925 for(to = step->hp, from = (P_)src; size_to_copy>0; --size_to_copy) {
930 step->hp += size_to_reserve;
931 upd_evacuee(src,(StgClosure *)dest);
932 return (StgClosure *)dest;
935 /* -----------------------------------------------------------------------------
936 Evacuate a large object
938 This just consists of removing the object from the (doubly-linked)
939 large_alloc_list, and linking it on to the (singly-linked)
940 new_large_objects list, from where it will be scavenged later.
942 Convention: bd->evacuated is /= 0 for a large object that has been
943 evacuated, or 0 otherwise.
944 -------------------------------------------------------------------------- */
947 evacuate_large(StgPtr p, rtsBool mutable)
949 bdescr *bd = Bdescr(p);
952 /* should point to the beginning of the block */
953 ASSERT(((W_)p & BLOCK_MASK) == 0);
955 /* already evacuated? */
957 /* Don't forget to set the failed_to_evac flag if we didn't get
958 * the desired destination (see comments in evacuate()).
960 if (bd->gen->no < evac_gen) {
961 failed_to_evac = rtsTrue;
962 TICK_GC_FAILED_PROMOTION();
968 /* remove from large_object list */
970 bd->back->link = bd->link;
971 } else { /* first object in the list */
972 step->large_objects = bd->link;
975 bd->link->back = bd->back;
978 /* link it on to the evacuated large object list of the destination step
981 if (step->gen->no < evac_gen) {
982 #ifdef NO_EAGER_PROMOTION
983 failed_to_evac = rtsTrue;
985 step = &generations[evac_gen].steps[0];
991 bd->link = step->new_large_objects;
992 step->new_large_objects = bd;
996 recordMutable((StgMutClosure *)p);
1000 /* -----------------------------------------------------------------------------
1001 Adding a MUT_CONS to an older generation.
1003 This is necessary from time to time when we end up with an
1004 old-to-new generation pointer in a non-mutable object. We defer
1005 the promotion until the next GC.
1006 -------------------------------------------------------------------------- */
1009 mkMutCons(StgClosure *ptr, generation *gen)
1014 step = &gen->steps[0];
1016 /* chain a new block onto the to-space for the destination step if
1019 if (step->hp + sizeofW(StgIndOldGen) >= step->hpLim) {
1023 q = (StgMutVar *)step->hp;
1024 step->hp += sizeofW(StgMutVar);
1026 SET_HDR(q,&MUT_CONS_info,CCS_GC);
1028 recordOldToNewPtrs((StgMutClosure *)q);
1030 return (StgClosure *)q;
1033 /* -----------------------------------------------------------------------------
1036 This is called (eventually) for every live object in the system.
1038 The caller to evacuate specifies a desired generation in the
1039 evac_gen global variable. The following conditions apply to
1040 evacuating an object which resides in generation M when we're
1041 collecting up to generation N
1045 else evac to step->to
1047 if M < evac_gen evac to evac_gen, step 0
1049 if the object is already evacuated, then we check which generation
1052 if M >= evac_gen do nothing
1053 if M < evac_gen set failed_to_evac flag to indicate that we
1054 didn't manage to evacuate this object into evac_gen.
1056 -------------------------------------------------------------------------- */
1060 evacuate(StgClosure *q)
1065 const StgInfoTable *info;
1068 if (!LOOKS_LIKE_STATIC(q)) {
1070 if (bd->gen->no > N) {
1071 /* Can't evacuate this object, because it's in a generation
1072 * older than the ones we're collecting. Let's hope that it's
1073 * in evac_gen or older, or we will have to make an IND_OLDGEN object.
1075 if (bd->gen->no < evac_gen) {
1077 failed_to_evac = rtsTrue;
1078 TICK_GC_FAILED_PROMOTION();
1082 step = bd->step->to;
1085 /* make sure the info pointer is into text space */
1086 ASSERT(q && (LOOKS_LIKE_GHC_INFO(GET_INFO(q))
1087 || IS_HUGS_CONSTR_INFO(GET_INFO(q))));
1090 switch (info -> type) {
1093 return copy(q,bco_sizeW(stgCast(StgBCO*,q)),step);
1096 ASSERT(q->header.info != &MUT_CONS_info);
1098 to = copy(q,sizeW_fromITBL(info),step);
1099 recordMutable((StgMutClosure *)to);
1103 stable_ptr_table[((StgStableName *)q)->sn].keep = rtsTrue;
1104 return copy(q,sizeofW(StgStableName),step);
1110 return copy(q,sizeofW(StgHeader)+1,step);
1112 case THUNK_1_0: /* here because of MIN_UPD_SIZE */
1117 #ifdef NO_PROMOTE_THUNKS
1118 if (bd->gen->no == 0 &&
1119 bd->step->no != 0 &&
1120 bd->step->no == bd->gen->n_steps-1) {
1124 return copy(q,sizeofW(StgHeader)+2,step);
1132 return copy(q,sizeofW(StgHeader)+2,step);
1138 case IND_OLDGEN_PERM:
1143 return copy(q,sizeW_fromITBL(info),step);
1147 return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step);
1150 to = copy(q,BLACKHOLE_sizeW(),step);
1151 recordMutable((StgMutClosure *)to);
1154 case THUNK_SELECTOR:
1156 const StgInfoTable* selectee_info;
1157 StgClosure* selectee = ((StgSelector*)q)->selectee;
1160 selectee_info = get_itbl(selectee);
1161 switch (selectee_info->type) {
1170 StgNat32 offset = info->layout.selector_offset;
1172 /* check that the size is in range */
1174 (StgNat32)(selectee_info->layout.payload.ptrs +
1175 selectee_info->layout.payload.nptrs));
1177 /* perform the selection! */
1178 q = selectee->payload[offset];
1180 /* if we're already in to-space, there's no need to continue
1181 * with the evacuation, just update the source address with
1182 * a pointer to the (evacuated) constructor field.
1184 if (IS_USER_PTR(q)) {
1185 bdescr *bd = Bdescr((P_)q);
1186 if (bd->evacuated) {
1187 if (bd->gen->no < evac_gen) {
1188 failed_to_evac = rtsTrue;
1189 TICK_GC_FAILED_PROMOTION();
1195 /* otherwise, carry on and evacuate this constructor field,
1196 * (but not the constructor itself)
1205 case IND_OLDGEN_PERM:
1206 selectee = stgCast(StgInd *,selectee)->indirectee;
1210 selectee = stgCast(StgCAF *,selectee)->value;
1214 selectee = stgCast(StgEvacuated*,selectee)->evacuee;
1224 case THUNK_SELECTOR:
1225 /* aargh - do recursively???? */
1230 /* not evaluated yet */
1234 barf("evacuate: THUNK_SELECTOR: strange selectee");
1237 return copy(q,THUNK_SELECTOR_sizeW(),step);
1241 /* follow chains of indirections, don't evacuate them */
1242 q = ((StgInd*)q)->indirectee;
1245 /* ToDo: optimise STATIC_LINK for known cases.
1246 - FUN_STATIC : payload[0]
1247 - THUNK_STATIC : payload[1]
1248 - IND_STATIC : payload[1]
1252 if (info->srt_len == 0) { /* small optimisation */
1258 /* don't want to evacuate these, but we do want to follow pointers
1259 * from SRTs - see scavenge_static.
1262 /* put the object on the static list, if necessary.
1264 if (major_gc && STATIC_LINK(info,(StgClosure *)q) == NULL) {
1265 STATIC_LINK(info,(StgClosure *)q) = static_objects;
1266 static_objects = (StgClosure *)q;
1270 case CONSTR_INTLIKE:
1271 case CONSTR_CHARLIKE:
1272 case CONSTR_NOCAF_STATIC:
1273 /* no need to put these on the static linked list, they don't need
1288 /* shouldn't see these */
1289 barf("evacuate: stack frame\n");
1293 /* these are special - the payload is a copy of a chunk of stack,
1295 return copy(q,pap_sizeW(stgCast(StgPAP*,q)),step);
1298 /* Already evacuated, just return the forwarding address.
1299 * HOWEVER: if the requested destination generation (evac_gen) is
1300 * older than the actual generation (because the object was
1301 * already evacuated to a younger generation) then we have to
1302 * set the failed_to_evac flag to indicate that we couldn't
1303 * manage to promote the object to the desired generation.
1305 if (evac_gen > 0) { /* optimisation */
1306 StgClosure *p = ((StgEvacuated*)q)->evacuee;
1307 if (Bdescr((P_)p)->gen->no < evac_gen) {
1308 /* fprintf(stderr,"evac failed!\n");*/
1309 failed_to_evac = rtsTrue;
1310 TICK_GC_FAILED_PROMOTION();
1313 return ((StgEvacuated*)q)->evacuee;
1317 nat size = arr_words_sizeW(stgCast(StgArrWords*,q));
1319 if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1320 evacuate_large((P_)q, rtsFalse);
1323 /* just copy the block */
1324 return copy(q,size,step);
1329 case MUT_ARR_PTRS_FROZEN:
1331 nat size = mut_arr_ptrs_sizeW(stgCast(StgMutArrPtrs*,q));
1333 if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1334 evacuate_large((P_)q, info->type == MUT_ARR_PTRS);
1337 /* just copy the block */
1338 to = copy(q,size,step);
1339 if (info->type == MUT_ARR_PTRS) {
1340 recordMutable((StgMutClosure *)to);
1348 StgTSO *tso = stgCast(StgTSO *,q);
1349 nat size = tso_sizeW(tso);
1352 /* Large TSOs don't get moved, so no relocation is required.
1354 if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1355 evacuate_large((P_)q, rtsTrue);
1358 /* To evacuate a small TSO, we need to relocate the update frame
1362 StgTSO *new_tso = (StgTSO *)copy((StgClosure *)tso,tso_sizeW(tso),step);
1364 diff = (StgPtr)new_tso - (StgPtr)tso; /* In *words* */
1366 /* relocate the stack pointers... */
1367 new_tso->su = (StgUpdateFrame *) ((StgPtr)new_tso->su + diff);
1368 new_tso->sp = (StgPtr)new_tso->sp + diff;
1369 new_tso->splim = (StgPtr)new_tso->splim + diff;
1371 relocate_TSO(tso, new_tso);
1373 recordMutable((StgMutClosure *)new_tso);
1374 return (StgClosure *)new_tso;
1380 fprintf(stderr,"evacuate: unimplemented/strange closure type\n");
1384 barf("evacuate: strange closure type");
1390 /* -----------------------------------------------------------------------------
1391 relocate_TSO is called just after a TSO has been copied from src to
1392 dest. It adjusts the update frame list for the new location.
1393 -------------------------------------------------------------------------- */
1396 relocate_TSO(StgTSO *src, StgTSO *dest)
1403 diff = (StgPtr)dest->sp - (StgPtr)src->sp; /* In *words* */
1407 while ((P_)su < dest->stack + dest->stack_size) {
1408 switch (get_itbl(su)->type) {
1410 /* GCC actually manages to common up these three cases! */
1413 su->link = (StgUpdateFrame *) ((StgPtr)su->link + diff);
1418 cf = (StgCatchFrame *)su;
1419 cf->link = (StgUpdateFrame *) ((StgPtr)cf->link + diff);
1424 sf = (StgSeqFrame *)su;
1425 sf->link = (StgUpdateFrame *) ((StgPtr)sf->link + diff);
1434 barf("relocate_TSO");
1443 scavenge_srt(const StgInfoTable *info)
1445 StgClosure **srt, **srt_end;
1447 /* evacuate the SRT. If srt_len is zero, then there isn't an
1448 * srt field in the info table. That's ok, because we'll
1449 * never dereference it.
1451 srt = stgCast(StgClosure **,info->srt);
1452 srt_end = srt + info->srt_len;
1453 for (; srt < srt_end; srt++) {
1458 /* -----------------------------------------------------------------------------
1459 Scavenge a given step until there are no more objects in this step
1462 evac_gen is set by the caller to be either zero (for a step in a
1463 generation < N) or G where G is the generation of the step being
1466 We sometimes temporarily change evac_gen back to zero if we're
1467 scavenging a mutable object where early promotion isn't such a good
1469 -------------------------------------------------------------------------- */
1473 scavenge(step *step)
1476 const StgInfoTable *info;
1478 nat saved_evac_gen = evac_gen; /* used for temporarily changing evac_gen */
1483 failed_to_evac = rtsFalse;
1485 /* scavenge phase - standard breadth-first scavenging of the
1489 while (bd != step->hp_bd || p < step->hp) {
1491 /* If we're at the end of this block, move on to the next block */
1492 if (bd != step->hp_bd && p == bd->free) {
1498 q = p; /* save ptr to object */
1500 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO((StgClosure *)p))
1501 || IS_HUGS_CONSTR_INFO(GET_INFO((StgClosure *)p))));
1503 info = get_itbl((StgClosure *)p);
1504 switch (info -> type) {
1508 StgBCO* bco = stgCast(StgBCO*,p);
1510 for (i = 0; i < bco->n_ptrs; i++) {
1511 bcoConstCPtr(bco,i) = evacuate(bcoConstCPtr(bco,i));
1513 p += bco_sizeW(bco);
1518 /* treat MVars specially, because we don't want to evacuate the
1519 * mut_link field in the middle of the closure.
1522 StgMVar *mvar = ((StgMVar *)p);
1524 (StgClosure *)mvar->head = evacuate((StgClosure *)mvar->head);
1525 (StgClosure *)mvar->tail = evacuate((StgClosure *)mvar->tail);
1526 (StgClosure *)mvar->value = evacuate((StgClosure *)mvar->value);
1527 p += sizeofW(StgMVar);
1528 evac_gen = saved_evac_gen;
1536 ((StgClosure *)p)->payload[1] = evacuate(((StgClosure *)p)->payload[1]);
1537 ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1538 p += sizeofW(StgHeader) + 2;
1543 ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1544 p += sizeofW(StgHeader) + 2; /* MIN_UPD_SIZE */
1550 ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1551 p += sizeofW(StgHeader) + 1;
1556 p += sizeofW(StgHeader) + 2; /* MIN_UPD_SIZE */
1562 p += sizeofW(StgHeader) + 1;
1569 p += sizeofW(StgHeader) + 2;
1576 ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1577 p += sizeofW(StgHeader) + 2;
1590 case IND_OLDGEN_PERM:
1596 end = (P_)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1597 for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
1598 (StgClosure *)*p = evacuate((StgClosure *)*p);
1600 p += info->layout.payload.nptrs;
1605 /* ignore MUT_CONSs */
1606 if (((StgMutVar *)p)->header.info != &MUT_CONS_info) {
1608 ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
1609 evac_gen = saved_evac_gen;
1611 p += sizeofW(StgMutVar);
1616 p += BLACKHOLE_sizeW();
1621 StgBlockingQueue *bh = (StgBlockingQueue *)p;
1622 (StgClosure *)bh->blocking_queue =
1623 evacuate((StgClosure *)bh->blocking_queue);
1624 if (failed_to_evac) {
1625 failed_to_evac = rtsFalse;
1626 recordMutable((StgMutClosure *)bh);
1628 p += BLACKHOLE_sizeW();
1632 case THUNK_SELECTOR:
1634 StgSelector *s = (StgSelector *)p;
1635 s->selectee = evacuate(s->selectee);
1636 p += THUNK_SELECTOR_sizeW();
1642 barf("scavenge:IND???\n");
1644 case CONSTR_INTLIKE:
1645 case CONSTR_CHARLIKE:
1647 case CONSTR_NOCAF_STATIC:
1651 /* Shouldn't see a static object here. */
1652 barf("scavenge: STATIC object\n");
1664 /* Shouldn't see stack frames here. */
1665 barf("scavenge: stack frame\n");
1667 case AP_UPD: /* same as PAPs */
1669 /* Treat a PAP just like a section of stack, not forgetting to
1670 * evacuate the function pointer too...
1673 StgPAP* pap = stgCast(StgPAP*,p);
1675 pap->fun = evacuate(pap->fun);
1676 scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1677 p += pap_sizeW(pap);
1682 /* nothing to follow */
1683 p += arr_words_sizeW(stgCast(StgArrWords*,p));
1687 /* follow everything */
1691 evac_gen = 0; /* repeatedly mutable */
1692 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1693 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1694 (StgClosure *)*p = evacuate((StgClosure *)*p);
1696 evac_gen = saved_evac_gen;
1700 case MUT_ARR_PTRS_FROZEN:
1701 /* follow everything */
1703 StgPtr start = p, next;
1705 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1706 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1707 (StgClosure *)*p = evacuate((StgClosure *)*p);
1709 if (failed_to_evac) {
1710 /* we can do this easier... */
1711 recordMutable((StgMutClosure *)start);
1712 failed_to_evac = rtsFalse;
1723 /* chase the link field for any TSOs on the same queue */
1724 (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
1725 /* scavenge this thread's stack */
1726 scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
1727 evac_gen = saved_evac_gen;
1728 p += tso_sizeW(tso);
1735 barf("scavenge: unimplemented/strange closure type\n");
1741 /* If we didn't manage to promote all the objects pointed to by
1742 * the current object, then we have to designate this object as
1743 * mutable (because it contains old-to-new generation pointers).
1745 if (failed_to_evac) {
1746 mkMutCons((StgClosure *)q, &generations[evac_gen]);
1747 failed_to_evac = rtsFalse;
1755 /* -----------------------------------------------------------------------------
1756 Scavenge one object.
1758 This is used for objects that are temporarily marked as mutable
1759 because they contain old-to-new generation pointers. Only certain
1760 objects can have this property.
1761 -------------------------------------------------------------------------- */
1763 scavenge_one(StgClosure *p)
1768 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1769 || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1773 switch (info -> type) {
1776 case FUN_1_0: /* hardly worth specialising these guys */
1796 case IND_OLDGEN_PERM:
1802 end = (P_)p->payload + info->layout.payload.ptrs;
1803 for (q = (P_)p->payload; q < end; q++) {
1804 (StgClosure *)*q = evacuate((StgClosure *)*q);
1813 case THUNK_SELECTOR:
1815 StgSelector *s = (StgSelector *)p;
1816 s->selectee = evacuate(s->selectee);
1820 case AP_UPD: /* same as PAPs */
1822 /* Treat a PAP just like a section of stack, not forgetting to
1823 * evacuate the function pointer too...
1826 StgPAP* pap = (StgPAP *)p;
1828 pap->fun = evacuate(pap->fun);
1829 scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1834 /* This might happen if for instance a MUT_CONS was pointing to a
1835 * THUNK which has since been updated. The IND_OLDGEN will
1836 * be on the mutable list anyway, so we don't need to do anything
1842 barf("scavenge_one: strange object");
1845 no_luck = failed_to_evac;
1846 failed_to_evac = rtsFalse;
1851 /* -----------------------------------------------------------------------------
1852 Scavenging mutable lists.
1854 We treat the mutable list of each generation > N (i.e. all the
1855 generations older than the one being collected) as roots. We also
1856 remove non-mutable objects from the mutable list at this point.
1857 -------------------------------------------------------------------------- */
1860 scavenge_mut_once_list(generation *gen)
1863 StgMutClosure *p, *next, *new_list;
1865 p = gen->mut_once_list;
1866 new_list = END_MUT_LIST;
1870 failed_to_evac = rtsFalse;
1872 for (; p != END_MUT_LIST; p = next, next = p->mut_link) {
1874 /* make sure the info pointer is into text space */
1875 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1876 || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1879 switch(info->type) {
1882 case IND_OLDGEN_PERM:
1884 /* Try to pull the indirectee into this generation, so we can
1885 * remove the indirection from the mutable list.
1887 ((StgIndOldGen *)p)->indirectee =
1888 evacuate(((StgIndOldGen *)p)->indirectee);
1891 /* Debugging code to print out the size of the thing we just
1895 StgPtr start = gen->steps[0].scan;
1896 bdescr *start_bd = gen->steps[0].scan_bd;
1898 scavenge(&gen->steps[0]);
1899 if (start_bd != gen->steps[0].scan_bd) {
1900 size += (P_)BLOCK_ROUND_UP(start) - start;
1901 start_bd = start_bd->link;
1902 while (start_bd != gen->steps[0].scan_bd) {
1903 size += BLOCK_SIZE_W;
1904 start_bd = start_bd->link;
1906 size += gen->steps[0].scan -
1907 (P_)BLOCK_ROUND_DOWN(gen->steps[0].scan);
1909 size = gen->steps[0].scan - start;
1911 fprintf(stderr,"evac IND_OLDGEN: %d bytes\n", size * sizeof(W_));
1915 /* failed_to_evac might happen if we've got more than two
1916 * generations, we're collecting only generation 0, the
1917 * indirection resides in generation 2 and the indirectee is
1920 if (failed_to_evac) {
1921 failed_to_evac = rtsFalse;
1922 p->mut_link = new_list;
1925 /* the mut_link field of an IND_STATIC is overloaded as the
1926 * static link field too (it just so happens that we don't need
1927 * both at the same time), so we need to NULL it out when
1928 * removing this object from the mutable list because the static
1929 * link fields are all assumed to be NULL before doing a major
1937 /* MUT_CONS is a kind of MUT_VAR, except it that we try to remove
1938 * it from the mutable list if possible by promoting whatever it
1941 ASSERT(p->header.info == &MUT_CONS_info);
1942 if (scavenge_one(((StgMutVar *)p)->var) == rtsTrue) {
1943 /* didn't manage to promote everything, so put the
1944 * MUT_CONS back on the list.
1946 p->mut_link = new_list;
1952 /* shouldn't have anything else on the mutables list */
1953 barf("scavenge_mut_once_list: strange object?");
1957 gen->mut_once_list = new_list;
1962 scavenge_mutable_list(generation *gen)
1965 StgMutClosure *p, *next;
1967 p = gen->saved_mut_list;
1971 failed_to_evac = rtsFalse;
1973 for (; p != END_MUT_LIST; p = next, next = p->mut_link) {
1975 /* make sure the info pointer is into text space */
1976 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1977 || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1980 switch(info->type) {
1982 case MUT_ARR_PTRS_FROZEN:
1983 /* remove this guy from the mutable list, but follow the ptrs
1984 * anyway (and make sure they get promoted to this gen).
1989 end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1991 for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
1992 (StgClosure *)*q = evacuate((StgClosure *)*q);
1996 if (failed_to_evac) {
1997 failed_to_evac = rtsFalse;
1998 p->mut_link = gen->mut_list;
2005 /* follow everything */
2006 p->mut_link = gen->mut_list;
2011 end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2012 for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
2013 (StgClosure *)*q = evacuate((StgClosure *)*q);
2019 /* MUT_CONS is a kind of MUT_VAR, except that we try to remove
2020 * it from the mutable list if possible by promoting whatever it
2023 ASSERT(p->header.info != &MUT_CONS_info);
2024 ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
2025 p->mut_link = gen->mut_list;
2031 StgMVar *mvar = (StgMVar *)p;
2032 (StgClosure *)mvar->head = evacuate((StgClosure *)mvar->head);
2033 (StgClosure *)mvar->tail = evacuate((StgClosure *)mvar->tail);
2034 (StgClosure *)mvar->value = evacuate((StgClosure *)mvar->value);
2035 p->mut_link = gen->mut_list;
2041 /* follow ptrs and remove this from the mutable list */
2043 StgTSO *tso = (StgTSO *)p;
2045 /* Don't bother scavenging if this thread is dead
2047 if (!(tso->whatNext == ThreadComplete ||
2048 tso->whatNext == ThreadKilled)) {
2049 /* Don't need to chase the link field for any TSOs on the
2050 * same queue. Just scavenge this thread's stack
2052 scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
2055 /* Don't take this TSO off the mutable list - it might still
2056 * point to some younger objects (because we set evac_gen to 0
2059 tso->mut_link = gen->mut_list;
2060 gen->mut_list = (StgMutClosure *)tso;
2066 StgBlockingQueue *bh = (StgBlockingQueue *)p;
2067 (StgClosure *)bh->blocking_queue =
2068 evacuate((StgClosure *)bh->blocking_queue);
2069 p->mut_link = gen->mut_list;
2075 /* shouldn't have anything else on the mutables list */
2076 barf("scavenge_mut_list: strange object?");
2082 scavenge_static(void)
2084 StgClosure* p = static_objects;
2085 const StgInfoTable *info;
2087 /* Always evacuate straight to the oldest generation for static
2089 evac_gen = oldest_gen->no;
2091 /* keep going until we've scavenged all the objects on the linked
2093 while (p != END_OF_STATIC_LIST) {
2097 /* make sure the info pointer is into text space */
2098 ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
2099 || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
2101 /* Take this object *off* the static_objects list,
2102 * and put it on the scavenged_static_objects list.
2104 static_objects = STATIC_LINK(info,p);
2105 STATIC_LINK(info,p) = scavenged_static_objects;
2106 scavenged_static_objects = p;
2108 switch (info -> type) {
2112 StgInd *ind = (StgInd *)p;
2113 ind->indirectee = evacuate(ind->indirectee);
2115 /* might fail to evacuate it, in which case we have to pop it
2116 * back on the mutable list (and take it off the
2117 * scavenged_static list because the static link and mut link
2118 * pointers are one and the same).
2120 if (failed_to_evac) {
2121 failed_to_evac = rtsFalse;
2122 scavenged_static_objects = STATIC_LINK(info,p);
2123 ((StgMutClosure *)ind)->mut_link = oldest_gen->mut_once_list;
2124 oldest_gen->mut_once_list = (StgMutClosure *)ind;
2138 next = (P_)p->payload + info->layout.payload.ptrs;
2139 /* evacuate the pointers */
2140 for (q = (P_)p->payload; q < next; q++) {
2141 (StgClosure *)*q = evacuate((StgClosure *)*q);
2147 barf("scavenge_static");
2150 ASSERT(failed_to_evac == rtsFalse);
2152 /* get the next static object from the list. Remeber, there might
2153 * be more stuff on this list now that we've done some evacuating!
2154 * (static_objects is a global)
2160 /* -----------------------------------------------------------------------------
2161 scavenge_stack walks over a section of stack and evacuates all the
2162 objects pointed to by it. We can use the same code for walking
2163 PAPs, since these are just sections of copied stack.
2164 -------------------------------------------------------------------------- */
2167 scavenge_stack(StgPtr p, StgPtr stack_end)
2170 const StgInfoTable* info;
2174 * Each time around this loop, we are looking at a chunk of stack
2175 * that starts with either a pending argument section or an
2176 * activation record.
2179 while (p < stack_end) {
2180 q = *stgCast(StgPtr*,p);
2182 /* If we've got a tag, skip over that many words on the stack */
2183 if (IS_ARG_TAG(stgCast(StgWord,q))) {
2188 /* Is q a pointer to a closure?
2190 if (! LOOKS_LIKE_GHC_INFO(q)) {
2193 if (LOOKS_LIKE_STATIC(q)) { /* Is it a static closure? */
2194 ASSERT(closure_STATIC(stgCast(StgClosure*,q)));
2196 /* otherwise, must be a pointer into the allocation space.
2200 (StgClosure *)*p = evacuate((StgClosure *)q);
2206 * Otherwise, q must be the info pointer of an activation
2207 * record. All activation records have 'bitmap' style layout
2210 info = get_itbl(stgCast(StgClosure*,p));
2212 switch (info->type) {
2214 /* Dynamic bitmap: the mask is stored on the stack */
2216 bitmap = stgCast(StgRetDyn*,p)->liveness;
2217 p = &payloadWord(stgCast(StgRetDyn*,p),0);
2220 /* probably a slow-entry point return address: */
2226 /* Specialised code for update frames, since they're so common.
2227 * We *know* the updatee points to a BLACKHOLE, CAF_BLACKHOLE,
2228 * or BLACKHOLE_BQ, so just inline the code to evacuate it here.
2232 StgUpdateFrame *frame = (StgUpdateFrame *)p;
2234 StgClosureType type = get_itbl(frame->updatee)->type;
2236 p += sizeofW(StgUpdateFrame);
2237 if (type == EVACUATED) {
2238 frame->updatee = evacuate(frame->updatee);
2241 bdescr *bd = Bdescr((P_)frame->updatee);
2243 if (bd->gen->no > N) {
2244 if (bd->gen->no < evac_gen) {
2245 failed_to_evac = rtsTrue;
2250 /* Don't promote blackholes */
2252 if (!(step->gen->no == 0 &&
2254 step->no == step->gen->n_steps-1)) {
2261 to = copyPart(frame->updatee, BLACKHOLE_sizeW(),
2262 sizeofW(StgHeader), step);
2263 frame->updatee = to;
2266 to = copy(frame->updatee, BLACKHOLE_sizeW(), step);
2267 frame->updatee = to;
2268 recordMutable((StgMutClosure *)to);
2271 barf("scavenge_stack: UPDATE_FRAME updatee");
2276 /* small bitmap (< 32 entries, or 64 on a 64-bit machine) */
2283 bitmap = info->layout.bitmap;
2286 while (bitmap != 0) {
2287 if ((bitmap & 1) == 0) {
2288 (StgClosure *)*p = evacuate((StgClosure *)*p);
2291 bitmap = bitmap >> 1;
2298 /* large bitmap (> 32 entries) */
2303 StgLargeBitmap *large_bitmap;
2306 large_bitmap = info->layout.large_bitmap;
2309 for (i=0; i<large_bitmap->size; i++) {
2310 bitmap = large_bitmap->bitmap[i];
2311 q = p + sizeof(W_) * 8;
2312 while (bitmap != 0) {
2313 if ((bitmap & 1) == 0) {
2314 (StgClosure *)*p = evacuate((StgClosure *)*p);
2317 bitmap = bitmap >> 1;
2319 if (i+1 < large_bitmap->size) {
2321 (StgClosure *)*p = evacuate((StgClosure *)*p);
2327 /* and don't forget to follow the SRT */
2332 barf("scavenge_stack: weird activation record found on stack.\n");
2337 /*-----------------------------------------------------------------------------
2338 scavenge the large object list.
2340 evac_gen set by caller; similar games played with evac_gen as with
2341 scavenge() - see comment at the top of scavenge(). Most large
2342 objects are (repeatedly) mutable, so most of the time evac_gen will
2344 --------------------------------------------------------------------------- */
2347 scavenge_large(step *step)
2351 const StgInfoTable* info;
2352 nat saved_evac_gen = evac_gen; /* used for temporarily changing evac_gen */
2354 evac_gen = 0; /* most objects are mutable */
2355 bd = step->new_large_objects;
2357 for (; bd != NULL; bd = step->new_large_objects) {
2359 /* take this object *off* the large objects list and put it on
2360 * the scavenged large objects list. This is so that we can
2361 * treat new_large_objects as a stack and push new objects on
2362 * the front when evacuating.
2364 step->new_large_objects = bd->link;
2365 dbl_link_onto(bd, &step->scavenged_large_objects);
2368 info = get_itbl(stgCast(StgClosure*,p));
2370 switch (info->type) {
2372 /* only certain objects can be "large"... */
2375 /* nothing to follow */
2379 /* follow everything */
2383 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2384 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
2385 (StgClosure *)*p = evacuate((StgClosure *)*p);
2390 case MUT_ARR_PTRS_FROZEN:
2391 /* follow everything */
2393 StgPtr start = p, next;
2395 evac_gen = saved_evac_gen; /* not really mutable */
2396 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2397 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
2398 (StgClosure *)*p = evacuate((StgClosure *)*p);
2401 if (failed_to_evac) {
2402 recordMutable((StgMutClosure *)start);
2409 StgBCO* bco = stgCast(StgBCO*,p);
2411 evac_gen = saved_evac_gen;
2412 for (i = 0; i < bco->n_ptrs; i++) {
2413 bcoConstCPtr(bco,i) = evacuate(bcoConstCPtr(bco,i));
2424 /* chase the link field for any TSOs on the same queue */
2425 (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
2426 /* scavenge this thread's stack */
2427 scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
2432 barf("scavenge_large: unknown/strange object");
2438 zeroStaticObjectList(StgClosure* first_static)
2442 const StgInfoTable *info;
2444 for (p = first_static; p != END_OF_STATIC_LIST; p = link) {
2446 link = STATIC_LINK(info, p);
2447 STATIC_LINK(info,p) = NULL;
2451 /* This function is only needed because we share the mutable link
2452 * field with the static link field in an IND_STATIC, so we have to
2453 * zero the mut_link field before doing a major GC, which needs the
2454 * static link field.
2456 * It doesn't do any harm to zero all the mutable link fields on the
2460 zeroMutableList(StgMutClosure *first)
2462 StgMutClosure *next, *c;
2464 for (c = first; c != END_MUT_LIST; c = next) {
2470 /* -----------------------------------------------------------------------------
2472 -------------------------------------------------------------------------- */
2474 void RevertCAFs(void)
2476 while (enteredCAFs != END_CAF_LIST) {
2477 StgCAF* caf = enteredCAFs;
2479 enteredCAFs = caf->link;
2480 ASSERT(get_itbl(caf)->type == CAF_ENTERED);
2481 SET_INFO(caf,&CAF_UNENTERED_info);
2482 caf->value = stgCast(StgClosure*,0xdeadbeef);
2483 caf->link = stgCast(StgCAF*,0xdeadbeef);
2487 void revertDeadCAFs(void)
2489 StgCAF* caf = enteredCAFs;
2490 enteredCAFs = END_CAF_LIST;
2491 while (caf != END_CAF_LIST) {
2492 StgCAF* next = caf->link;
2494 switch(GET_INFO(caf)->type) {
2497 /* This object has been evacuated, it must be live. */
2498 StgCAF* new = stgCast(StgCAF*,stgCast(StgEvacuated*,caf)->evacuee);
2499 new->link = enteredCAFs;
2505 SET_INFO(caf,&CAF_UNENTERED_info);
2506 caf->value = stgCast(StgClosure*,0xdeadbeef);
2507 caf->link = stgCast(StgCAF*,0xdeadbeef);
2511 barf("revertDeadCAFs: enteredCAFs list corrupted");
2517 /* -----------------------------------------------------------------------------
2518 Sanity code for CAF garbage collection.
2520 With DEBUG turned on, we manage a CAF list in addition to the SRT
2521 mechanism. After GC, we run down the CAF list and blackhole any
2522 CAFs which have been garbage collected. This means we get an error
2523 whenever the program tries to enter a garbage collected CAF.
2525 Any garbage collected CAFs are taken off the CAF list at the same
2527 -------------------------------------------------------------------------- */
2535 const StgInfoTable *info;
2546 ASSERT(info->type == IND_STATIC);
2548 if (STATIC_LINK(info,p) == NULL) {
2549 IF_DEBUG(gccafs, fprintf(stderr, "CAF gc'd at 0x%04x\n", (int)p));
2551 SET_INFO(p,&BLACKHOLE_info);
2552 p = STATIC_LINK2(info,p);
2556 pp = &STATIC_LINK2(info,p);
2563 /* fprintf(stderr, "%d CAFs live\n", i); */
2567 /* -----------------------------------------------------------------------------
2570 Whenever a thread returns to the scheduler after possibly doing
2571 some work, we have to run down the stack and black-hole all the
2572 closures referred to by update frames.
2573 -------------------------------------------------------------------------- */
2576 threadLazyBlackHole(StgTSO *tso)
2578 StgUpdateFrame *update_frame;
2579 StgBlockingQueue *bh;
2582 stack_end = &tso->stack[tso->stack_size];
2583 update_frame = tso->su;
2586 switch (get_itbl(update_frame)->type) {
2589 update_frame = stgCast(StgCatchFrame*,update_frame)->link;
2593 bh = (StgBlockingQueue *)update_frame->updatee;
2595 /* if the thunk is already blackholed, it means we've also
2596 * already blackholed the rest of the thunks on this stack,
2597 * so we can stop early.
2599 * The blackhole made for a CAF is a CAF_BLACKHOLE, so they
2600 * don't interfere with this optimisation.
2602 if (bh->header.info == &BLACKHOLE_info) {
2606 if (bh->header.info != &BLACKHOLE_BQ_info &&
2607 bh->header.info != &CAF_BLACKHOLE_info) {
2608 SET_INFO(bh,&BLACKHOLE_info);
2611 update_frame = update_frame->link;
2615 update_frame = stgCast(StgSeqFrame*,update_frame)->link;
2621 barf("threadPaused");
2626 /* -----------------------------------------------------------------------------
2629 * Code largely pinched from old RTS, then hacked to bits. We also do
2630 * lazy black holing here.
2632 * -------------------------------------------------------------------------- */
2635 threadSqueezeStack(StgTSO *tso)
2637 lnat displacement = 0;
2638 StgUpdateFrame *frame;
2639 StgUpdateFrame *next_frame; /* Temporally next */
2640 StgUpdateFrame *prev_frame; /* Temporally previous */
2642 rtsBool prev_was_update_frame;
2644 bottom = &(tso->stack[tso->stack_size]);
2647 /* There must be at least one frame, namely the STOP_FRAME.
2649 ASSERT((P_)frame < bottom);
2651 /* Walk down the stack, reversing the links between frames so that
2652 * we can walk back up as we squeeze from the bottom. Note that
2653 * next_frame and prev_frame refer to next and previous as they were
2654 * added to the stack, rather than the way we see them in this
2655 * walk. (It makes the next loop less confusing.)
2657 * Stop if we find an update frame pointing to a black hole
2658 * (see comment in threadLazyBlackHole()).
2662 while ((P_)frame < bottom - 1) { /* bottom - 1 is the STOP_FRAME */
2663 prev_frame = frame->link;
2664 frame->link = next_frame;
2667 if (get_itbl(frame)->type == UPDATE_FRAME
2668 && frame->updatee->header.info == &BLACKHOLE_info) {
2673 /* Now, we're at the bottom. Frame points to the lowest update
2674 * frame on the stack, and its link actually points to the frame
2675 * above. We have to walk back up the stack, squeezing out empty
2676 * update frames and turning the pointers back around on the way
2679 * The bottom-most frame (the STOP_FRAME) has not been altered, and
2680 * we never want to eliminate it anyway. Just walk one step up
2681 * before starting to squeeze. When you get to the topmost frame,
2682 * remember that there are still some words above it that might have
2689 prev_was_update_frame = (get_itbl(prev_frame)->type == UPDATE_FRAME);
2692 * Loop through all of the frames (everything except the very
2693 * bottom). Things are complicated by the fact that we have
2694 * CATCH_FRAMEs and SEQ_FRAMEs interspersed with the update frames.
2695 * We can only squeeze when there are two consecutive UPDATE_FRAMEs.
2697 while (frame != NULL) {
2699 StgPtr frame_bottom = (P_)frame + sizeofW(StgUpdateFrame);
2700 rtsBool is_update_frame;
2702 next_frame = frame->link;
2703 is_update_frame = (get_itbl(frame)->type == UPDATE_FRAME);
2706 * 1. both the previous and current frame are update frames
2707 * 2. the current frame is empty
2709 if (prev_was_update_frame && is_update_frame &&
2710 (P_)prev_frame == frame_bottom + displacement) {
2712 /* Now squeeze out the current frame */
2713 StgClosure *updatee_keep = prev_frame->updatee;
2714 StgClosure *updatee_bypass = frame->updatee;
2717 fprintf(stderr, "squeezing frame at %p\n", frame);
2720 /* Deal with blocking queues. If both updatees have blocked
2721 * threads, then we should merge the queues into the update
2722 * frame that we're keeping.
2724 * Alternatively, we could just wake them up: they'll just go
2725 * straight to sleep on the proper blackhole! This is less code
2726 * and probably less bug prone, although it's probably much
2729 #if 0 /* do it properly... */
2730 if (GET_INFO(updatee_bypass) == BLACKHOLE_BQ_info) {
2731 /* Sigh. It has one. Don't lose those threads! */
2732 if (GET_INFO(updatee_keep) == BLACKHOLE_BQ_info) {
2733 /* Urgh. Two queues. Merge them. */
2734 P_ keep_tso = ((StgBlockingQueue *)updatee_keep)->blocking_queue;
2736 while (keep_tso->link != END_TSO_QUEUE) {
2737 keep_tso = keep_tso->link;
2739 keep_tso->link = ((StgBlockingQueue *)updatee_bypass)->blocking_queue;
2742 /* For simplicity, just swap the BQ for the BH */
2743 P_ temp = updatee_keep;
2745 updatee_keep = updatee_bypass;
2746 updatee_bypass = temp;
2748 /* Record the swap in the kept frame (below) */
2749 prev_frame->updatee = updatee_keep;
2754 TICK_UPD_SQUEEZED();
2755 UPD_IND(updatee_bypass, updatee_keep); /* this wakes the threads up */
2757 sp = (P_)frame - 1; /* sp = stuff to slide */
2758 displacement += sizeofW(StgUpdateFrame);
2761 /* No squeeze for this frame */
2762 sp = frame_bottom - 1; /* Keep the current frame */
2764 /* Do lazy black-holing.
2766 if (is_update_frame) {
2767 StgBlockingQueue *bh = (StgBlockingQueue *)frame->updatee;
2768 if (bh->header.info != &BLACKHOLE_BQ_info &&
2769 bh->header.info != &CAF_BLACKHOLE_info) {
2770 SET_INFO(bh,&BLACKHOLE_info);
2774 /* Fix the link in the current frame (should point to the frame below) */
2775 frame->link = prev_frame;
2776 prev_was_update_frame = is_update_frame;
2779 /* Now slide all words from sp up to the next frame */
2781 if (displacement > 0) {
2782 P_ next_frame_bottom;
2784 if (next_frame != NULL)
2785 next_frame_bottom = (P_)next_frame + sizeofW(StgUpdateFrame);
2787 next_frame_bottom = tso->sp - 1;
2790 fprintf(stderr, "sliding [%p, %p] by %ld\n", sp, next_frame_bottom,
2794 while (sp >= next_frame_bottom) {
2795 sp[displacement] = *sp;
2799 (P_)prev_frame = (P_)frame + displacement;
2803 tso->sp += displacement;
2804 tso->su = prev_frame;
2807 /* -----------------------------------------------------------------------------
2810 * We have to prepare for GC - this means doing lazy black holing
2811 * here. We also take the opportunity to do stack squeezing if it's
2813 * -------------------------------------------------------------------------- */
2816 threadPaused(StgTSO *tso)
2818 if ( RtsFlags.GcFlags.squeezeUpdFrames == rtsTrue )
2819 threadSqueezeStack(tso); /* does black holing too */
2821 threadLazyBlackHole(tso);