[Git][ghc/ghc][wip/torsten.schmits/oneshot-bytecode-pkgdeps] reimplement lookup avoidance

Torsten Schmits (@torsten.schmits) gitlab at gitlab.haskell.org
Fri Jul 12 12:09:48 UTC 2024



Torsten Schmits pushed to branch wip/torsten.schmits/oneshot-bytecode-pkgdeps at Glasgow Haskell Compiler / GHC


Commits:
a9d81178 by Torsten Schmits at 2024-07-12T14:09:19+02:00
reimplement lookup avoidance

- - - - -


3 changed files:

- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Unit/Finder.hs


Changes:

=====================================
compiler/GHC/Linker/Deps.hs
=====================================
@@ -6,6 +6,7 @@
 {-# LANGUAGE CPP #-}
 {-# LANGUAGE RecordWildCards #-}
 {-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE NamedFieldPuns #-}
 
 module GHC.Linker.Deps
   ( LinkDepsOpts (..)
@@ -82,8 +83,8 @@ data LinkDepsOpts = LinkDepsOpts
 data LinkDeps = LinkDeps
   { ldNeededLinkables :: [Linkable]
   , ldAllLinkables    :: [Linkable]
-  , ldUnits           :: [UnitId]
-  , ldNeededUnits     :: UniqDSet UnitId
+  , ldNeededUnits     :: [UnitId]
+  , ldAllUnits        :: UniqDSet UnitId
   }
 
 -- | Find all the packages and linkables that a set of modules depends on
@@ -109,7 +110,6 @@ getLinkDeps opts interp pls span mods = do
 
       get_link_deps opts pls maybe_normal_osuf span mods
 
-
 get_link_deps
   :: LinkDepsOpts
   -> LoaderState
@@ -118,43 +118,33 @@ get_link_deps
   -> [Module]
   -> IO LinkDeps
 get_link_deps opts pls maybe_normal_osuf span mods = do
-        -- 1.  Find the dependent home-pkg-modules/packages from each iface
-        -- (omitting modules from the interactive package, which is already linked)
-      deps <-
-          -- Why two code paths here? There is a significant amount of repeated work
-          -- performed calculating transitive dependencies
-          -- if --make uses the oneShot code path (see MultiLayerModulesTH_* tests)
-          if ldOneShotMode opts
+  -- 1.  Find the dependent home-pkg-modules/packages from each iface
+  --     (omitting modules from the interactive package, which is already linked)
+  --     Why two code paths here? There is a significant amount of repeated work
+  --     performed calculating transitive dependencies
+  --     if --make uses the oneShot code path (see MultiLayerModulesTH_* tests)
+  deps <- if ldOneShotMode opts
           then oneshot_deps opts (filterOut isInteractiveModule mods)
           else make_deps
 
-            -- TODO this used to avoid some lookups, maybe we can move that to
-            -- oneshot_deps now
-            -- (mods_needed, links_got) = partitionWith split_mods mods_s
-            --
-            -- split_mods mod =
-            --     let is_linked = lookupModuleEnv (objs_loaded pls) mod
-            --                     <|> lookupModuleEnv (bcos_loaded pls) mod
-            --     in case is_linked of
-            --          Just linkable -> Right linkable
-            --          Nothing -> Left mod
-
-        -- 3.  For each dependent module, find its linkable
-        --     This will either be in the HPT or (in the case of one-shot
-        --     compilation) we may need to use maybe_getFileLinkable
-      (lnks, pkgs_s) <- partitionWithM dep_linkable deps
-      let
-        lnks_needed = concat lnks
-        pkgs_s' = mkUniqDSet pkgs_s
-        pkgs_needed = eltsUDFM $ getUniqDSet pkgs_s' `minusUDFM` pkgs_loaded pls
-
-      return $ LinkDeps
-        { ldNeededLinkables = lnks_needed
-        -- , ldAllLinkables    = links_got ++ lnks_needed
-        , ldAllLinkables    = lnks_needed
-        , ldUnits           = pkgs_needed
-        , ldNeededUnits     = pkgs_s'
-        }
+  -- 2.  Exclude ones already linked
+  --     Main reason: avoid findModule calls in get_linkable
+  -- TODO outdated
+  let (loaded_modules, needed_modules, ldAllUnits, ldNeededUnits) =
+        classify_deps pls deps
+
+  -- 3.  For each dependent module, find its linkable
+  --     This will either be in the HPT or (in the case of one-shot
+  --     compilation) we may need to use maybe_getFileLinkable
+  -- TODO outdated
+  ldNeededLinkables <- mapM module_linkable needed_modules
+
+  pure LinkDeps {
+    ldNeededLinkables,
+    ldAllLinkables = loaded_modules ++ ldNeededLinkables,
+    ldNeededUnits,
+    ldAllUnits
+  }
   where
     mod_graph = ldModuleGraph opts
     unit_env  = ldUnitEnv     opts
@@ -217,11 +207,7 @@ get_link_deps opts pls maybe_normal_osuf span mods = do
 
     while_linking_expr = text "while linking an interpreted expression"
 
-    dep_linkable = \case
-      LinkModules mods -> Left <$> mapM get_linkable (eltsUDFM mods)
-      LinkLibrary uid -> pure (Right uid)
-
-    get_linkable = \case
+    module_linkable = \case
       LinkHomeModule hmi ->
         pure (expectJust "getLinkDeps" (homeModLinkable hmi))
 
@@ -271,21 +257,27 @@ get_link_deps opts pls maybe_normal_osuf span mods = do
     adjust_ul _ l at LoadedBCOs{} = return l
     adjust_ul _ (CoreBindings (WholeCoreBindings _ mod _))     = pprPanic "Unhydrated core bindings" (ppr mod)
 
-data LinkObjectModule =
+data LinkModule =
   LinkHomeModule HomeModInfo
   |
   LinkObjectModule ModIface ModLocation
   |
   LinkByteCodeModule ModIface WholeCoreBindings
 
-instance Outputable LinkObjectModule where
+link_module_iface :: LinkModule -> ModIface
+link_module_iface = \case
+  LinkHomeModule hmi -> hm_iface hmi
+  LinkObjectModule iface _ -> iface
+  LinkByteCodeModule iface _ -> iface
+
+instance Outputable LinkModule where
   ppr = \case
     LinkHomeModule hmi -> ppr (mi_module (hm_iface hmi)) <+> brackets (text "HMI")
     LinkObjectModule iface _ -> ppr (mi_module iface)
     LinkByteCodeModule _ wcb -> ppr (wcb_module wcb) <+> brackets (text "BC")
 
 data LinkDep =
-  LinkModules (UniqDFM ModuleName LinkObjectModule)
+  LinkModules (UniqDFM ModuleName LinkModule)
   |
   LinkLibrary UnitId
 
@@ -433,6 +425,33 @@ link_boot_mod_error mod =
   text "module" <+> ppr mod <+>
   text "cannot be linked; it is only available as a boot module"
 
+classify_deps ::
+  LoaderState ->
+  [LinkDep] ->
+  ([Linkable], [LinkModule], UniqDSet UnitId, [UnitId])
+classify_deps pls deps =
+  (loaded_modules, needed_modules, all_packages, needed_packages)
+  where
+    (loaded_modules, needed_modules) =
+      partitionWith loaded_or_needed (concatMap eltsUDFM modules)
+
+    needed_packages =
+      eltsUDFM (getUniqDSet all_packages `minusUDFM` pkgs_loaded pls)
+
+    all_packages = mkUniqDSet packages
+
+    (modules, packages) = flip partitionWith deps $ \case
+      LinkModules mods -> Left mods
+      LinkLibrary lib -> Right lib
+
+    loaded_or_needed lm =
+      maybe (Right lm) Left (loaded_linkable (mi_module (link_module_iface lm)))
+
+    loaded_linkable mod =
+      lookupModuleEnv (objs_loaded pls) mod
+      <|>
+      lookupModuleEnv (bcos_loaded pls) mod
+
 {-
 Note [Using Byte Code rather than Object Code for Template Haskell]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


=====================================
compiler/GHC/Linker/Loader.hs
=====================================
@@ -230,10 +230,10 @@ loadDependencies interp hsc_env pls span needed_mods = do
    -- Find what packages and linkables are required
    deps <- getLinkDeps opts interp pls span needed_mods
 
-   let this_pkgs_needed = ldNeededUnits deps
+   let this_pkgs_needed = ldAllUnits deps
 
    -- Link the packages and modules required
-   pls1 <- loadPackages' interp hsc_env (ldUnits deps) pls
+   pls1 <- loadPackages' interp hsc_env (ldNeededUnits deps) pls
    (pls2, succ) <- loadModuleLinkables interp hsc_env pls1 (ldNeededLinkables deps)
    let this_pkgs_loaded = udfmRestrictKeys all_pkgs_loaded $ getUniqDSet trans_pkgs_needed
        all_pkgs_loaded = pkgs_loaded pls2


=====================================
compiler/GHC/Unit/Finder.hs
=====================================
@@ -748,7 +748,7 @@ mkStubPaths fopts mod location
         stub_basename <.> os "h"
 
 -- -----------------------------------------------------------------------------
--- findLinkable isn't related to the other stuff in here,
+-- findObjectLinkable isn't related to the other stuff in here,
 -- but there's no other obvious place for it
 
 findObjectLinkableMaybe :: Module -> ModLocation -> IO (Maybe Linkable)



View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a9d811785554315d3a6d722ca31acba52079b908

-- 
This project does not include diff previews in email notifications.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/a9d811785554315d3a6d722ca31acba52079b908
You're receiving this email because of your account on gitlab.haskell.org.


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


More information about the ghc-commits mailing list