[Git][ghc/ghc][wip/marge_bot_batch_merge_job] 4 commits: Bump bytestring submodule to 0.11.5.1

Marge Bot (@marge-bot) gitlab at gitlab.haskell.org
Sat Aug 5 02:25:38 UTC 2023



Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC


Commits:
43c2911f by Matthew Craven at 2023-08-04T22:25:24-04:00
Bump bytestring submodule to 0.11.5.1

- - - - -
1c71b502 by Ben Gamari at 2023-08-04T22:25:25-04:00
Initial commit of Note [Thunks, blackholes, and indirections]

This Note attempts to summarize the treatment of thunks, thunk update,
and indirections.

This fell out of work on #23185.

- - - - -
d5e564eb by sheaf at 2023-08-04T22:25:30-04:00
Remove zonk in tcVTA

This removes the zonk in GHC.Tc.Gen.App.tc_inst_forall_arg and its
accompanying Note [Visible type application zonk]. Indeed, this zonk
is no longer necessary, as we no longer maintain the invariant that
types are well-kinded without zonking; only that typeKind does not
crash; see Note [The Purely Kinded Type Invariant (PKTI)].

This commit removes this zonking step (as well as a secondary zonk),
and replaces the aforementioned Note with the explanatory
Note [Type application substitution], which justifies why the
substitution performed in tc_inst_forall_arg remains valid without
this zonking step.

Fixes #23661

- - - - -
51596290 by Ben Gamari at 2023-08-04T22:25:31-04:00
Bump nofib submodule

Ensuring that nofib can be build using the same range of bootstrap
compilers as GHC itself.

- - - - -


9 changed files:

- .gitlab-ci.yml
- compiler/GHC/Tc/Gen/App.hs
- compiler/GHC/Utils/Binary.hs
- hadrian/src/Settings/Warnings.hs
- libraries/bytestring
- nofib
- rts/Updates.h
- testsuite/tests/ghci/scripts/T9881.stdout
- testsuite/tests/ghci/scripts/ghci025.stdout


Changes:

=====================================
.gitlab-ci.yml
=====================================
@@ -401,7 +401,7 @@ hadrian-multi:
     # workaround for docker permissions
     - sudo chown ghc:ghc -R .
   variables:
-    GHC_FLAGS: -Werror
+    GHC_FLAGS: "-Werror -Wwarn=deprecations"
     CONFIGURE_ARGS: --enable-bootstrap-with-devel-snapshot
   tags:
     - x86_64-linux


=====================================
compiler/GHC/Tc/Gen/App.hs
=====================================
@@ -840,19 +840,14 @@ tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_ty
              -- Example: user wrote e.g. (#,#) @(F Bool) for a type family F.
              -- Emit [W] F Bool ~ kappa[conc] and pretend the user wrote (#,#) @kappa.
              do { mco <- unifyConcrete (occNameFS $ getOccName $ tv_nm) conc ty_arg0
-                ; let ty_arg = case mco of { MRefl -> ty_arg0; MCo co -> coercionRKind co }
-                ; liftZonkM $ zonkTcType ty_arg }
-                -- (zonk here to match the zonk below, because unifyConcrete can
-                -- perform unification)
-
-       ; inner_ty <- liftZonkM $ zonkTcType inner_ty
-             -- See Note [Visible type application zonk]
+                ; return $ case mco of { MRefl -> ty_arg0; MCo co -> coercionRKind co } }
 
        ; let fun_ty    = mkForAllTy tvb inner_ty
              in_scope  = mkInScopeSet (tyCoVarsOfTypes [fun_ty, ty_arg])
              insted_ty = substTyWithInScope in_scope [tv] [ty_arg] inner_ty
-                         -- NB: tv and ty_arg have the same kind, so this
-                         --     substitution is kind-respecting
+               -- This substitution is well-kinded even when inner_ty
+               -- is not fully zonked, because ty_arg is fully zonked.
+               -- See Note [Type application substitution].
 
        ; traceTc "tc_inst_forall_arg (VTA/VDQ)" (
                   vcat [ text "fun_ty" <+> ppr fun_ty
@@ -1141,35 +1136,39 @@ Downside: the typechecked term has lost its visible type arguments; we
 don't even kind-check them.  But let's jump that bridge if we come to
 it.  Meanwhile, let's not crash!
 
-
-Note [Visible type application zonk]
+Note [Type application substitution]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-* Substitutions should be kind-preserving, so we need kind(tv) = kind(ty_arg).
-
-* tcHsTypeApp only guarantees that
-    - ty_arg is zonked
-    - kind(zonk(tv)) = kind(ty_arg)
-  (checkExpectedKind zonks as it goes).
-
-So we must zonk inner_ty as well, to guarantee consistency between zonk(tv)
-and inner_ty. Otherwise we can build an ill-kinded type. An example was #14158,
-where we had:
-   id :: forall k. forall (cat :: k -> k -> *). forall (a :: k). cat a a
-and we had the visible type application
-  id @(->)
-
-* We instantiated k := kappa, yielding
-    forall (cat :: kappa -> kappa -> *). forall (a :: kappa). cat a a
-* Then we called tcHsTypeApp (->) with expected kind (kappa -> kappa -> *).
-* That instantiated (->) as ((->) q1 q1), and unified kappa := q1,
-  Here q1 :: RuntimeRep
-* Now we substitute
-     cat  :->  (->) q1 q1 :: TYPE q1 -> TYPE q1 -> *
-  but we must first zonk the inner_ty to get
-      forall (a :: TYPE q1). cat a a
-  so that the result of substitution is well-kinded
-  Failing to do so led to #14158.
-
+In `tc_inst_forall_arg`, suppose we are checking a visible type
+application `f @hs_ty`, where `f :: forall (a :: k). body`.  We will:
+  * Compute `ty <- tcHsTypeApp hs_ty k`
+  * Then substitute `a :-> ty` in `body`.
+Now, you might worry that `a` might not have the same kind as `ty`, so that the
+substitution isn't kind-preserving.  How can that happen?  The kinds will
+definitely be the same after zonking, and `ty` will be zonked (as this is
+a postcondition of `tcHsTypeApp`). But the function type `forall a. body`
+might not be fully zonked (hence the worry).
+
+But it's OK!  During type checking, we don't require types to be well-kinded (without
+zonking); we only require them to satsisfy the Purely Kinded Type Invariant (PKTI).
+See Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType.
+
+In the case of a type application:
+  * `forall a. body` satisfies the PKTI
+  * `ty` is zonked
+  * If we substitute a fully-zonked thing into an un-zonked Type that
+    satisfies the PKTI, the result still satisfies the PKTI.
+
+This last statement isn't obvious, but read
+Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType.
+The tricky case is when `body` contains an application of the form `a b1 ... bn`,
+and we substitute `a :-> ty` where `ty` has fewer arrows in its kind than `a` does.
+That can't happen: the call `tcHsTypeApp hs_ty k` would have rejected the
+type application as ill-kinded.
+
+Historical remark: we used to require a stronger invariant than the PKTI,
+namely that all types are well-kinded prior to zonking. In that context, we did
+need to zonk `body` before performing the substitution above. See test case
+#14158, as well as the discussion in #23661.
 -}
 
 {- *********************************************************************


=====================================
compiler/GHC/Utils/Binary.hs
=====================================
@@ -1240,13 +1240,13 @@ putBS :: BinHandle -> ByteString -> IO ()
 putBS bh bs =
   BS.unsafeUseAsCStringLen bs $ \(ptr, l) -> do
     put_ bh l
-    putPrim bh l (\op -> BS.memcpy op (castPtr ptr) l)
+    putPrim bh l (\op -> copyBytes op (castPtr ptr) l)
 
 getBS :: BinHandle -> IO ByteString
 getBS bh = do
   l <- get bh :: IO Int
   BS.create l $ \dest -> do
-    getPrim bh l (\src -> BS.memcpy dest src l)
+    getPrim bh l (\src -> copyBytes dest src l)
 
 instance Binary ByteString where
   put_ bh f = putBS bh f


=====================================
hadrian/src/Settings/Warnings.hs
=====================================
@@ -53,10 +53,12 @@ ghcWarningsArgs = do
         , package primitive    ? pure [ "-Wno-unused-imports"
                                       , "-Wno-deprecations" ]
         , package rts          ? pure [ "-Wcpp-undef" ]
+        , package text         ? pure [ "-Wno-deprecations" ]
         , package terminfo     ? pure [ "-Wno-unused-imports" ]
         , package transformers ? pure [ "-Wno-unused-matches"
                                       , "-Wno-unused-imports"
                                       , "-Wno-redundant-constraints"
                                       , "-Wno-orphans" ]
+        , package unix         ? pure [ "-Wno-deprecations" ]
         , package win32        ? pure [ "-Wno-trustworthy-safe" ]
         , package xhtml        ? pure [ "-Wno-unused-imports" ] ] ]


=====================================
libraries/bytestring
=====================================
@@ -1 +1 @@
-Subproject commit 9cab76dc861f651c3940e873ce921d9e09733cc8
+Subproject commit 602fd2f3470f180d64cb8baadf63e94baec66b60


=====================================
nofib
=====================================
@@ -1 +1 @@
-Subproject commit 2cee92861c43ac74154bbd155a83f9f4ad0b9f2f
+Subproject commit 274cc3f7479431e3a52c78840b3daee887e0414f


=====================================
rts/Updates.h
=====================================
@@ -12,6 +12,347 @@
 #include "BeginPrivate.h"
 #endif
 
+/* Note [Thunks, blackholes, and indirections]
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Consider the following STG binding:
+ *
+ *     thnk = {fv_0, fv_1} \u [] g x y;
+ *
+ * This binding is a updatable thunk carrying free variables `fv_0` and `fv_1`.
+ * Over its lifetime, this closure may transition through three states:
+ *
+ *  1. it starts life as a thunk, which carries with it free variables
+ *  2. if a thread enters it, it may turn into a blackhole
+ *  3. if evaluation finishes, it will be "updated", turning it into an
+ *     indirection pointing to the result of the evaluation
+ *
+ * On the heap, state (1) is represented as a closure with the following layout
+ * (embodied in the C runtime by the `StgThunk` struct):
+ *
+ *      thnk
+ *     ┌───────────────────────┐  ╮
+ *     │ blah_info             │  │
+ *     ├────────────┬──────────┤  │ StgThunkHeader
+ *     │ indirectee │ NULL     │  │
+ *     ├────────────┼──────────┤  ╯
+ *     │ payload[0] │ fv_0     │
+ *     ├────────────┼──────────┤
+ *     │ payload[1] │ fv_1     │
+ *     └────────────┴──────────┘
+ *
+ * Here `blah_info` is a pointer to the thunk's info table, which will be of
+ * type THUNK. The `indirectee` field (also known as the "SMP header") is
+ * initially NULL and is unused while the closure remains a thunk. However, as
+ * we will see, it will eventually point to the result of the thunk's
+ * evaluation.
+ *
+ *
+ * Entry
+ * -----
+ * As usual, to enter `thnk` (step (2) of the lifetime) a mutator thread
+ * `tso_0` will jump to its entry code (which is recorded in or next to its
+ * info table, depending upon whether tables-next-to-code is enabled). This
+ * entry code will push an "update frame" (namely, either `stg_upd_frame` or
+ * `stg_bh_upd_frame`) to `tso_0`'s stack and begin the evaluation of the
+ * thunk's RHS.
+ *
+ * However, before commencing evaluation, the entry code may also mark the
+ * thunk as being under evaluation; this process is known a "blackholing".
+ * Whether this happens depends upon which of GHC's two blackholing strategies
+ * which was selected during the compilation of the defining module. We will
+ * discuss the simpler "eager blackholing" case first and later introduce the
+ * more-efficient "lazy blackholing" strategy.
+ *
+ *
+ * Eager blackholing
+ * -----------------
+ * Under the eager blackholing strategy (which is enabled via the
+ * `-feager-blackholing` flag), a thunk's entry code (generated by
+ * `GHC.StgToCmm.Bind.emitBlackHoleCode`) will immediately turn the thunk into
+ * a blackhole, indicating that the thunk is under evaluation. Additionally,
+ * the indirectee field will be updated to point to the thread performing the
+ * evaluation, `tso_0`. Since we know statically that the thunk is now a
+ * `BLACKHOLE`, the thunk entry code will push an `stg_bh_upd_frame` to the
+ * stack in this case (in contrast to the lazy strategy, as we will see later).
+ *
+ * After this, `thnk` will look like,
+ *
+ *      thnk
+ *     ┌───────────────────────┐
+ *     │ EAGER_BLACKHOLE_info  │
+ *     ├────────────┬──────────┤           tso_0
+ *     │ indirectee │ tso_0    │─────────►┌──────┐
+ *     ├────────────┼──────────┤          │ ...  │
+ *     │ payload[0] │ fv_0     │          └──────┘
+ *     ├────────────┼──────────┤
+ *     │ payload[1] │ fv_1     │
+ *     └────────────┴──────────┘
+ *
+ * Note that blackholing in this way does not guarantee mutual exclusion: two
+ * threads may indeed race to enter `thnk`. This will result in both threads
+ * performing evaluation and, in some cases, the blackhole being updated
+ * multiple times.
+ *
+ *
+ * Updating a thunk
+ * ----------------
+ * When `tso_0` finishes the evaluation of `thnk`, it will return to the entry
+ * code of the update frame pushed when the thunk was entered (e.g.
+ * `stg_bh_upd_frame`). This code first checks whether the blackhole
+ * has already been updated by another thread; if it has then `tso_0` will
+ * throw out its result and reuse that which the earlier thread recorded in the
+ * blackhole's `indirectee` field.
+ *
+ * If the blackhole has not yet been updated then `tso_0` will:
+ *
+ *  2A. set `thnk`'s `indirectee` field to point to the result of its
+ *     evaluation, and
+ *  2B. set its info table to `BLACKHOLE_info`
+ *
+ * N.B. You might notice that step (2B) here appears to be redundant as we
+ * already set the info table pointer to `EAGER_BLACKHOLE_info` above. However,
+ * as we will see below, this may not be the case when lazy blackholing is in
+ * use.
+ *
+ * After these updates, we will have the following:
+ *
+ *      thnk
+ *     ┌───────────────────────┐
+ *     │ BLACKHOLE_info        │
+ *     ├────────────┬──────────┤           result
+ *     │ indirectee │ result   │─────────►┌────────┐
+ *     ├────────────┼──────────┤          │ ...    │
+ *     │ payload[0] │ fv_0     │          └────────┘
+ *     ├────────────┼──────────┤
+ *     │ payload[1] │ fv_1     │
+ *     └────────────┴──────────┘
+ *
+ * In addition, the code will check the blocking queues that were added to the
+ * blackhole (recorded in the `indirectee` field, as we will see below) and
+ * wake them up (see `Threads.c:updateThunk`).
+ *
+ * Note that we are using `BLACKHOLE_info` to represent two distinct states of
+ * a thunk:
+ *
+ *  - if the indirectee points to a `TSO` or `BLOCKING_QUEUE`, then the
+ *    `BLACKHOLE` represents a thunk currently being evaluated
+ *
+ *  - otherwise `BLACKHOLE` is merely representing an evaluated thunk and
+ *    serves as an indirection to the final result.
+ *
+ * This overloading may seem odd given that we also have `stg_IND_info`, which
+ * also represents an indirection.  However, the overloading serves a purpose:
+ * it means that safely updating a blackhole (step (3) of the lifetime above)
+ * requires only a single store (namely the store to the `indirectee` field).
+ *
+ * If we were to instead use `stg_IND` to represent the updated thunk, we would
+ * require two stores and consequently have an awkward period where the info
+ * table and indirectee fields are inconsistent:
+ *
+ *  - if we were to update the info table first, there would be a period where
+ *    the `indirectee` field pointed to the TSO which did the evaluation and
+ *    not the result as one would expect.
+ *
+ *  - if we were to update the indirectee first, there would be a period where
+ *    the closure is still a `BLACKHOLE_info` yet the indirectee points to the
+ *    evaluation result.
+ *
+ * For this reason, it is simpler to use `BLACKHOLE` to represent both states
+ * (2) and (3), distinguishing them using the identity of the indirectee. The
+ * uses of `stg_IND` are few and will be discussed below.
+ *
+ *
+ * Lazy blackholing
+ * ----------------
+ * While the strict blackholing strategy described above is simple and is
+ * faithful to the semantics of the STG machine, it is fairly costly on modern
+ * hardware. Specifically, thunk entry can be extremely common and in a
+ * parallel program blackholing may induce considerable pressure on the
+ * machine's memory subsystem.
+ *
+ * To mitigate this, GHC uses a lazy blackholing strategy by default. Here we
+ * take advantage of the fact that redundant evaluation of a thunk is
+ * acceptable, and defer blackholing until the thread returns to the scheduler.
+ * This is an optimisation, because we will often finish evaluation *before*
+ * yielding; in this case we avoid incurring the memory writes necessary to
+ * blackhole the thunk (step (2)), and rather update the thunk straight to an
+ * indirection.
+ *
+ * When entering a thunk compiled with lazy blackholing, we push an
+ * `stg_upd_frame` (not `stg_upd_bh_frame`) frame to the stack and do not
+ * modify the thunk closure itself.
+ *
+ * If the thread yields before finishing evaluation, the thunk will be turned
+ * into a `BLACKHOLE` in `ThreadPaused.c:threadPaused`. This function traverses
+ * the stack of the yielding thread looking for update frames; when such a
+ * frame is encountered, it checks the info table of the updatee and:
+ *
+ *  - if it is `BLACKHOLE`, then the thunk has already been claimed for evaluation
+ *    by another thread, and the yielding thread is instead added to the
+ *    `BLACKHOLE`'s blocking queue (see Note [suspend duplicate work] in
+ *    `ThreadPaused.c`).
+ *
+ *  - if not, then it blackholes the thunk as done in eager blackholing (but
+ *    using the `BLACKHOLE_info` info table instead of `EAGER_BLACKHOLE_info`).
+ *
+ * Update frames processed in this manner are rewritten to become
+ * `stg_marked_upd_frame`s. The stack traversal continues until a
+ * `stg_marked_upd_frame_info` frame is encountered, at which point we know
+ * that all subsequent frames have already been processed in a previous yield.
+ *
+ * The entry code of `stg_upd_frame` is considerably simpler than that of
+ * `stg_bh_upd_frame` since we know that the thunk has not accumulated any
+ * `BLOCKING_QUEUE`s in need of waking (since it was never blackhole'd). This
+ * is itself a small optimisation for the common case of uncontended thunk
+ * update. By contrast, the entry code of `stg_marked_upd_frame` is identical
+ * to that of `stg_bh_upd_frame` and must deal with waking of blocked threads.
+ *
+ * See `Note [suspend duplicate work]` in `ThreadPaused.c` for a subtle case
+ * involving the interaction between lazy and eager blackholing.
+ *
+ * See `Note [upd-black-hole]` in `Scav.c` for another subtle case.
+ *
+ *
+ * Blocking on a blackhole'd thunk
+ * -------------------------------
+ * If another thread `tso_1` enters `thnk` while it is blackholed by `tso_0`,
+ * the entry code of `BLACKHOLE` will allocate a `MSG_BLACKHOLE` object
+ * `msg_bh_0`. This message will be sent to the capability where the thread
+ * owning the thunk resides (see `Messages.c:messageBlackHole`). This
+ * capability will allocate a `BLOCKING_QUEUE` object `bq_0` recording the fact
+ * that `tso_1` is waiting for the result of `thnk`'s evaluation, and link it to
+ * `thnk` as follows:
+ *
+ *         thnk
+ *     ┌─►┌───────────────────────┐
+ *     │  │ EAGER_BLACKHOLE_info  │
+ *     │  ├────────────┬──────────┤
+ *     │  │ indirectee │ bq_0     ├──────┐
+ *     │  ├────────────┼──────────┤      │
+ *     │  │ payload[0] │ fv_0     │      │
+ *     │  ├────────────┼──────────┤      │
+ *     │  │ payload[1] │ fv_1     │      │
+ *     │  └────────────┴──────────┘      │
+ *     │                                 │       msg_bh_0
+ *     │     ┌───────────────────────────┘  ┌──►┌───────────────────────────┐
+ *     │     │                              │   │ MSG_BLACKHOLE_info        │
+ *     │     │                              │   ├───────────┬───────────────┤
+ *     │     │   bq_0                       │   │ link      │ END_TSO_QUEUE │
+ *     │     └─►┌──────────────────────┐    │   ├───────────┼───────────────┤
+ *     │        │ BLOCKING_QUEUE_info  │    │   │ result    │ NULL          │
+ *     │        ├───────────┬──────────┤    │   ├───────────┼───────────────┤      tso_1
+ *     │        │ link      │ NULL     │    │   │ tso       │ tso_1         ├────►┌──────┐
+ *     │        ├───────────┼──────────┤    │   └───────────┴───────────────┘     │ ...  │
+ *     │        │ queue     │ msg_bh_0 ├────┘                                     └──────┘
+ *     │        ├───────────┼──────────┤         tso_0
+ *     │        │ owner     │ tso_0    ├───────►┌──────┐
+ *     │        ├───────────┼──────────┤        │ ...  │
+ *     │        │ bh        │ thnk     ├────┐   └──────┘
+ *     │        └───────────┴──────────┘    │
+ *     │                                    │
+ *     └────────────────────────────────────┘
+ *
+ * Additionally, the `BLOCKING_QUEUE` is added to the `bq` list of the owning
+ * TSO, which collects all blocking queue objects which are blocked on thunks
+ * owned by the thread.
+ *
+ * In addition to this book-keeping, the `MSG_BLACKHOLE` message results in
+ * `tso_0` being promoted in its capability's run queue in the hope that
+ * `tso_1` and other blocked threads may be unblocked more quickly.
+ *
+ *
+ * Exception handling
+ * ------------------
+ * When an exception is thrown to a thread which is evaluating a thunk, it is
+ * important that we put things back into a state in which evaluation can
+ * be resumed by another thread. This is done by
+ * `RaiseAsync.c:raiseAsync` which walks the stack looking for update
+ * frames and rewrites the updatees into indirections pointing to an
+ * `AP_STACK` closure recording the aborted execution state.
+ * See `RaiseAsync.c:raiseAsync` for details.
+ *
+ *
+ * CAFs
+ * ----
+ * Top-level thunks (CAFs) reuse much of this machinery. The only differences
+ * are:
+ *
+ *  - CAF entry ensures mutual exclusion (see `Note [atomic CAF entry]`
+ *    in `Storage.c` for why)
+ *
+ *  - we have a distinct blackhole type, `stg_CAF_BLACKHOLE_info`; it is not
+ *    clear that maintaining this distinction from `stg_EAGER_BLACKHOLE_info`
+ *    is strictly necessary.
+ *
+ * See `Note [CAF management]` in `Storage.c` .
+ *
+ *
+ * Memory ordering
+ * ---------------
+ * The memory orderings necessary for safe concurrent thunk evaluation
+ * are rather subtle and described in Note [Heap memory barriers] in `SMP.h`.
+ *
+ *
+ * The uses of `stg_IND`
+ * ---------------------
+ * As noted above, `stg_IND_info` is not used for thunk evaluation. Instead, it
+ * merely serves as a general-purpose indirection in a few miscellaneous cases:
+ *
+ *  * it is used to "short-out" `BLOCKING_QUEUE`s and `MVAR_TSO_QUEUES` that have
+ *    already been woken-up. See Note [BLACKHOLE pointing to IND] in `Evac.c`.
+ *
+ *  * It is used to perform indirection of selector thunks (see
+ *    `Evac.c:unchain_thunk_selectors`).
+ *
+ *
+ * Indirection shortcutting
+ * ------------------------
+ * Note that the garbage collector can "shortcut" both `IND` and
+ * `BLACKHOLE` indirections. That is, the heap:
+ *
+ *  ref
+ * ┌──────────┐          evald_thunk
+ * │          ├────────►┌───────────────┬──────┐
+ * └──────────┘         │ stg_IND_info  │      │
+ *                      ├───────────────┼──────┤          x
+ *                      │ indirectee    │      ├────────►┌──────────────┐
+ *                      └───────────────┴──────┘         │ ...          │
+ *                                                       │              │
+ *                                                       └──────────────┘
+ * Can be rewritten to:
+ *
+ *  ref            ┌────────────────────────────────────┐
+ * ┌──────────┐    │     evald_thunk                    │
+ * │          ├────┘    ┌───────────────┬──────┐        │
+ * └──────────┘         │ stg_IND_info  │      │        │
+ *                      ├───────────────┼──────┤        ▼ x
+ *                      │ indirectee    │      ├────────►┌──────────────┐
+ *                      └───────────────┴──────┘         │ ...          │
+ *                                                       │              │
+ *                                                       └──────────────┘
+ *
+ *
+ * Selector optimisation
+ * ---------------------
+ * In addition to shortcutting indirections, the garbage collector can do a
+ * limited form of evaluation known as the "selector optimisation"
+ * [Wadler1987]. Specifically, the GC knows to rewrite a certain class of thunk
+ * (so-called "selector thunks", which are applications of selector functions
+ * like `fst`) into their result. For instance, given
+ *
+ *     x = (a,b)
+ *     y = fst x
+ *
+ * the GC can rewrite `y` into an indirection to `a`. References to `y` can
+ * then be further shortcutted via indirection shortcutting as described above.
+ *
+ *
+ * [Wadler1987]:
+ *   Wadler, P. (1987), Fixing some space leaks with a garbage collector.
+ *   Softw: Pract. Exper., 17: 595-608. https://doi.org/10.1002/spe.4380170904
+ */
+
+
 /* -----------------------------------------------------------------------------
    Updates
    -------------------------------------------------------------------------- */


=====================================
testsuite/tests/ghci/scripts/T9881.stdout
=====================================
@@ -19,19 +19,19 @@ instance Ord Data.ByteString.Lazy.ByteString
 
 type Data.ByteString.ByteString :: *
 data Data.ByteString.ByteString
-  = bytestring-0.11.4.0:Data.ByteString.Internal.Type.BS {-# UNPACK #-}(GHC.ForeignPtr.ForeignPtr
+  = bytestring-0.11.5.1:Data.ByteString.Internal.Type.BS {-# UNPACK #-}(GHC.ForeignPtr.ForeignPtr
                                                                           GHC.Word.Word8)
                                                          {-# UNPACK #-}Int
-  	-- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  	-- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’
 instance Monoid Data.ByteString.ByteString
-  -- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  -- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’
 instance Read Data.ByteString.ByteString
-  -- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  -- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’
 instance Semigroup Data.ByteString.ByteString
-  -- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  -- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’
 instance Show Data.ByteString.ByteString
-  -- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  -- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’
 instance Eq Data.ByteString.ByteString
-  -- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  -- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’
 instance Ord Data.ByteString.ByteString
-  -- Defined in ‘bytestring-0.11.4.0:Data.ByteString.Internal.Type’
+  -- Defined in ‘bytestring-0.11.5.1:Data.ByteString.Internal.Type’


=====================================
testsuite/tests/ghci/scripts/ghci025.stdout
=====================================
@@ -54,7 +54,7 @@ Prelude.length :: Data.Foldable.Foldable t => t a -> GHC.Types.Int
 type T.Integer :: *
 data T.Integer = ...
 T.length ::
-  bytestring-0.11.4.0:Data.ByteString.Internal.Type.ByteString
+  bytestring-0.11.5.1:Data.ByteString.Internal.Type.ByteString
   -> GHC.Types.Int
 :browse! T
 -- defined locally



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/641762b16dabbd35b26847560a47c88542dfd8b9...515962908307547e47fc9c94f7f776c6e8ecd259

-- 
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/641762b16dabbd35b26847560a47c88542dfd8b9...515962908307547e47fc9c94f7f776c6e8ecd259
You're receiving this email because of your account on gitlab.haskell.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20230804/cd9dda5c/attachment-0001.html>


More information about the ghc-commits mailing list