Hannes Siebenhandl pushed to branch wip/fendor/linkable-usage at Glasgow Haskell Compiler / GHC
Commits:
-
4439d674
by fendor at 2026-03-19T14:53:03+01:00
-
11ffef7a
by fendor at 2026-03-19T14:53:03+01:00
-
f78ea8aa
by fendor at 2026-03-19T14:53:03+01:00
25 changed files:
- compiler/GHC/ByteCode/Binary.hs
- + compiler/GHC/ByteCode/Recomp/Binary.hs
- compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/Driver/Hooks.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Plugins.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Iface/Recomp/Types.hs
- compiler/GHC/Linker/ByteCode.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Runtime/Loader.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Unit/Home/ModInfo.hs
- compiler/GHC/Unit/Module/Deps.hs
- compiler/GHC/Unit/Module/Status.hs
- compiler/ghc.cabal.in
- ghc/GHCi/Leak.hs
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/driver/multipleHomeUnits/multipleHomeUnits_recomp_th.stdout
Changes:
| ... | ... | @@ -20,7 +20,6 @@ import GHC.Prelude |
| 20 | 20 | |
| 21 | 21 | import GHC.ByteCode.Types
|
| 22 | 22 | import GHC.Data.FastString
|
| 23 | -import GHC.Driver.Env.Types (HscEnv(..))
|
|
| 24 | 23 | import GHC.Types.Name
|
| 25 | 24 | import GHC.Types.Name.Cache
|
| 26 | 25 | import GHC.Types.Name.Env
|
| ... | ... | @@ -30,6 +29,7 @@ import GHC.Utils.Binary |
| 30 | 29 | import GHC.Utils.Exception
|
| 31 | 30 | import GHC.Utils.Panic
|
| 32 | 31 | import GHC.Utils.Outputable
|
| 32 | +import GHC.Utils.Fingerprint (Fingerprint)
|
|
| 33 | 33 | |
| 34 | 34 | import Control.Monad
|
| 35 | 35 | import Data.Binary qualified as Binary
|
| ... | ... | @@ -47,6 +47,7 @@ import System.IO.Unsafe (unsafeInterleaveIO) |
| 47 | 47 | -- contained by 'ModuleByteCode' are stored in-memory rather than as file paths to
|
| 48 | 48 | -- temporary files.
|
| 49 | 49 | data OnDiskModuleByteCode = OnDiskModuleByteCode { odgbc_module :: Module
|
| 50 | + , odgbc_hash :: Fingerprint
|
|
| 50 | 51 | , odgbc_compiled_byte_code :: CompiledByteCode
|
| 51 | 52 | , odgbc_foreign :: [ByteString] -- ^ Contents of object files
|
| 52 | 53 | }
|
| ... | ... | @@ -94,6 +95,20 @@ instance Binary InterpreterLibraryContents where |
| 94 | 95 | putByte bh 1
|
| 95 | 96 | put_ bh contents
|
| 96 | 97 | |
| 98 | +instance Binary OnDiskModuleByteCode where
|
|
| 99 | + get bh = do
|
|
| 100 | + odgbc_hash <- get bh
|
|
| 101 | + odgbc_module <- get bh
|
|
| 102 | + odgbc_compiled_byte_code <- lazyGet bh
|
|
| 103 | + odgbc_foreign <- lazyGet bh
|
|
| 104 | + pure OnDiskModuleByteCode {..}
|
|
| 105 | + |
|
| 106 | + put_ bh OnDiskModuleByteCode {..} = do
|
|
| 107 | + put_ bh odgbc_hash
|
|
| 108 | + put_ bh odgbc_module
|
|
| 109 | + lazyPut bh odgbc_compiled_byte_code
|
|
| 110 | + lazyPut bh odgbc_foreign
|
|
| 111 | + |
|
| 97 | 112 | instance Binary OnDiskBytecodeLib where
|
| 98 | 113 | get bh = do
|
| 99 | 114 | bytecodeLibUnitId <- get bh
|
| ... | ... | @@ -106,18 +121,6 @@ instance Binary OnDiskBytecodeLib where |
| 106 | 121 | put_ bh bytecodeLibFiles
|
| 107 | 122 | put_ bh bytecodeLibForeign
|
| 108 | 123 | |
| 109 | -instance Binary OnDiskModuleByteCode where
|
|
| 110 | - get bh = do
|
|
| 111 | - odgbc_module <- get bh
|
|
| 112 | - odgbc_compiled_byte_code <- get bh
|
|
| 113 | - odgbc_foreign <- get bh
|
|
| 114 | - pure OnDiskModuleByteCode {..}
|
|
| 115 | - |
|
| 116 | - put_ bh OnDiskModuleByteCode {..} = do
|
|
| 117 | - put_ bh odgbc_module
|
|
| 118 | - put_ bh odgbc_compiled_byte_code
|
|
| 119 | - put_ bh odgbc_foreign
|
|
| 120 | - |
|
| 121 | 124 | instance Binary CompiledByteCode where
|
| 122 | 125 | get bh = do
|
| 123 | 126 | bc_bcos <- get bh
|
| ... | ... | @@ -252,8 +255,8 @@ addBinNameWriter bh' = do |
| 252 | 255 | Just idx -> (b, idx)
|
| 253 | 256 | Nothing -> (ByteCodeNameEnv (next + 1) (extendNameEnv subst name next), next))
|
| 254 | 257 | |
| 255 | -addBinNameReader :: HscEnv -> ReadBinHandle -> IO ReadBinHandle
|
|
| 256 | -addBinNameReader HscEnv {hsc_NC} bh' = do
|
|
| 258 | +addBinNameReader :: NameCache -> ReadBinHandle -> IO ReadBinHandle
|
|
| 259 | +addBinNameReader nc bh' = do
|
|
| 257 | 260 | env_ref <- newIORef emptyOccEnv
|
| 258 | 261 | pure $ flip addReaderToUserData bh' $ BinaryReader $ \bh -> do
|
| 259 | 262 | t <- getByte bh
|
| ... | ... | @@ -266,7 +269,7 @@ addBinNameReader HscEnv {hsc_NC} bh' = do |
| 266 | 269 | -- We don't want to get a new unique from the NameCache each time we
|
| 267 | 270 | -- see a name.
|
| 268 | 271 | nm' <- unsafeInterleaveIO $ do
|
| 269 | - u <- takeUniqFromNameCache hsc_NC
|
|
| 272 | + u <- takeUniqFromNameCache nc
|
|
| 270 | 273 | evaluate $ mkInternalName u occ noSrcSpan
|
| 271 | 274 | fmap BinName $ atomicModifyIORef' env_ref $ \env ->
|
| 272 | 275 | case lookupOccEnv env occ of
|
| 1 | +module GHC.ByteCode.Recomp.Binary (
|
|
| 2 | + -- * Fingerprinting ByteCode objects
|
|
| 3 | + computeFingerprint,
|
|
| 4 | +) where
|
|
| 5 | + |
|
| 6 | +import GHC.Prelude
|
|
| 7 | + |
|
| 8 | +import GHC.ByteCode.Binary (addBinNameWriter)
|
|
| 9 | +import GHC.Iface.Binary
|
|
| 10 | +import GHC.Iface.Recomp.Binary (putNameLiterally, fingerprintBinMem)
|
|
| 11 | +import GHC.Types.Name
|
|
| 12 | +import GHC.Utils.Fingerprint
|
|
| 13 | +import GHC.Utils.Binary
|
|
| 14 | + |
|
| 15 | +import System.IO.Unsafe
|
|
| 16 | + |
|
| 17 | +-- | Create a 'Fingerprint' using the appropriate serializers
|
|
| 18 | +-- for 'ModuleByteCode'.
|
|
| 19 | +--
|
|
| 20 | +computeFingerprint :: (Binary a)
|
|
| 21 | + => (WriteBinHandle -> Name -> IO ())
|
|
| 22 | + -> a
|
|
| 23 | + -> Fingerprint
|
|
| 24 | +computeFingerprint put_nonbinding_name a = unsafePerformIO $ do
|
|
| 25 | + bh <- fmap set_user_data $ openBinMem (3*1024) -- just less than a block
|
|
| 26 | + bh' <- addBinNameWriter bh
|
|
| 27 | + putWithUserData QuietBinIFace NormalCompression bh' a
|
|
| 28 | + fingerprintBinMem bh'
|
|
| 29 | + where
|
|
| 30 | + set_user_data bh = setWriterUserData bh $ mkWriterUserData
|
|
| 31 | + [ mkSomeBinaryWriter $ mkWriter put_nonbinding_name
|
|
| 32 | + , mkSomeBinaryWriter $ simpleBindingNameWriter $ mkWriter putNameLiterally
|
|
| 33 | + , mkSomeBinaryWriter $ mkWriter putFS
|
|
| 34 | + ] |
| ... | ... | @@ -2,11 +2,11 @@ |
| 2 | 2 | {-# LANGUAGE RecordWildCards #-}
|
| 3 | 3 | -- Orphans are here since the Binary instances use an ad-hoc means of serialising
|
| 4 | 4 | -- names which we don't want to pollute the rest of the codebase with.
|
| 5 | -{-# OPTIONS_GHC -Wno-orphans #-}
|
|
| 6 | 5 | {- | This module implements the serialization of bytecode objects to and from disk.
|
| 7 | 6 | -}
|
| 8 | 7 | module GHC.ByteCode.Serialize
|
| 9 | - ( writeBinByteCode, readBinByteCode, ModuleByteCode(..)
|
|
| 8 | + ( writeBinByteCode, readBinByteCode
|
|
| 9 | + , ModuleByteCode(..)
|
|
| 10 | 10 | , BytecodeLibX(..)
|
| 11 | 11 | , BytecodeLib
|
| 12 | 12 | , OnDiskBytecodeLib
|
| ... | ... | @@ -14,26 +14,34 @@ module GHC.ByteCode.Serialize |
| 14 | 14 | , InterpreterLibraryContents(..)
|
| 15 | 15 | , writeBytecodeLib
|
| 16 | 16 | , readBytecodeLib
|
| 17 | + , mkModuleByteCode
|
|
| 18 | + , fingerprintModuleByteCodeContents
|
|
| 17 | 19 | , decodeOnDiskModuleByteCode
|
| 18 | 20 | , decodeOnDiskBytecodeLib
|
| 19 | 21 | )
|
| 20 | 22 | where
|
| 21 | 23 | |
| 22 | -import Control.Monad
|
|
| 24 | +import GHC.Prelude
|
|
| 25 | + |
|
| 26 | +import GHC.ByteCode.Binary
|
|
| 27 | +import GHC.ByteCode.Types
|
|
| 28 | +import GHC.ByteCode.Recomp.Binary (computeFingerprint)
|
|
| 23 | 29 | import GHC.Driver.Env
|
| 30 | +import GHC.Driver.DynFlags
|
|
| 24 | 31 | import GHC.Iface.Binary
|
| 25 | -import GHC.Prelude
|
|
| 32 | +import GHC.Iface.Recomp.Binary (putNameLiterally)
|
|
| 33 | +import GHC.Linker.Types
|
|
| 34 | +import GHC.Unit.Types
|
|
| 26 | 35 | import GHC.Utils.Binary
|
| 27 | 36 | import GHC.Utils.TmpFs
|
| 28 | -import System.FilePath
|
|
| 29 | -import GHC.Driver.DynFlags
|
|
| 30 | -import System.Directory
|
|
| 37 | +import GHC.Utils.Logger
|
|
| 38 | +import GHC.Utils.Fingerprint (Fingerprint)
|
|
| 39 | + |
|
| 31 | 40 | import Data.ByteString (ByteString)
|
| 32 | 41 | import qualified Data.ByteString as BS
|
| 33 | 42 | import Data.Traversable
|
| 34 | -import GHC.Utils.Logger
|
|
| 35 | -import GHC.Linker.Types
|
|
| 36 | -import GHC.ByteCode.Binary
|
|
| 43 | +import System.Directory
|
|
| 44 | +import System.FilePath
|
|
| 37 | 45 | |
| 38 | 46 | {- Note [Overview of persistent bytecode]
|
| 39 | 47 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -85,7 +93,7 @@ writeBytecodeLib lib path = do |
| 85 | 93 | readBytecodeLib :: HscEnv -> FilePath -> IO OnDiskBytecodeLib
|
| 86 | 94 | readBytecodeLib hsc_env path = do
|
| 87 | 95 | bh' <- readBinMem path
|
| 88 | - bh <- addBinNameReader hsc_env bh'
|
|
| 96 | + bh <- addBinNameReader (hsc_NC hsc_env) bh'
|
|
| 89 | 97 | res <- getWithUserData (hsc_NC hsc_env) bh
|
| 90 | 98 | pure res
|
| 91 | 99 | |
| ... | ... | @@ -103,7 +111,8 @@ decodeOnDiskModuleByteCode hsc_env odbco = do |
| 103 | 111 | pure $ ModuleByteCode {
|
| 104 | 112 | gbc_module = odgbc_module odbco,
|
| 105 | 113 | gbc_compiled_byte_code = odgbc_compiled_byte_code odbco,
|
| 106 | - gbc_foreign_files = foreign_files
|
|
| 114 | + gbc_foreign_files = foreign_files,
|
|
| 115 | + gbc_hash = odgbc_hash odbco
|
|
| 107 | 116 | }
|
| 108 | 117 | |
| 109 | 118 | decodeOnDiskBytecodeLib :: HscEnv -> OnDiskBytecodeLib -> IO BytecodeLib
|
| ... | ... | @@ -162,7 +171,8 @@ encodeOnDiskModuleByteCode bco = do |
| 162 | 171 | pure $ OnDiskModuleByteCode {
|
| 163 | 172 | odgbc_module = gbc_module bco,
|
| 164 | 173 | odgbc_compiled_byte_code = gbc_compiled_byte_code bco,
|
| 165 | - odgbc_foreign = foreign_contents
|
|
| 174 | + odgbc_foreign = foreign_contents,
|
|
| 175 | + odgbc_hash = gbc_hash bco
|
|
| 166 | 176 | }
|
| 167 | 177 | |
| 168 | 178 | -- | Read a 'ModuleByteCode' from a file.
|
| ... | ... | @@ -174,7 +184,7 @@ readBinByteCode hsc_env f = do |
| 174 | 184 | readOnDiskModuleByteCode :: HscEnv -> FilePath -> IO OnDiskModuleByteCode
|
| 175 | 185 | readOnDiskModuleByteCode hsc_env f = do
|
| 176 | 186 | bh' <- readBinMem f
|
| 177 | - bh <- addBinNameReader hsc_env bh'
|
|
| 187 | + bh <- addBinNameReader (hsc_NC hsc_env) bh'
|
|
| 178 | 188 | getWithUserData (hsc_NC hsc_env) bh
|
| 179 | 189 | |
| 180 | 190 | -- | Write a 'ModuleByteCode' to a file.
|
| ... | ... | @@ -186,3 +196,13 @@ writeBinByteCode f cbc = do |
| 186 | 196 | odbco <- encodeOnDiskModuleByteCode cbc
|
| 187 | 197 | putWithUserData QuietBinIFace NormalCompression bh odbco
|
| 188 | 198 | writeBinMem bh f
|
| 199 | + |
|
| 200 | +mkModuleByteCode :: Module -> CompiledByteCode -> [FilePath] -> IO ModuleByteCode
|
|
| 201 | +mkModuleByteCode modl cbc foreign_files = do
|
|
| 202 | + !bcos_hash <- fingerprintModuleByteCodeContents modl cbc foreign_files
|
|
| 203 | + return $! ModuleByteCode modl cbc foreign_files bcos_hash
|
|
| 204 | + |
|
| 205 | +fingerprintModuleByteCodeContents :: Module -> CompiledByteCode -> [FilePath] -> IO Fingerprint
|
|
| 206 | +fingerprintModuleByteCodeContents modl cbc foreign_files = do
|
|
| 207 | + foreign_contents <- readObjectFiles foreign_files
|
|
| 208 | + pure $ computeFingerprint putNameLiterally (modl, cbc, foreign_contents) |
| ... | ... | @@ -137,7 +137,7 @@ data Hooks = Hooks |
| 137 | 137 | , tcForeignExportsHook :: !(Maybe ([LForeignDecl GhcRn]
|
| 138 | 138 | -> TcM (LHsBinds GhcTc, [LForeignDecl GhcTc], Bag GlobalRdrElt)))
|
| 139 | 139 | , hscFrontendHook :: !(Maybe (ModSummary -> Hsc FrontendResult))
|
| 140 | - , hscCompileCoreExprHook :: !(Maybe (HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)))
|
|
| 140 | + , hscCompileCoreExprHook :: !(Maybe (HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)))
|
|
| 141 | 141 | , ghcPrimIfaceHook :: !(Maybe ModIface)
|
| 142 | 142 | , runPhaseHook :: !(Maybe PhaseHook)
|
| 143 | 143 | , runMetaHook :: !(Maybe (MetaHook TcM))
|
| ... | ... | @@ -145,7 +145,7 @@ data Hooks = Hooks |
| 145 | 145 | -> HomePackageTable -> IO SuccessFlag))
|
| 146 | 146 | , runRnSpliceHook :: !(Maybe (HsUntypedSplice GhcRn -> RnM (HsUntypedSplice GhcRn)))
|
| 147 | 147 | , getValueSafelyHook :: !(Maybe (HscEnv -> Name -> Type
|
| 148 | - -> IO (Either Type (HValue, [Linkable], PkgsLoaded))))
|
|
| 148 | + -> IO (Either Type (HValue, [LinkableUsage], PkgsLoaded))))
|
|
| 149 | 149 | , createIservProcessHook :: !(Maybe (CreateProcess -> IO ProcessHandle))
|
| 150 | 150 | , stgToCmmHook :: !(Maybe (StgToCmmConfig -> InfoTableProvMap -> [TyCon] -> CollectedCCs
|
| 151 | 151 | -> [CgStgTopBinding] -> CgStream CmmGroup ModuleLFInfos))
|
| ... | ... | @@ -297,8 +297,7 @@ import GHC.Cmm.Config (CmmConfig) |
| 297 | 297 | import Data.Bifunctor
|
| 298 | 298 | import qualified GHC.Unit.Home.Graph as HUG
|
| 299 | 299 | import GHC.Unit.Home.PackageTable
|
| 300 | - |
|
| 301 | -import GHC.ByteCode.Serialize
|
|
| 300 | +import qualified GHC.ByteCode.Serialize as ByteCode
|
|
| 302 | 301 | |
| 303 | 302 | {- **********************************************************************
|
| 304 | 303 | %* *
|
| ... | ... | @@ -973,23 +972,22 @@ checkObjects dflags mb_old_linkable summary = do |
| 973 | 972 | -- | Check to see if we can reuse the old linkable, by this point we will
|
| 974 | 973 | -- have just checked that the old interface matches up with the source hash, so
|
| 975 | 974 | -- no need to check that again here
|
| 976 | -checkByteCodeInMemory :: HscEnv -> ModSummary -> Maybe Linkable -> IO (MaybeValidated Linkable)
|
|
| 975 | +checkByteCodeInMemory :: HscEnv -> ModSummary -> Maybe (LinkableWith ModuleByteCode) -> IO (MaybeValidated (LinkableWith ModuleByteCode))
|
|
| 977 | 976 | checkByteCodeInMemory hsc_env mod_sum mb_old_linkable =
|
| 978 | 977 | case mb_old_linkable of
|
| 979 | 978 | Just old_linkable
|
| 980 | - | not (linkableIsNativeCodeOnly old_linkable)
|
|
| 981 | 979 | -- If `-fwrite-byte-code` is enabled, then check that the .gbc file is
|
| 982 | 980 | -- up-to-date with the linkable we have in our hand.
|
| 983 | 981 | -- If ms_bytecode_date is Nothing, then the .gbc file does not exist yet.
|
| 984 | 982 | -- Otherwise, check that the date matches the linkable date exactly.
|
| 985 | - , if gopt Opt_WriteByteCode (hsc_dflags hsc_env)
|
|
| 983 | + | if gopt Opt_WriteByteCode (hsc_dflags hsc_env)
|
|
| 986 | 984 | then maybe False (linkableTime old_linkable ==) (ms_bytecode_date mod_sum)
|
| 987 | 985 | else True
|
| 988 | 986 | -> return $ (UpToDateItem old_linkable)
|
| 989 | 987 | _ -> return $ outOfDateItemBecause MissingBytecode Nothing
|
| 990 | 988 | |
| 991 | 989 | -- | Load bytecode from a ".gbc" object file if it exists and is up-to-date
|
| 992 | -checkByteCodeFromObject :: HscEnv -> ModSummary -> IO (MaybeValidated Linkable)
|
|
| 990 | +checkByteCodeFromObject :: HscEnv -> ModSummary -> IO (MaybeValidated (LinkableWith ModuleByteCode))
|
|
| 993 | 991 | checkByteCodeFromObject hsc_env mod_sum = do
|
| 994 | 992 | let
|
| 995 | 993 | obj_fn = ml_bytecode_file (ms_location mod_sum)
|
| ... | ... | @@ -1001,8 +999,8 @@ checkByteCodeFromObject hsc_env mod_sum = do |
| 1001 | 999 | -- Don't force this if we reuse the linkable already loaded into memory, but we have to check
|
| 1002 | 1000 | -- that the one we have on disk would be suitable as well.
|
| 1003 | 1001 | linkable <- unsafeInterleaveIO $ do
|
| 1004 | - bco <- readBinByteCode hsc_env obj_fn
|
|
| 1005 | - return $ mkModuleByteCodeLinkable obj_date bco
|
|
| 1002 | + bco <- ByteCode.readBinByteCode hsc_env obj_fn
|
|
| 1003 | + return $ mkOnlyModuleByteCodeLinkable obj_date bco
|
|
| 1006 | 1004 | return $ UpToDateItem linkable
|
| 1007 | 1005 | _ -> return $ outOfDateItemBecause MissingBytecode Nothing
|
| 1008 | 1006 | |
| ... | ... | @@ -1086,7 +1084,7 @@ loadIfaceByteCodeLazy :: |
| 1086 | 1084 | ModIface ->
|
| 1087 | 1085 | ModLocation ->
|
| 1088 | 1086 | TypeEnv ->
|
| 1089 | - IO (Maybe Linkable)
|
|
| 1087 | + IO (Maybe (LinkableWith ModuleByteCode))
|
|
| 1090 | 1088 | loadIfaceByteCodeLazy hsc_env iface location type_env =
|
| 1091 | 1089 | case iface_core_bindings iface location of
|
| 1092 | 1090 | Nothing -> return Nothing
|
| ... | ... | @@ -1094,8 +1092,9 @@ loadIfaceByteCodeLazy hsc_env iface location type_env = |
| 1094 | 1092 | Just <$> compile wcb
|
| 1095 | 1093 | where
|
| 1096 | 1094 | compile decls = do
|
| 1097 | - bco <- unsafeInterleaveIO $ compileWholeCoreBindings hsc_env type_env decls
|
|
| 1098 | - linkable $ NE.singleton (DotGBC bco)
|
|
| 1095 | + bco <- unsafeInterleaveIO $ do
|
|
| 1096 | + compileWholeCoreBindings hsc_env type_env decls
|
|
| 1097 | + linkable bco
|
|
| 1099 | 1098 | |
| 1100 | 1099 | linkable parts = do
|
| 1101 | 1100 | if_time <- modificationTimeIfExists (ml_hi_file_ospath location)
|
| ... | ... | @@ -1136,14 +1135,14 @@ initWholeCoreBindings hsc_env iface details (RecompLinkables bc o) = do |
| 1136 | 1135 | where
|
| 1137 | 1136 | type_env = md_types details
|
| 1138 | 1137 | |
| 1139 | - go :: RecompBytecodeLinkable -> IO (Maybe Linkable)
|
|
| 1138 | + go :: RecompBytecodeLinkable -> IO (Maybe (LinkableWith ModuleByteCode))
|
|
| 1140 | 1139 | go (NormalLinkable l) = pure l
|
| 1141 | 1140 | go (WholeCoreBindingsLinkable wcbl) =
|
| 1142 | 1141 | fmap Just $ for wcbl $ \wcb -> do
|
| 1143 | 1142 | add_iface_to_hpt iface details hsc_env
|
| 1144 | - bco <- unsafeInterleaveIO $
|
|
| 1145 | - compileWholeCoreBindings hsc_env type_env wcb
|
|
| 1146 | - pure $ NE.singleton (DotGBC bco)
|
|
| 1143 | + bco <- unsafeInterleaveIO $ do
|
|
| 1144 | + compileWholeCoreBindings hsc_env type_env wcb
|
|
| 1145 | + pure bco
|
|
| 1147 | 1146 | |
| 1148 | 1147 | -- | Hydrate interface Core bindings and compile them to bytecode.
|
| 1149 | 1148 | --
|
| ... | ... | @@ -2205,7 +2204,7 @@ generateAndWriteByteCode hsc_env cgguts mod_location = do |
| 2205 | 2204 | -- See Note [-fwrite-byte-code is not the default]
|
| 2206 | 2205 | when (gopt Opt_WriteByteCode dflags) $ do
|
| 2207 | 2206 | let bc_path = ml_bytecode_file mod_location
|
| 2208 | - writeBinByteCode bc_path comp_bc
|
|
| 2207 | + ByteCode.writeBinByteCode bc_path comp_bc
|
|
| 2209 | 2208 | return comp_bc
|
| 2210 | 2209 | |
| 2211 | 2210 | {-
|
| ... | ... | @@ -2220,20 +2219,20 @@ make user's opt into writing the files. |
| 2220 | 2219 | -}
|
| 2221 | 2220 | |
| 2222 | 2221 | -- | Generate a 'ModuleByteCode' and write it to disk if `-fwrite-byte-code` is enabled.
|
| 2223 | -generateAndWriteByteCodeLinkable :: HscEnv -> CgInteractiveGuts -> ModLocation -> IO Linkable
|
|
| 2222 | +generateAndWriteByteCodeLinkable :: HscEnv -> CgInteractiveGuts -> ModLocation -> IO (LinkableWith ModuleByteCode)
|
|
| 2224 | 2223 | generateAndWriteByteCodeLinkable hsc_env cgguts mod_location = do
|
| 2225 | 2224 | bco_object <- generateAndWriteByteCode hsc_env cgguts mod_location
|
| 2226 | 2225 | -- Either, get the same time as the .gbc file if it exists, or just the current time.
|
| 2227 | 2226 | -- It's important the time of the linkable matches the time of the .gbc file for recompilation
|
| 2228 | 2227 | -- checking.
|
| 2229 | 2228 | bco_time <- maybe getCurrentTime pure =<< modificationTimeIfExists (ml_bytecode_file_ospath mod_location)
|
| 2230 | - return $ mkModuleByteCodeLinkable bco_time bco_object
|
|
| 2229 | + return $ mkOnlyModuleByteCodeLinkable bco_time bco_object
|
|
| 2231 | 2230 | |
| 2232 | 2231 | mkModuleByteCode :: HscEnv -> Module -> ModLocation -> CgInteractiveGuts -> IO ModuleByteCode
|
| 2233 | 2232 | mkModuleByteCode hsc_env mod mod_location cgguts = do
|
| 2234 | 2233 | bcos <- hscGenerateByteCode hsc_env cgguts mod_location
|
| 2235 | 2234 | objs <- outputAndCompileForeign hsc_env mod mod_location (cgi_foreign_files cgguts) (cgi_foreign cgguts)
|
| 2236 | - return $! ModuleByteCode mod bcos objs
|
|
| 2235 | + ByteCode.mkModuleByteCode mod bcos objs
|
|
| 2237 | 2236 | |
| 2238 | 2237 | -- | Generate a fresh 'ModuleByteCode' for a given module but do not write it to disk.
|
| 2239 | 2238 | generateFreshByteCodeLinkable :: HscEnv
|
| ... | ... | @@ -2755,13 +2754,13 @@ hscTidy hsc_env guts = do |
| 2755 | 2754 | %* *
|
| 2756 | 2755 | %********************************************************************* -}
|
| 2757 | 2756 | |
| 2758 | -hscCompileCoreExpr :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
|
|
| 2757 | +hscCompileCoreExpr :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
|
|
| 2759 | 2758 | hscCompileCoreExpr hsc_env loc expr =
|
| 2760 | 2759 | case hscCompileCoreExprHook (hsc_hooks hsc_env) of
|
| 2761 | 2760 | Nothing -> hscCompileCoreExpr' hsc_env loc expr
|
| 2762 | 2761 | Just h -> h hsc_env loc expr
|
| 2763 | 2762 | |
| 2764 | -hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [Linkable], PkgsLoaded)
|
|
| 2763 | +hscCompileCoreExpr' :: HscEnv -> SrcSpan -> CoreExpr -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
|
|
| 2765 | 2764 | hscCompileCoreExpr' hsc_env srcspan ds_expr = do
|
| 2766 | 2765 | {- Simplify it -}
|
| 2767 | 2766 | -- Question: should we call SimpleOpt.simpleOptExpr here instead?
|
| ... | ... | @@ -2847,8 +2846,9 @@ hscCompileCoreExpr' hsc_env srcspan ds_expr = do |
| 2847 | 2846 | |
| 2848 | 2847 | {- load it -}
|
| 2849 | 2848 | bco_time <- getCurrentTime
|
| 2849 | + mbc <- ByteCode.mkModuleByteCode this_mod bcos []
|
|
| 2850 | 2850 | (mods_needed, units_needed) <- loadDecls interp hsc_env srcspan $
|
| 2851 | - Linkable bco_time this_mod $ NE.singleton $ DotGBC (ModuleByteCode this_mod bcos [])
|
|
| 2851 | + Linkable bco_time this_mod $ NE.singleton (DotGBC mbc)
|
|
| 2852 | 2852 | -- Get the foreign reference to the name we should have just loaded.
|
| 2853 | 2853 | mhvs <- lookupFromLoadedEnv interp (idName binding_id)
|
| 2854 | 2854 | {- Get the HValue for the root -}
|
| ... | ... | @@ -2864,7 +2864,7 @@ jsCodeGen |
| 2864 | 2864 | -> Module
|
| 2865 | 2865 | -> [(CgStgTopBinding,IdSet)]
|
| 2866 | 2866 | -> Id
|
| 2867 | - -> IO (ForeignHValue, [Linkable], PkgsLoaded)
|
|
| 2867 | + -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
|
|
| 2868 | 2868 | jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id = do
|
| 2869 | 2869 | let logger = hsc_logger hsc_env
|
| 2870 | 2870 | tmpfs = hsc_tmpfs hsc_env
|
| ... | ... | @@ -430,7 +430,7 @@ link' hsc_env batch_attempt_linking mHscMessager hpt |
| 430 | 430 | let obj_files = concatMap linkableObjs linkables
|
| 431 | 431 | in action obj_files
|
| 432 | 432 | linkBytecodeLinkable action =
|
| 433 | - checkLinkablesUpToDate hsc_env mHscMessager home_mods pkg_deps staticLink checkBytecodeLibraryLinkingNeeded homeMod_bytecode $ \linkables ->
|
|
| 433 | + checkLinkablesUpToDate hsc_env mHscMessager home_mods pkg_deps staticLink checkBytecodeLibraryLinkingNeeded homeModLinkableByteCode $ \linkables ->
|
|
| 434 | 434 | let bytecode = concatMap linkableModuleByteCodes linkables
|
| 435 | 435 | in action bytecode
|
| 436 | 436 |
| ... | ... | @@ -342,7 +342,7 @@ data Plugins = Plugins |
| 342 | 342 | -- The purpose of this field is to cache the plugins so they
|
| 343 | 343 | -- don't have to be loaded each time they are needed. See
|
| 344 | 344 | -- 'GHC.Runtime.Loader.initializePlugins'.
|
| 345 | - , loadedPluginDeps :: !([Linkable], PkgsLoaded)
|
|
| 345 | + , loadedPluginDeps :: !([LinkableUsage], PkgsLoaded)
|
|
| 346 | 346 | -- ^ The object files required by the loaded plugins
|
| 347 | 347 | -- See Note [Plugin dependencies]
|
| 348 | 348 | }
|
| ... | ... | @@ -7,8 +7,6 @@ module GHC.HsToCore.Usage ( |
| 7 | 7 | |
| 8 | 8 | import GHC.Prelude
|
| 9 | 9 | |
| 10 | -import GHC.Driver.Env
|
|
| 11 | - |
|
| 12 | 10 | import GHC.Tc.Types
|
| 13 | 11 | |
| 14 | 12 | import GHC.Iface.Load
|
| ... | ... | @@ -27,7 +25,6 @@ import GHC.Types.Unique.Set |
| 27 | 25 | |
| 28 | 26 | import GHC.Unit
|
| 29 | 27 | import GHC.Unit.Env
|
| 30 | -import GHC.Unit.External
|
|
| 31 | 28 | import GHC.Unit.Module.Imported
|
| 32 | 29 | import GHC.Unit.Module.ModIface
|
| 33 | 30 | import GHC.Unit.Module.Deps
|
| ... | ... | @@ -35,18 +32,17 @@ import GHC.Unit.Module.Deps |
| 35 | 32 | import GHC.Data.Maybe
|
| 36 | 33 | import GHC.Data.FastString
|
| 37 | 34 | |
| 38 | -import Data.IORef
|
|
| 39 | 35 | import Data.List (sortBy)
|
| 40 | 36 | import Data.Map (Map)
|
| 41 | 37 | import qualified Data.Map as Map
|
| 42 | 38 | import qualified Data.Set as Set
|
| 43 | -import qualified Data.List.NonEmpty as NE
|
|
| 44 | 39 | |
| 45 | 40 | import GHC.Linker.Types
|
| 46 | 41 | import GHC.Unit.Finder
|
| 47 | 42 | import GHC.Types.Unique.DFM
|
| 48 | 43 | import GHC.Driver.Plugins
|
| 49 | 44 | import qualified GHC.Unit.Home.Graph as HUG
|
| 45 | +import qualified Data.List.NonEmpty as NE
|
|
| 50 | 46 | |
| 51 | 47 | {- Note [Module self-dependency]
|
| 52 | 48 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| ... | ... | @@ -75,19 +71,17 @@ data UsageConfig = UsageConfig |
| 75 | 71 | |
| 76 | 72 | mkUsageInfo :: UsageConfig -> Plugins -> FinderCache -> UnitEnv
|
| 77 | 73 | -> Module -> ImportedMods -> [ImportUserSpec] -> NameSet
|
| 78 | - -> [FilePath] -> [FilePath] -> [(Module, Fingerprint)] -> [Linkable] -> PkgsLoaded
|
|
| 74 | + -> [FilePath] -> [FilePath] -> [(Module, Fingerprint)] -> [LinkableUsage] -> PkgsLoaded
|
|
| 79 | 75 | -> IfG [Usage]
|
| 80 | 76 | mkUsageInfo uc plugins fc unit_env
|
| 81 | 77 | this_mod dir_imp_mods imp_decls used_names
|
| 82 | 78 | dependent_files dependent_dirs merged needed_links needed_pkgs
|
| 83 | 79 | = do
|
| 84 | - eps <- liftIO $ readIORef (euc_eps (ue_eps unit_env))
|
|
| 85 | 80 | file_hashes <- liftIO $ mapM getFileHash dependent_files
|
| 86 | 81 | dirs_hashes <- liftIO $ mapM getDirHash dependent_dirs
|
| 87 | 82 | let hu = ue_unsafeHomeUnit unit_env
|
| 88 | - hug = ue_home_unit_graph unit_env
|
|
| 89 | 83 | -- Dependencies on object files due to TH and plugins
|
| 90 | - object_usages <- liftIO $ mkObjectUsage (eps_PIT eps) plugins fc hug needed_links needed_pkgs
|
|
| 84 | + object_usages <- liftIO $ mkObjectUsage plugins fc needed_links needed_pkgs
|
|
| 91 | 85 | let all_home_ids = HUG.allUnits (ue_home_unit_graph unit_env)
|
| 92 | 86 | mod_usages <- mk_mod_usage_info uc hu all_home_ids this_mod
|
| 93 | 87 | dir_imp_mods imp_decls used_names
|
| ... | ... | @@ -176,44 +170,39 @@ For bytecode objects there are also two forms of dependencies. |
| 176 | 170 | 1. The existence of the .gbc file for the module you are currently compiling.
|
| 177 | 171 | 2. The usage of bytecode to evaluate TH splices (similar to Note [Object File Dependencies])
|
| 178 | 172 | |
| 179 | -In situation (2), we would ideally want to record the hash of the `CompiledByteCode` which
|
|
| 180 | -was used when evaluating the TH splice. This was a bit tricky to implement so it's tracked as a future
|
|
| 181 | -improvement to the recompilation checking for bytecode objects.
|
|
| 182 | - |
|
| 183 | -For now, the interface hash is used as a proxy to determine if the BCO will have changed
|
|
| 184 | -for a module or not. This is similar to how the recompilation checking for the legacy
|
|
| 185 | -`-fwrite-if-simplified-core` code path which generated bytecode from core bindings used to work.
|
|
| 186 | - |
|
| 173 | +In both cases, we record the hash of the 'CompiledByteCode' which was used when evaluating
|
|
| 174 | +the TH splice.
|
|
| 187 | 175 | -}
|
| 188 | 176 | |
| 189 | 177 | |
| 190 | 178 | |
| 191 | 179 | -- | Find object files corresponding to the transitive closure of given home
|
| 192 | 180 | -- modules and direct object files for pkg dependencies
|
| 193 | -mkObjectUsage :: PackageIfaceTable -> Plugins -> FinderCache -> HomeUnitGraph-> [Linkable] -> PkgsLoaded -> IO [Usage]
|
|
| 194 | -mkObjectUsage pit plugins fc hug th_links_needed th_pkgs_needed = do
|
|
| 181 | +mkObjectUsage :: Plugins -> FinderCache -> [LinkableUsage] -> PkgsLoaded -> IO [Usage]
|
|
| 182 | +mkObjectUsage plugins fc th_links_needed th_pkgs_needed = do
|
|
| 195 | 183 | let ls = ordNubOn linkableModule (th_links_needed ++ plugins_links_needed)
|
| 196 | 184 | ds = concatMap loaded_pkg_hs_objs $ eltsUDFM (plusUDFM th_pkgs_needed plugin_pkgs_needed) -- TODO possibly record loaded_pkg_non_hs_objs as well
|
| 197 | 185 | (plugins_links_needed, plugin_pkgs_needed) = loadedPluginDeps plugins
|
| 198 | 186 | concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds)
|
| 199 | 187 | where
|
| 200 | - linkableToUsage (Linkable _ m uls) = mapM (partToUsage m) (NE.toList uls)
|
|
| 188 | + linkableToUsage (Linkable _ _m parts) = traverse partToUsage (NE.toList parts)
|
|
| 201 | 189 | |
| 202 | 190 | msg m = moduleNameString (moduleName m) ++ "[TH] changed"
|
| 203 | 191 | |
| 204 | - fing mmsg fn = UsageFile (mkFastString fn) <$> lookupFileCache fc fn <*> pure mmsg
|
|
| 192 | + partToUsage link_usage =
|
|
| 193 | + case link_usage of
|
|
| 194 | + FileLinkablePartUsage{flu_file, flu_module} -> do
|
|
| 195 | + fing (Just $ msg flu_module) flu_file
|
|
| 205 | 196 | |
| 206 | - partToUsage m part =
|
|
| 207 | - case linkablePartPath part of
|
|
| 208 | - Just fn -> fing (Just (msg m)) fn
|
|
| 209 | - Nothing -> do
|
|
| 210 | - -- This should only happen for home package things but oneshot puts
|
|
| 211 | - -- home package ifaces in the PIT.
|
|
| 212 | - miface <- lookupIfaceByModule hug pit m
|
|
| 213 | - case miface of
|
|
| 214 | - Nothing -> pprPanic "linkableToUsage" (ppr m)
|
|
| 215 | - Just iface ->
|
|
| 216 | - return $ UsageHomeModuleInterface (moduleName m) (toUnitId $ moduleUnit m) (mi_iface_hash iface)
|
|
| 197 | + ByteCodeLinkablePartUsage{bclu_module, bclu_hash} ->
|
|
| 198 | + pure $
|
|
| 199 | + UsageHomeModuleBytecode
|
|
| 200 | + { usg_mod_name = moduleName bclu_module
|
|
| 201 | + , usg_unit_id = toUnitId $ moduleUnit bclu_module
|
|
| 202 | + , usg_bytecode_hash = bclu_hash
|
|
| 203 | + }
|
|
| 204 | + |
|
| 205 | + fing mmsg fn = UsageFile (mkFastString fn) <$> lookupFileCache fc fn <*> pure mmsg
|
|
| 217 | 206 | |
| 218 | 207 | librarySpecToUsage :: LibrarySpec -> IO [Usage]
|
| 219 | 208 | librarySpecToUsage (Objects os) = traverse (fing Nothing) os
|
| ... | ... | @@ -88,6 +88,10 @@ import GHC.Iface.Errors.Ppr |
| 88 | 88 | import Data.Functor
|
| 89 | 89 | import Data.Bifunctor (first)
|
| 90 | 90 | import GHC.Types.PkgQual
|
| 91 | +import GHC.ByteCode.Serialize (ModuleByteCode, gbc_hash)
|
|
| 92 | +import GHC.Unit.Home.Graph (lookupHugByModule)
|
|
| 93 | +import GHC.Unit.Home.ModInfo (HomeModLinkable(..), HomeModInfo (..))
|
|
| 94 | +import GHC.Linker.Types (linkableParts)
|
|
| 91 | 95 | |
| 92 | 96 | {-
|
| 93 | 97 | -----------------------------------------------
|
| ... | ... | @@ -190,6 +194,7 @@ data RecompReason |
| 190 | 194 | | ModuleAdded (ImportLevel, UnitId, ModuleName)
|
| 191 | 195 | | ModuleChangedRaw ModuleName
|
| 192 | 196 | | ModuleChangedIface ModuleName
|
| 197 | + | ModuleChangedBytecode ModuleName
|
|
| 193 | 198 | | FileChanged FilePath
|
| 194 | 199 | | DirChanged FilePath
|
| 195 | 200 | | CustomReason String
|
| ... | ... | @@ -224,6 +229,7 @@ instance Outputable RecompReason where |
| 224 | 229 | ModuleChanged m -> ppr m <+> text "changed"
|
| 225 | 230 | ModuleChangedRaw m -> ppr m <+> text "changed (raw)"
|
| 226 | 231 | ModuleChangedIface m -> ppr m <+> text "changed (interface)"
|
| 232 | + ModuleChangedBytecode m -> ppr m <+> text "changed (bytecode)"
|
|
| 227 | 233 | ModuleRemoved (_st, _uid, m) -> ppr m <+> text "removed"
|
| 228 | 234 | ModuleAdded (_st, _uid, m) -> ppr m <+> text "added"
|
| 229 | 235 | FileChanged fp -> text fp <+> text "changed"
|
| ... | ... | @@ -716,6 +722,15 @@ needInterface mod continue |
| 716 | 722 | Nothing -> return $ NeedsRecompile MustCompile
|
| 717 | 723 | Just iface -> liftIO $ continue iface
|
| 718 | 724 | |
| 725 | +needBytecode :: Module -> (ModuleByteCode -> IO RecompileRequired)
|
|
| 726 | + -> IfG RecompileRequired
|
|
| 727 | +needBytecode mod continue
|
|
| 728 | + = do
|
|
| 729 | + mb_recomp <- tryGetBytecode mod
|
|
| 730 | + case mb_recomp of
|
|
| 731 | + Nothing -> return $ NeedsRecompile MustCompile
|
|
| 732 | + Just mbc -> liftIO $ continue mbc
|
|
| 733 | + |
|
| 719 | 734 | tryGetModIface :: String -> Module -> IfG (Maybe ModIface)
|
| 720 | 735 | tryGetModIface doc_msg mod
|
| 721 | 736 | = do -- Load the imported interface if possible
|
| ... | ... | @@ -737,6 +752,27 @@ tryGetModIface doc_msg mod |
| 737 | 752 | -- import and it's been deleted
|
| 738 | 753 | Succeeded iface -> pure $ Just iface
|
| 739 | 754 | |
| 755 | +tryGetBytecode :: Module -> IfG (Maybe ModuleByteCode)
|
|
| 756 | +tryGetBytecode mod
|
|
| 757 | + = do -- Load the imported bytecode if possible
|
|
| 758 | + logger <- getLogger
|
|
| 759 | + liftIO $ trace_hi_diffs logger (text "Checking bytecode hash for module" <+> ppr mod <+> ppr (moduleUnit mod))
|
|
| 760 | + |
|
| 761 | + mb_module_bytecode <- do
|
|
| 762 | + env <- getTopEnv
|
|
| 763 | + liftIO (lookupHugByModule mod (hsc_HUG env)) >>= \ case
|
|
| 764 | + Nothing -> pure Nothing
|
|
| 765 | + Just hmi ->
|
|
| 766 | + case homeMod_bytecode (hm_linkable hmi) of
|
|
| 767 | + Nothing -> pure Nothing
|
|
| 768 | + Just gbc_linkable -> pure $ Just $ linkableParts gbc_linkable
|
|
| 769 | + |
|
| 770 | + case mb_module_bytecode of
|
|
| 771 | + Nothing -> do
|
|
| 772 | + liftIO $ trace_hi_diffs logger (sep [text "Couldn't find bytecode for module", ppr mod])
|
|
| 773 | + return Nothing
|
|
| 774 | + Just module_bytecode -> pure $ Just module_bytecode
|
|
| 775 | + |
|
| 740 | 776 | -- | Given the usage information extracted from the old
|
| 741 | 777 | -- M.hi file for the module being compiled, figure out
|
| 742 | 778 | -- whether M needs to be recompiled.
|
| ... | ... | @@ -758,14 +794,14 @@ checkModUsage _ UsageMergedRequirement{ usg_mod = mod, usg_mod_hash = old_mod_ha |
| 758 | 794 | needInterface mod $ \iface -> do
|
| 759 | 795 | let reason = ModuleChangedRaw (moduleName mod)
|
| 760 | 796 | checkModuleFingerprint logger reason old_mod_hash (mi_mod_hash iface)
|
| 761 | -checkModUsage _ UsageHomeModuleInterface{ usg_mod_name = mod_name
|
|
| 797 | +checkModUsage _ UsageHomeModuleBytecode{ usg_mod_name = mod_name
|
|
| 762 | 798 | , usg_unit_id = uid
|
| 763 | - , usg_iface_hash = old_mod_hash } = do
|
|
| 799 | + , usg_bytecode_hash = old_bytecode_hash } = do
|
|
| 764 | 800 | let mod = mkModule (RealUnit (Definite uid)) mod_name
|
| 765 | 801 | logger <- getLogger
|
| 766 | - needInterface mod $ \iface -> do
|
|
| 767 | - let reason = ModuleChangedIface mod_name
|
|
| 768 | - checkIfaceFingerprint logger reason old_mod_hash (mi_iface_hash iface)
|
|
| 802 | + needBytecode mod $ \cbc -> do
|
|
| 803 | + let reason = ModuleChangedBytecode mod_name
|
|
| 804 | + checkBytecodeFingerprint logger reason old_bytecode_hash (gbc_hash cbc)
|
|
| 769 | 805 | |
| 770 | 806 | checkModUsage _ UsageHomeModule{
|
| 771 | 807 | usg_mod_name = mod_name,
|
| ... | ... | @@ -1030,19 +1066,18 @@ checkModuleFingerprint logger reason old_mod_hash new_mod_hash |
| 1030 | 1066 | = out_of_date_hash logger reason (text " Module fingerprint has changed")
|
| 1031 | 1067 | old_mod_hash new_mod_hash
|
| 1032 | 1068 | |
| 1033 | -checkIfaceFingerprint
|
|
| 1069 | +checkBytecodeFingerprint
|
|
| 1034 | 1070 | :: Logger
|
| 1035 | 1071 | -> RecompReason
|
| 1036 | 1072 | -> Fingerprint
|
| 1037 | 1073 | -> Fingerprint
|
| 1038 | 1074 | -> IO RecompileRequired
|
| 1039 | -checkIfaceFingerprint logger reason old_mod_hash new_mod_hash
|
|
| 1040 | - | new_mod_hash == old_mod_hash
|
|
| 1041 | - = up_to_date logger (text "Iface fingerprint unchanged")
|
|
| 1042 | - |
|
| 1075 | +checkBytecodeFingerprint logger reason old_bytecode_hash new_bytecode_hash
|
|
| 1076 | + | old_bytecode_hash == new_bytecode_hash
|
|
| 1077 | + = up_to_date logger (text "Bytecode fingerprint unchanged")
|
|
| 1043 | 1078 | | otherwise
|
| 1044 | - = out_of_date_hash logger reason (text " Iface fingerprint has changed")
|
|
| 1045 | - old_mod_hash new_mod_hash
|
|
| 1079 | + = out_of_date_hash logger reason (text " Bytecode fingerprint has changed")
|
|
| 1080 | + old_bytecode_hash new_bytecode_hash
|
|
| 1046 | 1081 | |
| 1047 | 1082 | ------------------------
|
| 1048 | 1083 | checkEntityUsage :: Logger
|
| ... | ... | @@ -146,10 +146,10 @@ pprUsage usage@UsageDirectory{} |
| 146 | 146 | ppr (usg_dir_hash usage)]
|
| 147 | 147 | pprUsage usage@UsageMergedRequirement{}
|
| 148 | 148 | = hsep [text "merged", ppr (usg_mod usage), ppr (usg_mod_hash usage)]
|
| 149 | -pprUsage usage@UsageHomeModuleInterface{}
|
|
| 150 | - = hsep [text "implementation", ppr (usg_mod_name usage)
|
|
| 149 | +pprUsage usage@UsageHomeModuleBytecode{}
|
|
| 150 | + = hsep [text "Bytecode", ppr (usg_mod_name usage)
|
|
| 151 | 151 | , ppr (usg_unit_id usage)
|
| 152 | - , ppr (usg_iface_hash usage)]
|
|
| 152 | + , ppr (usg_bytecode_hash usage)]
|
|
| 153 | 153 | |
| 154 | 154 | pprUsageImport :: Outputable mod => mod -> Fingerprint -> IsSafeImport -> SDoc
|
| 155 | 155 | pprUsageImport mod hash safe
|
| ... | ... | @@ -157,4 +157,4 @@ pprUsageImport mod hash safe |
| 157 | 157 | , ppr hash ]
|
| 158 | 158 | where
|
| 159 | 159 | pp_safe | safe = text "safe"
|
| 160 | - | otherwise = text " -/ " |
|
| \ No newline at end of file | ||
| 160 | + | otherwise = text " -/ " |
| ... | ... | @@ -31,7 +31,7 @@ linkBytecodeLib hsc_env gbcs = do |
| 31 | 31 | |
| 32 | 32 | on_disk_bcos <- mapM (readBinByteCode hsc_env) bytecodeObjects
|
| 33 | 33 | |
| 34 | - let (all_cbcs, foreign_stubs) = unzip [ (bs, fs) | ModuleByteCode _m bs fs <- on_disk_bcos ++ gbcs]
|
|
| 34 | + let (all_cbcs, foreign_stubs) = unzip [ (bs, fs) | ModuleByteCode _m bs fs _hash <- on_disk_bcos ++ gbcs]
|
|
| 35 | 35 | |
| 36 | 36 | interpreter_foreign_lib <- mkInterpreterLib hsc_env (concat foreign_stubs ++ objectFiles)
|
| 37 | 37 | |
| ... | ... | @@ -67,4 +67,4 @@ mkInterpreterLib hsc_env files = |
| 67 | 67 | return $ Just (InterpreterSharedObject foreign_stub_lib_path foreign_stub_lib_dir foreign_stub_lib_name)
|
| 68 | 68 | Nothing -> pure Nothing
|
| 69 | 69 | False -> do
|
| 70 | - pure $ Just (InterpreterStaticObjects files) |
|
| \ No newline at end of file | ||
| 70 | + pure $ Just (InterpreterStaticObjects files) |
| ... | ... | @@ -63,7 +63,7 @@ data LinkDepsOpts = LinkDepsOpts |
| 63 | 63 | |
| 64 | 64 | data LinkDeps = LinkDeps
|
| 65 | 65 | { ldNeededLinkables :: [Linkable]
|
| 66 | - , ldAllLinkables :: [Linkable]
|
|
| 66 | + , ldAllLinkables :: [LinkableUsage]
|
|
| 67 | 67 | , ldUnits :: [UnitId]
|
| 68 | 68 | , ldNeededUnits :: UniqDSet UnitId
|
| 69 | 69 | }
|
| ... | ... | @@ -126,7 +126,7 @@ get_link_deps opts pls maybe_normal_osuf span mods = do |
| 126 | 126 | |
| 127 | 127 | return $ LinkDeps
|
| 128 | 128 | { ldNeededLinkables = lnks_needed
|
| 129 | - , ldAllLinkables = links_got ++ lnks_needed
|
|
| 129 | + , ldAllLinkables = links_got ++ mkLinkablesUsage lnks_needed
|
|
| 130 | 130 | , ldUnits = pkgs_needed
|
| 131 | 131 | , ldNeededUnits = pkgs_s
|
| 132 | 132 | }
|
| ... | ... | @@ -230,7 +230,7 @@ lookupFromLoadedEnv interp name = do |
| 230 | 230 | -- | Load the module containing the given Name and get its associated 'HValue'.
|
| 231 | 231 | --
|
| 232 | 232 | -- Throws a 'ProgramError' if loading fails or the name cannot be found.
|
| 233 | -loadName :: Interp -> HscEnv -> Name -> IO (ForeignHValue, [Linkable], PkgsLoaded)
|
|
| 233 | +loadName :: Interp -> HscEnv -> Name -> IO (ForeignHValue, [LinkableUsage], PkgsLoaded)
|
|
| 234 | 234 | loadName interp hsc_env name = do
|
| 235 | 235 | initLoaderState interp hsc_env
|
| 236 | 236 | modifyLoaderState interp $ \pls0 -> do
|
| ... | ... | @@ -274,7 +274,7 @@ loadDependencies |
| 274 | 274 | -> LoaderState
|
| 275 | 275 | -> SrcSpan
|
| 276 | 276 | -> [Module]
|
| 277 | - -> IO (LoaderState, SuccessFlag, [Linkable], PkgsLoaded) -- ^ returns the set of linkables required
|
|
| 277 | + -> IO (LoaderState, SuccessFlag, [LinkableUsage], PkgsLoaded) -- ^ returns the set of linkables required
|
|
| 278 | 278 | -- When called, the loader state must have been initialized (see `initLoaderState`)
|
| 279 | 279 | loadDependencies interp hsc_env pls span needed_mods = do
|
| 280 | 280 | let opts = initLinkDepsOpts hsc_env
|
| ... | ... | @@ -656,7 +656,7 @@ initLinkDepsOpts hsc_env = opts |
| 656 | 656 | dflags = hsc_dflags hsc_env
|
| 657 | 657 | |
| 658 | 658 | ldLoadByteCode mod locn = do
|
| 659 | - bytecode_linkable <- findBytecodeLinkableMaybe hsc_env mod locn
|
|
| 659 | + bytecode_linkable <- findBytecodeLinkableMaybe hsc_env locn
|
|
| 660 | 660 | case bytecode_linkable of
|
| 661 | 661 | Nothing -> findWholeCoreBindings hsc_env mod
|
| 662 | 662 | Just bco -> return (Just bco)
|
| ... | ... | @@ -670,19 +670,14 @@ findWholeCoreBindings hsc_env mod = do |
| 670 | 670 | sequence (lookupModuleEnv eps_iface_bytecode mod)
|
| 671 | 671 | |
| 672 | 672 | |
| 673 | -findBytecodeLinkableMaybe :: HscEnv -> Module -> ModLocation -> IO (Maybe Linkable)
|
|
| 674 | -findBytecodeLinkableMaybe hsc_env mod locn = do
|
|
| 673 | +findBytecodeLinkableMaybe :: HscEnv -> ModLocation -> IO (Maybe Linkable)
|
|
| 674 | +findBytecodeLinkableMaybe hsc_env locn = do
|
|
| 675 | 675 | let bytecode_fn = ml_bytecode_file locn
|
| 676 | 676 | bytecode_fn_os = ml_bytecode_file_ospath locn
|
| 677 | 677 | maybe_bytecode_time <- modificationTimeIfExists bytecode_fn_os
|
| 678 | 678 | case maybe_bytecode_time of
|
| 679 | 679 | Nothing -> return Nothing
|
| 680 | 680 | Just bytecode_time -> do
|
| 681 | - -- Also load the interface, for reasons to do with recompilation avoidance.
|
|
| 682 | - -- See Note [Recompilation avoidance with bytecode objects]
|
|
| 683 | - _ <- initIfaceLoad hsc_env $
|
|
| 684 | - loadInterface (text "get_reachable_nodes" <+> parens (ppr mod))
|
|
| 685 | - mod ImportBySystem
|
|
| 686 | 681 | bco <- readBinByteCode hsc_env bytecode_fn
|
| 687 | 682 | return $ Just $ mkModuleByteCodeLinkable bytecode_time bco
|
| 688 | 683 | |
| ... | ... | @@ -734,7 +729,7 @@ get_reachable_nodes hsc_env mods |
| 734 | 729 | ********************************************************************* -}
|
| 735 | 730 | |
| 736 | 731 | -- | Load the dependencies of a linkable, and then load the linkable itself.
|
| 737 | -loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([Linkable], PkgsLoaded)
|
|
| 732 | +loadDecls :: Interp -> HscEnv -> SrcSpan -> Linkable -> IO ([LinkableUsage], PkgsLoaded)
|
|
| 738 | 733 | loadDecls interp hsc_env span linkable = do
|
| 739 | 734 | -- Initialise the linker (if it's not been done already)
|
| 740 | 735 | initLoaderState interp hsc_env
|
| ... | ... | @@ -834,7 +829,7 @@ loadModuleLinkables interp hsc_env pls keep_spec linkables |
| 834 | 829 | (objs, bcos) = partitionLinkables linkables
|
| 835 | 830 | |
| 836 | 831 | |
| 837 | -linkableInSet :: Linkable -> LinkableSet -> Bool
|
|
| 832 | +linkableInSet :: Linkable -> LinkableSet LinkableUsage -> Bool
|
|
| 838 | 833 | linkableInSet l objs_loaded =
|
| 839 | 834 | case lookupModuleEnv objs_loaded (linkableModule l) of
|
| 840 | 835 | Nothing -> False
|
| ... | ... | @@ -963,17 +958,17 @@ dynLoadObjs interp hsc_env pls objs = do |
| 963 | 958 | then addWay WayProf
|
| 964 | 959 | else id
|
| 965 | 960 | |
| 966 | -rmDupLinkables :: LinkableSet -- Already loaded
|
|
| 967 | - -> [Linkable] -- New linkables
|
|
| 968 | - -> (LinkableSet, -- New loaded set (including new ones)
|
|
| 961 | +rmDupLinkables :: LinkableSet LinkableUsage -- ^ Already loaded
|
|
| 962 | + -> [Linkable] -- ^ New linkables
|
|
| 963 | + -> (LinkableSet LinkableUsage, -- New loaded set (including new ones)
|
|
| 969 | 964 | [Linkable]) -- New linkables (excluding dups)
|
| 970 | 965 | rmDupLinkables already ls
|
| 971 | 966 | = go already [] ls
|
| 972 | 967 | where
|
| 973 | - go already extras [] = (already, extras)
|
|
| 974 | - go already extras (l:ls)
|
|
| 968 | + go !already extras [] = (already, extras)
|
|
| 969 | + go !already extras (l:ls)
|
|
| 975 | 970 | | linkableInSet l already = go already extras ls
|
| 976 | - | otherwise = go (extendModuleEnv already (linkableModule l) l) (l:extras) ls
|
|
| 971 | + | otherwise = go (extendModuleEnv already (linkableModule l) $! mkLinkableUsage l) (l:extras) ls
|
|
| 977 | 972 | |
| 978 | 973 | {- **********************************************************************
|
| 979 | 974 | |
| ... | ... | @@ -1126,7 +1121,7 @@ unload_wkr interp pls@LoaderState{..} = do |
| 1126 | 1121 | |
| 1127 | 1122 | -- If we unloaded any object files at all, we need to purge the cache
|
| 1128 | 1123 | -- of lookupSymbol results.
|
| 1129 | - when (not (null (filter (not . null . linkableObjs) linkables_to_unload))) $
|
|
| 1124 | + when (not (null (filter (not . null . linkableUsageObjs) linkables_to_unload))) $
|
|
| 1130 | 1125 | purgeLookupSymbolCache interp
|
| 1131 | 1126 | |
| 1132 | 1127 | let !new_pls = pls { bco_loader_state = modifyHomePackageBytecodeState bco_loader_state $ \_ -> emptyBytecodeState,
|
| ... | ... | @@ -1136,7 +1131,7 @@ unload_wkr interp pls@LoaderState{..} = do |
| 1136 | 1131 | |
| 1137 | 1132 | return new_pls
|
| 1138 | 1133 | where
|
| 1139 | - unloadObjs :: Linkable -> IO ()
|
|
| 1134 | + unloadObjs :: LinkableUsage -> IO ()
|
|
| 1140 | 1135 | unloadObjs lnk
|
| 1141 | 1136 | | interpreterDynamic interp = return ()
|
| 1142 | 1137 | -- We don't do any cleanup when linking objects with the
|
| ... | ... | @@ -1144,7 +1139,7 @@ unload_wkr interp pls@LoaderState{..} = do |
| 1144 | 1139 | -- not much benefit.
|
| 1145 | 1140 | |
| 1146 | 1141 | | otherwise
|
| 1147 | - = mapM_ (unloadObj interp) (linkableObjs lnk)
|
|
| 1142 | + = mapM_ (unloadObj interp) (linkableUsageObjs lnk)
|
|
| 1148 | 1143 | -- The components of a BCO linkable may contain
|
| 1149 | 1144 | -- dot-o files (generated from C stubs).
|
| 1150 | 1145 | --
|
| ... | ... | @@ -49,6 +49,7 @@ module GHC.Linker.Types |
| 49 | 49 | , WholeCoreBindingsLinkable
|
| 50 | 50 | , LinkableWith(..)
|
| 51 | 51 | , mkModuleByteCodeLinkable
|
| 52 | + , mkOnlyModuleByteCodeLinkable
|
|
| 52 | 53 | , LinkablePart(..)
|
| 53 | 54 | , LinkableObjectSort (..)
|
| 54 | 55 | , linkableIsNativeCodeOnly
|
| ... | ... | @@ -67,6 +68,11 @@ module GHC.Linker.Types |
| 67 | 68 | , linkableFilterNative
|
| 68 | 69 | , partitionLinkables
|
| 69 | 70 | |
| 71 | + , LinkableUsage
|
|
| 72 | + , linkableUsageObjs
|
|
| 73 | + , mkLinkablesUsage
|
|
| 74 | + , mkLinkableUsage
|
|
| 75 | + |
|
| 70 | 76 | , ModuleByteCode(..)
|
| 71 | 77 | )
|
| 72 | 78 | where
|
| ... | ... | @@ -78,26 +84,29 @@ import GHCi.BreakArray |
| 78 | 84 | import GHCi.RemoteTypes
|
| 79 | 85 | import GHCi.Message ( LoadedDLL )
|
| 80 | 86 | |
| 87 | +import qualified GHC.Data.OsPath as OsPath
|
|
| 88 | +import qualified GHC.Data.FlatBag as FlatBag
|
|
| 89 | +import GHC.Fingerprint (Fingerprint)
|
|
| 81 | 90 | import GHC.Stack.CCS
|
| 82 | 91 | import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnvList, lookupNameEnv )
|
| 83 | 92 | import GHC.Types.Name ( Name )
|
| 84 | 93 | import GHC.Types.SptEntry
|
| 94 | +import GHC.Types.Unique.DSet
|
|
| 95 | +import GHC.Types.Unique.DFM
|
|
| 96 | +import GHC.Unit.Module.Deps (LinkablePartUsage (..), linkablePartUsageObjectPaths)
|
|
| 97 | +import GHC.Unit.Module.Env
|
|
| 98 | +import GHC.Unit.Module.WholeCoreBindings
|
|
| 85 | 99 | |
| 86 | 100 | import GHC.Utils.Outputable
|
| 87 | 101 | |
| 102 | +import Control.Applicative ((<|>))
|
|
| 88 | 103 | import Control.Concurrent.MVar
|
| 89 | 104 | import Data.Array
|
| 105 | +import Data.Functor.Identity
|
|
| 90 | 106 | import Data.Time ( UTCTime )
|
| 91 | -import GHC.Unit.Module.Env
|
|
| 92 | -import GHC.Types.Unique.DSet
|
|
| 93 | -import GHC.Types.Unique.DFM
|
|
| 94 | -import GHC.Unit.Module.WholeCoreBindings
|
|
| 95 | 107 | import Data.Maybe (mapMaybe)
|
| 96 | 108 | import Data.List.NonEmpty (NonEmpty, nonEmpty)
|
| 97 | 109 | import qualified Data.List.NonEmpty as NE
|
| 98 | -import Control.Applicative ((<|>))
|
|
| 99 | -import Data.Functor.Identity
|
|
| 100 | - |
|
| 101 | 110 | |
| 102 | 111 | {- **********************************************************************
|
| 103 | 112 | |
| ... | ... | @@ -172,10 +181,10 @@ data LoaderState = LoaderState |
| 172 | 181 | -- ^ Information about bytecode objects we have loaded into the
|
| 173 | 182 | -- interpreter.
|
| 174 | 183 | |
| 175 | - , bcos_loaded :: !LinkableSet
|
|
| 184 | + , bcos_loaded :: !(LinkableSet LinkableUsage)
|
|
| 176 | 185 | -- ^ The currently loaded interpreted modules (home package)
|
| 177 | 186 | |
| 178 | - , objs_loaded :: !LinkableSet
|
|
| 187 | + , objs_loaded :: !(LinkableSet LinkableUsage)
|
|
| 179 | 188 | -- ^ And the currently-loaded compiled modules (home package)
|
| 180 | 189 | |
| 181 | 190 | , pkgs_loaded :: !PkgsLoaded
|
| ... | ... | @@ -384,15 +393,17 @@ type Linkable = LinkableWith (NonEmpty LinkablePart) |
| 384 | 393 | |
| 385 | 394 | type WholeCoreBindingsLinkable = LinkableWith WholeCoreBindings
|
| 386 | 395 | |
| 387 | -type LinkableSet = ModuleEnv Linkable
|
|
| 396 | +type LinkableUsage = LinkableWith (NonEmpty LinkablePartUsage)
|
|
| 388 | 397 | |
| 389 | -mkLinkableSet :: [Linkable] -> LinkableSet
|
|
| 398 | +type LinkableSet = ModuleEnv
|
|
| 399 | + |
|
| 400 | +mkLinkableSet :: [Linkable] -> LinkableSet Linkable
|
|
| 390 | 401 | mkLinkableSet ls = mkModuleEnv [(linkableModule l, l) | l <- ls]
|
| 391 | 402 | |
| 392 | 403 | -- | Union of LinkableSets.
|
| 393 | 404 | --
|
| 394 | 405 | -- In case of conflict, keep the most recent Linkable (as per linkableTime)
|
| 395 | -unionLinkableSet :: LinkableSet -> LinkableSet -> LinkableSet
|
|
| 406 | +unionLinkableSet :: LinkableSet (LinkableWith a) -> LinkableSet (LinkableWith a) -> LinkableSet (LinkableWith a)
|
|
| 396 | 407 | unionLinkableSet = plusModuleEnv_C go
|
| 397 | 408 | where
|
| 398 | 409 | go l1 l2
|
| ... | ... | @@ -435,8 +446,9 @@ data LinkablePart |
| 435 | 446 | | DotDLL FilePath
|
| 436 | 447 | -- ^ Dynamically linked library file (.so, .dll, .dylib)
|
| 437 | 448 | |
| 438 | - | DotGBC ModuleByteCode
|
|
| 439 | - -- ^ A byte-code object, lives only in memory.
|
|
| 449 | + | DotGBC
|
|
| 450 | + -- ^ A byte-code object, lives only in memory.
|
|
| 451 | + ModuleByteCode
|
|
| 440 | 452 | |
| 441 | 453 | |
| 442 | 454 | -- | The in-memory representation of a bytecode object
|
| ... | ... | @@ -444,14 +456,19 @@ data LinkablePart |
| 444 | 456 | data ModuleByteCode = ModuleByteCode { gbc_module :: Module
|
| 445 | 457 | , gbc_compiled_byte_code :: CompiledByteCode
|
| 446 | 458 | , gbc_foreign_files :: [FilePath] -- ^ Path to object files
|
| 459 | + , gbc_hash :: !Fingerprint
|
|
| 447 | 460 | }
|
| 448 | 461 | |
| 449 | 462 | mkModuleByteCodeLinkable :: UTCTime -> ModuleByteCode -> Linkable
|
| 450 | -mkModuleByteCodeLinkable linkable_time bco =
|
|
| 463 | +mkModuleByteCodeLinkable linkable_time bco = do
|
|
| 451 | 464 | Linkable linkable_time (gbc_module bco) (pure (DotGBC bco))
|
| 452 | 465 | |
| 466 | +mkOnlyModuleByteCodeLinkable :: UTCTime -> ModuleByteCode -> LinkableWith ModuleByteCode
|
|
| 467 | +mkOnlyModuleByteCodeLinkable linkable_time bco = do
|
|
| 468 | + Linkable linkable_time (gbc_module bco) bco
|
|
| 469 | + |
|
| 453 | 470 | instance Outputable ModuleByteCode where
|
| 454 | - ppr (ModuleByteCode mod _cbc _fos) = text "ModuleByteCode" <+> ppr mod
|
|
| 471 | + ppr (ModuleByteCode mod _cbc _fos _) = text "ModuleByteCode" <+> ppr mod
|
|
| 455 | 472 | |
| 456 | 473 | instance Outputable LinkablePart where
|
| 457 | 474 | ppr (DotO path sort) = text "DotO" <+> text path <+> pprSort sort
|
| ... | ... | @@ -544,8 +561,8 @@ linkablePartObjectPaths = \case |
| 544 | 561 | -- Contrary to linkableBCOs, this includes byte-code from LazyBCOs.
|
| 545 | 562 | linkablePartBCOs :: LinkablePart -> [CompiledByteCode]
|
| 546 | 563 | linkablePartBCOs = \case
|
| 547 | - DotGBC bco -> [gbc_compiled_byte_code bco]
|
|
| 548 | - _ -> []
|
|
| 564 | + DotGBC bco -> [gbc_compiled_byte_code bco]
|
|
| 565 | + _ -> []
|
|
| 549 | 566 | |
| 550 | 567 | linkableFilter :: (LinkablePart -> [LinkablePart]) -> Linkable -> Maybe Linkable
|
| 551 | 568 | linkableFilter f linkable = do
|
| ... | ... | @@ -586,6 +603,59 @@ partitionLinkables linkables = |
| 586 | 603 | mapMaybe linkableFilterByteCode linkables
|
| 587 | 604 | )
|
| 588 | 605 | |
| 606 | +-- | Turn a 'Linkable' into a 'LinkableUsage'.
|
|
| 607 | +-- This stores much less information than 'Linkable' and allows us
|
|
| 608 | +-- to free the fields of the 'Linkable'.
|
|
| 609 | +--
|
|
| 610 | +-- Each 'LinkablePartUsage' is fully evaluated to avoid retaining any reference
|
|
| 611 | +-- to the original 'LinkablePart'.
|
|
| 612 | +mkLinkableUsage :: Linkable -> LinkableUsage
|
|
| 613 | +mkLinkableUsage lnk =
|
|
| 614 | + let
|
|
| 615 | + linkablesWithUsage = NE.map (go (linkableModule lnk)) (linkableParts lnk)
|
|
| 616 | + lnkUsage = lnk
|
|
| 617 | + { linkableParts =
|
|
| 618 | + -- We force the elements intentionally to whnf.
|
|
| 619 | + --
|
|
| 620 | + elemsToWhnf linkablesWithUsage `seq` linkablesWithUsage
|
|
| 621 | + }
|
|
| 622 | + in
|
|
| 623 | + linkableParts lnkUsage `seq` lnkUsage
|
|
| 624 | + where
|
|
| 625 | + -- Make sure 'LinkableUsagePart' is evaluated to whnf
|
|
| 626 | + elemsToWhnf :: NonEmpty a -> ()
|
|
| 627 | + elemsToWhnf = foldr seq ()
|
|
| 628 | + |
|
| 629 | + |
|
| 630 | + mkFileLinkablePartUsage m fp objs =
|
|
| 631 | + FileLinkablePartUsage
|
|
| 632 | + { flu_file = fp
|
|
| 633 | + , flu_module = m
|
|
| 634 | + , flu_linkable_objs =
|
|
| 635 | + FlatBag.fromList (strictGenericLength objs) [ OsPath.unsafeEncodeUtf obj | obj <- objs ]
|
|
| 636 | + }
|
|
| 637 | + |
|
| 638 | + mkByteCodeLinkablePartUsage m fp objs =
|
|
| 639 | + ByteCodeLinkablePartUsage
|
|
| 640 | + { bclu_module = m
|
|
| 641 | + , bclu_hash = fp
|
|
| 642 | + , bclu_linkable_objs =
|
|
| 643 | + FlatBag.fromList (strictGenericLength objs) [ OsPath.unsafeEncodeUtf obj | obj <- objs ]
|
|
| 644 | + }
|
|
| 645 | + |
|
| 646 | + go :: Module -> LinkablePart -> LinkablePartUsage
|
|
| 647 | + go m lnkPart = case lnkPart of
|
|
| 648 | + DotO fn _ -> mkFileLinkablePartUsage m fn (linkablePartObjectPaths lnkPart)
|
|
| 649 | + DotA fn -> mkFileLinkablePartUsage m fn (linkablePartObjectPaths lnkPart)
|
|
| 650 | + DotDLL fn -> mkFileLinkablePartUsage m fn (linkablePartObjectPaths lnkPart)
|
|
| 651 | + DotGBC mbc -> mkByteCodeLinkablePartUsage m (gbc_hash mbc) (linkablePartObjectPaths lnkPart)
|
|
| 652 | + |
|
| 653 | +mkLinkablesUsage :: [Linkable] -> [LinkableUsage]
|
|
| 654 | +mkLinkablesUsage linkables = map mkLinkableUsage linkables
|
|
| 655 | + |
|
| 656 | +linkableUsageObjs :: LinkableUsage -> [FilePath]
|
|
| 657 | +linkableUsageObjs lnkWithUsage = concatMap linkablePartUsageObjectPaths (linkableParts lnkWithUsage)
|
|
| 658 | + |
|
| 589 | 659 | {- **********************************************************************
|
| 590 | 660 | |
| 591 | 661 | Loading packages
|
| ... | ... | @@ -153,7 +153,7 @@ initializePlugins hsc_env |
| 153 | 153 | ([] , _ ) -> False -- some external plugin added
|
| 154 | 154 | (p:ps,s:ss) -> check_external_plugin p s && check_external_plugins ps ss
|
| 155 | 155 | |
| 156 | -loadPlugins :: HscEnv -> IO ([LoadedPlugin], [Linkable], PkgsLoaded)
|
|
| 156 | +loadPlugins :: HscEnv -> IO ([LoadedPlugin], [LinkableUsage], PkgsLoaded)
|
|
| 157 | 157 | loadPlugins hsc_env
|
| 158 | 158 | = do { unless (null to_load) $
|
| 159 | 159 | checkExternalInterpreter hsc_env
|
| ... | ... | @@ -173,7 +173,7 @@ loadPlugins hsc_env |
| 173 | 173 | loadPlugin = loadPlugin' (mkVarOccFS (fsLit "plugin")) pluginTyConName hsc_env
|
| 174 | 174 | |
| 175 | 175 | |
| 176 | -loadFrontendPlugin :: HscEnv -> ModuleName -> IO (FrontendPlugin, [Linkable], PkgsLoaded)
|
|
| 176 | +loadFrontendPlugin :: HscEnv -> ModuleName -> IO (FrontendPlugin, [LinkableUsage], PkgsLoaded)
|
|
| 177 | 177 | loadFrontendPlugin hsc_env mod_name = do
|
| 178 | 178 | checkExternalInterpreter hsc_env
|
| 179 | 179 | (plugin, _iface, links, pkgs)
|
| ... | ... | @@ -188,7 +188,7 @@ checkExternalInterpreter hsc_env = case interpInstance <$> hsc_interp hsc_env of |
| 188 | 188 | -> throwIO (InstallationError "Plugins require -fno-external-interpreter")
|
| 189 | 189 | _ -> pure ()
|
| 190 | 190 | |
| 191 | -loadPlugin' :: OccName -> Name -> HscEnv -> ModuleName -> IO (a, ModIface, [Linkable], PkgsLoaded)
|
|
| 191 | +loadPlugin' :: OccName -> Name -> HscEnv -> ModuleName -> IO (a, ModIface, [LinkableUsage], PkgsLoaded)
|
|
| 192 | 192 | loadPlugin' occ_name plugin_name hsc_env mod_name
|
| 193 | 193 | = do { let plugin_rdr_name = mkRdrQual mod_name occ_name
|
| 194 | 194 | dflags = hsc_dflags hsc_env
|
| ... | ... | @@ -266,7 +266,7 @@ forceLoadTyCon hsc_env con_name = do |
| 266 | 266 | -- * If the Name does not exist in the module
|
| 267 | 267 | -- * If the link failed
|
| 268 | 268 | |
| 269 | -getValueSafely :: HscEnv -> Name -> Type -> IO (Either Type (a, [Linkable], PkgsLoaded))
|
|
| 269 | +getValueSafely :: HscEnv -> Name -> Type -> IO (Either Type (a, [LinkableUsage], PkgsLoaded))
|
|
| 270 | 270 | getValueSafely hsc_env val_name expected_type = do
|
| 271 | 271 | eith_hval <- case getValueSafelyHook hooks of
|
| 272 | 272 | Nothing -> getHValueSafely interp hsc_env val_name expected_type
|
| ... | ... | @@ -281,7 +281,7 @@ getValueSafely hsc_env val_name expected_type = do |
| 281 | 281 | logger = hsc_logger hsc_env
|
| 282 | 282 | hooks = hsc_hooks hsc_env
|
| 283 | 283 | |
| 284 | -getHValueSafely :: Interp -> HscEnv -> Name -> Type -> IO (Either Type (HValue, [Linkable], PkgsLoaded))
|
|
| 284 | +getHValueSafely :: Interp -> HscEnv -> Name -> Type -> IO (Either Type (HValue, [LinkableUsage], PkgsLoaded))
|
|
| 285 | 285 | getHValueSafely interp hsc_env val_name expected_type = do
|
| 286 | 286 | forceLoadNameModuleInterface hsc_env (text "contains a name used in an invocation of getHValueSafely") val_name
|
| 287 | 287 | -- Now look up the names for the value and type constructor in the type environment
|
| ... | ... | @@ -562,7 +562,7 @@ data TcGblEnv |
| 562 | 562 | -- is implicit rather than explicit, so we have to zap a
|
| 563 | 563 | -- mutable variable.
|
| 564 | 564 | |
| 565 | - tcg_th_needed_deps :: TcRef ([Linkable], PkgsLoaded),
|
|
| 565 | + tcg_th_needed_deps :: TcRef ([LinkableUsage], PkgsLoaded),
|
|
| 566 | 566 | -- ^ The set of runtime dependencies required by this module
|
| 567 | 567 | -- See Note [Object File Dependencies]
|
| 568 | 568 |
| ... | ... | @@ -2259,7 +2259,7 @@ fillCoercionHole (CH { ch_ref = ref, ch_co_var = cv }) co |
| 2259 | 2259 | recordThUse :: TcM ()
|
| 2260 | 2260 | recordThUse = do { env <- getGblEnv; writeTcRef (tcg_th_used env) True }
|
| 2261 | 2261 | |
| 2262 | -recordThNeededRuntimeDeps :: [Linkable] -> PkgsLoaded -> TcM ()
|
|
| 2262 | +recordThNeededRuntimeDeps :: [LinkableUsage] -> PkgsLoaded -> TcM ()
|
|
| 2263 | 2263 | recordThNeededRuntimeDeps new_links new_pkgs
|
| 2264 | 2264 | = do { env <- getGblEnv
|
| 2265 | 2265 | ; updTcRef (tcg_th_needed_deps env) $ \(needed_links, needed_pkgs) ->
|
| ... | ... | @@ -3,9 +3,11 @@ |
| 3 | 3 | module GHC.Unit.Home.ModInfo
|
| 4 | 4 | (
|
| 5 | 5 | HomeModInfo (..)
|
| 6 | - , HomeModLinkable (..)
|
|
| 7 | 6 | , homeModInfoObject
|
| 8 | 7 | , homeModInfoByteCode
|
| 8 | + , HomeModLinkable (..)
|
|
| 9 | + , homeModLinkableByteCode
|
|
| 10 | + , homeModLinkableObject
|
|
| 9 | 11 | , emptyHomeModInfoLinkable
|
| 10 | 12 | )
|
| 11 | 13 | where
|
| ... | ... | @@ -15,9 +17,10 @@ import GHC.Prelude |
| 15 | 17 | import GHC.Unit.Module.ModIface
|
| 16 | 18 | import GHC.Unit.Module.ModDetails
|
| 17 | 19 | |
| 18 | -import GHC.Linker.Types ( Linkable )
|
|
| 20 | +import GHC.Linker.Types ( Linkable, LinkableWith, ModuleByteCode, LinkablePart (..) )
|
|
| 19 | 21 | |
| 20 | 22 | import GHC.Utils.Outputable
|
| 23 | +import qualified Data.List.NonEmpty as NE
|
|
| 21 | 24 | |
| 22 | 25 | -- | Information about modules in the package being compiled
|
| 23 | 26 | data HomeModInfo = HomeModInfo
|
| ... | ... | @@ -48,18 +51,24 @@ data HomeModInfo = HomeModInfo |
| 48 | 51 | }
|
| 49 | 52 | |
| 50 | 53 | homeModInfoByteCode :: HomeModInfo -> Maybe Linkable
|
| 51 | -homeModInfoByteCode = homeMod_bytecode . hm_linkable
|
|
| 54 | +homeModInfoByteCode = homeModLinkableByteCode . hm_linkable
|
|
| 52 | 55 | |
| 53 | 56 | homeModInfoObject :: HomeModInfo -> Maybe Linkable
|
| 54 | -homeModInfoObject = homeMod_object . hm_linkable
|
|
| 57 | +homeModInfoObject = homeModLinkableObject . hm_linkable
|
|
| 55 | 58 | |
| 56 | 59 | emptyHomeModInfoLinkable :: HomeModLinkable
|
| 57 | 60 | emptyHomeModInfoLinkable = HomeModLinkable Nothing Nothing
|
| 58 | 61 | |
| 59 | 62 | -- See Note [Home module build products]
|
| 60 | -data HomeModLinkable = HomeModLinkable { homeMod_bytecode :: !(Maybe Linkable)
|
|
| 63 | +data HomeModLinkable = HomeModLinkable { homeMod_bytecode :: !(Maybe (LinkableWith ModuleByteCode))
|
|
| 61 | 64 | , homeMod_object :: !(Maybe Linkable) }
|
| 62 | 65 | |
| 66 | +homeModLinkableByteCode :: HomeModLinkable -> Maybe Linkable
|
|
| 67 | +homeModLinkableByteCode = fmap (fmap (NE.singleton . DotGBC)) . homeMod_bytecode
|
|
| 68 | + |
|
| 69 | +homeModLinkableObject :: HomeModLinkable -> Maybe Linkable
|
|
| 70 | +homeModLinkableObject = homeMod_object
|
|
| 71 | + |
|
| 63 | 72 | instance Outputable HomeModLinkable where
|
| 64 | 73 | ppr (HomeModLinkable l1 l2) = ppr l1 $$ ppr l2
|
| 65 | 74 |
| ... | ... | @@ -22,16 +22,22 @@ module GHC.Unit.Module.Deps |
| 22 | 22 | , ImportAvails (..)
|
| 23 | 23 | , IfaceImportLevel(..)
|
| 24 | 24 | , tcImportLevel
|
| 25 | + , LinkablePartUsage(..)
|
|
| 26 | + , linkablePartUsageObjectPaths
|
|
| 25 | 27 | )
|
| 26 | 28 | where
|
| 27 | 29 | |
| 28 | 30 | import GHC.Prelude
|
| 29 | 31 | |
| 30 | 32 | import GHC.Data.FastString
|
| 33 | +import GHC.Data.FlatBag
|
|
| 34 | +import GHC.Data.OsPath
|
|
| 35 | +import qualified GHC.Data.OsPath as OsPath
|
|
| 31 | 36 | |
| 32 | 37 | import GHC.Types.Avail
|
| 33 | 38 | import GHC.Types.SafeHaskell
|
| 34 | 39 | import GHC.Types.Name
|
| 40 | +import GHC.Types.Name.Set
|
|
| 35 | 41 | import GHC.Types.Basic
|
| 36 | 42 | |
| 37 | 43 | import GHC.Unit.Module.Imported
|
| ... | ... | @@ -43,13 +49,12 @@ import GHC.Utils.Fingerprint |
| 43 | 49 | import GHC.Utils.Binary
|
| 44 | 50 | import GHC.Utils.Outputable
|
| 45 | 51 | |
| 52 | +import Control.DeepSeq
|
|
| 53 | +import Data.Bifunctor
|
|
| 54 | +import qualified Data.Foldable as Foldable
|
|
| 46 | 55 | import Data.List (sortBy, sort, partition)
|
| 47 | 56 | import Data.Set (Set)
|
| 48 | 57 | import qualified Data.Set as Set
|
| 49 | -import Data.Bifunctor
|
|
| 50 | -import Control.DeepSeq
|
|
| 51 | -import GHC.Types.Name.Set
|
|
| 52 | - |
|
| 53 | 58 | |
| 54 | 59 | |
| 55 | 60 | -- | Dependency information about ALL modules and packages below this one
|
| ... | ... | @@ -372,12 +377,12 @@ data Usage |
| 372 | 377 | -- we won't spot it here. If you do want to spot that, the caller
|
| 373 | 378 | -- should recursively add them to their useage.
|
| 374 | 379 | }
|
| 375 | - | UsageHomeModuleInterface {
|
|
| 380 | + | UsageHomeModuleBytecode {
|
|
| 376 | 381 | usg_mod_name :: ModuleName
|
| 377 | 382 | -- ^ Name of the module
|
| 378 | 383 | , usg_unit_id :: UnitId
|
| 379 | 384 | -- ^ UnitId of the HomeUnit the module is from
|
| 380 | - , usg_iface_hash :: Fingerprint
|
|
| 385 | + , usg_bytecode_hash :: Fingerprint
|
|
| 381 | 386 | -- ^ The *interface* hash of the module, not the ABI hash.
|
| 382 | 387 | -- This changes when anything about the interface (and hence the
|
| 383 | 388 | -- module) has changed.
|
| ... | ... | @@ -412,7 +417,7 @@ instance NFData Usage where |
| 412 | 417 | rnf (UsageFile file hash label) = rnf file `seq` rnf hash `seq` rnf label `seq` ()
|
| 413 | 418 | rnf (UsageDirectory dir hash label) = rnf dir `seq` rnf hash `seq` rnf label `seq` ()
|
| 414 | 419 | rnf (UsageMergedRequirement mod hash) = rnf mod `seq` rnf hash `seq` ()
|
| 415 | - rnf (UsageHomeModuleInterface mod uid hash) = rnf mod `seq` rnf uid `seq` rnf hash `seq` ()
|
|
| 420 | + rnf (UsageHomeModuleBytecode mod uid hash) = rnf mod `seq` rnf uid `seq` rnf hash `seq` ()
|
|
| 416 | 421 | |
| 417 | 422 | instance Binary Usage where
|
| 418 | 423 | put_ bh usg@UsagePackageModule{} = do
|
| ... | ... | @@ -441,11 +446,11 @@ instance Binary Usage where |
| 441 | 446 | put_ bh (usg_mod usg)
|
| 442 | 447 | put_ bh (usg_mod_hash usg)
|
| 443 | 448 | |
| 444 | - put_ bh usg@UsageHomeModuleInterface{} = do
|
|
| 449 | + put_ bh usg@UsageHomeModuleBytecode{} = do
|
|
| 445 | 450 | putByte bh 4
|
| 446 | 451 | put_ bh (usg_mod_name usg)
|
| 447 | 452 | put_ bh (usg_unit_id usg)
|
| 448 | - put_ bh (usg_iface_hash usg)
|
|
| 453 | + put_ bh (usg_bytecode_hash usg)
|
|
| 449 | 454 | |
| 450 | 455 | put_ bh usg@UsageDirectory{} = do
|
| 451 | 456 | putByte bh 5
|
| ... | ... | @@ -483,7 +488,7 @@ instance Binary Usage where |
| 483 | 488 | mod <- get bh
|
| 484 | 489 | uid <- get bh
|
| 485 | 490 | hash <- get bh
|
| 486 | - return UsageHomeModuleInterface { usg_mod_name = mod, usg_unit_id = uid, usg_iface_hash = hash }
|
|
| 491 | + return UsageHomeModuleBytecode { usg_mod_name = mod, usg_unit_id = uid, usg_bytecode_hash = hash }
|
|
| 487 | 492 | 5 -> do
|
| 488 | 493 | dp <- get bh
|
| 489 | 494 | hash <- get bh
|
| ... | ... | @@ -695,3 +700,33 @@ data ImportAvails |
| 695 | 700 | -- ^ Family instance modules below us in the import tree (and maybe
|
| 696 | 701 | -- including us for imported modules)
|
| 697 | 702 | }
|
| 703 | + |
|
| 704 | +-- | Record usage of a 'LinkablePart'.
|
|
| 705 | +data LinkablePartUsage
|
|
| 706 | + = FileLinkablePartUsage
|
|
| 707 | + { flu_file :: !FilePath
|
|
| 708 | + , flu_module :: !Module
|
|
| 709 | + , flu_linkable_objs :: !(FlatBag OsPath)
|
|
| 710 | + }
|
|
| 711 | + | ByteCodeLinkablePartUsage
|
|
| 712 | + { bclu_module :: !Module
|
|
| 713 | + , bclu_hash :: !Fingerprint
|
|
| 714 | + , bclu_linkable_objs :: !(FlatBag OsPath)
|
|
| 715 | + }
|
|
| 716 | + |
|
| 717 | +instance Outputable LinkablePartUsage where
|
|
| 718 | + ppr = \ case
|
|
| 719 | + FileLinkablePartUsage fp modl _objs ->
|
|
| 720 | + text "FileLinkableUsage" <+> text fp <+> ppr modl
|
|
| 721 | + |
|
| 722 | + ByteCodeLinkablePartUsage modl hash _objs ->
|
|
| 723 | + text "ByteCodeLinkableUsage" <+> ppr modl <+> ppr hash
|
|
| 724 | + |
|
| 725 | +linkablePartUsageObjectPaths :: LinkablePartUsage -> [FilePath]
|
|
| 726 | +linkablePartUsageObjectPaths lnkUsage =
|
|
| 727 | + map OsPath.unsafeDecodeUtf . Foldable.toList $ linkableUsageObjectOsPaths lnkUsage
|
|
| 728 | + |
|
| 729 | +linkableUsageObjectOsPaths :: LinkablePartUsage -> FlatBag OsPath
|
|
| 730 | +linkableUsageObjectOsPaths lnkUsage = case lnkUsage of
|
|
| 731 | + FileLinkablePartUsage{flu_linkable_objs} -> flu_linkable_objs
|
|
| 732 | + ByteCodeLinkablePartUsage{bclu_linkable_objs} -> bclu_linkable_objs |
| ... | ... | @@ -18,7 +18,7 @@ import GHC.Unit.Home.ModInfo |
| 18 | 18 | import GHC.Unit.Module.ModGuts
|
| 19 | 19 | import GHC.Unit.Module.ModIface
|
| 20 | 20 | |
| 21 | -import GHC.Linker.Types ( Linkable, WholeCoreBindingsLinkable, linkableIsNativeCodeOnly )
|
|
| 21 | +import GHC.Linker.Types ( Linkable, WholeCoreBindingsLinkable, linkableIsNativeCodeOnly, ModuleByteCode, LinkableWith )
|
|
| 22 | 22 | |
| 23 | 23 | import GHC.Utils.Fingerprint
|
| 24 | 24 | import GHC.Utils.Outputable
|
| ... | ... | @@ -59,7 +59,7 @@ data RecompLinkables = RecompLinkables { recompLinkables_bytecode :: !RecompByte |
| 59 | 59 | , recompLinkables_object :: !(Maybe Linkable) }
|
| 60 | 60 | |
| 61 | 61 | data RecompBytecodeLinkable
|
| 62 | - = NormalLinkable !(Maybe Linkable)
|
|
| 62 | + = NormalLinkable !(Maybe (LinkableWith ModuleByteCode))
|
|
| 63 | 63 | | WholeCoreBindingsLinkable !WholeCoreBindingsLinkable
|
| 64 | 64 | |
| 65 | 65 | instance Outputable HscRecompStatus where
|
| ... | ... | @@ -83,11 +83,9 @@ emptyRecompLinkables = RecompLinkables (NormalLinkable Nothing) Nothing |
| 83 | 83 | safeCastHomeModLinkable :: HomeModLinkable -> RecompLinkables
|
| 84 | 84 | safeCastHomeModLinkable (HomeModLinkable bc o) = RecompLinkables (NormalLinkable bc) o
|
| 85 | 85 | |
| 86 | -justBytecode :: Either Linkable WholeCoreBindingsLinkable -> RecompLinkables
|
|
| 86 | +justBytecode :: Either (LinkableWith ModuleByteCode) WholeCoreBindingsLinkable -> RecompLinkables
|
|
| 87 | 87 | justBytecode = \case
|
| 88 | - Left lm ->
|
|
| 89 | - assertPpr (not (linkableIsNativeCodeOnly lm)) (ppr lm)
|
|
| 90 | - $ emptyRecompLinkables { recompLinkables_bytecode = NormalLinkable (Just lm) }
|
|
| 88 | + Left lm -> emptyRecompLinkables { recompLinkables_bytecode = NormalLinkable (Just lm) }
|
|
| 91 | 89 | Right lm -> emptyRecompLinkables { recompLinkables_bytecode = WholeCoreBindingsLinkable lm }
|
| 92 | 90 | |
| 93 | 91 | justObjects :: Linkable -> RecompLinkables
|
| ... | ... | @@ -95,10 +93,10 @@ justObjects lm = |
| 95 | 93 | assertPpr (linkableIsNativeCodeOnly lm) (ppr lm)
|
| 96 | 94 | $ emptyRecompLinkables { recompLinkables_object = Just lm }
|
| 97 | 95 | |
| 98 | -bytecodeAndObjects :: Either Linkable WholeCoreBindingsLinkable -> Linkable -> RecompLinkables
|
|
| 96 | +bytecodeAndObjects :: Either (LinkableWith ModuleByteCode) WholeCoreBindingsLinkable -> Linkable -> RecompLinkables
|
|
| 99 | 97 | bytecodeAndObjects either_bc o = case either_bc of
|
| 100 | 98 | Left bc ->
|
| 101 | - assertPpr (not (linkableIsNativeCodeOnly bc) && linkableIsNativeCodeOnly o) (ppr bc $$ ppr o)
|
|
| 99 | + assertPpr (linkableIsNativeCodeOnly o) (ppr o)
|
|
| 102 | 100 | $ RecompLinkables (NormalLinkable (Just bc)) (Just o)
|
| 103 | 101 | Right bc ->
|
| 104 | 102 | assertPpr (linkableIsNativeCodeOnly o) (ppr o)
|
| ... | ... | @@ -215,6 +215,7 @@ Library |
| 215 | 215 | GHC.ByteCode.InfoTable
|
| 216 | 216 | GHC.ByteCode.Instr
|
| 217 | 217 | GHC.ByteCode.Linker
|
| 218 | + GHC.ByteCode.Recomp.Binary
|
|
| 218 | 219 | GHC.ByteCode.Serialize
|
| 219 | 220 | GHC.ByteCode.Types
|
| 220 | 221 | GHC.Cmm
|
| ... | ... | @@ -52,8 +52,11 @@ getLeakIndicators hsc_env = |
| 52 | 52 | return $ LeakModIndicators{..}
|
| 53 | 53 | where
|
| 54 | 54 | mkWeakLinkables :: HomeModLinkable -> IO [Maybe (Weak Linkable)]
|
| 55 | - mkWeakLinkables (HomeModLinkable mbc mo) =
|
|
| 56 | - mapM (\ln -> traverse (flip mkWeakPtr Nothing <=< evaluate) ln) [mbc, mo]
|
|
| 55 | + mkWeakLinkables hml =
|
|
| 56 | + mapM (\ln -> traverse (flip mkWeakPtr Nothing <=< evaluate) ln)
|
|
| 57 | + [ homeModLinkableByteCode hml
|
|
| 58 | + , homeModLinkableObject hml
|
|
| 59 | + ]
|
|
| 57 | 60 | |
| 58 | 61 | -- | Look at the LeakIndicators collected by an earlier call to
|
| 59 | 62 | -- `getLeakIndicators`, and print messasges if any of them are still
|
| ... | ... | @@ -60,6 +60,7 @@ GHC.Data.FastMutInt |
| 60 | 60 | GHC.Data.FastString
|
| 61 | 61 | GHC.Data.FastString.Env
|
| 62 | 62 | GHC.Data.FiniteMap
|
| 63 | +GHC.Data.FlatBag
|
|
| 63 | 64 | GHC.Data.Graph.Directed
|
| 64 | 65 | GHC.Data.Graph.Directed.Internal
|
| 65 | 66 | GHC.Data.Graph.UnVar
|
| ... | ... | @@ -61,6 +61,7 @@ GHC.Data.FastMutInt |
| 61 | 61 | GHC.Data.FastString
|
| 62 | 62 | GHC.Data.FastString.Env
|
| 63 | 63 | GHC.Data.FiniteMap
|
| 64 | +GHC.Data.FlatBag
|
|
| 64 | 65 | GHC.Data.Graph.Directed
|
| 65 | 66 | GHC.Data.Graph.Directed.Internal
|
| 66 | 67 | GHC.Data.Graph.Directed.Reachability
|
| ... | ... | @@ -3,6 +3,6 @@ GHCi, version 9.15.20260122: https://www.haskell.org/ghc/ :? for help |
| 3 | 3 | [2 of 2] Compiling RecompTH ( RecompTH.hs, interpreted )[recomp]
|
| 4 | 4 | Ok, two modules loaded.
|
| 5 | 5 | ghci> ghci> ghci> [1 of 2] Compiling Dep ( Dep.hs, interpreted )[dep] [Source file changed]
|
| 6 | -[2 of 2] Compiling RecompTH ( RecompTH.hs, interpreted )[recomp] [Dep changed (interface)]
|
|
| 6 | +[2 of 2] Compiling RecompTH ( RecompTH.hs, interpreted )[recomp] [Dep changed (bytecode)]
|
|
| 7 | 7 | Ok, two modules reloaded.
|
| 8 | 8 | ghci> Leaving GHCi. |