diff options
author | Ben Gamari <ben@smart-cactus.org> | 2022-11-30 15:43:05 -0500 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2023-03-08 15:02:30 -0500 |
commit | 1b06967176559d6b2b530dd16e127fa4479ae47f (patch) | |
tree | 3c844098df62dac63bc8461a834296e7e9624b46 /rts/sm/NonMovingMark.c | |
parent | e4c3249f00a406a406b6f1190ca8be628b643042 (diff) | |
download | haskell-1b06967176559d6b2b530dd16e127fa4479ae47f.tar.gz |
nonmoving: Add missing write barriers in selector optimisation
This fixes the selector optimisation, adding a few write barriers which
are necessary for soundness. See the inline comments for details.
Fixes #22930.
Diffstat (limited to 'rts/sm/NonMovingMark.c')
-rw-r--r-- | rts/sm/NonMovingMark.c | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/rts/sm/NonMovingMark.c b/rts/sm/NonMovingMark.c index 56cb73b5e4..1b1e1c7b79 100644 --- a/rts/sm/NonMovingMark.c +++ b/rts/sm/NonMovingMark.c @@ -648,6 +648,16 @@ void updateRemembSetPushThunkEager(Capability *cap, } break; } + case THUNK_SELECTOR: + { + StgSelector *sel = (StgSelector *) thunk; + if (check_in_nonmoving_heap(sel->selectee)) { + // Don't bother to push origin; it makes the barrier needlessly + // expensive with little benefit. + push_closure(queue, sel->selectee, NULL); + } + break; + } case AP: { StgAP *ap = (StgAP *) thunk; @@ -657,9 +667,11 @@ void updateRemembSetPushThunkEager(Capability *cap, trace_PAP_payload(queue, ap->fun, ap->payload, ap->n_args); break; } - case THUNK_SELECTOR: + // We may end up here if a thunk update races with another update. + // In this case there is nothing to do as the other thread will have + // already pushed the updated thunk's free variables to the update + // remembered set. case BLACKHOLE: - // TODO: This is right, right? break; // The selector optimization performed by the nonmoving mark may have // overwritten a thunk which we are updating with an indirection. @@ -1588,8 +1600,15 @@ mark_closure (MarkQueue *queue, const StgClosure *p0, StgClosure **origin) } case THUNK_SELECTOR: - nonmoving_eval_thunk_selector(queue, (StgSelector*)p, origin); + { + StgSelector *sel = (StgSelector *) p; + // We may be able to evaluate this selector which may render the + // selectee unreachable. However, we must mark the selectee regardless + // to satisfy the snapshot invariant. + PUSH_FIELD(sel, selectee); + nonmoving_eval_thunk_selector(queue, sel, origin); break; + } case AP_STACK: { StgAP_STACK *ap = (StgAP_STACK *)p; |