- if (HEAP_ALLOCED(p) &&
- ((bd->gen_no > N)
- || (bd->flags & BF_EVACUATED)
- || ((bd->flags & BF_COMPACTED) &&
- is_marked((P_)p,bd)))) {
- unchain_thunk_selectors(prev_thunk_selector, (StgClosure *)p);
- return (StgClosure *)p;
+ if (HEAP_ALLOCED(p)) {
+ // If the THUNK_SELECTOR is in to-space or in a generation that we
+ // are not collecting, then bale out early. We won't be able to
+ // save any space in any case, and updating with an indirection is
+ // trickier in a non-collected gen: we would have to update the
+ // mutable list.
+ if ((bd->gen_no > N) || (bd->flags & BF_EVACUATED)) {
+ unchain_thunk_selectors(prev_thunk_selector, (StgClosure *)p);
+ return (StgClosure *)p;
+ }
+ // we don't update THUNK_SELECTORS in the compacted
+ // generation, because compaction does not remove the INDs
+ // that result, this causes confusion later
+ // (scavenge_mark_stack doesn't deal with IND). BEWARE! This
+ // bit is very tricky to get right. If you make changes
+ // around here, test by compiling stage 3 with +RTS -c -RTS.
+ if (bd->flags & BF_COMPACTED) {
+ // must call evacuate() to mark this closure if evac==rtsTrue
+ if (evac) p = (StgSelector *)evacuate((StgClosure *)p);
+ unchain_thunk_selectors(prev_thunk_selector, (StgClosure *)p);
+ return (StgClosure *)p;
+ }