Matthew Pickering pushed to branch wip/bytecode-lib-shared-object at Glasgow Haskell Compiler / GHC
Commits:
-
35968c75
by Matthew Pickering at 2025-10-30T10:11:34+00:00
-
0655c75c
by Matthew Pickering at 2025-10-30T10:47:28+00:00
-
15c6d35a
by Matthew Pickering at 2025-10-30T16:30:49+00:00
9 changed files:
- compiler/GHC/ByteCode/Linker.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/Phases.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Runtime/Debugger.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Unit/State.hs
- utils/ghc-pkg/Main.hs
Changes:
| ... | ... | @@ -28,7 +28,6 @@ import GHCi.ResolvedBCO |
| 28 | 28 | import GHC.Builtin.PrimOps
|
| 29 | 29 | import GHC.Builtin.PrimOps.Ids
|
| 30 | 30 | |
| 31 | -import GHC.Unit.Module.Env
|
|
| 32 | 31 | import GHC.Unit.Types
|
| 33 | 32 | |
| 34 | 33 | import GHC.Data.FastString
|
| ... | ... | @@ -57,17 +56,16 @@ import GHC.Exts |
| 57 | 56 | linkBCO
|
| 58 | 57 | :: Interp
|
| 59 | 58 | -> PkgsLoaded
|
| 60 | - -> LinkerEnv
|
|
| 61 | - -> LinkedBreaks
|
|
| 59 | + -> BytecodeLoaderState
|
|
| 62 | 60 | -> NameEnv Int
|
| 63 | 61 | -> UnlinkedBCO
|
| 64 | 62 | -> IO ResolvedBCO
|
| 65 | -linkBCO interp pkgs_loaded le lb bco_ix
|
|
| 63 | +linkBCO interp pkgs_loaded bytecode_state bco_ix
|
|
| 66 | 64 | (UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do
|
| 67 | 65 | -- fromIntegral Word -> Word64 should be a no op if Word is Word64
|
| 68 | 66 | -- otherwise it will result in a cast to longlong on 32bit systems.
|
| 69 | - (lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le lb) (elemsFlatBag lits0)
|
|
| 70 | - ptrs <- mapM (resolvePtr interp pkgs_loaded le lb bco_ix) (elemsFlatBag ptrs0)
|
|
| 67 | + (lits :: [Word]) <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded bytecode_state) (elemsFlatBag lits0)
|
|
| 68 | + ptrs <- mapM (resolvePtr interp pkgs_loaded bytecode_state bco_ix) (elemsFlatBag ptrs0)
|
|
| 71 | 69 | let lits' = listArray (0 :: Int, fromIntegral (sizeFlatBag lits0)-1) lits
|
| 72 | 70 | return $ ResolvedBCO { resolvedBCOIsLE = isLittleEndian
|
| 73 | 71 | , resolvedBCOArity = arity
|
| ... | ... | @@ -77,17 +75,17 @@ linkBCO interp pkgs_loaded le lb bco_ix |
| 77 | 75 | , resolvedBCOPtrs = addListToSS emptySS ptrs
|
| 78 | 76 | }
|
| 79 | 77 | |
| 80 | -lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> LinkedBreaks -> BCONPtr -> IO Word
|
|
| 81 | -lookupLiteral interp pkgs_loaded le lb ptr = case ptr of
|
|
| 78 | +lookupLiteral :: Interp -> PkgsLoaded -> BytecodeLoaderState -> BCONPtr -> IO Word
|
|
| 79 | +lookupLiteral interp pkgs_loaded bytecode_state ptr = case ptr of
|
|
| 82 | 80 | BCONPtrWord lit -> return lit
|
| 83 | 81 | BCONPtrLbl sym -> do
|
| 84 | 82 | Ptr a# <- lookupStaticPtr interp sym
|
| 85 | 83 | return (W# (int2Word# (addr2Int# a#)))
|
| 86 | 84 | BCONPtrItbl nm -> do
|
| 87 | - Ptr a# <- lookupIE interp pkgs_loaded (itbl_env le) nm
|
|
| 85 | + Ptr a# <- lookupIE interp pkgs_loaded bytecode_state nm
|
|
| 88 | 86 | return (W# (int2Word# (addr2Int# a#)))
|
| 89 | 87 | BCONPtrAddr nm -> do
|
| 90 | - Ptr a# <- lookupAddr interp pkgs_loaded (addr_env le) nm
|
|
| 88 | + Ptr a# <- lookupAddr interp pkgs_loaded bytecode_state nm
|
|
| 91 | 89 | return (W# (int2Word# (addr2Int# a#)))
|
| 92 | 90 | BCONPtrStr bs -> do
|
| 93 | 91 | RemotePtr p <- fmap head $ interpCmd interp $ MallocStrings [bs]
|
| ... | ... | @@ -100,7 +98,7 @@ lookupLiteral interp pkgs_loaded le lb ptr = case ptr of |
| 100 | 98 | pure $ fromIntegral p
|
| 101 | 99 | BCONPtrCostCentre InternalBreakpointId{..}
|
| 102 | 100 | | interpreterProfiled interp -> do
|
| 103 | - case expectJust (lookupModuleEnv (ccs_env lb) ibi_info_mod) ! ibi_info_index of
|
|
| 101 | + case expectJust (lookupCCSBytecodeState bytecode_state ibi_info_mod) ! ibi_info_index of
|
|
| 104 | 102 | RemotePtr p -> pure $ fromIntegral p
|
| 105 | 103 | | otherwise ->
|
| 106 | 104 | case toRemotePtr nullPtr of
|
| ... | ... | @@ -114,9 +112,9 @@ lookupStaticPtr interp addr_of_label_string = do |
| 114 | 112 | Nothing -> linkFail "GHC.ByteCode.Linker: can't find label"
|
| 115 | 113 | (ppr addr_of_label_string)
|
| 116 | 114 | |
| 117 | -lookupIE :: Interp -> PkgsLoaded -> ItblEnv -> Name -> IO (Ptr ())
|
|
| 118 | -lookupIE interp pkgs_loaded ie con_nm =
|
|
| 119 | - case lookupNameEnv ie con_nm of
|
|
| 115 | +lookupIE :: Interp -> PkgsLoaded -> BytecodeLoaderState -> Name -> IO (Ptr ())
|
|
| 116 | +lookupIE interp pkgs_loaded bytecode_state con_nm =
|
|
| 117 | + case lookupInfoTableBytecodeState bytecode_state con_nm of
|
|
| 120 | 118 | Just (_, ItblPtr a) -> return (fromRemotePtr (castRemotePtr a))
|
| 121 | 119 | Nothing -> do -- try looking up in the object files.
|
| 122 | 120 | let sym_to_find1 = IConInfoSymbol con_nm
|
| ... | ... | @@ -134,9 +132,9 @@ lookupIE interp pkgs_loaded ie con_nm = |
| 134 | 132 | ppr sym_to_find2)
|
| 135 | 133 | |
| 136 | 134 | -- see Note [Generating code for top-level string literal bindings] in GHC.StgToByteCode
|
| 137 | -lookupAddr :: Interp -> PkgsLoaded -> AddrEnv -> Name -> IO (Ptr ())
|
|
| 138 | -lookupAddr interp pkgs_loaded ae addr_nm = do
|
|
| 139 | - case lookupNameEnv ae addr_nm of
|
|
| 135 | +lookupAddr :: Interp -> PkgsLoaded -> BytecodeLoaderState -> Name -> IO (Ptr ())
|
|
| 136 | +lookupAddr interp pkgs_loaded bytecode_state addr_nm = do
|
|
| 137 | + case lookupAddressBytecodeState bytecode_state addr_nm of
|
|
| 140 | 138 | Just (_, AddrPtr ptr) -> return (fromRemotePtr ptr)
|
| 141 | 139 | Nothing -> do -- try looking up in the object files.
|
| 142 | 140 | let sym_to_find = IBytesSymbol addr_nm
|
| ... | ... | @@ -158,17 +156,16 @@ lookupPrimOp interp pkgs_loaded primop = do |
| 158 | 156 | resolvePtr
|
| 159 | 157 | :: Interp
|
| 160 | 158 | -> PkgsLoaded
|
| 161 | - -> LinkerEnv
|
|
| 162 | - -> LinkedBreaks
|
|
| 159 | + -> BytecodeLoaderState
|
|
| 163 | 160 | -> NameEnv Int
|
| 164 | 161 | -> BCOPtr
|
| 165 | 162 | -> IO ResolvedBCOPtr
|
| 166 | -resolvePtr interp pkgs_loaded le lb bco_ix ptr = case ptr of
|
|
| 163 | +resolvePtr interp pkgs_loaded bco_loader_state bco_ix ptr = case ptr of
|
|
| 167 | 164 | BCOPtrName nm
|
| 168 | 165 | | Just ix <- lookupNameEnv bco_ix nm
|
| 169 | 166 | -> return (ResolvedBCORef ix) -- ref to another BCO in this group
|
| 170 | 167 | |
| 171 | - | Just (_, rhv) <- lookupNameEnv (closure_env le) nm
|
|
| 168 | + | Just (_, rhv) <- lookupNameBytecodeState bco_loader_state nm
|
|
| 172 | 169 | -> return (ResolvedBCOPtr (unsafeForeignRefToRemoteRef rhv))
|
| 173 | 170 | |
| 174 | 171 | | otherwise
|
| ... | ... | @@ -184,10 +181,10 @@ resolvePtr interp pkgs_loaded le lb bco_ix ptr = case ptr of |
| 184 | 181 | -> ResolvedBCOStaticPtr <$> lookupPrimOp interp pkgs_loaded op
|
| 185 | 182 | |
| 186 | 183 | BCOPtrBCO bco
|
| 187 | - -> ResolvedBCOPtrBCO <$> linkBCO interp pkgs_loaded le lb bco_ix bco
|
|
| 184 | + -> ResolvedBCOPtrBCO <$> linkBCO interp pkgs_loaded bco_loader_state bco_ix bco
|
|
| 188 | 185 | |
| 189 | 186 | BCOPtrBreakArray tick_mod ->
|
| 190 | - withForeignRef (expectJust (lookupModuleEnv (breakarray_env lb) tick_mod)) $
|
|
| 187 | + withForeignRef (expectJust (lookupBreakArrayBytecodeState bco_loader_state tick_mod)) $
|
|
| 191 | 188 | \ba -> pure $ ResolvedBCOPtrBreakArray ba
|
| 192 | 189 | |
| 193 | 190 | -- | Look up the address of a Haskell symbol in the currently
|
| ... | ... | @@ -822,7 +822,7 @@ pruneCache hpt summ |
| 822 | 822 | unload :: Interp -> HscEnv -> IO ()
|
| 823 | 823 | unload interp hsc_env
|
| 824 | 824 | = case ghcLink (hsc_dflags hsc_env) of
|
| 825 | - LinkInMemory -> Linker.unload interp hsc_env []
|
|
| 825 | + LinkInMemory -> Linker.unload interp hsc_env
|
|
| 826 | 826 | _other -> return ()
|
| 827 | 827 | |
| 828 | 828 |
| ... | ... | @@ -32,6 +32,7 @@ module GHC.Driver.Phases ( |
| 32 | 32 | isHaskellSrcFilename,
|
| 33 | 33 | isHaskellSigFilename,
|
| 34 | 34 | isObjectFilename,
|
| 35 | + isBytecodeFilename,
|
|
| 35 | 36 | isCishFilename,
|
| 36 | 37 | isDynLibFilename,
|
| 37 | 38 | isHaskellUserSrcFilename,
|
| ... | ... | @@ -235,7 +236,9 @@ phaseInputExt Js = "js" |
| 235 | 236 | phaseInputExt StopLn = "o"
|
| 236 | 237 | |
| 237 | 238 | haskellish_src_suffixes, backpackish_suffixes, haskellish_suffixes, cish_suffixes,
|
| 238 | - js_suffixes, haskellish_user_src_suffixes, haskellish_sig_suffixes, haskellish_boot_suffixes
|
|
| 239 | + js_suffixes, haskellish_user_src_suffixes, haskellish_sig_suffixes, haskellish_boot_suffixes,
|
|
| 240 | + bytecode_suffixes
|
|
| 241 | + |
|
| 239 | 242 | :: [String]
|
| 240 | 243 | -- When a file with an extension in the haskellish_src_suffixes group is
|
| 241 | 244 | -- loaded in --make mode, its imports will be loaded too.
|
| ... | ... | @@ -252,6 +255,7 @@ haskellish_user_src_suffixes = |
| 252 | 255 | haskellish_boot_suffixes = [ "hs-boot", "lhs-boot" ]
|
| 253 | 256 | haskellish_sig_suffixes = [ "hsig", "lhsig" ]
|
| 254 | 257 | backpackish_suffixes = [ "bkp" ]
|
| 258 | +bytecode_suffixes = [ "gbc" ]
|
|
| 255 | 259 | |
| 256 | 260 | objish_suffixes :: Platform -> [String]
|
| 257 | 261 | -- Use the appropriate suffix for the system on which
|
| ... | ... | @@ -267,7 +271,8 @@ dynlib_suffixes platform = case platformOS platform of |
| 267 | 271 | _ -> ["so"]
|
| 268 | 272 | |
| 269 | 273 | isHaskellishSuffix, isBackpackishSuffix, isHaskellSrcSuffix, isCishSuffix,
|
| 270 | - isHaskellUserSrcSuffix, isJsSuffix, isHaskellSigSuffix, isHaskellBootSuffix
|
|
| 274 | + isHaskellUserSrcSuffix, isJsSuffix, isHaskellSigSuffix, isHaskellBootSuffix,
|
|
| 275 | + isBytecodeSuffix
|
|
| 271 | 276 | :: String -> Bool
|
| 272 | 277 | isHaskellishSuffix s = s `elem` haskellish_suffixes
|
| 273 | 278 | isBackpackishSuffix s = s `elem` backpackish_suffixes
|
| ... | ... | @@ -277,6 +282,7 @@ isHaskellSrcSuffix s = s `elem` haskellish_src_suffixes |
| 277 | 282 | isCishSuffix s = s `elem` cish_suffixes
|
| 278 | 283 | isJsSuffix s = s `elem` js_suffixes
|
| 279 | 284 | isHaskellUserSrcSuffix s = s `elem` haskellish_user_src_suffixes
|
| 285 | +isBytecodeSuffix s = s `elem` bytecode_suffixes
|
|
| 280 | 286 | |
| 281 | 287 | isObjectSuffix, isDynLibSuffix :: Platform -> String -> Bool
|
| 282 | 288 | isObjectSuffix platform s = s `elem` objish_suffixes platform
|
| ... | ... | @@ -306,7 +312,8 @@ isHaskellishTarget (_,Just phase) = |
| 306 | 312 | , StopLn]
|
| 307 | 313 | |
| 308 | 314 | isHaskellishFilename, isHaskellSrcFilename, isCishFilename,
|
| 309 | - isHaskellUserSrcFilename, isSourceFilename, isHaskellSigFilename
|
|
| 315 | + isHaskellUserSrcFilename, isSourceFilename, isHaskellSigFilename,
|
|
| 316 | + isBytecodeFilename
|
|
| 310 | 317 | :: FilePath -> Bool
|
| 311 | 318 | -- takeExtension return .foo, so we drop 1 to get rid of the .
|
| 312 | 319 | isHaskellishFilename f = isHaskellishSuffix (drop 1 $ takeExtension f)
|
| ... | ... | @@ -315,6 +322,7 @@ isCishFilename f = isCishSuffix (drop 1 $ takeExtension f) |
| 315 | 322 | isHaskellUserSrcFilename f = isHaskellUserSrcSuffix (drop 1 $ takeExtension f)
|
| 316 | 323 | isSourceFilename f = isSourceSuffix (drop 1 $ takeExtension f)
|
| 317 | 324 | isHaskellSigFilename f = isHaskellSigSuffix (drop 1 $ takeExtension f)
|
| 325 | +isBytecodeFilename f = isBytecodeSuffix (drop 1 $ takeExtension f)
|
|
| 318 | 326 | |
| 319 | 327 | isObjectFilename, isDynLibFilename :: Platform -> FilePath -> Bool
|
| 320 | 328 | isObjectFilename platform f = isObjectSuffix platform (drop 1 $ takeExtension f)
|
| ... | ... | @@ -27,7 +27,7 @@ module GHC.Linker.Loader |
| 27 | 27 | -- * LoadedEnv
|
| 28 | 28 | , withExtendedLoadedEnv
|
| 29 | 29 | , extendLoadedEnv
|
| 30 | - , deleteFromLoadedEnv
|
|
| 30 | + , deleteFromLoadedHomeEnv
|
|
| 31 | 31 | , lookupFromLoadedEnv
|
| 32 | 32 | -- * Internals
|
| 33 | 33 | , allocateBreakArrays
|
| ... | ... | @@ -183,19 +183,11 @@ getLoaderState interp = readMVar (loader_state (interpLoader interp)) |
| 183 | 183 | |
| 184 | 184 | emptyLoaderState :: LoaderState
|
| 185 | 185 | emptyLoaderState = LoaderState
|
| 186 | - { linker_env = LinkerEnv
|
|
| 187 | - { closure_env = emptyNameEnv
|
|
| 188 | - , itbl_env = emptyNameEnv
|
|
| 189 | - , addr_env = emptyNameEnv
|
|
| 190 | - }
|
|
| 186 | + { bco_loader_state = emptyBytecodeLoaderState
|
|
| 191 | 187 | , pkgs_loaded = init_pkgs
|
| 192 | 188 | , bcos_loaded = emptyModuleEnv
|
| 193 | 189 | , objs_loaded = emptyModuleEnv
|
| 194 | 190 | , temp_sos = []
|
| 195 | - , linked_breaks = LinkedBreaks
|
|
| 196 | - { breakarray_env = emptyModuleEnv
|
|
| 197 | - , ccs_env = emptyModuleEnv
|
|
| 198 | - }
|
|
| 199 | 191 | }
|
| 200 | 192 | -- Packages that don't need loading, because the compiler
|
| 201 | 193 | -- shares them with the interpreted program.
|
| ... | ... | @@ -204,18 +196,18 @@ emptyLoaderState = LoaderState |
| 204 | 196 | -- explicit list. See rts/Linker.c for details.
|
| 205 | 197 | where init_pkgs = unitUDFM rtsUnitId (LoadedPkgInfo rtsUnitId [] [] [] emptyUniqDSet)
|
| 206 | 198 | |
| 207 | -extendLoadedEnv :: Interp -> [(Name,ForeignHValue)] -> IO ()
|
|
| 208 | -extendLoadedEnv interp new_bindings =
|
|
| 199 | +extendLoadedEnv :: Interp -> BytecodeLoaderStateModifier -> [(Name,ForeignHValue)] -> IO ()
|
|
| 200 | +extendLoadedEnv interp modify_bytecode_loader_state new_bindings =
|
|
| 209 | 201 | modifyLoaderState_ interp $ \pls -> do
|
| 210 | - return $! modifyClosureEnv pls $ \ce ->
|
|
| 211 | - extendClosureEnv ce new_bindings
|
|
| 202 | + return $! modifyBytecodeLoaderState modify_bytecode_loader_state pls $ \bco_loader_state ->
|
|
| 203 | + modifyClosureEnv bco_loader_state $ \ce -> extendClosureEnv ce new_bindings
|
|
| 212 | 204 | -- strictness is important for not retaining old copies of the pls
|
| 213 | 205 | |
| 214 | -deleteFromLoadedEnv :: Interp -> [Name] -> IO ()
|
|
| 215 | -deleteFromLoadedEnv interp to_remove =
|
|
| 206 | +deleteFromLoadedHomeEnv :: Interp -> [Name] -> IO ()
|
|
| 207 | +deleteFromLoadedHomeEnv interp to_remove =
|
|
| 216 | 208 | modifyLoaderState_ interp $ \pls -> do
|
| 217 | - return $ modifyClosureEnv pls $ \ce ->
|
|
| 218 | - delListFromNameEnv ce to_remove
|
|
| 209 | + return $ modifyBytecodeLoaderState modifyHomePackageBytecodeState pls $ \bco_state ->
|
|
| 210 | + modifyClosureEnv bco_state $ \ce -> delListFromNameEnv ce to_remove
|
|
| 219 | 211 | |
| 220 | 212 | -- | Have we already loaded a name into the interpreter?
|
| 221 | 213 | lookupFromLoadedEnv :: Interp -> Name -> IO (Maybe ForeignHValue)
|
| ... | ... | @@ -223,7 +215,7 @@ lookupFromLoadedEnv interp name = do |
| 223 | 215 | mstate <- getLoaderState interp
|
| 224 | 216 | return $ do
|
| 225 | 217 | pls <- mstate
|
| 226 | - res <- lookupNameEnv (closure_env (linker_env pls)) name
|
|
| 218 | + res <- lookupNameBytecodeState (bco_loader_state pls) name
|
|
| 227 | 219 | return (snd res)
|
| 228 | 220 | |
| 229 | 221 | -- | Load the module containing the given Name and get its associated 'HValue'.
|
| ... | ... | @@ -242,7 +234,7 @@ loadName interp hsc_env name = do |
| 242 | 234 | then throwGhcExceptionIO (ProgramError "")
|
| 243 | 235 | else return (pls', links, pkgs)
|
| 244 | 236 | |
| 245 | - case lookupNameEnv (closure_env (linker_env pls)) name of
|
|
| 237 | + case lookupNameBytecodeState (bco_loader_state pls) name of
|
|
| 246 | 238 | Just (_,aa) -> return (pls,(aa, links, pkgs))
|
| 247 | 239 | Nothing -> assertPpr (isExternalName name) (ppr name) $
|
| 248 | 240 | do let sym_to_find = IClosureSymbol name
|
| ... | ... | @@ -289,7 +281,7 @@ withExtendedLoadedEnv |
| 289 | 281 | -> m a
|
| 290 | 282 | -> m a
|
| 291 | 283 | withExtendedLoadedEnv interp new_env action
|
| 292 | - = MC.bracket (liftIO $ extendLoadedEnv interp new_env)
|
|
| 284 | + = MC.bracket (liftIO $ extendLoadedEnv interp modifyHomePackageBytecodeState new_env)
|
|
| 293 | 285 | (\_ -> reset_old_env)
|
| 294 | 286 | (\_ -> action)
|
| 295 | 287 | where
|
| ... | ... | @@ -299,7 +291,7 @@ withExtendedLoadedEnv interp new_env action |
| 299 | 291 | -- package), so the reset action only removes the names we
|
| 300 | 292 | -- added earlier.
|
| 301 | 293 | reset_old_env = liftIO $
|
| 302 | - deleteFromLoadedEnv interp (map fst new_env)
|
|
| 294 | + deleteFromLoadedHomeEnv interp (map fst new_env)
|
|
| 303 | 295 | |
| 304 | 296 | |
| 305 | 297 | -- | Display the loader state.
|
| ... | ... | @@ -862,7 +854,7 @@ loadObjects interp hsc_env pls objs = do |
| 862 | 854 | if succeeded ok then
|
| 863 | 855 | return (pls1, Succeeded)
|
| 864 | 856 | else do
|
| 865 | - pls2 <- unload_wkr interp [] pls1
|
|
| 857 | + pls2 <- unload_wkr interp pls1
|
|
| 866 | 858 | return (pls2, Failed)
|
| 867 | 859 | |
| 868 | 860 | |
| ... | ... | @@ -981,21 +973,33 @@ dynLinkBCOs interp pls keep_spec bcos = |
| 981 | 973 | |
| 982 | 974 | cbcs :: [CompiledByteCode]
|
| 983 | 975 | cbcs = concatMap linkableBCOs new_bcos
|
| 984 | - in dynLinkCompiledByteCode interp pls1 keep_spec cbcs
|
|
| 985 | - |
|
| 986 | -dynLinkCompiledByteCode :: Interp -> LoaderState -> KeepModuleLinkableDefinitions -> [CompiledByteCode] -> IO LoaderState
|
|
| 987 | -dynLinkCompiledByteCode interp pls keep_spec cbcs = do
|
|
| 988 | - let
|
|
| 989 | - le1 = linker_env pls
|
|
| 990 | - lb1 = linked_breaks pls
|
|
| 991 | - ie2 <- linkITbls interp (itbl_env le1) (concatMap bc_itbls cbcs)
|
|
| 992 | - ae2 <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le1) cbcs
|
|
| 993 | - be2 <- allocateBreakArrays interp (breakarray_env lb1) (catMaybes $ map bc_breaks cbcs)
|
|
| 994 | - ce2 <- allocateCCS interp (ccs_env lb1) (catMaybes $ map bc_breaks cbcs)
|
|
| 995 | - let le2 = le1 { itbl_env = ie2, addr_env = ae2 }
|
|
| 996 | - let lb2 = lb1 { breakarray_env = be2, ccs_env = ce2 }
|
|
| 997 | - |
|
| 998 | - names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 lb2 cbcs
|
|
| 976 | + in do
|
|
| 977 | + bco_state <- dynLinkCompiledByteCode interp (pkgs_loaded pls) (bco_loader_state pls) traverseHomePackageBytecodeState keep_spec cbcs
|
|
| 978 | + return $! pls1 { bco_loader_state = bco_state }
|
|
| 979 | + |
|
| 980 | +dynLinkCompiledByteCode :: Interp
|
|
| 981 | + -> PkgsLoaded
|
|
| 982 | + -> BytecodeLoaderState
|
|
| 983 | + -> BytecodeLoaderStateTraverser IO -- ^ The traverser tells us to update home package bytecode state or external package bytecode state
|
|
| 984 | + -> KeepModuleLinkableDefinitions
|
|
| 985 | + -> [CompiledByteCode]
|
|
| 986 | + -> IO BytecodeLoaderState
|
|
| 987 | +dynLinkCompiledByteCode interp pkgs_loaded whole_bytecode_state traverse_bytecode_state keep_spec cbcs = do
|
|
| 988 | + st1 <- traverse_bytecode_state whole_bytecode_state $ \bytecode_state -> do
|
|
| 989 | + let
|
|
| 990 | + le1 = bco_linker_env bytecode_state
|
|
| 991 | + lb1 = bco_linked_breaks bytecode_state
|
|
| 992 | + ie2 <- linkITbls interp (itbl_env le1) (concatMap bc_itbls cbcs)
|
|
| 993 | + ae2 <- foldlM (\env cbc -> allocateTopStrings interp (bc_strs cbc) env) (addr_env le1) cbcs
|
|
| 994 | + be2 <- allocateBreakArrays interp (breakarray_env lb1) (catMaybes $ map bc_breaks cbcs)
|
|
| 995 | + ce2 <- allocateCCS interp (ccs_env lb1) (catMaybes $ map bc_breaks cbcs)
|
|
| 996 | + let le2 = le1 { itbl_env = ie2, addr_env = ae2 }
|
|
| 997 | + let lb2 = lb1 { breakarray_env = be2, ccs_env = ce2 }
|
|
| 998 | + return $! bytecode_state { bco_linker_env = le2, bco_linked_breaks = lb2 }
|
|
| 999 | + |
|
| 1000 | + -- NB: Important to pass the whole bytecode loader state to linkSomeBCOs so that you can find Names in local
|
|
| 1001 | + -- and external packages.
|
|
| 1002 | + names_and_refs <- linkSomeBCOs interp pkgs_loaded st1 cbcs
|
|
| 999 | 1003 | |
| 1000 | 1004 | -- We only want to add the external ones to the ClosureEnv
|
| 1001 | 1005 | let (to_add, to_drop) = partition (keepDefinitions keep_spec . fst) names_and_refs
|
| ... | ... | @@ -1005,14 +1009,11 @@ dynLinkCompiledByteCode interp pls keep_spec cbcs = do |
| 1005 | 1009 | -- Wrap finalizers on the ones we want to keep
|
| 1006 | 1010 | new_binds <- makeForeignNamedHValueRefs interp to_add
|
| 1007 | 1011 | |
| 1008 | - |
|
| 1009 | - let ce2 = extendClosureEnv (closure_env le2) new_binds
|
|
| 1010 | - |
|
| 1011 | - -- Add SPT entries
|
|
| 1012 | - mapM_ (linkSptEntry interp ce2) (concatMap bc_spt_entries cbcs)
|
|
| 1013 | - |
|
| 1014 | - return $! pls { linker_env = le2 { closure_env = ce2 }
|
|
| 1015 | - , linked_breaks = lb2 }
|
|
| 1012 | + traverse_bytecode_state st1 $ \bytecode_state -> do
|
|
| 1013 | + let ce2 = extendClosureEnv (closure_env (bco_linker_env bytecode_state)) new_binds
|
|
| 1014 | + -- Add SPT entries
|
|
| 1015 | + mapM_ (linkSptEntry interp ce2) (concatMap bc_spt_entries cbcs)
|
|
| 1016 | + return $! bytecode_state { bco_linker_env = (bco_linker_env bytecode_state) { closure_env = ce2 } }
|
|
| 1016 | 1017 | |
| 1017 | 1018 | -- | Register SPT entries for this module in the interpreter
|
| 1018 | 1019 | -- Assumes that the name from the SPT has already been loaded into the interpreter.
|
| ... | ... | @@ -1030,15 +1031,14 @@ linkSptEntry interp ce (SptEntry name fpr) = do |
| 1030 | 1031 | -- Link a bunch of BCOs and return references to their values
|
| 1031 | 1032 | linkSomeBCOs :: Interp
|
| 1032 | 1033 | -> PkgsLoaded
|
| 1033 | - -> LinkerEnv
|
|
| 1034 | - -> LinkedBreaks
|
|
| 1034 | + -> BytecodeLoaderState
|
|
| 1035 | 1035 | -> [CompiledByteCode]
|
| 1036 | 1036 | -> IO [(Name,HValueRef)]
|
| 1037 | 1037 | -- The returned HValueRefs are associated 1-1 with
|
| 1038 | 1038 | -- the incoming unlinked BCOs. Each gives the
|
| 1039 | 1039 | -- value of the corresponding unlinked BCO
|
| 1040 | 1040 | |
| 1041 | -linkSomeBCOs interp pkgs_loaded le lb mods = foldr fun do_link mods []
|
|
| 1041 | +linkSomeBCOs interp pkgs_loaded bytecode_state mods = foldr fun do_link mods []
|
|
| 1042 | 1042 | where
|
| 1043 | 1043 | fun CompiledByteCode{..} inner accum =
|
| 1044 | 1044 | inner (Foldable.toList bc_bcos : accum)
|
| ... | ... | @@ -1048,7 +1048,7 @@ linkSomeBCOs interp pkgs_loaded le lb mods = foldr fun do_link mods [] |
| 1048 | 1048 | let flat = [ bco | bcos <- mods, bco <- bcos ]
|
| 1049 | 1049 | names = map unlinkedBCOName flat
|
| 1050 | 1050 | bco_ix = mkNameEnv (zip names [0..])
|
| 1051 | - resolved <- sequence [ linkBCO interp pkgs_loaded le lb bco_ix bco | bco <- flat ]
|
|
| 1051 | + resolved <- sequence [ linkBCO interp pkgs_loaded bytecode_state bco_ix bco | bco <- flat ]
|
|
| 1052 | 1052 | hvrefs <- createBCOs interp resolved
|
| 1053 | 1053 | return (zip names hvrefs)
|
| 1054 | 1054 | |
| ... | ... | @@ -1071,66 +1071,39 @@ linkITbls interp = foldlM $ \env (nm, itbl) -> do |
| 1071 | 1071 | |
| 1072 | 1072 | -- ---------------------------------------------------------------------------
|
| 1073 | 1073 | -- | Unloading old objects ready for a new compilation sweep.
|
| 1074 | ---
|
|
| 1075 | --- The compilation manager provides us with a list of linkables that it
|
|
| 1076 | --- considers \"stable\", i.e. won't be recompiled this time around. For
|
|
| 1077 | --- each of the modules current linked in memory,
|
|
| 1078 | ---
|
|
| 1079 | --- * if the linkable is stable (and it's the same one -- the user may have
|
|
| 1080 | --- recompiled the module on the side), we keep it,
|
|
| 1081 | ---
|
|
| 1082 | --- * otherwise, we unload it.
|
|
| 1083 | ---
|
|
| 1074 | +-- * compilation artifacts for home modules that we might be about to recompile
|
|
| 1075 | +-- are unloaded from the interpreter.
|
|
| 1084 | 1076 | -- * we also implicitly unload all temporary bindings at this point.
|
| 1085 | 1077 | --
|
| 1086 | 1078 | unload
|
| 1087 | 1079 | :: Interp
|
| 1088 | 1080 | -> HscEnv
|
| 1089 | - -> [Linkable] -- ^ The linkables to *keep*.
|
|
| 1090 | 1081 | -> IO ()
|
| 1091 | -unload interp hsc_env linkables
|
|
| 1082 | +unload interp hsc_env
|
|
| 1092 | 1083 | = mask_ $ do -- mask, so we're safe from Ctrl-C in here
|
| 1093 | 1084 | |
| 1094 | 1085 | -- Initialise the linker (if it's not been done already)
|
| 1095 | 1086 | initLoaderState interp hsc_env
|
| 1096 | 1087 | |
| 1097 | - new_pls
|
|
| 1098 | - <- modifyLoaderState interp $ \pls -> do
|
|
| 1099 | - pls1 <- unload_wkr interp linkables pls
|
|
| 1088 | + _new_pls <- modifyLoaderState interp $ \pls -> do
|
|
| 1089 | + pls1 <- unload_wkr interp pls
|
|
| 1100 | 1090 | return (pls1, pls1)
|
| 1101 | 1091 | |
| 1102 | - let logger = hsc_logger hsc_env
|
|
| 1103 | - debugTraceMsg logger 3 $
|
|
| 1104 | - text "unload: retaining objs" <+> ppr (moduleEnvElts $ objs_loaded new_pls)
|
|
| 1105 | - debugTraceMsg logger 3 $
|
|
| 1106 | - text "unload: retaining bcos" <+> ppr (moduleEnvElts $ bcos_loaded new_pls)
|
|
| 1107 | 1092 | return ()
|
| 1108 | 1093 | |
| 1109 | 1094 | unload_wkr
|
| 1110 | 1095 | :: Interp
|
| 1111 | - -> [Linkable] -- stable linkables
|
|
| 1112 | 1096 | -> LoaderState
|
| 1113 | 1097 | -> IO LoaderState
|
| 1114 | 1098 | -- Does the core unload business
|
| 1115 | 1099 | -- (the wrapper blocks exceptions and deals with the LS get and put)
|
| 1116 | 1100 | |
| 1117 | -unload_wkr interp keep_linkables pls@LoaderState{..} = do
|
|
| 1101 | +unload_wkr interp pls@LoaderState{..} = do
|
|
| 1118 | 1102 | -- NB. careful strictness here to avoid keeping the old LS when
|
| 1119 | 1103 | -- we're unloading some code. -fghci-leak-check with the tests in
|
| 1120 | 1104 | -- testsuite/ghci can detect space leaks here.
|
| 1121 | 1105 | |
| 1122 | - let (objs_to_keep', bcos_to_keep') = partition linkableIsNativeCodeOnly keep_linkables
|
|
| 1123 | - objs_to_keep = mkLinkableSet objs_to_keep'
|
|
| 1124 | - bcos_to_keep = mkLinkableSet bcos_to_keep'
|
|
| 1125 | - |
|
| 1126 | - discard keep l = not (linkableInSet l keep)
|
|
| 1127 | - |
|
| 1128 | - (objs_to_unload, remaining_objs_loaded) =
|
|
| 1129 | - partitionModuleEnv (discard objs_to_keep) objs_loaded
|
|
| 1130 | - (bcos_to_unload, remaining_bcos_loaded) =
|
|
| 1131 | - partitionModuleEnv (discard bcos_to_keep) bcos_loaded
|
|
| 1132 | - |
|
| 1133 | - linkables_to_unload = moduleEnvElts objs_to_unload ++ moduleEnvElts bcos_to_unload
|
|
| 1106 | + let linkables_to_unload = moduleEnvElts objs_loaded ++ moduleEnvElts bcos_loaded
|
|
| 1134 | 1107 | |
| 1135 | 1108 | mapM_ unloadObjs linkables_to_unload
|
| 1136 | 1109 | |
| ... | ... | @@ -1139,20 +1112,10 @@ unload_wkr interp keep_linkables pls@LoaderState{..} = do |
| 1139 | 1112 | when (not (null (filter (not . null . linkableObjs) linkables_to_unload))) $
|
| 1140 | 1113 | purgeLookupSymbolCache interp
|
| 1141 | 1114 | |
| 1142 | - let -- Note that we want to remove all *local*
|
|
| 1143 | - -- (i.e. non-isExternal) names too (these are the
|
|
| 1144 | - -- temporary bindings from the command line).
|
|
| 1145 | - keep_name :: Name -> Bool
|
|
| 1146 | - keep_name n = isExternalName n &&
|
|
| 1147 | - nameModule n `elemModuleEnv` remaining_bcos_loaded
|
|
| 1148 | - |
|
| 1149 | - keep_mod :: Module -> Bool
|
|
| 1150 | - keep_mod m = m `elemModuleEnv` remaining_bcos_loaded
|
|
| 1151 | - |
|
| 1152 | - !new_pls = pls { linker_env = filterLinkerEnv keep_name linker_env,
|
|
| 1153 | - linked_breaks = filterLinkedBreaks keep_mod linked_breaks,
|
|
| 1154 | - bcos_loaded = remaining_bcos_loaded,
|
|
| 1155 | - objs_loaded = remaining_objs_loaded }
|
|
| 1115 | + let !new_pls = pls { bco_loader_state = modifyHomePackageBytecodeState bco_loader_state $ \_ -> emptyBytecodeState,
|
|
| 1116 | + -- NB: we don't unload the external package
|
|
| 1117 | + bcos_loaded = emptyModuleEnv,
|
|
| 1118 | + objs_loaded = emptyModuleEnv }
|
|
| 1156 | 1119 | |
| 1157 | 1120 | return new_pls
|
| 1158 | 1121 | where
|
| ... | ... | @@ -1296,6 +1259,8 @@ loadPackage interp hsc_env pkgs pls |
| 1296 | 1259 | <- sequenceA [mapM (locateLib interp hsc_env False [] dirs_env_ gcc_paths) extra_libs_ | (dirs_env_, extra_libs_) <- zip dirs_env extra_libs]
|
| 1297 | 1260 | let classifieds = zipWith (++) hs_classifieds extra_classifieds
|
| 1298 | 1261 | |
| 1262 | + maybePutSDoc logger (text "Using these library specs: " $$ (vcat (map ppr classifieds)))
|
|
| 1263 | + |
|
| 1299 | 1264 | -- Complication: all the .so's must be loaded before any of the .o's.
|
| 1300 | 1265 | let known_hs_dlls = [[ dll | DLLPath dll <- hs_classifieds_ ] | hs_classifieds_ <- hs_classifieds]
|
| 1301 | 1266 | known_extra_dlls = [ dll | extra_classifieds_ <- extra_classifieds, DLLPath dll <- extra_classifieds_ ]
|
| ... | ... | @@ -1372,15 +1337,19 @@ loadBytecodeLibrary hsc_env interp pls path = do |
| 1372 | 1337 | -- 0. Get the modification time of the module
|
| 1373 | 1338 | _mod_time <- expectJust <$> modificationTimeIfExists path'
|
| 1374 | 1339 | -- 1. Read the bytecode library
|
| 1375 | - (BytecodeLib _uid cbcs stubs_so) <- decodeOnDiskBytecodeLib hsc_env =<< readBytecodeLib hsc_env path'
|
|
| 1376 | - pls' <-case stubs_so of
|
|
| 1340 | + (BytecodeLib uid cbcs stubs_so) <- decodeOnDiskBytecodeLib hsc_env =<< readBytecodeLib hsc_env path'
|
|
| 1341 | + debugTraceMsg (hsc_logger hsc_env) 3 $ text "loadBytecodeLibrary: " $$ vcat [ text "uid: " <+> ppr uid
|
|
| 1342 | + , text "cbcs: " <+> ppr (length cbcs)
|
|
| 1343 | + , text "stubs_so: " <+> ppr stubs_so ]
|
|
| 1344 | + pls' <- case stubs_so of
|
|
| 1377 | 1345 | Nothing -> return pls
|
| 1378 | 1346 | Just (SharedObject so_file libdir libname) -> do
|
| 1379 | 1347 | m <- loadDLLs interp [so_file]
|
| 1380 | 1348 | case m of
|
| 1381 | 1349 | Right _ -> return $! pls { temp_sos = (libdir, libname) : temp_sos pls }
|
| 1382 | 1350 | Left err -> linkFail err (text err)
|
| 1383 | - dynLinkCompiledByteCode interp pls' KeepExternalDefinitions cbcs
|
|
| 1351 | + bco_state <- dynLinkCompiledByteCode interp (pkgs_loaded pls') (bco_loader_state pls') traverseExternalPackageBytecodeState KeepExternalDefinitions cbcs
|
|
| 1352 | + return $! pls' { bco_loader_state = bco_state }
|
|
| 1384 | 1353 | |
| 1385 | 1354 | |
| 1386 | 1355 | {-
|
| ... | ... | @@ -12,14 +12,32 @@ module GHC.Linker.Types |
| 12 | 12 | ( Loader (..)
|
| 13 | 13 | , LoaderState (..)
|
| 14 | 14 | , uninitializedLoader
|
| 15 | + |
|
| 16 | + -- * Bytecode Loader State
|
|
| 17 | + , BytecodeLoaderState(..)
|
|
| 18 | + , BytecodeState(..)
|
|
| 19 | + , emptyBytecodeLoaderState
|
|
| 20 | + , emptyBytecodeState
|
|
| 21 | + , modifyHomePackageBytecodeState
|
|
| 22 | + , modifyExternalPackageBytecodeState
|
|
| 23 | + , modifyBytecodeLoaderState
|
|
| 24 | + , lookupNameBytecodeState
|
|
| 25 | + , lookupBreakArrayBytecodeState
|
|
| 26 | + , lookupInfoTableBytecodeState
|
|
| 27 | + , lookupAddressBytecodeState
|
|
| 28 | + , lookupCCSBytecodeState
|
|
| 29 | + , BytecodeLoaderStateModifier
|
|
| 30 | + , BytecodeLoaderStateTraverser
|
|
| 31 | + , traverseHomePackageBytecodeState
|
|
| 32 | + , traverseExternalPackageBytecodeState
|
|
| 15 | 33 | , modifyClosureEnv
|
| 16 | 34 | , LinkerEnv(..)
|
| 17 | - , filterLinkerEnv
|
|
| 35 | + , emptyLinkerEnv
|
|
| 18 | 36 | , ClosureEnv
|
| 19 | 37 | , emptyClosureEnv
|
| 20 | 38 | , extendClosureEnv
|
| 21 | 39 | , LinkedBreaks(..)
|
| 22 | - , filterLinkedBreaks
|
|
| 40 | + , emptyLinkedBreaks
|
|
| 23 | 41 | , LinkableSet
|
| 24 | 42 | , mkLinkableSet
|
| 25 | 43 | , unionLinkableSet
|
| ... | ... | @@ -62,7 +80,7 @@ import GHCi.RemoteTypes |
| 62 | 80 | import GHCi.Message ( LoadedDLL )
|
| 63 | 81 | |
| 64 | 82 | import GHC.Stack.CCS
|
| 65 | -import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnvList, filterNameEnv )
|
|
| 83 | +import GHC.Types.Name.Env ( NameEnv, emptyNameEnv, extendNameEnvList, lookupNameEnv )
|
|
| 66 | 84 | import GHC.Types.Name ( Name )
|
| 67 | 85 | import GHC.Types.SptEntry
|
| 68 | 86 | |
| ... | ... | @@ -78,6 +96,8 @@ import GHC.Unit.Module.WholeCoreBindings |
| 78 | 96 | import Data.Maybe (mapMaybe)
|
| 79 | 97 | import Data.List.NonEmpty (NonEmpty, nonEmpty)
|
| 80 | 98 | import qualified Data.List.NonEmpty as NE
|
| 99 | +import Control.Applicative ((<|>))
|
|
| 100 | +import Data.Functor.Identity
|
|
| 81 | 101 | |
| 82 | 102 | |
| 83 | 103 | {- **********************************************************************
|
| ... | ... | @@ -149,8 +169,9 @@ and be able to lookup symbols specifically in them too (similarly to |
| 149 | 169 | newtype Loader = Loader { loader_state :: MVar (Maybe LoaderState) }
|
| 150 | 170 | |
| 151 | 171 | data LoaderState = LoaderState
|
| 152 | - { linker_env :: !LinkerEnv
|
|
| 153 | - -- ^ Current global mapping from Names to their true values
|
|
| 172 | + { bco_loader_state :: !BytecodeLoaderState
|
|
| 173 | + -- ^ Information about bytecode objects we have loaded into the
|
|
| 174 | + -- interpreter.
|
|
| 154 | 175 | |
| 155 | 176 | , bcos_loaded :: !LinkableSet
|
| 156 | 177 | -- ^ The currently loaded interpreted modules (home package)
|
| ... | ... | @@ -165,19 +186,110 @@ data LoaderState = LoaderState |
| 165 | 186 | , temp_sos :: ![(FilePath, String)]
|
| 166 | 187 | -- ^ We need to remember the name of previous temporary DLL/.so
|
| 167 | 188 | -- libraries so we can link them (see #10322)
|
| 189 | + }
|
|
| 168 | 190 | |
| 169 | - , linked_breaks :: !LinkedBreaks
|
|
| 191 | +data BytecodeState = BytecodeState
|
|
| 192 | + { bco_linker_env :: !LinkerEnv
|
|
| 193 | + -- ^ Current global mapping from Names to their true values
|
|
| 194 | + , bco_linked_breaks :: !LinkedBreaks
|
|
| 170 | 195 | -- ^ Mapping from loaded modules to their breakpoint arrays
|
| 196 | + }
|
|
| 197 | + |
|
| 198 | +-- | The 'BytecodeLoaderState' captures all the information about bytecode loaded
|
|
| 199 | +-- into the interpreter.
|
|
| 200 | +-- It is separated into two parts. One for bytecode objects loaded by the home package and
|
|
| 201 | +-- one for bytecode objects loaded from bytecode libraries for external packages.
|
|
| 202 | +-- Much like the HPT/EPS split, the home package state can be unloaded by calling 'unload'.
|
|
| 203 | +data BytecodeLoaderState = BytecodeLoaderState
|
|
| 204 | + { homePackage_loaded :: BytecodeState
|
|
| 205 | + -- ^ Information about bytecode objects from the home package we have loaded into the interpreter.
|
|
| 206 | + , externalPackage_loaded :: BytecodeState
|
|
| 207 | + -- ^ Information about bytecode objects from external packages we have loaded into the interpreter.
|
|
| 208 | + }
|
|
| 209 | + |
|
| 210 | + |
|
| 211 | +-- | Find a name loaded from bytecode
|
|
| 212 | +lookupNameBytecodeState :: BytecodeLoaderState -> Name -> Maybe (Name, ForeignHValue)
|
|
| 213 | +lookupNameBytecodeState (BytecodeLoaderState home_package external_package) name = do
|
|
| 214 | + lookupNameEnv (closure_env (bco_linker_env home_package)) name
|
|
| 215 | + <|> lookupNameEnv (closure_env (bco_linker_env external_package)) name
|
|
| 216 | + |
|
| 217 | +-- | Look up a break array in the bytecode loader state.
|
|
| 218 | +lookupBreakArrayBytecodeState :: BytecodeLoaderState -> Module -> Maybe (ForeignRef BreakArray)
|
|
| 219 | +lookupBreakArrayBytecodeState (BytecodeLoaderState home_package external_package) break_mod = do
|
|
| 220 | + lookupModuleEnv (breakarray_env (bco_linked_breaks home_package)) break_mod
|
|
| 221 | + <|> lookupModuleEnv (breakarray_env (bco_linked_breaks external_package)) break_mod
|
|
| 222 | + |
|
| 223 | +-- | Look up an info table in the bytecode loader state.
|
|
| 224 | +lookupInfoTableBytecodeState :: BytecodeLoaderState -> Name -> Maybe (Name, ItblPtr)
|
|
| 225 | +lookupInfoTableBytecodeState (BytecodeLoaderState home_package external_package) info_mod = do
|
|
| 226 | + lookupNameEnv (itbl_env (bco_linker_env home_package)) info_mod
|
|
| 227 | + <|> lookupNameEnv (itbl_env (bco_linker_env external_package)) info_mod
|
|
| 228 | + |
|
| 229 | +-- | Look up an address in the bytecode loader state.
|
|
| 230 | +lookupAddressBytecodeState :: BytecodeLoaderState -> Name -> Maybe (Name, AddrPtr)
|
|
| 231 | +lookupAddressBytecodeState (BytecodeLoaderState home_package external_package) addr_mod = do
|
|
| 232 | + lookupNameEnv (addr_env (bco_linker_env home_package)) addr_mod
|
|
| 233 | + <|> lookupNameEnv (addr_env (bco_linker_env external_package)) addr_mod
|
|
| 234 | + |
|
| 235 | +-- | Look up a cost centre stack in the bytecode loader state.
|
|
| 236 | +lookupCCSBytecodeState :: BytecodeLoaderState -> Module -> Maybe (Array BreakTickIndex (RemotePtr CostCentre))
|
|
| 237 | +lookupCCSBytecodeState (BytecodeLoaderState home_package external_package) ccs_mod = do
|
|
| 238 | + lookupModuleEnv (ccs_env (bco_linked_breaks home_package)) ccs_mod
|
|
| 239 | + <|> lookupModuleEnv (ccs_env (bco_linked_breaks external_package)) ccs_mod
|
|
| 240 | + |
|
| 241 | +emptyBytecodeLoaderState :: BytecodeLoaderState
|
|
| 242 | +emptyBytecodeLoaderState = BytecodeLoaderState
|
|
| 243 | + { homePackage_loaded = emptyBytecodeState
|
|
| 244 | + , externalPackage_loaded = emptyBytecodeState
|
|
| 171 | 245 | }
|
| 172 | 246 | |
| 247 | +emptyBytecodeState :: BytecodeState
|
|
| 248 | +emptyBytecodeState = BytecodeState
|
|
| 249 | + { bco_linker_env = emptyLinkerEnv
|
|
| 250 | + , bco_linked_breaks = emptyLinkedBreaks
|
|
| 251 | + }
|
|
| 252 | + |
|
| 253 | + |
|
| 254 | +-- Some parts of the compiler can be used to load bytecode into either the home package or
|
|
| 255 | +-- external package state. They are parameterised by a 'BytecodeLoaderStateModifier' or
|
|
| 256 | +-- 'BytecodeLoaderStateTraverser' so they know which part of the state to update.
|
|
| 257 | + |
|
| 258 | +type BytecodeLoaderStateModifier = BytecodeLoaderState -> (BytecodeState -> BytecodeState) -> BytecodeLoaderState
|
|
| 259 | +type BytecodeLoaderStateTraverser m = BytecodeLoaderState -> (BytecodeState -> m BytecodeState) -> m BytecodeLoaderState
|
|
| 260 | + |
|
| 261 | +-- | Only update the home package bytecode state.
|
|
| 262 | +modifyHomePackageBytecodeState :: BytecodeLoaderState -> (BytecodeState -> BytecodeState) -> BytecodeLoaderState
|
|
| 263 | +modifyHomePackageBytecodeState bls f = runIdentity $ traverseHomePackageBytecodeState bls (return . f)
|
|
| 264 | + |
|
| 265 | +-- | Only update the external package bytecode state.
|
|
| 266 | +modifyExternalPackageBytecodeState :: BytecodeLoaderState -> (BytecodeState -> BytecodeState) -> BytecodeLoaderState
|
|
| 267 | +modifyExternalPackageBytecodeState bls f = runIdentity $ traverseExternalPackageBytecodeState bls (return . f)
|
|
| 268 | + |
|
| 269 | +-- | Effectfully update the home package bytecode state.
|
|
| 270 | +traverseHomePackageBytecodeState :: Monad m => BytecodeLoaderState -> (BytecodeState -> m BytecodeState) -> m BytecodeLoaderState
|
|
| 271 | +traverseHomePackageBytecodeState bls f = do
|
|
| 272 | + home_package <- f (homePackage_loaded bls)
|
|
| 273 | + return bls { homePackage_loaded = home_package }
|
|
| 274 | + |
|
| 275 | +-- | Effectfully update the external package bytecode state.
|
|
| 276 | +traverseExternalPackageBytecodeState :: Monad m => BytecodeLoaderState -> (BytecodeState -> m BytecodeState) -> m BytecodeLoaderState
|
|
| 277 | +traverseExternalPackageBytecodeState bls f = do
|
|
| 278 | + external_package <- f (externalPackage_loaded bls)
|
|
| 279 | + return bls { externalPackage_loaded = external_package }
|
|
| 280 | + |
|
| 281 | + |
|
| 282 | +modifyBytecodeLoaderState :: BytecodeLoaderStateModifier -> LoaderState -> (BytecodeState -> BytecodeState) -> LoaderState
|
|
| 283 | +modifyBytecodeLoaderState modify_bytecode_loader_state pls f = pls { bco_loader_state = modify_bytecode_loader_state (bco_loader_state pls) f }
|
|
| 284 | + |
|
| 173 | 285 | uninitializedLoader :: IO Loader
|
| 174 | 286 | uninitializedLoader = Loader <$> newMVar Nothing
|
| 175 | 287 | |
| 176 | -modifyClosureEnv :: LoaderState -> (ClosureEnv -> ClosureEnv) -> LoaderState
|
|
| 288 | +modifyClosureEnv :: BytecodeState -> (ClosureEnv -> ClosureEnv) -> BytecodeState
|
|
| 177 | 289 | modifyClosureEnv pls f =
|
| 178 | - let le = linker_env pls
|
|
| 290 | + let le = bco_linker_env pls
|
|
| 179 | 291 | ce = closure_env le
|
| 180 | - in pls { linker_env = le { closure_env = f ce } }
|
|
| 292 | + in pls { bco_linker_env = le { closure_env = f ce } }
|
|
| 181 | 293 | |
| 182 | 294 | data LinkerEnv = LinkerEnv
|
| 183 | 295 | { closure_env :: !ClosureEnv
|
| ... | ... | @@ -195,11 +307,11 @@ data LinkerEnv = LinkerEnv |
| 195 | 307 | -- see Note [Generating code for top-level string literal bindings] in GHC.StgToByteCode.
|
| 196 | 308 | }
|
| 197 | 309 | |
| 198 | -filterLinkerEnv :: (Name -> Bool) -> LinkerEnv -> LinkerEnv
|
|
| 199 | -filterLinkerEnv f (LinkerEnv closure_e itbl_e addr_e) = LinkerEnv
|
|
| 200 | - { closure_env = filterNameEnv (f . fst) closure_e
|
|
| 201 | - , itbl_env = filterNameEnv (f . fst) itbl_e
|
|
| 202 | - , addr_env = filterNameEnv (f . fst) addr_e
|
|
| 310 | +emptyLinkerEnv :: LinkerEnv
|
|
| 311 | +emptyLinkerEnv = LinkerEnv
|
|
| 312 | + { closure_env = emptyNameEnv
|
|
| 313 | + , itbl_env = emptyNameEnv
|
|
| 314 | + , addr_env = emptyNameEnv
|
|
| 203 | 315 | }
|
| 204 | 316 | |
| 205 | 317 | type ClosureEnv = NameEnv (Name, ForeignHValue)
|
| ... | ... | @@ -228,10 +340,10 @@ data LinkedBreaks |
| 228 | 340 | -- Untouched when not profiling.
|
| 229 | 341 | }
|
| 230 | 342 | |
| 231 | -filterLinkedBreaks :: (Module -> Bool) -> LinkedBreaks -> LinkedBreaks
|
|
| 232 | -filterLinkedBreaks f (LinkedBreaks ba_e ccs_e) = LinkedBreaks
|
|
| 233 | - { breakarray_env = filterModuleEnv (\m _ -> f m) ba_e
|
|
| 234 | - , ccs_env = filterModuleEnv (\m _ -> f m) ccs_e
|
|
| 343 | +emptyLinkedBreaks :: LinkedBreaks
|
|
| 344 | +emptyLinkedBreaks = LinkedBreaks
|
|
| 345 | + { breakarray_env = emptyModuleEnv
|
|
| 346 | + , ccs_env = emptyModuleEnv
|
|
| 235 | 347 | }
|
| 236 | 348 | |
| 237 | 349 | type PkgsLoaded = UniqDFM UnitId LoadedPkgInfo
|
| ... | ... | @@ -56,6 +56,7 @@ import Data.List ( partition ) |
| 56 | 56 | import qualified Data.List.NonEmpty as NE
|
| 57 | 57 | import Data.Maybe
|
| 58 | 58 | import Data.IORef
|
| 59 | +import GHC.Linker.Types
|
|
| 59 | 60 | |
| 60 | 61 | -------------------------------------
|
| 61 | 62 | -- | The :print & friends commands
|
| ... | ... | @@ -161,7 +162,7 @@ bindSuspensions t = do |
| 161 | 162 | | (name,ty) <- zip names tys]
|
| 162 | 163 | new_ic = extendInteractiveContextWithIds ictxt ids
|
| 163 | 164 | interp = hscInterp hsc_env
|
| 164 | - liftIO $ extendLoadedEnv interp (zip names fhvs)
|
|
| 165 | + liftIO $ extendLoadedEnv interp modifyHomePackageBytecodeState (zip names fhvs)
|
|
| 165 | 166 | setSession hsc_env {hsc_IC = new_ic }
|
| 166 | 167 | return t'
|
| 167 | 168 | where
|
| ... | ... | @@ -64,7 +64,7 @@ import GHCi.RemoteTypes |
| 64 | 64 | import GHC.ByteCode.Types
|
| 65 | 65 | |
| 66 | 66 | import GHC.Linker.Loader as Loader
|
| 67 | -import GHC.Linker.Types (LinkedBreaks (..))
|
|
| 67 | +import GHC.Linker.Types
|
|
| 68 | 68 | |
| 69 | 69 | import GHC.Hs
|
| 70 | 70 | |
| ... | ... | @@ -310,7 +310,7 @@ handleRunStatus step expr bindings final_ids status history0 = do |
| 310 | 310 | let
|
| 311 | 311 | final_ic = extendInteractiveContextWithIds (hsc_IC hsc_env) final_ids
|
| 312 | 312 | final_names = map getName final_ids
|
| 313 | - liftIO $ Loader.extendLoadedEnv interp (zip final_names hvals)
|
|
| 313 | + liftIO $ Loader.extendLoadedEnv interp modifyHomePackageBytecodeState (zip final_names hvals)
|
|
| 314 | 314 | hsc_env' <- liftIO $ rttiEnvironment hsc_env{hsc_IC=final_ic}
|
| 315 | 315 | setSession hsc_env'
|
| 316 | 316 | return (ExecComplete (Right final_names) allocs)
|
| ... | ... | @@ -433,7 +433,7 @@ resumeExec step mbCnt |
| 433 | 433 | , not (n `elem` old_names) ]
|
| 434 | 434 | interp = hscInterp hsc_env
|
| 435 | 435 | dflags = hsc_dflags hsc_env
|
| 436 | - liftIO $ Loader.deleteFromLoadedEnv interp new_names
|
|
| 436 | + liftIO $ Loader.deleteFromLoadedHomeEnv interp new_names
|
|
| 437 | 437 | |
| 438 | 438 | case r of
|
| 439 | 439 | Resume { resumeStmt = expr
|
| ... | ... | @@ -474,18 +474,18 @@ setupBreakpoint interp ibi cnt = do |
| 474 | 474 | |
| 475 | 475 | getBreakArray :: Interp -> InternalBreakpointId -> InternalModBreaks -> IO (ForeignRef BreakArray)
|
| 476 | 476 | getBreakArray interp InternalBreakpointId{ibi_info_mod} imbs = do
|
| 477 | - breaks0 <- linked_breaks . fromMaybe (panic "Loader not initialised") <$> getLoaderState interp
|
|
| 477 | + breaks0 <- bco_linked_breaks . homePackage_loaded . bco_loader_state . fromMaybe (panic "Loader not initialised") <$> getLoaderState interp
|
|
| 478 | 478 | case lookupModuleEnv (breakarray_env breaks0) ibi_info_mod of
|
| 479 | 479 | Just ba -> return ba
|
| 480 | 480 | Nothing -> do
|
| 481 | 481 | modifyLoaderState interp $ \ld_st -> do
|
| 482 | - let lb = linked_breaks ld_st
|
|
| 482 | + let lb = bco_linked_breaks . homePackage_loaded . bco_loader_state $ ld_st
|
|
| 483 | 483 | |
| 484 | 484 | -- Recall that BreakArrays are allocated only at BCO link time, so if we
|
| 485 | 485 | -- haven't linked the BCOs we intend to break at yet, we allocate the arrays here.
|
| 486 | 486 | ba_env <- allocateBreakArrays interp (breakarray_env lb) [imbs]
|
| 487 | 487 | |
| 488 | - let ld_st' = ld_st { linked_breaks = lb{breakarray_env = ba_env} }
|
|
| 488 | + let ld_st' = modifyBytecodeLoaderState modifyHomePackageBytecodeState ld_st $ \bco_state -> bco_state { bco_linked_breaks = (bco_linked_breaks bco_state) { breakarray_env = ba_env } }
|
|
| 489 | 489 | let ba = expectJust {- just computed -} $ lookupModuleEnv ba_env ibi_info_mod
|
| 490 | 490 | |
| 491 | 491 | return
|
| ... | ... | @@ -575,7 +575,7 @@ bindLocalsAtBreakpoint hsc_env apStack span Nothing = do |
| 575 | 575 | ictxt1 = extendInteractiveContextWithIds ictxt0 [exn_id]
|
| 576 | 576 | interp = hscInterp hsc_env
|
| 577 | 577 | --
|
| 578 | - Loader.extendLoadedEnv interp [(exn_name, apStack)]
|
|
| 578 | + Loader.extendLoadedEnv interp modifyHomePackageBytecodeState [(exn_name, apStack)]
|
|
| 579 | 579 | return (hsc_env{ hsc_IC = ictxt1 }, [exn_name])
|
| 580 | 580 | |
| 581 | 581 | -- Just case: we stopped at a breakpoint, we have information about the location
|
| ... | ... | @@ -634,8 +634,8 @@ bindLocalsAtBreakpoint hsc_env apStack_fhv span (Just ibi) = do |
| 634 | 634 | names = map idName new_ids
|
| 635 | 635 | |
| 636 | 636 | let fhvs = catMaybes mb_hValues
|
| 637 | - Loader.extendLoadedEnv interp (zip names fhvs)
|
|
| 638 | - when result_ok $ Loader.extendLoadedEnv interp [(result_name, apStack_fhv)]
|
|
| 637 | + Loader.extendLoadedEnv interp modifyHomePackageBytecodeState (zip names fhvs)
|
|
| 638 | + when result_ok $ Loader.extendLoadedEnv interp modifyHomePackageBytecodeState [(result_name, apStack_fhv)]
|
|
| 639 | 639 | hsc_env1 <- rttiEnvironment hsc_env{ hsc_IC = ictxt1 }
|
| 640 | 640 | return (hsc_env1, if result_ok then result_name:names else names)
|
| 641 | 641 | where
|
| ... | ... | @@ -851,7 +851,8 @@ distrustAllUnits pkgs = map distrust pkgs |
| 851 | 851 | mungeUnitInfo :: FilePath -> FilePath
|
| 852 | 852 | -> UnitInfo -> UnitInfo
|
| 853 | 853 | mungeUnitInfo top_dir pkgroot =
|
| 854 | - mungeDynLibFields
|
|
| 854 | + mungeBytecodeLibFields
|
|
| 855 | + . mungeDynLibFields
|
|
| 855 | 856 | . mungeUnitInfoPaths (ST.pack top_dir) (ST.pack pkgroot)
|
| 856 | 857 | |
| 857 | 858 | mungeDynLibFields :: UnitInfo -> UnitInfo
|
| ... | ... | @@ -862,6 +863,15 @@ mungeDynLibFields pkg = |
| 862 | 863 | ds -> ds
|
| 863 | 864 | }
|
| 864 | 865 | |
| 866 | +-- | Default to using library-dirs if bytecode library dirs is not explicitly set.
|
|
| 867 | +mungeBytecodeLibFields :: UnitInfo -> UnitInfo
|
|
| 868 | +mungeBytecodeLibFields pkg =
|
|
| 869 | + pkg {
|
|
| 870 | + unitLibraryBytecodeDirs = case unitLibraryBytecodeDirs pkg of
|
|
| 871 | + [] -> unitLibraryDirs pkg
|
|
| 872 | + ds -> ds
|
|
| 873 | + }
|
|
| 874 | + |
|
| 865 | 875 | -- -----------------------------------------------------------------------------
|
| 866 | 876 | -- Modify our copy of the unit database based on trust flags,
|
| 867 | 877 | -- -trust and -distrust.
|
| ... | ... | @@ -2056,7 +2056,8 @@ checkHSLib _verbosity dirs lib = do |
| 2056 | 2056 | "lib" ++ lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib",
|
| 2057 | 2057 | "lib" ++ lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dylib",
|
| 2058 | 2058 | lib ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll",
|
| 2059 | - lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll"
|
|
| 2059 | + lib ++ "_p" ++ "-ghc" ++ GHC.Version.cProjectVersion ++ ".dll",
|
|
| 2060 | + lib ++ ".bytecode"
|
|
| 2060 | 2061 | ]
|
| 2061 | 2062 | b <- liftIO $ doesFileExistOnPath filenames dirs
|
| 2062 | 2063 | when (not b) $
|