- // Select the right field from the constructor, and check
- // that the result isn't in to-space. It might be in
- // to-space if, for example, this constructor contains
- // pointers to younger-gen objects (and is on the mut-once
- // list).
- //
- {
- StgClosure *q;
- q = selectee->payload[field];
- if (is_to_space(UNTAG_CLOSURE(q))) {
- goto bale_out;
- } else {
- return q;
- }
- }
+ // Select the right field from the constructor
+ val = selectee->payload[field];
+
+#ifdef PROFILING
+ // For the purposes of LDV profiling, we have destroyed
+ // the original selector thunk, p.
+ SET_INFO(p, (StgInfoTable *)info_ptr);
+ LDV_RECORD_DEAD_FILL_SLOP_DYNAMIC((StgClosure *)p);
+ SET_INFO(p, &stg_BLACKHOLE_info);
+#endif
+
+ // the closure in val is now the "value" of the
+ // THUNK_SELECTOR in p. However, val may itself be a
+ // THUNK_SELECTOR, in which case we want to continue
+ // evaluating until we find the real value, and then
+ // update the whole chain to point to the value.
+ val_loop:
+ info_ptr = (StgWord)UNTAG_CLOSURE(val)->header.info;
+ if (!IS_FORWARDING_PTR(info_ptr))
+ {
+ info = INFO_PTR_TO_STRUCT(info_ptr);
+ switch (info->type) {
+ case IND:
+ case IND_PERM:
+ case IND_OLDGEN:
+ case IND_OLDGEN_PERM:
+ case IND_STATIC:
+ val = ((StgInd *)val)->indirectee;
+ goto val_loop;
+ case THUNK_SELECTOR:
+ ((StgClosure*)p)->payload[0] = (StgClosure *)prev_thunk_selector;
+ prev_thunk_selector = p;
+ p = (StgSelector*)val;
+ goto selector_chain;
+ default:
+ break;
+ }
+ }
+ ((StgClosure*)p)->payload[0] = (StgClosure *)prev_thunk_selector;
+ prev_thunk_selector = p;
+
+ *q = val;
+ if (evac) evacuate(q);
+ val = *q;
+ // evacuate() cannot recurse through
+ // eval_thunk_selector(), because we know val is not
+ // a THUNK_SELECTOR.
+ unchain_thunk_selectors(prev_thunk_selector, val);
+ return;
+ }