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