Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
42724462
by Simon Hengel at 2025-08-21T17:52:11-04:00
-
6a43f8ec
by Cheng Shao at 2025-08-21T17:52:52-04:00
-
0e575bfe
by Ben Gamari at 2025-08-25T10:29:17-04:00
-
b69a9c35
by Cheng Shao at 2025-08-25T10:29:17-04:00
12 changed files:
- compiler/GHC/Iface/Ext/Binary.hs
- compiler/GHC/Iface/Ext/Types.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/Types/Name/Cache.hs
- rts/PrimOps.cmm
- rts/RaiseAsync.c
- rts/STM.c
- − testsuite/tests/lib/stm/T26028.hs
- − testsuite/tests/lib/stm/T26028.stdout
- − testsuite/tests/lib/stm/all.T
- utils/haddock/haddock-api/src/Haddock/InterfaceFile.hs
- utils/jsffi/dyld.mjs
Changes:
| ... | ... | @@ -17,7 +17,6 @@ where |
| 17 | 17 | |
| 18 | 18 | import GHC.Prelude
|
| 19 | 19 | |
| 20 | -import GHC.Builtin.Utils
|
|
| 21 | 20 | import GHC.Settings.Utils ( maybeRead )
|
| 22 | 21 | import GHC.Settings.Config ( cProjectVersion )
|
| 23 | 22 | import GHC.Utils.Binary
|
| ... | ... | @@ -28,10 +27,8 @@ import GHC.Iface.Binary ( putAllTables ) |
| 28 | 27 | import GHC.Types.Name
|
| 29 | 28 | import GHC.Types.Name.Cache
|
| 30 | 29 | import GHC.Types.SrcLoc as SrcLoc
|
| 31 | -import GHC.Types.Unique
|
|
| 32 | 30 | import GHC.Types.Unique.FM
|
| 33 | 31 | import qualified GHC.Utils.Binary as Binary
|
| 34 | -import GHC.Utils.Outputable
|
|
| 35 | 32 | import GHC.Utils.Panic
|
| 36 | 33 | |
| 37 | 34 | import qualified Data.Array as A
|
| ... | ... | @@ -290,6 +287,9 @@ fromHieName nc hie_name = do |
| 290 | 287 | case hie_name of
|
| 291 | 288 | ExternalName mod occ span -> updateNameCache nc mod occ $ \cache -> do
|
| 292 | 289 | case lookupOrigNameCache cache mod occ of
|
| 290 | + -- Note that this may be a wired-in name (provided that the NameCache
|
|
| 291 | + -- was initialized with known-key names, which is always the case if you
|
|
| 292 | + -- use `newNameCache`).
|
|
| 293 | 293 | Just name -> pure (cache, name)
|
| 294 | 294 | Nothing -> do
|
| 295 | 295 | uniq <- takeUniqFromNameCache nc
|
| ... | ... | @@ -302,11 +302,6 @@ fromHieName nc hie_name = do |
| 302 | 302 | -- don't update the NameCache for local names
|
| 303 | 303 | pure $ mkInternalName uniq occ span
|
| 304 | 304 | |
| 305 | - KnownKeyName u -> case lookupKnownKeyName u of
|
|
| 306 | - Nothing -> pprPanic "fromHieName:unknown known-key unique"
|
|
| 307 | - (ppr u)
|
|
| 308 | - Just n -> pure n
|
|
| 309 | - |
|
| 310 | 305 | -- ** Reading and writing `HieName`'s
|
| 311 | 306 | |
| 312 | 307 | putHieName :: WriteBinHandle -> HieName -> IO ()
|
| ... | ... | @@ -316,9 +311,6 @@ putHieName bh (ExternalName mod occ span) = do |
| 316 | 311 | putHieName bh (LocalName occName span) = do
|
| 317 | 312 | putByte bh 1
|
| 318 | 313 | put_ bh (occName, BinSrcSpan span)
|
| 319 | -putHieName bh (KnownKeyName uniq) = do
|
|
| 320 | - putByte bh 2
|
|
| 321 | - put_ bh $ unpkUnique uniq
|
|
| 322 | 314 | |
| 323 | 315 | getHieName :: ReadBinHandle -> IO HieName
|
| 324 | 316 | getHieName bh = do
|
| ... | ... | @@ -330,7 +322,4 @@ getHieName bh = do |
| 330 | 322 | 1 -> do
|
| 331 | 323 | (occ, span) <- get bh
|
| 332 | 324 | return $ LocalName occ $ unBinSrcSpan span
|
| 333 | - 2 -> do
|
|
| 334 | - (c,i) <- get bh
|
|
| 335 | - return $ KnownKeyName $ mkUnique c i
|
|
| 336 | 325 | _ -> panic "GHC.Iface.Ext.Binary.getHieName: invalid tag" |
| ... | ... | @@ -19,14 +19,12 @@ import GHC.Prelude |
| 19 | 19 | import GHC.Settings.Config
|
| 20 | 20 | import GHC.Utils.Binary
|
| 21 | 21 | import GHC.Data.FastString
|
| 22 | -import GHC.Builtin.Utils
|
|
| 23 | 22 | import GHC.Iface.Type
|
| 24 | 23 | import GHC.Unit.Module ( ModuleName, Module )
|
| 25 | 24 | import GHC.Types.Name
|
| 26 | 25 | import GHC.Utils.Outputable hiding ( (<>) )
|
| 27 | 26 | import GHC.Types.SrcLoc
|
| 28 | 27 | import GHC.Types.Avail
|
| 29 | -import GHC.Types.Unique
|
|
| 30 | 28 | import qualified GHC.Utils.Outputable as O ( (<>) )
|
| 31 | 29 | import GHC.Utils.Panic
|
| 32 | 30 | import GHC.Core.ConLike ( ConLike(..) )
|
| ... | ... | @@ -766,7 +764,6 @@ instance Binary TyVarScope where |
| 766 | 764 | data HieName
|
| 767 | 765 | = ExternalName !Module !OccName !SrcSpan
|
| 768 | 766 | | LocalName !OccName !SrcSpan
|
| 769 | - | KnownKeyName !Unique
|
|
| 770 | 767 | deriving (Eq)
|
| 771 | 768 | |
| 772 | 769 | instance Ord HieName where
|
| ... | ... | @@ -774,34 +771,28 @@ instance Ord HieName where |
| 774 | 771 | -- TODO (int-index): Perhaps use RealSrcSpan in HieName?
|
| 775 | 772 | compare (LocalName a b) (LocalName c d) = compare a c S.<> leftmost_smallest b d
|
| 776 | 773 | -- TODO (int-index): Perhaps use RealSrcSpan in HieName?
|
| 777 | - compare (KnownKeyName a) (KnownKeyName b) = nonDetCmpUnique a b
|
|
| 778 | - -- Not actually non deterministic as it is a KnownKey
|
|
| 779 | 774 | compare ExternalName{} _ = LT
|
| 780 | 775 | compare LocalName{} ExternalName{} = GT
|
| 781 | - compare LocalName{} _ = LT
|
|
| 782 | - compare KnownKeyName{} _ = GT
|
|
| 783 | 776 | |
| 784 | 777 | instance Outputable HieName where
|
| 785 | 778 | ppr (ExternalName m n sp) = text "ExternalName" <+> ppr m <+> ppr n <+> ppr sp
|
| 786 | 779 | ppr (LocalName n sp) = text "LocalName" <+> ppr n <+> ppr sp
|
| 787 | - ppr (KnownKeyName u) = text "KnownKeyName" <+> ppr u
|
|
| 788 | 780 | |
| 789 | 781 | hieNameOcc :: HieName -> OccName
|
| 790 | 782 | hieNameOcc (ExternalName _ occ _) = occ
|
| 791 | 783 | hieNameOcc (LocalName occ _) = occ
|
| 792 | -hieNameOcc (KnownKeyName u) =
|
|
| 793 | - case lookupKnownKeyName u of
|
|
| 794 | - Just n -> nameOccName n
|
|
| 795 | - Nothing -> pprPanic "hieNameOcc:unknown known-key unique"
|
|
| 796 | - (ppr u)
|
|
| 797 | 784 | |
| 798 | 785 | toHieName :: Name -> HieName
|
| 799 | -toHieName name
|
|
| 800 | - | isKnownKeyName name = KnownKeyName (nameUnique name)
|
|
| 801 | - | isExternalName name = ExternalName (nameModule name)
|
|
| 802 | - (nameOccName name)
|
|
| 803 | - (removeBufSpan $ nameSrcSpan name)
|
|
| 804 | - | otherwise = LocalName (nameOccName name) (removeBufSpan $ nameSrcSpan name)
|
|
| 786 | +toHieName name =
|
|
| 787 | + case nameModule_maybe name of
|
|
| 788 | + Nothing -> LocalName occName span
|
|
| 789 | + Just m -> ExternalName m occName span
|
|
| 790 | + where
|
|
| 791 | + occName :: OccName
|
|
| 792 | + occName = nameOccName name
|
|
| 793 | + |
|
| 794 | + span :: SrcSpan
|
|
| 795 | + span = removeBufSpan $ nameSrcSpan name
|
|
| 805 | 796 | |
| 806 | 797 | |
| 807 | 798 | {- Note [Capture Entity Information]
|
| ... | ... | @@ -17,18 +17,18 @@ |
| 17 | 17 | -- > static void hs_hpc_init_Main(void) {
|
| 18 | 18 | -- >
|
| 19 | 19 | -- > static StgWord64 k0[2] = {16252233372134256ULL,7370534374096082ULL};
|
| 20 | --- > extern StgPtr Main_r2wb_closure;
|
|
| 20 | +-- > extern StgClosure Main_r2wb_closure;
|
|
| 21 | 21 | -- > hs_spt_insert(k0, &Main_r2wb_closure);
|
| 22 | 22 | -- >
|
| 23 | 23 | -- > static StgWord64 k1[2] = {12545634534567898ULL,5409674567544151ULL};
|
| 24 | --- > extern StgPtr Main_r2wc_closure;
|
|
| 24 | +-- > extern StgClosure Main_r2wc_closure;
|
|
| 25 | 25 | -- > hs_spt_insert(k1, &Main_r2wc_closure);
|
| 26 | 26 | -- >
|
| 27 | 27 | -- > }
|
| 28 | 28 | --
|
| 29 | 29 | -- where the constants are fingerprints produced from the static forms.
|
| 30 | 30 | --
|
| 31 | --- The linker must find the definitions matching the @extern StgPtr <name>@
|
|
| 31 | +-- The linker must find the definitions matching the @extern StgClosure <name>@
|
|
| 32 | 32 | -- declarations. For this to work, the identifiers of static pointers need to be
|
| 33 | 33 | -- exported. This is done in 'GHC.Core.Opt.SetLevels.newLvlVar'.
|
| 34 | 34 | --
|
| ... | ... | @@ -263,7 +263,7 @@ sptModuleInitCode platform this_mod entries |
| 263 | 263 | -- CLabel. Regardless, MayHaveCafRefs/NoCafRefs wouldn't make
|
| 264 | 264 | -- any difference here, they would pretty-print to the same
|
| 265 | 265 | -- foreign stub content.
|
| 266 | - $$ text "extern StgPtr "
|
|
| 266 | + $$ text "extern StgClosure "
|
|
| 267 | 267 | <> (pprCLabel platform $ mkClosureLabel n MayHaveCafRefs) <> semi
|
| 268 | 268 | $$ text "hs_spt_insert" <> parens
|
| 269 | 269 | (hcat $ punctuate comma
|
| ... | ... | @@ -101,9 +101,14 @@ OrigNameCache at all? Good question; after all, |
| 101 | 101 | 3) Loading of interface files encodes names via Uniques, as detailed in
|
| 102 | 102 | Note [Symbol table representation of names] in GHC.Iface.Binary
|
| 103 | 103 | |
| 104 | -It turns out that we end up looking up built-in syntax in the cache when we
|
|
| 105 | -generate Haddock documentation. E.g. if we don't find tuple data constructors
|
|
| 106 | -there, hyperlinks won't work as expected. Test case: haddockHtmlTest (Bug923.hs)
|
|
| 104 | + |
|
| 105 | +However note that:
|
|
| 106 | + 1) It turns out that we end up looking up built-in syntax in the cache when
|
|
| 107 | + we generate Haddock documentation. E.g. if we don't find tuple data
|
|
| 108 | + constructors there, hyperlinks won't work as expected. Test case:
|
|
| 109 | + haddockHtmlTest (Bug923.hs)
|
|
| 110 | + 2) HIE de-serialization relies on wired-in names, including built-in syntax,
|
|
| 111 | + being present in the OrigNameCache.
|
|
| 107 | 112 | -}
|
| 108 | 113 | |
| 109 | 114 | -- | The NameCache makes sure that there is just one Unique assigned for
|
| ... | ... | @@ -1211,27 +1211,16 @@ INFO_TABLE_RET(stg_catch_retry_frame, CATCH_RETRY_FRAME, |
| 1211 | 1211 | gcptr trec, outer, arg;
|
| 1212 | 1212 | |
| 1213 | 1213 | trec = StgTSO_trec(CurrentTSO);
|
| 1214 | - if (running_alt_code != 1) {
|
|
| 1215 | - // When exiting the lhs code of catchRetry# lhs rhs, we need to cleanup
|
|
| 1216 | - // the nested transaction.
|
|
| 1217 | - // See Note [catchRetry# implementation]
|
|
| 1218 | - outer = StgTRecHeader_enclosing_trec(trec);
|
|
| 1219 | - (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
|
|
| 1220 | - if (r != 0) {
|
|
| 1221 | - // Succeeded in first branch
|
|
| 1222 | - StgTSO_trec(CurrentTSO) = outer;
|
|
| 1223 | - return (ret);
|
|
| 1224 | - } else {
|
|
| 1225 | - // Did not commit: abort and restart.
|
|
| 1226 | - StgTSO_trec(CurrentTSO) = outer;
|
|
| 1227 | - jump stg_abort();
|
|
| 1228 | - }
|
|
| 1229 | - }
|
|
| 1230 | - else {
|
|
| 1231 | - // nothing to do in the rhs code of catchRetry# lhs rhs, it's already
|
|
| 1232 | - // using the parent transaction (not a nested one).
|
|
| 1233 | - // See Note [catchRetry# implementation]
|
|
| 1234 | - return (ret);
|
|
| 1214 | + outer = StgTRecHeader_enclosing_trec(trec);
|
|
| 1215 | + (r) = ccall stmCommitNestedTransaction(MyCapability() "ptr", trec "ptr");
|
|
| 1216 | + if (r != 0) {
|
|
| 1217 | + // Succeeded (either first branch or second branch)
|
|
| 1218 | + StgTSO_trec(CurrentTSO) = outer;
|
|
| 1219 | + return (ret);
|
|
| 1220 | + } else {
|
|
| 1221 | + // Did not commit: abort and restart.
|
|
| 1222 | + StgTSO_trec(CurrentTSO) = outer;
|
|
| 1223 | + jump stg_abort();
|
|
| 1235 | 1224 | }
|
| 1236 | 1225 | }
|
| 1237 | 1226 | |
| ... | ... | @@ -1464,26 +1453,21 @@ retry_pop_stack: |
| 1464 | 1453 | outer = StgTRecHeader_enclosing_trec(trec);
|
| 1465 | 1454 | |
| 1466 | 1455 | if (frame_type == CATCH_RETRY_FRAME) {
|
| 1467 | - // The retry reaches a CATCH_RETRY_FRAME before the ATOMICALLY_FRAME
|
|
| 1468 | - |
|
| 1456 | + // The retry reaches a CATCH_RETRY_FRAME before the atomic frame
|
|
| 1457 | + ASSERT(outer != NO_TREC);
|
|
| 1458 | + // Abort the transaction attempting the current branch
|
|
| 1459 | + ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
|
|
| 1460 | + ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
|
|
| 1469 | 1461 | if (!StgCatchRetryFrame_running_alt_code(frame) != 0) {
|
| 1470 | - // Retrying in the lhs of catchRetry# lhs rhs, i.e. in a nested
|
|
| 1471 | - // transaction. See Note [catchRetry# implementation]
|
|
| 1472 | - |
|
| 1473 | - // check that we have a parent transaction
|
|
| 1474 | - ASSERT(outer != NO_TREC);
|
|
| 1475 | - |
|
| 1476 | - // Abort the nested transaction
|
|
| 1477 | - ccall stmAbortTransaction(MyCapability() "ptr", trec "ptr");
|
|
| 1478 | - ccall stmFreeAbortedTRec(MyCapability() "ptr", trec "ptr");
|
|
| 1479 | - |
|
| 1480 | - // As we are retrying in the lhs code, we must now try the rhs code
|
|
| 1481 | - StgTSO_trec(CurrentTSO) = outer;
|
|
| 1462 | + // Retry in the first branch: try the alternative
|
|
| 1463 | + ("ptr" trec) = ccall stmStartTransaction(MyCapability() "ptr", outer "ptr");
|
|
| 1464 | + StgTSO_trec(CurrentTSO) = trec;
|
|
| 1482 | 1465 | StgCatchRetryFrame_running_alt_code(frame) = 1 :: CInt; // true;
|
| 1483 | 1466 | R1 = StgCatchRetryFrame_alt_code(frame);
|
| 1484 | 1467 | jump stg_ap_v_fast [R1];
|
| 1485 | 1468 | } else {
|
| 1486 | - // Retry in the rhs code: propagate the retry
|
|
| 1469 | + // Retry in the alternative code: propagate the retry
|
|
| 1470 | + StgTSO_trec(CurrentTSO) = outer;
|
|
| 1487 | 1471 | Sp = Sp + SIZEOF_StgCatchRetryFrame;
|
| 1488 | 1472 | goto retry_pop_stack;
|
| 1489 | 1473 | }
|
| ... | ... | @@ -1043,7 +1043,8 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception, |
| 1043 | 1043 | }
|
| 1044 | 1044 | |
| 1045 | 1045 | case CATCH_STM_FRAME:
|
| 1046 | - // CATCH_STM frame within an atomically block: abort the
|
|
| 1046 | + case CATCH_RETRY_FRAME:
|
|
| 1047 | + // CATCH frames within an atomically block: abort the
|
|
| 1047 | 1048 | // inner transaction and continue. Eventually we will
|
| 1048 | 1049 | // hit the outer transaction that will get frozen (see
|
| 1049 | 1050 | // above).
|
| ... | ... | @@ -1055,40 +1056,14 @@ raiseAsync(Capability *cap, StgTSO *tso, StgClosure *exception, |
| 1055 | 1056 | {
|
| 1056 | 1057 | StgTRecHeader *trec = tso -> trec;
|
| 1057 | 1058 | StgTRecHeader *outer = trec -> enclosing_trec;
|
| 1058 | - debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_STM frame");
|
|
| 1059 | + debugTraceCap(DEBUG_stm, cap,
|
|
| 1060 | + "found atomically block delivering async exception");
|
|
| 1059 | 1061 | stmAbortTransaction(cap, trec);
|
| 1060 | 1062 | stmFreeAbortedTRec(cap, trec);
|
| 1061 | 1063 | tso -> trec = outer;
|
| 1062 | 1064 | break;
|
| 1063 | 1065 | };
|
| 1064 | 1066 | |
| 1065 | - case CATCH_RETRY_FRAME:
|
|
| 1066 | - // CATCH_RETY frame within an atomically block: if we're executing
|
|
| 1067 | - // the lhs code, abort the inner transaction and continue; if we're
|
|
| 1068 | - // executing thr rhs, continue (no nested transaction to abort. See
|
|
| 1069 | - // Note [catchRetry# implementation]). Eventually we will hit the
|
|
| 1070 | - // outer transaction that will get frozen (see above).
|
|
| 1071 | - //
|
|
| 1072 | - // As for the CATCH_STM_FRAME case above, we do not care
|
|
| 1073 | - // whether the transaction is valid or not because its
|
|
| 1074 | - // possible validity cannot have caused the exception
|
|
| 1075 | - // and will not be visible after the abort.
|
|
| 1076 | - {
|
|
| 1077 | - if (!((StgCatchRetryFrame *)frame) -> running_alt_code) {
|
|
| 1078 | - debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (lhs)");
|
|
| 1079 | - StgTRecHeader *trec = tso -> trec;
|
|
| 1080 | - StgTRecHeader *outer = trec -> enclosing_trec;
|
|
| 1081 | - stmAbortTransaction(cap, trec);
|
|
| 1082 | - stmFreeAbortedTRec(cap, trec);
|
|
| 1083 | - tso -> trec = outer;
|
|
| 1084 | - }
|
|
| 1085 | - else
|
|
| 1086 | - {
|
|
| 1087 | - debugTraceCap(DEBUG_stm, cap, "raiseAsync: traversing CATCH_RETRY frame (rhs)");
|
|
| 1088 | - }
|
|
| 1089 | - break;
|
|
| 1090 | - };
|
|
| 1091 | - |
|
| 1092 | 1067 | default:
|
| 1093 | 1068 | // see Note [Update async masking state on unwind] in Schedule.c
|
| 1094 | 1069 | if (*frame == (W_)&stg_unmaskAsyncExceptionszh_ret_info) {
|
| ... | ... | @@ -1505,30 +1505,3 @@ void stmWriteTVar(Capability *cap, |
| 1505 | 1505 | }
|
| 1506 | 1506 | |
| 1507 | 1507 | /*......................................................................*/ |
| 1508 | - |
|
| 1509 | - |
|
| 1510 | - |
|
| 1511 | -/*
|
|
| 1512 | - |
|
| 1513 | -Note [catchRetry# implementation]
|
|
| 1514 | -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
| 1515 | -catchRetry# creates a nested transaction for its lhs:
|
|
| 1516 | -- if the lhs transaction succeeds:
|
|
| 1517 | - - the lhs transaction is committed
|
|
| 1518 | - - its read-variables are merged with those of the parent transaction
|
|
| 1519 | - - the rhs code is ignored
|
|
| 1520 | -- if the lhs transaction retries:
|
|
| 1521 | - - the lhs transaction is aborted
|
|
| 1522 | - - its read-variables are merged with those of the parent transaction
|
|
| 1523 | - - the rhs code is executed directly in the parent transaction (see #26028).
|
|
| 1524 | - |
|
| 1525 | -So note that:
|
|
| 1526 | -- lhs code uses a nested transaction
|
|
| 1527 | -- rhs code doesn't use a nested transaction
|
|
| 1528 | - |
|
| 1529 | -We have to take which case we're in into account (using the running_alt_code
|
|
| 1530 | -field of the catchRetry frame) in catchRetry's entry code, in retry#
|
|
| 1531 | -implementation, and also when an async exception is received (to cleanup the
|
|
| 1532 | -right number of transactions).
|
|
| 1533 | - |
|
| 1534 | -*/ |
| 1 | -module Main where
|
|
| 2 | - |
|
| 3 | -import GHC.Conc
|
|
| 4 | - |
|
| 5 | -forever :: IO String
|
|
| 6 | -forever = delay 10 >> forever
|
|
| 7 | - |
|
| 8 | -terminates :: IO String
|
|
| 9 | -terminates = delay 1 >> pure "terminates"
|
|
| 10 | - |
|
| 11 | -delay s = threadDelay (1000000 * s)
|
|
| 12 | - |
|
| 13 | -async :: IO a -> IO (STM a)
|
|
| 14 | -async a = do
|
|
| 15 | - var <- atomically (newTVar Nothing)
|
|
| 16 | - forkIO (a >>= atomically . writeTVar var . Just)
|
|
| 17 | - pure (readTVar var >>= maybe retry pure)
|
|
| 18 | - |
|
| 19 | -main :: IO ()
|
|
| 20 | -main = do
|
|
| 21 | - x <- mapM async $ terminates : replicate 50000 forever
|
|
| 22 | - r <- atomically (foldr1 orElse x)
|
|
| 23 | - print r |
| 1 | -"terminates" |
| 1 | -test('T26028', only_ways(['threaded1']), compile_and_run, ['-O2']) |
| ... | ... | @@ -229,10 +229,7 @@ writeInterfaceFile filename iface = do |
| 229 | 229 | return ()
|
| 230 | 230 | |
| 231 | 231 | freshNameCache :: IO NameCache
|
| 232 | -freshNameCache =
|
|
| 233 | - initNameCache
|
|
| 234 | - 'a' -- ??
|
|
| 235 | - []
|
|
| 232 | +freshNameCache = newNameCache
|
|
| 236 | 233 | |
| 237 | 234 | -- | Read a Haddock (@.haddock@) interface file. Return either an
|
| 238 | 235 | -- 'InterfaceFile' or an error message.
|
| ... | ... | @@ -1105,6 +1105,20 @@ class DyLD { |
| 1105 | 1105 | if (/libHSghc-internal-\d+(\.\d+)*/i.test(soname)) {
|
| 1106 | 1106 | this.rts_init();
|
| 1107 | 1107 | delete this.rts_init;
|
| 1108 | + |
|
| 1109 | + // At this point the RTS symbols in linear memory are fixed
|
|
| 1110 | + // and constructors are run, especially the one in JSFFI.c
|
|
| 1111 | + // that does GHC RTS initialization for any code that links
|
|
| 1112 | + // JSFFI.o. Luckily no Haskell computation or gc has taken
|
|
| 1113 | + // place yet, so we must set keepCAFs=1 right now! Otherwise,
|
|
| 1114 | + // any BCO created by later TH splice or ghci expression may
|
|
| 1115 | + // refer to any CAF that's not reachable from GC roots (here
|
|
| 1116 | + // our only entry point is defaultServer) and the CAF could
|
|
| 1117 | + // have been GC'ed! (#26106)
|
|
| 1118 | + //
|
|
| 1119 | + // We call it here instead of in RTS C code, since we only
|
|
| 1120 | + // want keepCAFs=1 for ghci, not user code.
|
|
| 1121 | + this.exportFuncs.setKeepCAFs();
|
|
| 1108 | 1122 | }
|
| 1109 | 1123 | init();
|
| 1110 | 1124 | }
|