[project @ 1999-02-26 12:46:45 by simonm]
[ghc-hetmet.git] / ghc / rts / GC.c
1 /* -----------------------------------------------------------------------------
2  * $Id: GC.c,v 1.43 1999/02/26 12:46:46 simonm Exp $
3  *
4  * (c) The GHC Team 1998-1999
5  *
6  * Generational garbage collector
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "Rts.h"
11 #include "RtsFlags.h"
12 #include "RtsUtils.h"
13 #include "Storage.h"
14 #include "StoragePriv.h"
15 #include "Stats.h"
16 #include "Schedule.h"
17 #include "SchedAPI.h" /* for ReverCAFs prototype */
18 #include "Sanity.h"
19 #include "GC.h"
20 #include "BlockAlloc.h"
21 #include "Main.h"
22 #include "DebugProf.h"
23 #include "SchedAPI.h"
24 #include "Weak.h"
25 #include "StablePriv.h"
26
27 StgCAF* enteredCAFs;
28
29 /* STATIC OBJECT LIST.
30  *
31  * During GC:
32  * We maintain a linked list of static objects that are still live.
33  * The requirements for this list are:
34  *
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).
38  *
39  *  - we need to be able to tell whether an object is already on
40  *    the list, to break loops.
41  *
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
46  * shouldn't matter).  
47  *
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.
50  *
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.  
53  *
54  * Extra notes for generational GC:
55  *
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.
59  *
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.
62  */
63 StgClosure* static_objects;           /* live static objects */
64 StgClosure* scavenged_static_objects; /* static objects scavenged so far */
65
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.
70  */
71 static nat N;
72 static rtsBool major_gc;
73
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).
77  */
78 static nat evac_gen;
79
80 /* WEAK POINTERS
81  */
82 static StgWeak *old_weak_ptr_list; /* also pending finaliser list */
83 static rtsBool weak_done;       /* all done for this pass */
84
85 /* Flag indicating failure to evacuate an object to the desired
86  * generation.
87  */
88 static rtsBool failed_to_evac;
89
90 /* Old to-space (used for two-space collector only)
91  */
92 bdescr *old_to_space;
93
94 /* Data used for allocation area sizing.
95  */
96 lnat new_blocks;                /* blocks allocated during this GC */
97 lnat g0s0_pcnt_kept = 30;       /* percentage of g0s0 live at last minor GC */
98
99 /* -----------------------------------------------------------------------------
100    Static function declarations
101    -------------------------------------------------------------------------- */
102
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);
108
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);
115
116 #ifdef DEBUG
117 static void gcCAFs(void);
118 #endif
119
120 /* -----------------------------------------------------------------------------
121    GarbageCollect
122
123    For garbage collecting generation N (and all younger generations):
124
125      - follow all pointers in the root set.  the root set includes all 
126        mutable objects in all steps in all generations.
127
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
132          generation.
133        + if the object's generation < N, then evacuate it to to-space
134          in the next generation.
135
136      - repeatedly scavenge to-space from each step in each generation
137        being collected until no more objects can be evacuated.
138       
139      - free from-space in each step, and set from-space = to-space.
140
141    -------------------------------------------------------------------------- */
142
143 void GarbageCollect(void (*get_roots)(void))
144 {
145   bdescr *bd;
146   step *step;
147   lnat live, allocated, collected = 0, copied = 0;
148   nat g, s;
149
150 #ifdef PROFILING
151   CostCentreStack *prev_CCS;
152 #endif
153
154   /* tell the stats department that we've started a GC */
155   stat_startGC();
156
157   /* attribute any costs to CCS_GC */
158 #ifdef PROFILING
159   prev_CCS = CCCS;
160   CCCS = CCS_GC;
161 #endif
162
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.
166    */
167   if (CurrentTSO) { threadPaused(CurrentTSO); }
168
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).
173    */
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;
177   }
178
179   /* Figure out which generation to collect
180    */
181   N = 0;
182   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
183     if (generations[g].steps[0].n_blocks >= generations[g].max_blocks) {
184       N = g;
185     }
186   }
187   major_gc = (N == RtsFlags.GcFlags.generations-1);
188
189   /* check stack sanity *before* GC (ToDo: check all threads) */
190   /*IF_DEBUG(sanity, checkTSO(MainTSO,0)); */
191   IF_DEBUG(sanity, checkFreeListSanity());
192
193   /* Initialise the static object lists
194    */
195   static_objects = END_OF_STATIC_LIST;
196   scavenged_static_objects = END_OF_STATIC_LIST;
197
198   /* zero the mutable list for the oldest generation (see comment by
199    * zeroMutableList below).
200    */
201   if (major_gc) { 
202     zeroMutableList(generations[RtsFlags.GcFlags.generations-1].mut_once_list);
203   }
204
205   /* Save the old to-space if we're doing a two-space collection
206    */
207   if (RtsFlags.GcFlags.generations == 1) {
208     old_to_space = g0s0->to_space;
209     g0s0->to_space = NULL;
210   }
211
212   /* Keep a count of how many new blocks we allocated during this GC
213    * (used for resizing the allocation area, later).
214    */
215   new_blocks = 0;
216
217   /* Initialise to-space in all the generations/steps that we're
218    * collecting.
219    */
220   for (g = 0; g <= N; g++) {
221     generations[g].mut_once_list = END_MUT_LIST;
222     generations[g].mut_list = END_MUT_LIST;
223
224     for (s = 0; s < generations[g].n_steps; s++) {
225
226       /* generation 0, step 0 doesn't need to-space */
227       if (g == 0 && s == 0 && RtsFlags.GcFlags.generations > 1) { 
228         continue; 
229       }
230
231       /* Get a free block for to-space.  Extra blocks will be chained on
232        * as necessary.
233        */
234       bd = allocBlock();
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];
239       bd->step = step;
240       bd->link = NULL;
241       bd->evacuated = 1;        /* it's a to-space block */
242       step->hp        = bd->start;
243       step->hpLim     = step->hp + BLOCK_SIZE_W;
244       step->hp_bd     = bd;
245       step->to_space  = bd;
246       step->to_blocks = 1;
247       step->scan      = bd->start;
248       step->scan_bd   = bd;
249       step->new_large_objects = NULL;
250       step->scavenged_large_objects = NULL;
251       new_blocks++;
252       /* mark the large objects as not evacuated yet */
253       for (bd = step->large_objects; bd; bd = bd->link) {
254         bd->evacuated = 0;
255       }
256     }
257   }
258
259   /* make sure the older generations have at least one block to
260    * allocate into (this makes things easier for copy(), see below.
261    */
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) {
266         bd = allocBlock();
267         bd->gen = &generations[g];
268         bd->step = step;
269         bd->link = NULL;
270         bd->evacuated = 0;      /* *not* a to-space block */
271         step->hp = bd->start;
272         step->hpLim = step->hp + BLOCK_SIZE_W;
273         step->hp_bd = bd;
274         step->blocks = bd;
275         step->n_blocks = 1;
276         new_blocks++;
277       }
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;
283       step->to_blocks = 0;
284       step->new_large_objects = NULL;
285       step->scavenged_large_objects = NULL;
286     }
287   }
288
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.
300    */
301   { 
302     int st;
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;
306     }
307
308     /* Do the mut-once lists first */
309     for (g = RtsFlags.GcFlags.generations-1; g > N; g--) {
310       scavenge_mut_once_list(&generations[g]);
311       evac_gen = g;
312       for (st = generations[g].n_steps-1; st >= 0; st--) {
313         scavenge(&generations[g].steps[st]);
314       }
315     }
316
317     for (g = RtsFlags.GcFlags.generations-1; g > N; g--) {
318       scavenge_mutable_list(&generations[g]);
319       evac_gen = g;
320       for (st = generations[g].n_steps-1; st >= 0; st--) {
321         scavenge(&generations[g].steps[st]);
322       }
323     }
324   }
325
326   /* follow all the roots that the application knows about.
327    */
328   evac_gen = 0;
329   get_roots();
330
331   /* And don't forget to mark the TSO if we got here direct from
332    * Haskell! */
333   if (CurrentTSO) {
334     CurrentTSO = (StgTSO *)MarkRoot((StgClosure *)CurrentTSO);
335   }
336
337   /* Mark the weak pointer list, and prepare to detect dead weak
338    * pointers.
339    */
340   markWeakList();
341   old_weak_ptr_list = weak_ptr_list;
342   weak_ptr_list = NULL;
343   weak_done = rtsFalse;
344
345   /* Mark the stable pointer table.
346    */
347   markStablePtrTable(major_gc);
348
349 #ifdef INTERPRETER
350   { 
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 
353        * the CAF document.
354        */
355       extern void markHugsObjects(void);
356 #if 0
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.
360        */
361       scavengeEverything();
362       /* revert dead CAFs and update enteredCAFs list */
363       revertDeadCAFs();
364 #endif      
365       markHugsObjects();
366 #if 0
367       /* This will keep the CAFs and the attached BCOs alive 
368        * but the values will have been reverted
369        */
370       scavengeEverything();
371 #endif
372   }
373 #endif
374
375   /* -------------------------------------------------------------------------
376    * Repeatedly scavenge all the areas we know about until there's no
377    * more scavenging to be done.
378    */
379   { 
380     rtsBool flag;
381   loop:
382     flag = rtsFalse;
383
384     /* scavenge static objects */
385     if (major_gc && static_objects != END_OF_STATIC_LIST) {
386       scavenge_static();
387     }
388
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
395      * generation.
396      */
397
398     /* scavenge each step in generations 0..maxgen */
399     { 
400       int gen, st; 
401     loop2:
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) { 
405             continue; 
406           }
407           step = &generations[gen].steps[st];
408           evac_gen = gen;
409           if (step->hp_bd != step->scan_bd || step->scan < step->hp) {
410             scavenge(step);
411             flag = rtsTrue;
412             goto loop2;
413           }
414           if (step->new_large_objects != NULL) {
415             scavenge_large(step);
416             flag = rtsTrue;
417             goto loop2;
418           }
419         }
420       }
421     }
422     if (flag) { goto loop; }
423
424     /* must be last... */
425     if (traverse_weak_ptr_list()) { /* returns rtsTrue if evaced something */
426       goto loop;
427     }
428   }
429
430   /* Now see which stable names are still alive
431    */
432   gcStablePtrTable(major_gc);
433
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
436    * size if necessary.  
437    *
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
440    * generations need.
441    */
442   if (RtsFlags.GcFlags.generations > 1) {
443     if (major_gc) {
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)) {
453           heapOverflow();
454         }
455       }
456     }
457   }
458
459   /* run through all the generations/steps and tidy up 
460    */
461   copied = new_blocks * BLOCK_SIZE_W;
462   for (g = 0; g < RtsFlags.GcFlags.generations; g++) {
463
464     if (g <= N) {
465       generations[g].collections++; /* for stats */
466     }
467
468     for (s = 0; s < generations[g].n_steps; s++) {
469       bdescr *next;
470       step = &generations[g].steps[s];
471
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 */
477         if (g <= N) {
478           copied -= step->hp_bd->start + BLOCK_SIZE_W -
479             step->hp_bd->free;
480         }
481       }
482
483       /* for generations we collected... */
484       if (g <= N) {
485
486         collected += step->n_blocks * BLOCK_SIZE_W; /* for stats */
487
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.
491          */
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;
497           step->to_blocks = 0;
498           for (bd = step->blocks; bd != NULL; bd = bd->link) {
499             bd->evacuated = 0;  /* now from-space */
500           }
501         }
502
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.
507          */
508         for (bd = step->large_objects; bd != NULL; bd = next) {
509           next = bd->link;
510           freeGroup(bd);
511           bd = next;
512         }
513         for (bd = step->scavenged_large_objects; bd != NULL; bd = bd->link) {
514           bd->evacuated = 0;
515         }
516         step->large_objects = step->scavenged_large_objects;
517
518         /* Set the maximum blocks for this generation, interpolating
519          * between the maximum size of the oldest and youngest
520          * generations.
521          *
522          * max_blocks =    oldgen_max_blocks * G
523          *                 ----------------------
524          *                      oldest_gen
525          */
526         if (g != 0) {
527 #if 0
528           generations[g].max_blocks = (oldest_gen->max_blocks * g)
529                / (RtsFlags.GcFlags.generations-1);
530 #endif
531           generations[g].max_blocks = oldest_gen->max_blocks;
532         }
533
534       /* for older generations... */
535       } else {
536         
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.
540          */
541         for (bd = step->scavenged_large_objects; bd; bd = next) {
542           next = bd->link;
543           bd->evacuated = 0;
544           dbl_link_onto(bd, &step->large_objects);
545         }
546
547         /* add the new blocks we promoted during this GC */
548         step->n_blocks += step->to_blocks;
549       }
550     }
551   }
552   
553   /* Guess the amount of live data for stats. */
554   live = calcLive();
555
556   /* Free the small objects allocated via allocate(), since this will
557    * all have been copied into G0S1 now.  
558    */
559   if (small_alloc_list != NULL) {
560     freeChain(small_alloc_list);
561   }
562   small_alloc_list = NULL;
563   alloc_blocks = 0;
564   alloc_Hp = NULL;
565   alloc_HpLim = NULL;
566   alloc_blocks_lim = RtsFlags.GcFlags.minAllocAreaSize;
567
568   /* Two-space collector:
569    * Free the old to-space, and estimate the amount of live data.
570    */
571   if (RtsFlags.GcFlags.generations == 1) {
572     nat blocks;
573     
574     if (old_to_space != NULL) {
575       freeChain(old_to_space);
576     }
577     for (bd = g0s0->to_space; bd != NULL; bd = bd->link) {
578       bd->evacuated = 0;        /* now from-space */
579     }
580
581     /* For a two-space collector, we need to resize the nursery. */
582     
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.
587      *
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.
592      * 
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.  
596      */
597     blocks = g0s0->to_blocks;
598
599     if ( blocks * RtsFlags.GcFlags.oldGenFactor * 2 > 
600          RtsFlags.GcFlags.maxHeapSize ) {
601       int adjusted_blocks;  /* signed on purpose */
602       int pc_free; 
603       
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 */ {
608         heapOverflow();
609       }
610       blocks = adjusted_blocks;
611       
612     } else {
613       blocks *= RtsFlags.GcFlags.oldGenFactor;
614       if (blocks < RtsFlags.GcFlags.minAllocAreaSize) {
615         blocks = RtsFlags.GcFlags.minAllocAreaSize;
616       }
617     }
618     resizeNursery(blocks);
619     
620   } else {
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.
624      */
625
626     if (RtsFlags.GcFlags.heapSizeSuggestion) {
627       int blocks;
628       nat needed = calcNeeded();        /* approx blocks needed at next GC */
629
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.
633        */
634       if (N == 0) {
635         g0s0_pcnt_kept = (new_blocks * 100) / g0s0->n_blocks;
636       }
637
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
641        * close on average.
642        *
643        * Formula:            suggested - needed
644        *                ----------------------------
645        *                    1 + g0s0_pcnt_kept/100
646        *
647        * where 'needed' is the amount of memory needed at the next
648        * collection for collecting all steps except g0s0.
649        */
650       blocks = 
651         (((int)RtsFlags.GcFlags.heapSizeSuggestion - (int)needed) * 100) /
652         (100 + (int)g0s0_pcnt_kept);
653       
654       if (blocks < (int)RtsFlags.GcFlags.minAllocAreaSize) {
655         blocks = RtsFlags.GcFlags.minAllocAreaSize;
656       }
657       
658       resizeNursery((nat)blocks);
659     }
660   }
661
662   /* revert dead CAFs and update enteredCAFs list */
663   revertDeadCAFs();
664   
665   /* mark the garbage collected CAFs as dead */
666 #ifdef DEBUG
667   if (major_gc) { gcCAFs(); }
668 #endif
669   
670   /* zero the scavenged static object list */
671   if (major_gc) {
672     zeroStaticObjectList(scavenged_static_objects);
673   }
674
675   /* Reset the nursery
676    */
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));
682   }
683   current_nursery = g0s0->blocks;
684
685   /* start any pending finalizers */
686   scheduleFinalizers(old_weak_ptr_list);
687   
688   /* check sanity after GC */
689   IF_DEBUG(sanity, checkSanity(N));
690
691   /* extra GC trace info */
692   IF_DEBUG(gc, stat_describe_gens());
693
694 #ifdef DEBUG
695   /* symbol-table based profiling */
696   /*  heapCensus(to_space); */ /* ToDo */
697 #endif
698
699   /* restore enclosing cost centre */
700 #ifdef PROFILING
701   CCCS = prev_CCS;
702 #endif
703
704   /* check for memory leaks if sanity checking is on */
705   IF_DEBUG(sanity, memInventory());
706
707   /* ok, GC over: tell the stats department what happened. */
708   stat_endGC(allocated, collected, live, copied, N);
709 }
710
711 /* -----------------------------------------------------------------------------
712    Weak Pointers
713
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).
717
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
723    dead.
724
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    -------------------------------------------------------------------------- */
730
731 static rtsBool 
732 traverse_weak_ptr_list(void)
733 {
734   StgWeak *w, **last_w, *next_w;
735   StgClosure *new;
736   rtsBool flag = rtsFalse;
737
738   if (weak_done) { return rtsFalse; }
739
740   /* doesn't matter where we evacuate values/finalizers to, since
741    * these pointers are treated as roots (iff the keys are alive).
742    */
743   evac_gen = 0;
744
745   last_w = &old_weak_ptr_list;
746   for (w = old_weak_ptr_list; w; w = next_w) {
747
748     if ((new = isAlive(w->key))) {
749       w->key = new;
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 */
754       *last_w = w->link;
755       /* and put it on the new weak ptr list */
756       next_w  = w->link;
757       w->link = weak_ptr_list;
758       weak_ptr_list = w;
759       flag = rtsTrue;
760       IF_DEBUG(weak, fprintf(stderr,"Weak pointer still alive at %p -> %p\n", w, w->key));
761       continue;
762     }
763     else {
764       last_w = &(w->link);
765       next_w = w->link;
766       continue;
767     }
768   }
769   
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.
773    */
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);
778     }
779     weak_done = rtsTrue;
780   }
781
782   return rtsTrue;
783 }
784
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    -------------------------------------------------------------------------- */
790
791 StgClosure *
792 isAlive(StgClosure *p)
793 {
794   StgInfoTable *info;
795
796   while (1) {
797
798     info = get_itbl(p);
799
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.
803      */
804
805     /* ignore closures in generations that we're not collecting. */
806     if (LOOKS_LIKE_STATIC(p) || Bdescr((P_)p)->gen->no > N) {
807       return p;
808     }
809     
810     switch (info->type) {
811       
812     case IND:
813     case IND_STATIC:
814     case IND_PERM:
815     case IND_OLDGEN:            /* rely on compatible layout with StgInd */
816     case IND_OLDGEN_PERM:
817       /* follow indirections */
818       p = ((StgInd *)p)->indirectee;
819       continue;
820       
821     case EVACUATED:
822       /* alive! */
823       return ((StgEvacuated *)p)->evacuee;
824
825     default:
826       /* dead. */
827       return NULL;
828     }
829   }
830 }
831
832 StgClosure *
833 MarkRoot(StgClosure *root)
834 {
835   return evacuate(root);
836 }
837
838 static void addBlock(step *step)
839 {
840   bdescr *bd = allocBlock();
841   bd->gen = step->gen;
842   bd->step = step;
843
844   if (step->gen->no <= N) {
845     bd->evacuated = 1;
846   } else {
847     bd->evacuated = 0;
848   }
849
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;
854   step->hp_bd = bd;
855   step->to_blocks++;
856   new_blocks++;
857 }
858
859 static __inline__ void 
860 upd_evacuee(StgClosure *p, StgClosure *dest)
861 {
862   p->header.info = &EVACUATED_info;
863   ((StgEvacuated *)p)->evacuee = dest;
864 }
865
866 static __inline__ StgClosure *
867 copy(StgClosure *src, nat size, step *step)
868 {
869   P_ to, from, dest;
870
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
875    * by evacuate()).
876    */
877   if (step->gen->no < evac_gen) {
878 #ifdef NO_EAGER_PROMOTION    
879     failed_to_evac = rtsTrue;
880 #else
881     step = &generations[evac_gen].steps[0];
882 #endif
883   }
884
885   /* chain a new block onto the to-space for the destination step if
886    * necessary.
887    */
888   if (step->hp + size >= step->hpLim) {
889     addBlock(step);
890   }
891
892   for(to = step->hp, from = (P_)src; size>0; --size) {
893     *to++ = *from++;
894   }
895
896   dest = step->hp;
897   step->hp = to;
898   upd_evacuee(src,(StgClosure *)dest);
899   return (StgClosure *)dest;
900 }
901
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.
905  */
906
907 static __inline__ StgClosure *
908 copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *step)
909 {
910   P_ dest, to, from;
911
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;
916 #else
917     step = &generations[evac_gen].steps[0];
918 #endif
919   }
920
921   if (step->hp + size_to_reserve >= step->hpLim) {
922     addBlock(step);
923   }
924
925   for(to = step->hp, from = (P_)src; size_to_copy>0; --size_to_copy) {
926     *to++ = *from++;
927   }
928   
929   dest = step->hp;
930   step->hp += size_to_reserve;
931   upd_evacuee(src,(StgClosure *)dest);
932   return (StgClosure *)dest;
933 }
934
935 /* -----------------------------------------------------------------------------
936    Evacuate a large object
937
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.
941
942    Convention: bd->evacuated is /= 0 for a large object that has been
943    evacuated, or 0 otherwise.
944    -------------------------------------------------------------------------- */
945
946 static inline void
947 evacuate_large(StgPtr p, rtsBool mutable)
948 {
949   bdescr *bd = Bdescr(p);
950   step *step;
951
952   /* should point to the beginning of the block */
953   ASSERT(((W_)p & BLOCK_MASK) == 0);
954   
955   /* already evacuated? */
956   if (bd->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()).
959      */
960     if (bd->gen->no < evac_gen) {
961       failed_to_evac = rtsTrue;
962       TICK_GC_FAILED_PROMOTION();
963     }
964     return;
965   }
966
967   step = bd->step;
968   /* remove from large_object list */
969   if (bd->back) {
970     bd->back->link = bd->link;
971   } else { /* first object in the list */
972     step->large_objects = bd->link;
973   }
974   if (bd->link) {
975     bd->link->back = bd->back;
976   }
977   
978   /* link it on to the evacuated large object list of the destination step
979    */
980   step = bd->step->to;
981   if (step->gen->no < evac_gen) {
982 #ifdef NO_EAGER_PROMOTION    
983     failed_to_evac = rtsTrue;
984 #else
985     step = &generations[evac_gen].steps[0];
986 #endif
987   }
988
989   bd->step = step;
990   bd->gen = step->gen;
991   bd->link = step->new_large_objects;
992   step->new_large_objects = bd;
993   bd->evacuated = 1;
994
995   if (mutable) {
996     recordMutable((StgMutClosure *)p);
997   }
998 }
999
1000 /* -----------------------------------------------------------------------------
1001    Adding a MUT_CONS to an older generation.
1002
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    -------------------------------------------------------------------------- */
1007
1008 static StgClosure *
1009 mkMutCons(StgClosure *ptr, generation *gen)
1010 {
1011   StgMutVar *q;
1012   step *step;
1013
1014   step = &gen->steps[0];
1015
1016   /* chain a new block onto the to-space for the destination step if
1017    * necessary.
1018    */
1019   if (step->hp + sizeofW(StgIndOldGen) >= step->hpLim) {
1020     addBlock(step);
1021   }
1022
1023   q = (StgMutVar *)step->hp;
1024   step->hp += sizeofW(StgMutVar);
1025
1026   SET_HDR(q,&MUT_CONS_info,CCS_GC);
1027   q->var = ptr;
1028   recordOldToNewPtrs((StgMutClosure *)q);
1029
1030   return (StgClosure *)q;
1031 }
1032
1033 /* -----------------------------------------------------------------------------
1034    Evacuate
1035
1036    This is called (eventually) for every live object in the system.
1037
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
1042
1043    if  M >= evac_gen 
1044            if  M > N     do nothing
1045            else          evac to step->to
1046
1047    if  M < evac_gen      evac to evac_gen, step 0
1048
1049    if the object is already evacuated, then we check which generation
1050    it now resides in.
1051
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.
1055
1056    -------------------------------------------------------------------------- */
1057
1058
1059 static StgClosure *
1060 evacuate(StgClosure *q)
1061 {
1062   StgClosure *to;
1063   bdescr *bd = NULL;
1064   step *step;
1065   const StgInfoTable *info;
1066
1067 loop:
1068   if (!LOOKS_LIKE_STATIC(q)) {
1069     bd = Bdescr((P_)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.
1074        */
1075       if (bd->gen->no < evac_gen) {
1076         /* nope */
1077         failed_to_evac = rtsTrue;
1078         TICK_GC_FAILED_PROMOTION();
1079       }
1080       return q;
1081     }
1082     step = bd->step->to;
1083   }
1084
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))));
1088
1089   info = get_itbl(q);
1090   switch (info -> type) {
1091
1092   case BCO:
1093     return copy(q,bco_sizeW(stgCast(StgBCO*,q)),step);
1094
1095   case MUT_VAR:
1096     ASSERT(q->header.info != &MUT_CONS_info);
1097   case MVAR:
1098     to = copy(q,sizeW_fromITBL(info),step);
1099     recordMutable((StgMutClosure *)to);
1100     return to;
1101
1102   case FUN_1_0:
1103   case FUN_0_1:
1104   case CONSTR_1_0:
1105   case CONSTR_0_1:
1106     return copy(q,sizeofW(StgHeader)+1,step);
1107
1108   case THUNK_1_0:               /* here because of MIN_UPD_SIZE */
1109   case THUNK_0_1:
1110   case THUNK_1_1:
1111   case THUNK_0_2:
1112   case THUNK_2_0:
1113 #ifdef NO_PROMOTE_THUNKS
1114     if (bd->gen->no == 0 && 
1115         bd->step->no != 0 &&
1116         bd->step->no == bd->gen->n_steps-1) {
1117       step = bd->step;
1118     }
1119 #endif
1120     return copy(q,sizeofW(StgHeader)+2,step);
1121
1122   case FUN_1_1:
1123   case FUN_0_2:
1124   case FUN_2_0:
1125   case CONSTR_1_1:
1126   case CONSTR_0_2:
1127   case CONSTR_2_0:
1128     return copy(q,sizeofW(StgHeader)+2,step);
1129
1130   case FUN:
1131   case THUNK:
1132   case CONSTR:
1133   case IND_PERM:
1134   case IND_OLDGEN_PERM:
1135   case CAF_UNENTERED:
1136   case CAF_ENTERED:
1137   case WEAK:
1138   case FOREIGN:
1139   case STABLE_NAME:
1140     return copy(q,sizeW_fromITBL(info),step);
1141
1142   case CAF_BLACKHOLE:
1143   case BLACKHOLE:
1144     return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),step);
1145
1146   case BLACKHOLE_BQ:
1147     to = copy(q,BLACKHOLE_sizeW(),step); 
1148     recordMutable((StgMutClosure *)to);
1149     return to;
1150
1151   case THUNK_SELECTOR:
1152     {
1153       const StgInfoTable* selectee_info;
1154       StgClosure* selectee = ((StgSelector*)q)->selectee;
1155
1156     selector_loop:
1157       selectee_info = get_itbl(selectee);
1158       switch (selectee_info->type) {
1159       case CONSTR:
1160       case CONSTR_1_0:
1161       case CONSTR_0_1:
1162       case CONSTR_2_0:
1163       case CONSTR_1_1:
1164       case CONSTR_0_2:
1165       case CONSTR_STATIC:
1166         { 
1167           StgNat32 offset = info->layout.selector_offset;
1168
1169           /* check that the size is in range */
1170           ASSERT(offset < 
1171                  (StgNat32)(selectee_info->layout.payload.ptrs + 
1172                             selectee_info->layout.payload.nptrs));
1173
1174           /* perform the selection! */
1175           q = selectee->payload[offset];
1176
1177           /* if we're already in to-space, there's no need to continue
1178            * with the evacuation, just update the source address with
1179            * a pointer to the (evacuated) constructor field.
1180            */
1181           if (IS_USER_PTR(q)) {
1182             bdescr *bd = Bdescr((P_)q);
1183             if (bd->evacuated) {
1184               if (bd->gen->no < evac_gen) {
1185                 failed_to_evac = rtsTrue;
1186                 TICK_GC_FAILED_PROMOTION();
1187               }
1188               return q;
1189             }
1190           }
1191
1192           /* otherwise, carry on and evacuate this constructor field,
1193            * (but not the constructor itself)
1194            */
1195           goto loop;
1196         }
1197
1198       case IND:
1199       case IND_STATIC:
1200       case IND_PERM:
1201       case IND_OLDGEN:
1202       case IND_OLDGEN_PERM:
1203         selectee = stgCast(StgInd *,selectee)->indirectee;
1204         goto selector_loop;
1205
1206       case CAF_ENTERED:
1207         selectee = stgCast(StgCAF *,selectee)->value;
1208         goto selector_loop;
1209
1210       case EVACUATED:
1211         selectee = stgCast(StgEvacuated*,selectee)->evacuee;
1212         goto selector_loop;
1213
1214       case THUNK:
1215       case THUNK_1_0:
1216       case THUNK_0_1:
1217       case THUNK_2_0:
1218       case THUNK_1_1:
1219       case THUNK_0_2:
1220       case THUNK_STATIC:
1221       case THUNK_SELECTOR:
1222         /* aargh - do recursively???? */
1223       case CAF_UNENTERED:
1224       case CAF_BLACKHOLE:
1225       case BLACKHOLE:
1226       case BLACKHOLE_BQ:
1227         /* not evaluated yet */
1228         break;
1229
1230       default:
1231         barf("evacuate: THUNK_SELECTOR: strange selectee");
1232       }
1233     }
1234     return copy(q,THUNK_SELECTOR_sizeW(),step);
1235
1236   case IND:
1237   case IND_OLDGEN:
1238     /* follow chains of indirections, don't evacuate them */
1239     q = ((StgInd*)q)->indirectee;
1240     goto loop;
1241
1242     /* ToDo: optimise STATIC_LINK for known cases.
1243        - FUN_STATIC       : payload[0]
1244        - THUNK_STATIC     : payload[1]
1245        - IND_STATIC       : payload[1]
1246     */
1247   case THUNK_STATIC:
1248   case FUN_STATIC:
1249     if (info->srt_len == 0) {   /* small optimisation */
1250       return q;
1251     }
1252     /* fall through */
1253   case CONSTR_STATIC:
1254   case IND_STATIC:
1255     /* don't want to evacuate these, but we do want to follow pointers
1256      * from SRTs  - see scavenge_static.
1257      */
1258
1259     /* put the object on the static list, if necessary.
1260      */
1261     if (major_gc && STATIC_LINK(info,(StgClosure *)q) == NULL) {
1262       STATIC_LINK(info,(StgClosure *)q) = static_objects;
1263       static_objects = (StgClosure *)q;
1264     }
1265     /* fall through */
1266
1267   case CONSTR_INTLIKE:
1268   case CONSTR_CHARLIKE:
1269   case CONSTR_NOCAF_STATIC:
1270     /* no need to put these on the static linked list, they don't need
1271      * to be scavenged.
1272      */
1273     return q;
1274
1275   case RET_BCO:
1276   case RET_SMALL:
1277   case RET_VEC_SMALL:
1278   case RET_BIG:
1279   case RET_VEC_BIG:
1280   case RET_DYN:
1281   case UPDATE_FRAME:
1282   case STOP_FRAME:
1283   case CATCH_FRAME:
1284   case SEQ_FRAME:
1285     /* shouldn't see these */
1286     barf("evacuate: stack frame\n");
1287
1288   case AP_UPD:
1289   case PAP:
1290     /* these are special - the payload is a copy of a chunk of stack,
1291        tagging and all. */
1292     return copy(q,pap_sizeW(stgCast(StgPAP*,q)),step);
1293
1294   case EVACUATED:
1295     /* Already evacuated, just return the forwarding address.
1296      * HOWEVER: if the requested destination generation (evac_gen) is
1297      * older than the actual generation (because the object was
1298      * already evacuated to a younger generation) then we have to
1299      * set the failed_to_evac flag to indicate that we couldn't 
1300      * manage to promote the object to the desired generation.
1301      */
1302     if (evac_gen > 0) {         /* optimisation */
1303       StgClosure *p = ((StgEvacuated*)q)->evacuee;
1304       if (Bdescr((P_)p)->gen->no < evac_gen) {
1305         /*      fprintf(stderr,"evac failed!\n");*/
1306         failed_to_evac = rtsTrue;
1307         TICK_GC_FAILED_PROMOTION();
1308       }
1309     }
1310     return ((StgEvacuated*)q)->evacuee;
1311
1312   case ARR_WORDS:
1313     {
1314       nat size = arr_words_sizeW(stgCast(StgArrWords*,q)); 
1315
1316       if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1317         evacuate_large((P_)q, rtsFalse);
1318         return q;
1319       } else {
1320         /* just copy the block */
1321         return copy(q,size,step);
1322       }
1323     }
1324
1325   case MUT_ARR_PTRS:
1326   case MUT_ARR_PTRS_FROZEN:
1327     {
1328       nat size = mut_arr_ptrs_sizeW(stgCast(StgMutArrPtrs*,q)); 
1329
1330       if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1331         evacuate_large((P_)q, info->type == MUT_ARR_PTRS);
1332         to = q;
1333       } else {
1334         /* just copy the block */
1335         to = copy(q,size,step);
1336         if (info->type == MUT_ARR_PTRS) {
1337           recordMutable((StgMutClosure *)to);
1338         }
1339       }
1340       return to;
1341     }
1342
1343   case TSO:
1344     {
1345       StgTSO *tso = stgCast(StgTSO *,q);
1346       nat size = tso_sizeW(tso);
1347       int diff;
1348
1349       /* Large TSOs don't get moved, so no relocation is required.
1350        */
1351       if (size >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
1352         evacuate_large((P_)q, rtsTrue);
1353         return q;
1354
1355       /* To evacuate a small TSO, we need to relocate the update frame
1356        * list it contains.  
1357        */
1358       } else {
1359         StgTSO *new_tso = (StgTSO *)copy((StgClosure *)tso,tso_sizeW(tso),step);
1360
1361         diff = (StgPtr)new_tso - (StgPtr)tso; /* In *words* */
1362
1363         /* relocate the stack pointers... */
1364         new_tso->su = (StgUpdateFrame *) ((StgPtr)new_tso->su + diff);
1365         new_tso->sp = (StgPtr)new_tso->sp + diff;
1366         new_tso->splim = (StgPtr)new_tso->splim + diff;
1367         
1368         relocate_TSO(tso, new_tso);
1369
1370         recordMutable((StgMutClosure *)new_tso);
1371         return (StgClosure *)new_tso;
1372       }
1373     }
1374
1375   case BLOCKED_FETCH:
1376   case FETCH_ME:
1377     fprintf(stderr,"evacuate: unimplemented/strange closure type\n");
1378     return q;
1379
1380   default:
1381     barf("evacuate: strange closure type");
1382   }
1383
1384   barf("evacuate");
1385 }
1386
1387 /* -----------------------------------------------------------------------------
1388    relocate_TSO is called just after a TSO has been copied from src to
1389    dest.  It adjusts the update frame list for the new location.
1390    -------------------------------------------------------------------------- */
1391
1392 StgTSO *
1393 relocate_TSO(StgTSO *src, StgTSO *dest)
1394 {
1395   StgUpdateFrame *su;
1396   StgCatchFrame  *cf;
1397   StgSeqFrame    *sf;
1398   int diff;
1399
1400   diff = (StgPtr)dest->sp - (StgPtr)src->sp; /* In *words* */
1401
1402   su = dest->su;
1403
1404   while ((P_)su < dest->stack + dest->stack_size) {
1405     switch (get_itbl(su)->type) {
1406    
1407       /* GCC actually manages to common up these three cases! */
1408
1409     case UPDATE_FRAME:
1410       su->link = (StgUpdateFrame *) ((StgPtr)su->link + diff);
1411       su = su->link;
1412       continue;
1413
1414     case CATCH_FRAME:
1415       cf = (StgCatchFrame *)su;
1416       cf->link = (StgUpdateFrame *) ((StgPtr)cf->link + diff);
1417       su = cf->link;
1418       continue;
1419
1420     case SEQ_FRAME:
1421       sf = (StgSeqFrame *)su;
1422       sf->link = (StgUpdateFrame *) ((StgPtr)sf->link + diff);
1423       su = sf->link;
1424       continue;
1425
1426     case STOP_FRAME:
1427       /* all done! */
1428       break;
1429
1430     default:
1431       barf("relocate_TSO");
1432     }
1433     break;
1434   }
1435
1436   return dest;
1437 }
1438
1439 static inline void
1440 scavenge_srt(const StgInfoTable *info)
1441 {
1442   StgClosure **srt, **srt_end;
1443
1444   /* evacuate the SRT.  If srt_len is zero, then there isn't an
1445    * srt field in the info table.  That's ok, because we'll
1446    * never dereference it.
1447    */
1448   srt = stgCast(StgClosure **,info->srt);
1449   srt_end = srt + info->srt_len;
1450   for (; srt < srt_end; srt++) {
1451     evacuate(*srt);
1452   }
1453 }
1454
1455 /* -----------------------------------------------------------------------------
1456    Scavenge a given step until there are no more objects in this step
1457    to scavenge.
1458
1459    evac_gen is set by the caller to be either zero (for a step in a
1460    generation < N) or G where G is the generation of the step being
1461    scavenged.  
1462
1463    We sometimes temporarily change evac_gen back to zero if we're
1464    scavenging a mutable object where early promotion isn't such a good
1465    idea.  
1466    -------------------------------------------------------------------------- */
1467    
1468
1469 static void
1470 scavenge(step *step)
1471 {
1472   StgPtr p, q;
1473   const StgInfoTable *info;
1474   bdescr *bd;
1475   nat saved_evac_gen = evac_gen; /* used for temporarily changing evac_gen */
1476
1477   p = step->scan;
1478   bd = step->scan_bd;
1479
1480   failed_to_evac = rtsFalse;
1481
1482   /* scavenge phase - standard breadth-first scavenging of the
1483    * evacuated objects 
1484    */
1485
1486   while (bd != step->hp_bd || p < step->hp) {
1487
1488     /* If we're at the end of this block, move on to the next block */
1489     if (bd != step->hp_bd && p == bd->free) {
1490       bd = bd->link;
1491       p = bd->start;
1492       continue;
1493     }
1494
1495     q = p;                      /* save ptr to object */
1496
1497     ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO((StgClosure *)p))
1498                  || IS_HUGS_CONSTR_INFO(GET_INFO((StgClosure *)p))));
1499
1500     info = get_itbl((StgClosure *)p);
1501     switch (info -> type) {
1502
1503     case BCO:
1504       {
1505         StgBCO* bco = stgCast(StgBCO*,p);
1506         nat i;
1507         for (i = 0; i < bco->n_ptrs; i++) {
1508           bcoConstCPtr(bco,i) = evacuate(bcoConstCPtr(bco,i));
1509         }
1510         p += bco_sizeW(bco);
1511         break;
1512       }
1513
1514     case MVAR:
1515       /* treat MVars specially, because we don't want to evacuate the
1516        * mut_link field in the middle of the closure.
1517        */
1518       { 
1519         StgMVar *mvar = ((StgMVar *)p);
1520         evac_gen = 0;
1521         (StgClosure *)mvar->head = evacuate((StgClosure *)mvar->head);
1522         (StgClosure *)mvar->tail = evacuate((StgClosure *)mvar->tail);
1523         (StgClosure *)mvar->value = evacuate((StgClosure *)mvar->value);
1524         p += sizeofW(StgMVar);
1525         evac_gen = saved_evac_gen;
1526         break;
1527       }
1528
1529     case THUNK_2_0:
1530     case FUN_2_0:
1531       scavenge_srt(info);
1532     case CONSTR_2_0:
1533       ((StgClosure *)p)->payload[1] = evacuate(((StgClosure *)p)->payload[1]);
1534       ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1535       p += sizeofW(StgHeader) + 2;
1536       break;
1537
1538     case THUNK_1_0:
1539       scavenge_srt(info);
1540       ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1541       p += sizeofW(StgHeader) + 2; /* MIN_UPD_SIZE */
1542       break;
1543
1544     case FUN_1_0:
1545       scavenge_srt(info);
1546     case CONSTR_1_0:
1547       ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1548       p += sizeofW(StgHeader) + 1;
1549       break;
1550
1551     case THUNK_0_1:
1552       scavenge_srt(info);
1553       p += sizeofW(StgHeader) + 2; /* MIN_UPD_SIZE */
1554       break;
1555
1556     case FUN_0_1:
1557       scavenge_srt(info);
1558     case CONSTR_0_1:
1559       p += sizeofW(StgHeader) + 1;
1560       break;
1561
1562     case THUNK_0_2:
1563     case FUN_0_2:
1564       scavenge_srt(info);
1565     case CONSTR_0_2:
1566       p += sizeofW(StgHeader) + 2;
1567       break;
1568
1569     case THUNK_1_1:
1570     case FUN_1_1:
1571       scavenge_srt(info);
1572     case CONSTR_1_1:
1573       ((StgClosure *)p)->payload[0] = evacuate(((StgClosure *)p)->payload[0]);
1574       p += sizeofW(StgHeader) + 2;
1575       break;
1576
1577     case FUN:
1578     case THUNK:
1579       scavenge_srt(info);
1580       /* fall through */
1581
1582     case CONSTR:
1583     case WEAK:
1584     case FOREIGN:
1585     case STABLE_NAME:
1586     case IND_PERM:
1587     case IND_OLDGEN_PERM:
1588     case CAF_UNENTERED:
1589     case CAF_ENTERED:
1590       {
1591         StgPtr end;
1592
1593         end = (P_)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1594         for (p = (P_)((StgClosure *)p)->payload; p < end; p++) {
1595           (StgClosure *)*p = evacuate((StgClosure *)*p);
1596         }
1597         p += info->layout.payload.nptrs;
1598         break;
1599       }
1600
1601     case MUT_VAR:
1602       /* ignore MUT_CONSs */
1603       if (((StgMutVar *)p)->header.info != &MUT_CONS_info) {
1604         evac_gen = 0;
1605         ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
1606         evac_gen = saved_evac_gen;
1607       }
1608       p += sizeofW(StgMutVar);
1609       break;
1610
1611     case CAF_BLACKHOLE:
1612     case BLACKHOLE:
1613         p += BLACKHOLE_sizeW();
1614         break;
1615
1616     case BLACKHOLE_BQ:
1617       { 
1618         StgBlockingQueue *bh = (StgBlockingQueue *)p;
1619         (StgClosure *)bh->blocking_queue = 
1620           evacuate((StgClosure *)bh->blocking_queue);
1621         if (failed_to_evac) {
1622           failed_to_evac = rtsFalse;
1623           recordMutable((StgMutClosure *)bh);
1624         }
1625         p += BLACKHOLE_sizeW();
1626         break;
1627       }
1628
1629     case THUNK_SELECTOR:
1630       { 
1631         StgSelector *s = (StgSelector *)p;
1632         s->selectee = evacuate(s->selectee);
1633         p += THUNK_SELECTOR_sizeW();
1634         break;
1635       }
1636
1637     case IND:
1638     case IND_OLDGEN:
1639       barf("scavenge:IND???\n");
1640
1641     case CONSTR_INTLIKE:
1642     case CONSTR_CHARLIKE:
1643     case CONSTR_STATIC:
1644     case CONSTR_NOCAF_STATIC:
1645     case THUNK_STATIC:
1646     case FUN_STATIC:
1647     case IND_STATIC:
1648       /* Shouldn't see a static object here. */
1649       barf("scavenge: STATIC object\n");
1650
1651     case RET_BCO:
1652     case RET_SMALL:
1653     case RET_VEC_SMALL:
1654     case RET_BIG:
1655     case RET_VEC_BIG:
1656     case RET_DYN:
1657     case UPDATE_FRAME:
1658     case STOP_FRAME:
1659     case CATCH_FRAME:
1660     case SEQ_FRAME:
1661       /* Shouldn't see stack frames here. */
1662       barf("scavenge: stack frame\n");
1663
1664     case AP_UPD: /* same as PAPs */
1665     case PAP:
1666       /* Treat a PAP just like a section of stack, not forgetting to
1667        * evacuate the function pointer too...
1668        */
1669       { 
1670         StgPAP* pap = stgCast(StgPAP*,p);
1671
1672         pap->fun = evacuate(pap->fun);
1673         scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1674         p += pap_sizeW(pap);
1675         break;
1676       }
1677       
1678     case ARR_WORDS:
1679       /* nothing to follow */
1680       p += arr_words_sizeW(stgCast(StgArrWords*,p));
1681       break;
1682
1683     case MUT_ARR_PTRS:
1684       /* follow everything */
1685       {
1686         StgPtr next;
1687
1688         evac_gen = 0;           /* repeatedly mutable */
1689         next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1690         for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1691           (StgClosure *)*p = evacuate((StgClosure *)*p);
1692         }
1693         evac_gen = saved_evac_gen;
1694         break;
1695       }
1696
1697     case MUT_ARR_PTRS_FROZEN:
1698       /* follow everything */
1699       {
1700         StgPtr start = p, next;
1701
1702         next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1703         for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1704           (StgClosure *)*p = evacuate((StgClosure *)*p);
1705         }
1706         if (failed_to_evac) {
1707           /* we can do this easier... */
1708           recordMutable((StgMutClosure *)start);
1709           failed_to_evac = rtsFalse;
1710         }
1711         break;
1712       }
1713
1714     case TSO:
1715       { 
1716         StgTSO *tso;
1717         
1718         tso = (StgTSO *)p;
1719         evac_gen = 0;
1720         /* chase the link field for any TSOs on the same queue */
1721         (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
1722         /* scavenge this thread's stack */
1723         scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
1724         evac_gen = saved_evac_gen;
1725         p += tso_sizeW(tso);
1726         break;
1727       }
1728
1729     case BLOCKED_FETCH:
1730     case FETCH_ME:
1731     case EVACUATED:
1732       barf("scavenge: unimplemented/strange closure type\n");
1733
1734     default:
1735       barf("scavenge");
1736     }
1737
1738     /* If we didn't manage to promote all the objects pointed to by
1739      * the current object, then we have to designate this object as
1740      * mutable (because it contains old-to-new generation pointers).
1741      */
1742     if (failed_to_evac) {
1743       mkMutCons((StgClosure *)q, &generations[evac_gen]);
1744       failed_to_evac = rtsFalse;
1745     }
1746   }
1747
1748   step->scan_bd = bd;
1749   step->scan = p;
1750 }    
1751
1752 /* -----------------------------------------------------------------------------
1753    Scavenge one object.
1754
1755    This is used for objects that are temporarily marked as mutable
1756    because they contain old-to-new generation pointers.  Only certain
1757    objects can have this property.
1758    -------------------------------------------------------------------------- */
1759 static rtsBool
1760 scavenge_one(StgClosure *p)
1761 {
1762   StgInfoTable *info;
1763   rtsBool no_luck;
1764
1765   ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1766                || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1767
1768   info = get_itbl(p);
1769
1770   switch (info -> type) {
1771
1772   case FUN:
1773   case FUN_1_0:                 /* hardly worth specialising these guys */
1774   case FUN_0_1:
1775   case FUN_1_1:
1776   case FUN_0_2:
1777   case FUN_2_0:
1778   case THUNK:
1779   case THUNK_1_0:
1780   case THUNK_0_1:
1781   case THUNK_1_1:
1782   case THUNK_0_2:
1783   case THUNK_2_0:
1784   case CONSTR:
1785   case CONSTR_1_0:
1786   case CONSTR_0_1:
1787   case CONSTR_1_1:
1788   case CONSTR_0_2:
1789   case CONSTR_2_0:
1790   case WEAK:
1791   case FOREIGN:
1792   case IND_PERM:
1793   case IND_OLDGEN_PERM:
1794   case CAF_UNENTERED:
1795   case CAF_ENTERED:
1796     {
1797       StgPtr q, end;
1798       
1799       end = (P_)p->payload + info->layout.payload.ptrs;
1800       for (q = (P_)p->payload; q < end; q++) {
1801         (StgClosure *)*q = evacuate((StgClosure *)*q);
1802       }
1803       break;
1804     }
1805
1806   case CAF_BLACKHOLE:
1807   case BLACKHOLE:
1808       break;
1809
1810   case THUNK_SELECTOR:
1811     { 
1812       StgSelector *s = (StgSelector *)p;
1813       s->selectee = evacuate(s->selectee);
1814       break;
1815     }
1816     
1817   case AP_UPD: /* same as PAPs */
1818   case PAP:
1819     /* Treat a PAP just like a section of stack, not forgetting to
1820      * evacuate the function pointer too...
1821      */
1822     { 
1823       StgPAP* pap = (StgPAP *)p;
1824       
1825       pap->fun = evacuate(pap->fun);
1826       scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1827       break;
1828     }
1829
1830   case IND_OLDGEN:
1831     /* This might happen if for instance a MUT_CONS was pointing to a
1832      * THUNK which has since been updated.  The IND_OLDGEN will
1833      * be on the mutable list anyway, so we don't need to do anything
1834      * here.
1835      */
1836     break;
1837
1838   default:
1839     barf("scavenge_one: strange object");
1840   }    
1841
1842   no_luck = failed_to_evac;
1843   failed_to_evac = rtsFalse;
1844   return (no_luck);
1845 }
1846
1847
1848 /* -----------------------------------------------------------------------------
1849    Scavenging mutable lists.
1850
1851    We treat the mutable list of each generation > N (i.e. all the
1852    generations older than the one being collected) as roots.  We also
1853    remove non-mutable objects from the mutable list at this point.
1854    -------------------------------------------------------------------------- */
1855
1856 static void
1857 scavenge_mut_once_list(generation *gen)
1858 {
1859   StgInfoTable *info;
1860   StgMutClosure *p, *next, *new_list;
1861
1862   p = gen->mut_once_list;
1863   new_list = END_MUT_LIST;
1864   next = p->mut_link;
1865
1866   evac_gen = gen->no;
1867   failed_to_evac = rtsFalse;
1868
1869   for (; p != END_MUT_LIST; p = next, next = p->mut_link) {
1870
1871     /* make sure the info pointer is into text space */
1872     ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1873                  || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1874     
1875     info = get_itbl(p);
1876     switch(info->type) {
1877       
1878     case IND_OLDGEN:
1879     case IND_OLDGEN_PERM:
1880     case IND_STATIC:
1881       /* Try to pull the indirectee into this generation, so we can
1882        * remove the indirection from the mutable list.  
1883        */
1884       ((StgIndOldGen *)p)->indirectee = 
1885         evacuate(((StgIndOldGen *)p)->indirectee);
1886       
1887 #if 0
1888       /* Debugging code to print out the size of the thing we just
1889        * promoted 
1890        */
1891       { 
1892         StgPtr start = gen->steps[0].scan;
1893         bdescr *start_bd = gen->steps[0].scan_bd;
1894         nat size = 0;
1895         scavenge(&gen->steps[0]);
1896         if (start_bd != gen->steps[0].scan_bd) {
1897           size += (P_)BLOCK_ROUND_UP(start) - start;
1898           start_bd = start_bd->link;
1899           while (start_bd != gen->steps[0].scan_bd) {
1900             size += BLOCK_SIZE_W;
1901             start_bd = start_bd->link;
1902           }
1903           size += gen->steps[0].scan -
1904             (P_)BLOCK_ROUND_DOWN(gen->steps[0].scan);
1905         } else {
1906           size = gen->steps[0].scan - start;
1907         }
1908         fprintf(stderr,"evac IND_OLDGEN: %d bytes\n", size * sizeof(W_));
1909       }
1910 #endif
1911
1912       /* failed_to_evac might happen if we've got more than two
1913        * generations, we're collecting only generation 0, the
1914        * indirection resides in generation 2 and the indirectee is
1915        * in generation 1.
1916        */
1917       if (failed_to_evac) {
1918         failed_to_evac = rtsFalse;
1919         p->mut_link = new_list;
1920         new_list = p;
1921       } else {
1922         /* the mut_link field of an IND_STATIC is overloaded as the
1923          * static link field too (it just so happens that we don't need
1924          * both at the same time), so we need to NULL it out when
1925          * removing this object from the mutable list because the static
1926          * link fields are all assumed to be NULL before doing a major
1927          * collection. 
1928          */
1929         p->mut_link = NULL;
1930       }
1931       continue;
1932       
1933     case MUT_VAR:
1934       /* MUT_CONS is a kind of MUT_VAR, except it that we try to remove
1935        * it from the mutable list if possible by promoting whatever it
1936        * points to.
1937        */
1938       ASSERT(p->header.info == &MUT_CONS_info);
1939       if (scavenge_one(((StgMutVar *)p)->var) == rtsTrue) {
1940         /* didn't manage to promote everything, so put the
1941          * MUT_CONS back on the list.
1942          */
1943         p->mut_link = new_list;
1944         new_list = p;
1945       } 
1946       continue;
1947       
1948     default:
1949       /* shouldn't have anything else on the mutables list */
1950       barf("scavenge_mut_once_list: strange object?");
1951     }
1952   }
1953
1954   gen->mut_once_list = new_list;
1955 }
1956
1957
1958 static void
1959 scavenge_mutable_list(generation *gen)
1960 {
1961   StgInfoTable *info;
1962   StgMutClosure *p, *next;
1963
1964   p = gen->saved_mut_list;
1965   next = p->mut_link;
1966
1967   evac_gen = 0;
1968   failed_to_evac = rtsFalse;
1969
1970   for (; p != END_MUT_LIST; p = next, next = p->mut_link) {
1971
1972     /* make sure the info pointer is into text space */
1973     ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
1974                  || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
1975     
1976     info = get_itbl(p);
1977     switch(info->type) {
1978       
1979     case MUT_ARR_PTRS_FROZEN:
1980       /* remove this guy from the mutable list, but follow the ptrs
1981        * anyway (and make sure they get promoted to this gen).
1982        */
1983       {
1984         StgPtr end, q;
1985         
1986         end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1987         evac_gen = gen->no;
1988         for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
1989           (StgClosure *)*q = evacuate((StgClosure *)*q);
1990         }
1991         evac_gen = 0;
1992
1993         if (failed_to_evac) {
1994           failed_to_evac = rtsFalse;
1995           p->mut_link = gen->mut_list;
1996           gen->mut_list = p;
1997         } 
1998         continue;
1999       }
2000
2001     case MUT_ARR_PTRS:
2002       /* follow everything */
2003       p->mut_link = gen->mut_list;
2004       gen->mut_list = p;
2005       {
2006         StgPtr end, q;
2007         
2008         end = (P_)p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2009         for (q = (P_)((StgMutArrPtrs *)p)->payload; q < end; q++) {
2010           (StgClosure *)*q = evacuate((StgClosure *)*q);
2011         }
2012         continue;
2013       }
2014       
2015     case MUT_VAR:
2016       /* MUT_CONS is a kind of MUT_VAR, except that we try to remove
2017        * it from the mutable list if possible by promoting whatever it
2018        * points to.
2019        */
2020       ASSERT(p->header.info != &MUT_CONS_info);
2021       ((StgMutVar *)p)->var = evacuate(((StgMutVar *)p)->var);
2022       p->mut_link = gen->mut_list;
2023       gen->mut_list = p;
2024       continue;
2025       
2026     case MVAR:
2027       {
2028         StgMVar *mvar = (StgMVar *)p;
2029         (StgClosure *)mvar->head = evacuate((StgClosure *)mvar->head);
2030         (StgClosure *)mvar->tail = evacuate((StgClosure *)mvar->tail);
2031         (StgClosure *)mvar->value = evacuate((StgClosure *)mvar->value);
2032         p->mut_link = gen->mut_list;
2033         gen->mut_list = p;
2034         continue;
2035       }
2036
2037     case TSO:
2038       /* follow ptrs and remove this from the mutable list */
2039       { 
2040         StgTSO *tso = (StgTSO *)p;
2041
2042         /* Don't bother scavenging if this thread is dead 
2043          */
2044         if (!(tso->whatNext == ThreadComplete ||
2045               tso->whatNext == ThreadKilled)) {
2046           /* Don't need to chase the link field for any TSOs on the
2047            * same queue. Just scavenge this thread's stack 
2048            */
2049           scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
2050         }
2051
2052         /* Don't take this TSO off the mutable list - it might still
2053          * point to some younger objects (because we set evac_gen to 0
2054          * above). 
2055          */
2056         tso->mut_link = gen->mut_list;
2057         gen->mut_list = (StgMutClosure *)tso;
2058         continue;
2059       }
2060       
2061     case BLACKHOLE_BQ:
2062       { 
2063         StgBlockingQueue *bh = (StgBlockingQueue *)p;
2064         (StgClosure *)bh->blocking_queue = 
2065           evacuate((StgClosure *)bh->blocking_queue);
2066         p->mut_link = gen->mut_list;
2067         gen->mut_list = p;
2068         continue;
2069       }
2070
2071     default:
2072       /* shouldn't have anything else on the mutables list */
2073       barf("scavenge_mut_list: strange object?");
2074     }
2075   }
2076 }
2077
2078 static void
2079 scavenge_static(void)
2080 {
2081   StgClosure* p = static_objects;
2082   const StgInfoTable *info;
2083
2084   /* Always evacuate straight to the oldest generation for static
2085    * objects */
2086   evac_gen = oldest_gen->no;
2087
2088   /* keep going until we've scavenged all the objects on the linked
2089      list... */
2090   while (p != END_OF_STATIC_LIST) {
2091
2092     info = get_itbl(p);
2093
2094     /* make sure the info pointer is into text space */
2095     ASSERT(p && (LOOKS_LIKE_GHC_INFO(GET_INFO(p))
2096                  || IS_HUGS_CONSTR_INFO(GET_INFO(p))));
2097     
2098     /* Take this object *off* the static_objects list,
2099      * and put it on the scavenged_static_objects list.
2100      */
2101     static_objects = STATIC_LINK(info,p);
2102     STATIC_LINK(info,p) = scavenged_static_objects;
2103     scavenged_static_objects = p;
2104     
2105     switch (info -> type) {
2106       
2107     case IND_STATIC:
2108       {
2109         StgInd *ind = (StgInd *)p;
2110         ind->indirectee = evacuate(ind->indirectee);
2111
2112         /* might fail to evacuate it, in which case we have to pop it
2113          * back on the mutable list (and take it off the
2114          * scavenged_static list because the static link and mut link
2115          * pointers are one and the same).
2116          */
2117         if (failed_to_evac) {
2118           failed_to_evac = rtsFalse;
2119           scavenged_static_objects = STATIC_LINK(info,p);
2120           ((StgMutClosure *)ind)->mut_link = oldest_gen->mut_once_list;
2121           oldest_gen->mut_once_list = (StgMutClosure *)ind;
2122         }
2123         break;
2124       }
2125       
2126     case THUNK_STATIC:
2127     case FUN_STATIC:
2128       scavenge_srt(info);
2129       /* fall through */
2130       
2131     case CONSTR_STATIC:
2132       { 
2133         StgPtr q, next;
2134         
2135         next = (P_)p->payload + info->layout.payload.ptrs;
2136         /* evacuate the pointers */
2137         for (q = (P_)p->payload; q < next; q++) {
2138           (StgClosure *)*q = evacuate((StgClosure *)*q);
2139         }
2140         break;
2141       }
2142       
2143     default:
2144       barf("scavenge_static");
2145     }
2146
2147     ASSERT(failed_to_evac == rtsFalse);
2148
2149     /* get the next static object from the list.  Remeber, there might
2150      * be more stuff on this list now that we've done some evacuating!
2151      * (static_objects is a global)
2152      */
2153     p = static_objects;
2154   }
2155 }
2156
2157 /* -----------------------------------------------------------------------------
2158    scavenge_stack walks over a section of stack and evacuates all the
2159    objects pointed to by it.  We can use the same code for walking
2160    PAPs, since these are just sections of copied stack.
2161    -------------------------------------------------------------------------- */
2162
2163 static void
2164 scavenge_stack(StgPtr p, StgPtr stack_end)
2165 {
2166   StgPtr q;
2167   const StgInfoTable* info;
2168   StgNat32 bitmap;
2169
2170   /* 
2171    * Each time around this loop, we are looking at a chunk of stack
2172    * that starts with either a pending argument section or an 
2173    * activation record. 
2174    */
2175
2176   while (p < stack_end) {
2177     q = *stgCast(StgPtr*,p);
2178
2179     /* If we've got a tag, skip over that many words on the stack */
2180     if (IS_ARG_TAG(stgCast(StgWord,q))) {
2181       p += ARG_SIZE(q);
2182       p++; continue;
2183     }
2184      
2185     /* Is q a pointer to a closure?
2186      */
2187     if (! LOOKS_LIKE_GHC_INFO(q)) {
2188
2189 #ifdef DEBUG
2190       if (LOOKS_LIKE_STATIC(q)) { /* Is it a static closure? */
2191         ASSERT(closure_STATIC(stgCast(StgClosure*,q)));
2192       } 
2193       /* otherwise, must be a pointer into the allocation space.
2194        */
2195 #endif
2196
2197       (StgClosure *)*p = evacuate((StgClosure *)q);
2198       p++; 
2199       continue;
2200     }
2201       
2202     /* 
2203      * Otherwise, q must be the info pointer of an activation
2204      * record.  All activation records have 'bitmap' style layout
2205      * info.
2206      */
2207     info  = get_itbl(stgCast(StgClosure*,p));
2208       
2209     switch (info->type) {
2210         
2211       /* Dynamic bitmap: the mask is stored on the stack */
2212     case RET_DYN:
2213       bitmap = stgCast(StgRetDyn*,p)->liveness;
2214       p      = &payloadWord(stgCast(StgRetDyn*,p),0);
2215       goto small_bitmap;
2216
2217       /* probably a slow-entry point return address: */
2218     case FUN:
2219     case FUN_STATIC:
2220       p++;
2221       goto follow_srt;
2222
2223       /* Specialised code for update frames, since they're so common.
2224        * We *know* the updatee points to a BLACKHOLE, CAF_BLACKHOLE,
2225        * or BLACKHOLE_BQ, so just inline the code to evacuate it here.  
2226        */
2227     case UPDATE_FRAME:
2228       {
2229         StgUpdateFrame *frame = (StgUpdateFrame *)p;
2230         StgClosure *to;
2231         StgClosureType type = get_itbl(frame->updatee)->type;
2232
2233         p += sizeofW(StgUpdateFrame);
2234         if (type == EVACUATED) {
2235           frame->updatee = evacuate(frame->updatee);
2236           continue;
2237         } else {
2238           bdescr *bd = Bdescr((P_)frame->updatee);
2239           step *step;
2240           if (bd->gen->no > N) { 
2241             if (bd->gen->no < evac_gen) {
2242               failed_to_evac = rtsTrue;
2243             }
2244             continue;
2245           }
2246
2247           /* Don't promote blackholes */
2248           step = bd->step;
2249           if (!(step->gen->no == 0 && 
2250                 step->no != 0 &&
2251                 step->no == step->gen->n_steps-1)) {
2252             step = step->to;
2253           }
2254
2255           switch (type) {
2256           case BLACKHOLE:
2257           case CAF_BLACKHOLE:
2258             to = copyPart(frame->updatee, BLACKHOLE_sizeW(), 
2259                           sizeofW(StgHeader), step);
2260             frame->updatee = to;
2261             continue;
2262           case BLACKHOLE_BQ:
2263             to = copy(frame->updatee, BLACKHOLE_sizeW(), step);
2264             frame->updatee = to;
2265             recordMutable((StgMutClosure *)to);
2266             continue;
2267           default:
2268             barf("scavenge_stack: UPDATE_FRAME updatee");
2269           }
2270         }
2271       }
2272
2273       /* small bitmap (< 32 entries, or 64 on a 64-bit machine) */
2274     case RET_BCO:
2275     case RET_SMALL:
2276     case RET_VEC_SMALL:
2277     case STOP_FRAME:
2278     case CATCH_FRAME:
2279     case SEQ_FRAME:
2280       bitmap = info->layout.bitmap;
2281       p++;
2282     small_bitmap:
2283       while (bitmap != 0) {
2284         if ((bitmap & 1) == 0) {
2285           (StgClosure *)*p = evacuate((StgClosure *)*p);
2286         }
2287         p++;
2288         bitmap = bitmap >> 1;
2289       }
2290       
2291     follow_srt:
2292       scavenge_srt(info);
2293       continue;
2294
2295       /* large bitmap (> 32 entries) */
2296     case RET_BIG:
2297     case RET_VEC_BIG:
2298       {
2299         StgPtr q;
2300         StgLargeBitmap *large_bitmap;
2301         nat i;
2302
2303         large_bitmap = info->layout.large_bitmap;
2304         p++;
2305
2306         for (i=0; i<large_bitmap->size; i++) {
2307           bitmap = large_bitmap->bitmap[i];
2308           q = p + sizeof(W_) * 8;
2309           while (bitmap != 0) {
2310             if ((bitmap & 1) == 0) {
2311               (StgClosure *)*p = evacuate((StgClosure *)*p);
2312             }
2313             p++;
2314             bitmap = bitmap >> 1;
2315           }
2316           if (i+1 < large_bitmap->size) {
2317             while (p < q) {
2318               (StgClosure *)*p = evacuate((StgClosure *)*p);
2319               p++;
2320             }
2321           }
2322         }
2323
2324         /* and don't forget to follow the SRT */
2325         goto follow_srt;
2326       }
2327
2328     default:
2329       barf("scavenge_stack: weird activation record found on stack.\n");
2330     }
2331   }
2332 }
2333
2334 /*-----------------------------------------------------------------------------
2335   scavenge the large object list.
2336
2337   evac_gen set by caller; similar games played with evac_gen as with
2338   scavenge() - see comment at the top of scavenge().  Most large
2339   objects are (repeatedly) mutable, so most of the time evac_gen will
2340   be zero.
2341   --------------------------------------------------------------------------- */
2342
2343 static void
2344 scavenge_large(step *step)
2345 {
2346   bdescr *bd;
2347   StgPtr p;
2348   const StgInfoTable* info;
2349   nat saved_evac_gen = evac_gen; /* used for temporarily changing evac_gen */
2350
2351   evac_gen = 0;                 /* most objects are mutable */
2352   bd = step->new_large_objects;
2353
2354   for (; bd != NULL; bd = step->new_large_objects) {
2355
2356     /* take this object *off* the large objects list and put it on
2357      * the scavenged large objects list.  This is so that we can
2358      * treat new_large_objects as a stack and push new objects on
2359      * the front when evacuating.
2360      */
2361     step->new_large_objects = bd->link;
2362     dbl_link_onto(bd, &step->scavenged_large_objects);
2363
2364     p = bd->start;
2365     info  = get_itbl(stgCast(StgClosure*,p));
2366
2367     switch (info->type) {
2368
2369     /* only certain objects can be "large"... */
2370
2371     case ARR_WORDS:
2372       /* nothing to follow */
2373       continue;
2374
2375     case MUT_ARR_PTRS:
2376       /* follow everything */
2377       {
2378         StgPtr next;
2379
2380         next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2381         for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
2382           (StgClosure *)*p = evacuate((StgClosure *)*p);
2383         }
2384         continue;
2385       }
2386
2387     case MUT_ARR_PTRS_FROZEN:
2388       /* follow everything */
2389       {
2390         StgPtr start = p, next;
2391
2392         evac_gen = saved_evac_gen; /* not really mutable */
2393         next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
2394         for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
2395           (StgClosure *)*p = evacuate((StgClosure *)*p);
2396         }
2397         evac_gen = 0;
2398         if (failed_to_evac) {
2399           recordMutable((StgMutClosure *)start);
2400         }
2401         continue;
2402       }
2403
2404     case BCO:
2405       {
2406         StgBCO* bco = stgCast(StgBCO*,p);
2407         nat i;
2408         evac_gen = saved_evac_gen;
2409         for (i = 0; i < bco->n_ptrs; i++) {
2410           bcoConstCPtr(bco,i) = evacuate(bcoConstCPtr(bco,i));
2411         }
2412         evac_gen = 0;
2413         continue;
2414       }
2415
2416     case TSO:
2417       { 
2418         StgTSO *tso;
2419         
2420         tso = (StgTSO *)p;
2421         /* chase the link field for any TSOs on the same queue */
2422         (StgClosure *)tso->link = evacuate((StgClosure *)tso->link);
2423         /* scavenge this thread's stack */
2424         scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
2425         continue;
2426       }
2427
2428     default:
2429       barf("scavenge_large: unknown/strange object");
2430     }
2431   }
2432 }
2433
2434 static void
2435 zeroStaticObjectList(StgClosure* first_static)
2436 {
2437   StgClosure* p;
2438   StgClosure* link;
2439   const StgInfoTable *info;
2440
2441   for (p = first_static; p != END_OF_STATIC_LIST; p = link) {
2442     info = get_itbl(p);
2443     link = STATIC_LINK(info, p);
2444     STATIC_LINK(info,p) = NULL;
2445   }
2446 }
2447
2448 /* This function is only needed because we share the mutable link
2449  * field with the static link field in an IND_STATIC, so we have to
2450  * zero the mut_link field before doing a major GC, which needs the
2451  * static link field.  
2452  *
2453  * It doesn't do any harm to zero all the mutable link fields on the
2454  * mutable list.
2455  */
2456 static void
2457 zeroMutableList(StgMutClosure *first)
2458 {
2459   StgMutClosure *next, *c;
2460
2461   for (c = first; c != END_MUT_LIST; c = next) {
2462     next = c->mut_link;
2463     c->mut_link = NULL;
2464   }
2465 }
2466
2467 /* -----------------------------------------------------------------------------
2468    Reverting CAFs
2469    -------------------------------------------------------------------------- */
2470
2471 void RevertCAFs(void)
2472 {
2473   while (enteredCAFs != END_CAF_LIST) {
2474     StgCAF* caf = enteredCAFs;
2475     
2476     enteredCAFs = caf->link;
2477     ASSERT(get_itbl(caf)->type == CAF_ENTERED);
2478     SET_INFO(caf,&CAF_UNENTERED_info);
2479     caf->value = stgCast(StgClosure*,0xdeadbeef);
2480     caf->link  = stgCast(StgCAF*,0xdeadbeef);
2481   }
2482 }
2483
2484 void revertDeadCAFs(void)
2485 {
2486     StgCAF* caf = enteredCAFs;
2487     enteredCAFs = END_CAF_LIST;
2488     while (caf != END_CAF_LIST) {
2489         StgCAF* next = caf->link;
2490
2491         switch(GET_INFO(caf)->type) {
2492         case EVACUATED:
2493             {
2494                 /* This object has been evacuated, it must be live. */
2495                 StgCAF* new = stgCast(StgCAF*,stgCast(StgEvacuated*,caf)->evacuee);
2496                 new->link = enteredCAFs;
2497                 enteredCAFs = new;
2498                 break;
2499             }
2500         case CAF_ENTERED:
2501             {
2502                 SET_INFO(caf,&CAF_UNENTERED_info);
2503                 caf->value = stgCast(StgClosure*,0xdeadbeef);
2504                 caf->link  = stgCast(StgCAF*,0xdeadbeef);
2505                 break;
2506             }
2507         default:
2508                 barf("revertDeadCAFs: enteredCAFs list corrupted");
2509         } 
2510         caf = next;
2511     }
2512 }
2513
2514 /* -----------------------------------------------------------------------------
2515    Sanity code for CAF garbage collection.
2516
2517    With DEBUG turned on, we manage a CAF list in addition to the SRT
2518    mechanism.  After GC, we run down the CAF list and blackhole any
2519    CAFs which have been garbage collected.  This means we get an error
2520    whenever the program tries to enter a garbage collected CAF.
2521
2522    Any garbage collected CAFs are taken off the CAF list at the same
2523    time. 
2524    -------------------------------------------------------------------------- */
2525
2526 #ifdef DEBUG
2527 static void
2528 gcCAFs(void)
2529 {
2530   StgClosure*  p;
2531   StgClosure** pp;
2532   const StgInfoTable *info;
2533   nat i;
2534
2535   i = 0;
2536   p = caf_list;
2537   pp = &caf_list;
2538
2539   while (p != NULL) {
2540     
2541     info = get_itbl(p);
2542
2543     ASSERT(info->type == IND_STATIC);
2544
2545     if (STATIC_LINK(info,p) == NULL) {
2546       IF_DEBUG(gccafs, fprintf(stderr, "CAF gc'd at 0x%04x\n", (int)p));
2547       /* black hole it */
2548       SET_INFO(p,&BLACKHOLE_info);
2549       p = STATIC_LINK2(info,p);
2550       *pp = p;
2551     }
2552     else {
2553       pp = &STATIC_LINK2(info,p);
2554       p = *pp;
2555       i++;
2556     }
2557
2558   }
2559
2560   /*  fprintf(stderr, "%d CAFs live\n", i); */
2561 }
2562 #endif
2563
2564 /* -----------------------------------------------------------------------------
2565    Lazy black holing.
2566
2567    Whenever a thread returns to the scheduler after possibly doing
2568    some work, we have to run down the stack and black-hole all the
2569    closures referred to by update frames.
2570    -------------------------------------------------------------------------- */
2571
2572 static void
2573 threadLazyBlackHole(StgTSO *tso)
2574 {
2575   StgUpdateFrame *update_frame;
2576   StgBlockingQueue *bh;
2577   StgPtr stack_end;
2578
2579   stack_end = &tso->stack[tso->stack_size];
2580   update_frame = tso->su;
2581
2582   while (1) {
2583     switch (get_itbl(update_frame)->type) {
2584
2585     case CATCH_FRAME:
2586       update_frame = stgCast(StgCatchFrame*,update_frame)->link;
2587       break;
2588
2589     case UPDATE_FRAME:
2590       bh = (StgBlockingQueue *)update_frame->updatee;
2591
2592       /* if the thunk is already blackholed, it means we've also
2593        * already blackholed the rest of the thunks on this stack,
2594        * so we can stop early.
2595        *
2596        * The blackhole made for a CAF is a CAF_BLACKHOLE, so they
2597        * don't interfere with this optimisation.
2598        */
2599       if (bh->header.info == &BLACKHOLE_info) {
2600         return;
2601       }
2602
2603       if (bh->header.info != &BLACKHOLE_BQ_info &&
2604           bh->header.info != &CAF_BLACKHOLE_info) {
2605         SET_INFO(bh,&BLACKHOLE_info);
2606       }
2607
2608       update_frame = update_frame->link;
2609       break;
2610
2611     case SEQ_FRAME:
2612       update_frame = stgCast(StgSeqFrame*,update_frame)->link;
2613       break;
2614
2615     case STOP_FRAME:
2616       return;
2617     default:
2618       barf("threadPaused");
2619     }
2620   }
2621 }
2622
2623 /* -----------------------------------------------------------------------------
2624  * Stack squeezing
2625  *
2626  * Code largely pinched from old RTS, then hacked to bits.  We also do
2627  * lazy black holing here.
2628  *
2629  * -------------------------------------------------------------------------- */
2630
2631 static void
2632 threadSqueezeStack(StgTSO *tso)
2633 {
2634   lnat displacement = 0;
2635   StgUpdateFrame *frame;
2636   StgUpdateFrame *next_frame;                   /* Temporally next */
2637   StgUpdateFrame *prev_frame;                   /* Temporally previous */
2638   StgPtr bottom;
2639   rtsBool prev_was_update_frame;
2640   
2641   bottom = &(tso->stack[tso->stack_size]);
2642   frame  = tso->su;
2643
2644   /* There must be at least one frame, namely the STOP_FRAME.
2645    */
2646   ASSERT((P_)frame < bottom);
2647
2648   /* Walk down the stack, reversing the links between frames so that
2649    * we can walk back up as we squeeze from the bottom.  Note that
2650    * next_frame and prev_frame refer to next and previous as they were
2651    * added to the stack, rather than the way we see them in this
2652    * walk. (It makes the next loop less confusing.)  
2653    *
2654    * Stop if we find an update frame pointing to a black hole 
2655    * (see comment in threadLazyBlackHole()).
2656    */
2657   
2658   next_frame = NULL;
2659   while ((P_)frame < bottom - 1) {  /* bottom - 1 is the STOP_FRAME */
2660     prev_frame = frame->link;
2661     frame->link = next_frame;
2662     next_frame = frame;
2663     frame = prev_frame;
2664     if (get_itbl(frame)->type == UPDATE_FRAME
2665         && frame->updatee->header.info == &BLACKHOLE_info) {
2666         break;
2667     }
2668   }
2669
2670   /* Now, we're at the bottom.  Frame points to the lowest update
2671    * frame on the stack, and its link actually points to the frame
2672    * above. We have to walk back up the stack, squeezing out empty
2673    * update frames and turning the pointers back around on the way
2674    * back up.
2675    *
2676    * The bottom-most frame (the STOP_FRAME) has not been altered, and
2677    * we never want to eliminate it anyway.  Just walk one step up
2678    * before starting to squeeze. When you get to the topmost frame,
2679    * remember that there are still some words above it that might have
2680    * to be moved.  
2681    */
2682   
2683   prev_frame = frame;
2684   frame = next_frame;
2685
2686   prev_was_update_frame = (get_itbl(prev_frame)->type == UPDATE_FRAME);
2687
2688   /*
2689    * Loop through all of the frames (everything except the very
2690    * bottom).  Things are complicated by the fact that we have 
2691    * CATCH_FRAMEs and SEQ_FRAMEs interspersed with the update frames.
2692    * We can only squeeze when there are two consecutive UPDATE_FRAMEs.
2693    */
2694   while (frame != NULL) {
2695     StgPtr sp;
2696     StgPtr frame_bottom = (P_)frame + sizeofW(StgUpdateFrame);
2697     rtsBool is_update_frame;
2698     
2699     next_frame = frame->link;
2700     is_update_frame = (get_itbl(frame)->type == UPDATE_FRAME);
2701
2702     /* Check to see if 
2703      *   1. both the previous and current frame are update frames
2704      *   2. the current frame is empty
2705      */
2706     if (prev_was_update_frame && is_update_frame &&
2707         (P_)prev_frame == frame_bottom + displacement) {
2708       
2709       /* Now squeeze out the current frame */
2710       StgClosure *updatee_keep   = prev_frame->updatee;
2711       StgClosure *updatee_bypass = frame->updatee;
2712       
2713 #if 0 /* DEBUG */
2714       fprintf(stderr, "squeezing frame at %p\n", frame);
2715 #endif
2716
2717       /* Deal with blocking queues.  If both updatees have blocked
2718        * threads, then we should merge the queues into the update
2719        * frame that we're keeping.
2720        *
2721        * Alternatively, we could just wake them up: they'll just go
2722        * straight to sleep on the proper blackhole!  This is less code
2723        * and probably less bug prone, although it's probably much
2724        * slower --SDM
2725        */
2726 #if 0 /* do it properly... */
2727       if (GET_INFO(updatee_bypass) == BLACKHOLE_BQ_info) {
2728         /* Sigh.  It has one.  Don't lose those threads! */
2729           if (GET_INFO(updatee_keep) == BLACKHOLE_BQ_info) {
2730           /* Urgh.  Two queues.  Merge them. */
2731           P_ keep_tso = ((StgBlockingQueue *)updatee_keep)->blocking_queue;
2732           
2733           while (keep_tso->link != END_TSO_QUEUE) {
2734             keep_tso = keep_tso->link;
2735           }
2736           keep_tso->link = ((StgBlockingQueue *)updatee_bypass)->blocking_queue;
2737
2738         } else {
2739           /* For simplicity, just swap the BQ for the BH */
2740           P_ temp = updatee_keep;
2741           
2742           updatee_keep = updatee_bypass;
2743           updatee_bypass = temp;
2744           
2745           /* Record the swap in the kept frame (below) */
2746           prev_frame->updatee = updatee_keep;
2747         }
2748       }
2749 #endif
2750
2751       TICK_UPD_SQUEEZED();
2752       UPD_IND(updatee_bypass, updatee_keep); /* this wakes the threads up */
2753       
2754       sp = (P_)frame - 1;       /* sp = stuff to slide */
2755       displacement += sizeofW(StgUpdateFrame);
2756       
2757     } else {
2758       /* No squeeze for this frame */
2759       sp = frame_bottom - 1;    /* Keep the current frame */
2760       
2761       /* Do lazy black-holing.
2762        */
2763       if (is_update_frame) {
2764         StgBlockingQueue *bh = (StgBlockingQueue *)frame->updatee;
2765         if (bh->header.info != &BLACKHOLE_BQ_info &&
2766             bh->header.info != &CAF_BLACKHOLE_info) {
2767           SET_INFO(bh,&BLACKHOLE_info);
2768         }
2769       }
2770
2771       /* Fix the link in the current frame (should point to the frame below) */
2772       frame->link = prev_frame;
2773       prev_was_update_frame = is_update_frame;
2774     }
2775     
2776     /* Now slide all words from sp up to the next frame */
2777     
2778     if (displacement > 0) {
2779       P_ next_frame_bottom;
2780
2781       if (next_frame != NULL)
2782         next_frame_bottom = (P_)next_frame + sizeofW(StgUpdateFrame);
2783       else
2784         next_frame_bottom = tso->sp - 1;
2785       
2786 #if 0 /* DEBUG */
2787       fprintf(stderr, "sliding [%p, %p] by %ld\n", sp, next_frame_bottom,
2788               displacement);
2789 #endif
2790       
2791       while (sp >= next_frame_bottom) {
2792         sp[displacement] = *sp;
2793         sp -= 1;
2794       }
2795     }
2796     (P_)prev_frame = (P_)frame + displacement;
2797     frame = next_frame;
2798   }
2799
2800   tso->sp += displacement;
2801   tso->su = prev_frame;
2802 }
2803
2804 /* -----------------------------------------------------------------------------
2805  * Pausing a thread
2806  * 
2807  * We have to prepare for GC - this means doing lazy black holing
2808  * here.  We also take the opportunity to do stack squeezing if it's
2809  * turned on.
2810  * -------------------------------------------------------------------------- */
2811
2812 void
2813 threadPaused(StgTSO *tso)
2814 {
2815   if ( RtsFlags.GcFlags.squeezeUpdFrames == rtsTrue )
2816     threadSqueezeStack(tso);    /* does black holing too */
2817   else
2818     threadLazyBlackHole(tso);
2819 }