Fix (yet another) odd interaction between selector thunks and compacting GC
[ghc-hetmet.git] / rts / sm / Evac.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team 1998-2006
4  *
5  * Generational garbage collector: evacuation functions
6  *
7  * Documentation on the architecture of the Garbage Collector can be
8  * found in the online commentary:
9  * 
10  *   http://hackage.haskell.org/trac/ghc/wiki/Commentary/Rts/Storage/GC
11  *
12  * ---------------------------------------------------------------------------*/
13
14 #include "Rts.h"
15 #include "Storage.h"
16 #include "MBlock.h"
17 #include "Evac.h"
18 #include "GC.h"
19 #include "GCUtils.h"
20 #include "Compact.h"
21 #include "Prelude.h"
22 #include "LdvProfile.h"
23
24 /* Used to avoid long recursion due to selector thunks
25  */
26 lnat thunk_selector_depth = 0;
27 #define MAX_THUNK_SELECTOR_DEPTH 8
28
29 static StgClosure * eval_thunk_selector ( nat field, StgSelector * p );
30
31 STATIC_INLINE void 
32 upd_evacuee(StgClosure *p, StgClosure *dest)
33 {
34     // not true: (ToDo: perhaps it should be)
35     // ASSERT(Bdescr((P_)dest)->flags & BF_EVACUATED);
36     SET_INFO(p, &stg_EVACUATED_info);
37     ((StgEvacuated *)p)->evacuee = dest;
38 }
39
40
41 STATIC_INLINE StgClosure *
42 copy(StgClosure *src, nat size, step *stp)
43 {
44   StgPtr to, from;
45   nat i;
46 #ifdef PROFILING
47   // @LDV profiling
48   nat size_org = size;
49 #endif
50
51   TICK_GC_WORDS_COPIED(size);
52   /* Find out where we're going, using the handy "to" pointer in 
53    * the step of the source object.  If it turns out we need to
54    * evacuate to an older generation, adjust it here (see comment
55    * by evacuate()).
56    */
57   if (stp->gen_no < evac_gen) {
58       if (eager_promotion) {
59           stp = &generations[evac_gen].steps[0];
60       } else {
61           failed_to_evac = rtsTrue;
62       }
63   }
64
65   /* chain a new block onto the to-space for the destination step if
66    * necessary.
67    */
68   if (stp->hp + size >= stp->hpLim) {
69     gc_alloc_block(stp);
70   }
71
72   to = stp->hp;
73   from = (StgPtr)src;
74   stp->hp = to + size;
75   for (i = 0; i < size; i++) { // unroll for small i
76       to[i] = from[i];
77   }
78   upd_evacuee((StgClosure *)from,(StgClosure *)to);
79
80 #ifdef PROFILING
81   // We store the size of the just evacuated object in the LDV word so that
82   // the profiler can guess the position of the next object later.
83   SET_EVACUAEE_FOR_LDV(from, size_org);
84 #endif
85   return (StgClosure *)to;
86 }
87
88 // Same as copy() above, except the object will be allocated in memory
89 // that will not be scavenged.  Used for object that have no pointer
90 // fields.
91 STATIC_INLINE StgClosure *
92 copy_noscav(StgClosure *src, nat size, step *stp)
93 {
94   StgPtr to, from;
95   nat i;
96 #ifdef PROFILING
97   // @LDV profiling
98   nat size_org = size;
99 #endif
100
101   TICK_GC_WORDS_COPIED(size);
102   /* Find out where we're going, using the handy "to" pointer in 
103    * the step of the source object.  If it turns out we need to
104    * evacuate to an older generation, adjust it here (see comment
105    * by evacuate()).
106    */
107   if (stp->gen_no < evac_gen) {
108       if (eager_promotion) {
109           stp = &generations[evac_gen].steps[0];
110       } else {
111           failed_to_evac = rtsTrue;
112       }
113   }
114
115   /* chain a new block onto the to-space for the destination step if
116    * necessary.
117    */
118   if (stp->scavd_hp + size >= stp->scavd_hpLim) {
119     gc_alloc_scavd_block(stp);
120   }
121
122   to = stp->scavd_hp;
123   from = (StgPtr)src;
124   stp->scavd_hp = to + size;
125   for (i = 0; i < size; i++) { // unroll for small i
126       to[i] = from[i];
127   }
128   upd_evacuee((StgClosure *)from,(StgClosure *)to);
129
130 #ifdef PROFILING
131   // We store the size of the just evacuated object in the LDV word so that
132   // the profiler can guess the position of the next object later.
133   SET_EVACUAEE_FOR_LDV(from, size_org);
134 #endif
135   return (StgClosure *)to;
136 }
137
138 /* Special version of copy() for when we only want to copy the info
139  * pointer of an object, but reserve some padding after it.  This is
140  * used to optimise evacuation of BLACKHOLEs.
141  */
142
143
144 static StgClosure *
145 copyPart(StgClosure *src, nat size_to_reserve, nat size_to_copy, step *stp)
146 {
147   P_ dest, to, from;
148 #ifdef PROFILING
149   // @LDV profiling
150   nat size_to_copy_org = size_to_copy;
151 #endif
152
153   TICK_GC_WORDS_COPIED(size_to_copy);
154   if (stp->gen_no < evac_gen) {
155       if (eager_promotion) {
156           stp = &generations[evac_gen].steps[0];
157       } else {
158           failed_to_evac = rtsTrue;
159       }
160   }
161
162   if (stp->hp + size_to_reserve >= stp->hpLim) {
163     gc_alloc_block(stp);
164   }
165
166   for(to = stp->hp, from = (P_)src; size_to_copy>0; --size_to_copy) {
167     *to++ = *from++;
168   }
169   
170   dest = stp->hp;
171   stp->hp += size_to_reserve;
172   upd_evacuee(src,(StgClosure *)dest);
173 #ifdef PROFILING
174   // We store the size of the just evacuated object in the LDV word so that
175   // the profiler can guess the position of the next object later.
176   // size_to_copy_org is wrong because the closure already occupies size_to_reserve
177   // words.
178   SET_EVACUAEE_FOR_LDV(src, size_to_reserve);
179   // fill the slop
180   if (size_to_reserve - size_to_copy_org > 0)
181     LDV_FILL_SLOP(stp->hp - 1, (int)(size_to_reserve - size_to_copy_org)); 
182 #endif
183   return (StgClosure *)dest;
184 }
185
186
187 /* -----------------------------------------------------------------------------
188    Evacuate a large object
189
190    This just consists of removing the object from the (doubly-linked)
191    step->large_objects list, and linking it on to the (singly-linked)
192    step->new_large_objects list, from where it will be scavenged later.
193
194    Convention: bd->flags has BF_EVACUATED set for a large object
195    that has been evacuated, or unset otherwise.
196    -------------------------------------------------------------------------- */
197
198
199 STATIC_INLINE void
200 evacuate_large(StgPtr p)
201 {
202   bdescr *bd = Bdescr(p);
203   step *stp;
204
205   // object must be at the beginning of the block (or be a ByteArray)
206   ASSERT(get_itbl((StgClosure *)p)->type == ARR_WORDS ||
207          (((W_)p & BLOCK_MASK) == 0));
208
209   // already evacuated? 
210   if (bd->flags & BF_EVACUATED) { 
211     /* Don't forget to set the failed_to_evac flag if we didn't get
212      * the desired destination (see comments in evacuate()).
213      */
214     if (bd->gen_no < evac_gen) {
215       failed_to_evac = rtsTrue;
216       TICK_GC_FAILED_PROMOTION();
217     }
218     return;
219   }
220
221   stp = bd->step;
222   // remove from large_object list 
223   if (bd->u.back) {
224     bd->u.back->link = bd->link;
225   } else { // first object in the list 
226     stp->large_objects = bd->link;
227   }
228   if (bd->link) {
229     bd->link->u.back = bd->u.back;
230   }
231   
232   /* link it on to the evacuated large object list of the destination step
233    */
234   stp = bd->step->to;
235   if (stp->gen_no < evac_gen) {
236       if (eager_promotion) {
237           stp = &generations[evac_gen].steps[0];
238       } else {
239           failed_to_evac = rtsTrue;
240       }
241   }
242
243   bd->step = stp;
244   bd->gen_no = stp->gen_no;
245   bd->link = stp->new_large_objects;
246   stp->new_large_objects = bd;
247   bd->flags |= BF_EVACUATED;
248 }
249
250 /* -----------------------------------------------------------------------------
251    Evacuate
252
253    This is called (eventually) for every live object in the system.
254
255    The caller to evacuate specifies a desired generation in the
256    evac_gen global variable.  The following conditions apply to
257    evacuating an object which resides in generation M when we're
258    collecting up to generation N
259
260    if  M >= evac_gen 
261            if  M > N     do nothing
262            else          evac to step->to
263
264    if  M < evac_gen      evac to evac_gen, step 0
265
266    if the object is already evacuated, then we check which generation
267    it now resides in.
268
269    if  M >= evac_gen     do nothing
270    if  M <  evac_gen     set failed_to_evac flag to indicate that we
271                          didn't manage to evacuate this object into evac_gen.
272
273
274    OPTIMISATION NOTES:
275
276    evacuate() is the single most important function performance-wise
277    in the GC.  Various things have been tried to speed it up, but as
278    far as I can tell the code generated by gcc 3.2 with -O2 is about
279    as good as it's going to get.  We pass the argument to evacuate()
280    in a register using the 'regparm' attribute (see the prototype for
281    evacuate() near the top of this file).
282
283    Changing evacuate() to take an (StgClosure **) rather than
284    returning the new pointer seems attractive, because we can avoid
285    writing back the pointer when it hasn't changed (eg. for a static
286    object, or an object in a generation > N).  However, I tried it and
287    it doesn't help.  One reason is that the (StgClosure **) pointer
288    gets spilled to the stack inside evacuate(), resulting in far more
289    extra reads/writes than we save.
290    -------------------------------------------------------------------------- */
291
292 REGPARM1 StgClosure *
293 evacuate(StgClosure *q)
294 {
295   bdescr *bd = NULL;
296   step *stp;
297   const StgInfoTable *info;
298
299 loop:
300   ASSERT(LOOKS_LIKE_CLOSURE_PTR(q));
301
302   if (!HEAP_ALLOCED(q)) {
303
304       if (!major_gc) return q;
305
306       info = get_itbl(q);
307       switch (info->type) {
308
309       case THUNK_STATIC:
310           if (info->srt_bitmap != 0 && 
311               *THUNK_STATIC_LINK((StgClosure *)q) == NULL) {
312               *THUNK_STATIC_LINK((StgClosure *)q) = static_objects;
313               static_objects = (StgClosure *)q;
314           }
315           return q;
316           
317       case FUN_STATIC:
318           if (info->srt_bitmap != 0 && 
319               *FUN_STATIC_LINK((StgClosure *)q) == NULL) {
320               *FUN_STATIC_LINK((StgClosure *)q) = static_objects;
321               static_objects = (StgClosure *)q;
322           }
323           return q;
324           
325       case IND_STATIC:
326           /* If q->saved_info != NULL, then it's a revertible CAF - it'll be
327            * on the CAF list, so don't do anything with it here (we'll
328            * scavenge it later).
329            */
330           if (((StgIndStatic *)q)->saved_info == NULL
331               && *IND_STATIC_LINK((StgClosure *)q) == NULL) {
332               *IND_STATIC_LINK((StgClosure *)q) = static_objects;
333               static_objects = (StgClosure *)q;
334           }
335           return q;
336           
337       case CONSTR_STATIC:
338           if (*STATIC_LINK(info,(StgClosure *)q) == NULL) {
339               *STATIC_LINK(info,(StgClosure *)q) = static_objects;
340               static_objects = (StgClosure *)q;
341           }
342           return q;
343           
344       case CONSTR_NOCAF_STATIC:
345           /* no need to put these on the static linked list, they don't need
346            * to be scavenged.
347            */
348           return q;
349           
350       default:
351           barf("evacuate(static): strange closure type %d", (int)(info->type));
352       }
353   }
354
355   bd = Bdescr((P_)q);
356
357   if (bd->gen_no > N) {
358       /* Can't evacuate this object, because it's in a generation
359        * older than the ones we're collecting.  Let's hope that it's
360        * in evac_gen or older, or we will have to arrange to track
361        * this pointer using the mutable list.
362        */
363       if (bd->gen_no < evac_gen) {
364           // nope 
365           failed_to_evac = rtsTrue;
366           TICK_GC_FAILED_PROMOTION();
367       }
368       return q;
369   }
370
371   if ((bd->flags & (BF_LARGE | BF_COMPACTED | BF_EVACUATED)) != 0) {
372
373       /* pointer into to-space: just return it.  This normally
374        * shouldn't happen, but alllowing it makes certain things
375        * slightly easier (eg. the mutable list can contain the same
376        * object twice, for example).
377        */
378       if (bd->flags & BF_EVACUATED) {
379           if (bd->gen_no < evac_gen) {
380               failed_to_evac = rtsTrue;
381               TICK_GC_FAILED_PROMOTION();
382           }
383           return q;
384       }
385
386       /* evacuate large objects by re-linking them onto a different list.
387        */
388       if (bd->flags & BF_LARGE) {
389           info = get_itbl(q);
390           if (info->type == TSO && 
391               ((StgTSO *)q)->what_next == ThreadRelocated) {
392               q = (StgClosure *)((StgTSO *)q)->link;
393               goto loop;
394           }
395           evacuate_large((P_)q);
396           return q;
397       }
398       
399       /* If the object is in a step that we're compacting, then we
400        * need to use an alternative evacuate procedure.
401        */
402       if (bd->flags & BF_COMPACTED) {
403           if (!is_marked((P_)q,bd)) {
404               mark((P_)q,bd);
405               if (mark_stack_full()) {
406                   mark_stack_overflowed = rtsTrue;
407                   reset_mark_stack();
408               }
409               push_mark_stack((P_)q);
410           }
411           return q;
412       }
413   }
414       
415   stp = bd->step->to;
416
417   info = get_itbl(q);
418   
419   switch (info->type) {
420
421   case MUT_VAR_CLEAN:
422   case MUT_VAR_DIRTY:
423   case MVAR:
424       return copy(q,sizeW_fromITBL(info),stp);
425
426   case CONSTR_0_1:
427   { 
428       StgWord w = (StgWord)q->payload[0];
429       if (q->header.info == Czh_con_info &&
430           // unsigned, so always true:  (StgChar)w >= MIN_CHARLIKE &&  
431           (StgChar)w <= MAX_CHARLIKE) {
432           return (StgClosure *)CHARLIKE_CLOSURE((StgChar)w);
433       }
434       if (q->header.info == Izh_con_info &&
435           (StgInt)w >= MIN_INTLIKE && (StgInt)w <= MAX_INTLIKE) {
436           return (StgClosure *)INTLIKE_CLOSURE((StgInt)w);
437       }
438       // else
439       return copy_noscav(q,sizeofW(StgHeader)+1,stp);
440   }
441
442   case FUN_0_1:
443   case FUN_1_0:
444   case CONSTR_1_0:
445     return copy(q,sizeofW(StgHeader)+1,stp);
446
447   case THUNK_1_0:
448   case THUNK_0_1:
449     return copy(q,sizeofW(StgThunk)+1,stp);
450
451   case THUNK_1_1:
452   case THUNK_2_0:
453   case THUNK_0_2:
454 #ifdef NO_PROMOTE_THUNKS
455     if (bd->gen_no == 0 && 
456         bd->step->no != 0 &&
457         bd->step->no == generations[bd->gen_no].n_steps-1) {
458       stp = bd->step;
459     }
460 #endif
461     return copy(q,sizeofW(StgThunk)+2,stp);
462
463   case FUN_1_1:
464   case FUN_2_0:
465   case CONSTR_1_1:
466   case CONSTR_2_0:
467   case FUN_0_2:
468     return copy(q,sizeofW(StgHeader)+2,stp);
469
470   case CONSTR_0_2:
471     return copy_noscav(q,sizeofW(StgHeader)+2,stp);
472
473   case THUNK:
474     return copy(q,thunk_sizeW_fromITBL(info),stp);
475
476   case FUN:
477   case CONSTR:
478   case IND_PERM:
479   case IND_OLDGEN_PERM:
480   case WEAK:
481   case STABLE_NAME:
482     return copy(q,sizeW_fromITBL(info),stp);
483
484   case BCO:
485       return copy(q,bco_sizeW((StgBCO *)q),stp);
486
487   case CAF_BLACKHOLE:
488   case SE_CAF_BLACKHOLE:
489   case SE_BLACKHOLE:
490   case BLACKHOLE:
491     return copyPart(q,BLACKHOLE_sizeW(),sizeofW(StgHeader),stp);
492
493   case THUNK_SELECTOR:
494     {
495         StgClosure *p;
496         const StgInfoTable *info_ptr;
497
498         if (thunk_selector_depth > MAX_THUNK_SELECTOR_DEPTH) {
499             return copy(q,THUNK_SELECTOR_sizeW(),stp);
500         }
501
502         // stashed away for LDV profiling, see below
503         info_ptr = q->header.info;
504
505         p = eval_thunk_selector(info->layout.selector_offset,
506                                 (StgSelector *)q);
507
508         if (p == NULL) {
509             return copy(q,THUNK_SELECTOR_sizeW(),stp);
510         } else {
511             StgClosure *val;
512             // q is still BLACKHOLE'd.
513             thunk_selector_depth++;
514             val = evacuate(p);
515             thunk_selector_depth--;
516
517 #ifdef PROFILING
518             // For the purposes of LDV profiling, we have destroyed
519             // the original selector thunk.
520             SET_INFO(q, info_ptr);
521             LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(q);
522 #endif
523
524             // Update the THUNK_SELECTOR with an indirection to the
525             // EVACUATED closure now at p.  Why do this rather than
526             // upd_evacuee(q,p)?  Because we have an invariant that an
527             // EVACUATED closure always points to an object in the
528             // same or an older generation (required by the short-cut
529             // test in the EVACUATED case, below).
530             SET_INFO(q, &stg_IND_info);
531             ((StgInd *)q)->indirectee = p;
532
533             // For the purposes of LDV profiling, we have created an
534             // indirection.
535             LDV_RECORD_CREATE(q);
536
537             return val;
538         }
539     }
540
541   case IND:
542   case IND_OLDGEN:
543     // follow chains of indirections, don't evacuate them 
544     q = ((StgInd*)q)->indirectee;
545     goto loop;
546
547   case RET_BCO:
548   case RET_SMALL:
549   case RET_VEC_SMALL:
550   case RET_BIG:
551   case RET_VEC_BIG:
552   case RET_DYN:
553   case UPDATE_FRAME:
554   case STOP_FRAME:
555   case CATCH_FRAME:
556   case CATCH_STM_FRAME:
557   case CATCH_RETRY_FRAME:
558   case ATOMICALLY_FRAME:
559     // shouldn't see these 
560     barf("evacuate: stack frame at %p\n", q);
561
562   case PAP:
563       return copy(q,pap_sizeW((StgPAP*)q),stp);
564
565   case AP:
566       return copy(q,ap_sizeW((StgAP*)q),stp);
567
568   case AP_STACK:
569       return copy(q,ap_stack_sizeW((StgAP_STACK*)q),stp);
570
571   case EVACUATED:
572     /* Already evacuated, just return the forwarding address.
573      * HOWEVER: if the requested destination generation (evac_gen) is
574      * older than the actual generation (because the object was
575      * already evacuated to a younger generation) then we have to
576      * set the failed_to_evac flag to indicate that we couldn't 
577      * manage to promote the object to the desired generation.
578      */
579     /* 
580      * Optimisation: the check is fairly expensive, but we can often
581      * shortcut it if either the required generation is 0, or the
582      * current object (the EVACUATED) is in a high enough generation.
583      * We know that an EVACUATED always points to an object in the
584      * same or an older generation.  stp is the lowest step that the
585      * current object would be evacuated to, so we only do the full
586      * check if stp is too low.
587      */
588     if (evac_gen > 0 && stp->gen_no < evac_gen) {  // optimisation 
589       StgClosure *p = ((StgEvacuated*)q)->evacuee;
590       if (HEAP_ALLOCED(p) && Bdescr((P_)p)->gen_no < evac_gen) {
591         failed_to_evac = rtsTrue;
592         TICK_GC_FAILED_PROMOTION();
593       }
594     }
595     return ((StgEvacuated*)q)->evacuee;
596
597   case ARR_WORDS:
598       // just copy the block 
599       return copy_noscav(q,arr_words_sizeW((StgArrWords *)q),stp);
600
601   case MUT_ARR_PTRS_CLEAN:
602   case MUT_ARR_PTRS_DIRTY:
603   case MUT_ARR_PTRS_FROZEN:
604   case MUT_ARR_PTRS_FROZEN0:
605       // just copy the block 
606       return copy(q,mut_arr_ptrs_sizeW((StgMutArrPtrs *)q),stp);
607
608   case TSO:
609     {
610       StgTSO *tso = (StgTSO *)q;
611
612       /* Deal with redirected TSOs (a TSO that's had its stack enlarged).
613        */
614       if (tso->what_next == ThreadRelocated) {
615         q = (StgClosure *)tso->link;
616         goto loop;
617       }
618
619       /* To evacuate a small TSO, we need to relocate the update frame
620        * list it contains.  
621        */
622       {
623           StgTSO *new_tso;
624           StgPtr p, q;
625
626           new_tso = (StgTSO *)copyPart((StgClosure *)tso,
627                                        tso_sizeW(tso),
628                                        sizeofW(StgTSO), stp);
629           move_TSO(tso, new_tso);
630           for (p = tso->sp, q = new_tso->sp;
631                p < tso->stack+tso->stack_size;) {
632               *q++ = *p++;
633           }
634           
635           return (StgClosure *)new_tso;
636       }
637     }
638
639   case TREC_HEADER: 
640     return copy(q,sizeofW(StgTRecHeader),stp);
641
642   case TVAR_WATCH_QUEUE:
643     return copy(q,sizeofW(StgTVarWatchQueue),stp);
644
645   case TVAR:
646     return copy(q,sizeofW(StgTVar),stp);
647     
648   case TREC_CHUNK:
649     return copy(q,sizeofW(StgTRecChunk),stp);
650
651   case ATOMIC_INVARIANT:
652     return copy(q,sizeofW(StgAtomicInvariant),stp);
653
654   case INVARIANT_CHECK_QUEUE:
655     return copy(q,sizeofW(StgInvariantCheckQueue),stp);
656
657   default:
658     barf("evacuate: strange closure type %d", (int)(info->type));
659   }
660
661   barf("evacuate");
662 }
663
664 /* -----------------------------------------------------------------------------
665    Evaluate a THUNK_SELECTOR if possible.
666
667    returns: NULL if we couldn't evaluate this THUNK_SELECTOR, or
668    a closure pointer if we evaluated it and this is the result.  Note
669    that "evaluating" the THUNK_SELECTOR doesn't necessarily mean
670    reducing it to HNF, just that we have eliminated the selection.
671    The result might be another thunk, or even another THUNK_SELECTOR.
672
673    If the return value is non-NULL, the original selector thunk has
674    been BLACKHOLE'd, and should be updated with an indirection or a
675    forwarding pointer.  If the return value is NULL, then the selector
676    thunk is unchanged.
677
678    ***
679    ToDo: the treatment of THUNK_SELECTORS could be improved in the
680    following way (from a suggestion by Ian Lynagh):
681
682    We can have a chain like this:
683
684       sel_0 --> (a,b)
685                  |
686                  |-----> sel_0 --> (a,b)
687                                     |
688                                     |-----> sel_0 --> ...
689
690    and the depth limit means we don't go all the way to the end of the
691    chain, which results in a space leak.  This affects the recursive
692    call to evacuate() in the THUNK_SELECTOR case in evacuate(): *not*
693    the recursive call to eval_thunk_selector() in
694    eval_thunk_selector().
695
696    We could eliminate the depth bound in this case, in the following
697    way:
698
699       - traverse the chain once to discover the *value* of the 
700         THUNK_SELECTOR.  Mark all THUNK_SELECTORS that we
701         visit on the way as having been visited already (somehow).
702
703       - in a second pass, traverse the chain again updating all
704         THUNK_SEELCTORS that we find on the way with indirections to
705         the value.
706
707       - if we encounter a "marked" THUNK_SELECTOR in a normal 
708         evacuate(), we konw it can't be updated so just evac it.
709
710    Program that illustrates the problem:
711
712         foo [] = ([], [])
713         foo (x:xs) = let (ys, zs) = foo xs
714                      in if x >= 0 then (x:ys, zs) else (ys, x:zs)
715
716         main = bar [1..(100000000::Int)]
717         bar xs = (\(ys, zs) -> print ys >> print zs) (foo xs)
718
719    -------------------------------------------------------------------------- */
720
721 static inline rtsBool
722 is_to_space ( StgClosure *p )
723 {
724     bdescr *bd;
725
726     bd = Bdescr((StgPtr)p);
727     if (HEAP_ALLOCED(p) &&
728         ((bd->flags & BF_EVACUATED) 
729          || ((bd->flags & BF_COMPACTED) &&
730              is_marked((P_)p,bd)))) {
731         return rtsTrue;
732     } else {
733         return rtsFalse;
734     }
735 }    
736
737 static StgClosure *
738 eval_thunk_selector( nat field, StgSelector * p )
739 {
740     StgInfoTable *info;
741     const StgInfoTable *info_ptr;
742     StgClosure *selectee;
743     
744     selectee = p->selectee;
745
746     // Save the real info pointer (NOTE: not the same as get_itbl()).
747     info_ptr = p->header.info;
748
749     // If the THUNK_SELECTOR is in a generation that we are not
750     // collecting, then bail out early.  We won't be able to save any
751     // space in any case, and updating with an indirection is trickier
752     // in an old gen.
753     if (Bdescr((StgPtr)p)->gen_no > N) {
754         return NULL;
755     }
756
757     // BLACKHOLE the selector thunk, since it is now under evaluation.
758     // This is important to stop us going into an infinite loop if
759     // this selector thunk eventually refers to itself.
760     SET_INFO(p,&stg_BLACKHOLE_info);
761
762 selector_loop:
763
764     // We don't want to end up in to-space, because this causes
765     // problems when the GC later tries to evacuate the result of
766     // eval_thunk_selector().  There are various ways this could
767     // happen:
768     //
769     // 1. following an IND_STATIC
770     //
771     // 2. when the old generation is compacted, the mark phase updates
772     //    from-space pointers to be to-space pointers, and we can't
773     //    reliably tell which we're following (eg. from an IND_STATIC).
774     // 
775     // 3. compacting GC again: if we're looking at a constructor in
776     //    the compacted generation, it might point directly to objects
777     //    in to-space.  We must bale out here, otherwise doing the selection
778     //    will result in a to-space pointer being returned.
779     //
780     //  (1) is dealt with using a BF_EVACUATED test on the
781     //  selectee. (2) and (3): we can tell if we're looking at an
782     //  object in the compacted generation that might point to
783     //  to-space objects by testing that (a) it is BF_COMPACTED, (b)
784     //  the compacted generation is being collected, and (c) the
785     //  object is marked.  Only a marked object may have pointers that
786     //  point to to-space objects, because that happens when
787     //  scavenging.
788     //
789     //  The to-space test is now embodied in the in_to_space() inline
790     //  function, as it is re-used below.
791     //
792     if (is_to_space(selectee)) {
793         goto bale_out;
794     }
795
796     info = get_itbl(selectee);
797     switch (info->type) {
798       case CONSTR:
799       case CONSTR_1_0:
800       case CONSTR_0_1:
801       case CONSTR_2_0:
802       case CONSTR_1_1:
803       case CONSTR_0_2:
804       case CONSTR_STATIC:
805       case CONSTR_NOCAF_STATIC:
806           // check that the size is in range 
807           ASSERT(field <  (StgWord32)(info->layout.payload.ptrs + 
808                                       info->layout.payload.nptrs));
809           
810           // Select the right field from the constructor, and check
811           // that the result isn't in to-space.  It might be in
812           // to-space if, for example, this constructor contains
813           // pointers to younger-gen objects (and is on the mut-once
814           // list).
815           //
816           { 
817               StgClosure *q;
818               q = selectee->payload[field];
819               if (is_to_space(q)) {
820                   goto bale_out;
821               } else {
822                   return q;
823               }
824           }
825
826       case IND:
827       case IND_PERM:
828       case IND_OLDGEN:
829       case IND_OLDGEN_PERM:
830       case IND_STATIC:
831           selectee = ((StgInd *)selectee)->indirectee;
832           goto selector_loop;
833
834       case EVACUATED:
835           // We don't follow pointers into to-space; the constructor
836           // has already been evacuated, so we won't save any space
837           // leaks by evaluating this selector thunk anyhow.
838           break;
839
840       case THUNK_SELECTOR:
841       {
842           StgClosure *val;
843
844           // check that we don't recurse too much, re-using the
845           // depth bound also used in evacuate().
846           if (thunk_selector_depth >= MAX_THUNK_SELECTOR_DEPTH) {
847               break;
848           }
849
850           // we don't update THUNK_SELECTORS in the compacted
851           // generation, because compaction does not remove the INDs
852           // that result, this causes confusion later.
853           if (Bdescr((P_)selectee)->flags && BF_COMPACTED) {
854               break;
855           }
856
857           thunk_selector_depth++;
858
859           val = eval_thunk_selector(info->layout.selector_offset, 
860                                     (StgSelector *)selectee);
861
862           thunk_selector_depth--;
863
864           if (val == NULL) { 
865               break;
866           } else {
867               // We evaluated this selector thunk, so update it with
868               // an indirection.  NOTE: we don't use UPD_IND here,
869               // because we are guaranteed that p is in a generation
870               // that we are collecting, and we never want to put the
871               // indirection on a mutable list.
872 #ifdef PROFILING
873               // For the purposes of LDV profiling, we have destroyed
874               // the original selector thunk.
875               SET_INFO(p, info_ptr);
876               LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC(selectee);
877 #endif
878               ((StgInd *)selectee)->indirectee = val;
879               SET_INFO(selectee,&stg_IND_info);
880
881               // For the purposes of LDV profiling, we have created an
882               // indirection.
883               LDV_RECORD_CREATE(selectee);
884
885               selectee = val;
886               goto selector_loop;
887           }
888       }
889
890       case AP:
891       case AP_STACK:
892       case THUNK:
893       case THUNK_1_0:
894       case THUNK_0_1:
895       case THUNK_2_0:
896       case THUNK_1_1:
897       case THUNK_0_2:
898       case THUNK_STATIC:
899       case CAF_BLACKHOLE:
900       case SE_CAF_BLACKHOLE:
901       case SE_BLACKHOLE:
902       case BLACKHOLE:
903           // not evaluated yet 
904           break;
905     
906       default:
907         barf("eval_thunk_selector: strange selectee %d",
908              (int)(info->type));
909     }
910
911 bale_out:
912     // We didn't manage to evaluate this thunk; restore the old info pointer
913     SET_INFO(p, info_ptr);
914     return NULL;
915 }
916
917 /* -----------------------------------------------------------------------------
918    move_TSO is called to update the TSO structure after it has been
919    moved from one place to another.
920    -------------------------------------------------------------------------- */
921
922 void
923 move_TSO (StgTSO *src, StgTSO *dest)
924 {
925     ptrdiff_t diff;
926
927     // relocate the stack pointer... 
928     diff = (StgPtr)dest - (StgPtr)src; // In *words* 
929     dest->sp = (StgPtr)dest->sp + diff;
930 }
931