--- For each module (or SCC of modules), we take:
---
--- - an on-disk linkable, if this is the first time around and one
--- is available.
---
--- - the old linkable, otherwise (and if one is available).
---
--- and we throw away the linkable if it is older than the source file.
--- In interactive mode, we also ignore the on-disk linkables unless
--- all of the dependents of this SCC also have on-disk linkables (we
--- can't have dynamically loaded objects that depend on interpreted
--- modules in GHCi).
---
--- If a module has a valid linkable, then it may be STABLE (see below),
--- and it is classified as SOURCE UNCHANGED for the purposes of calling
--- compile.
---
--- ToDo: this pass could be merged with the preUpsweep.
---
--- ****************
--- CAREFUL! This pass operates on the cyclic version of
--- the module graph (topSortModuleGraph True), whereas the upsweep operates on
--- the non-cyclic (topSortModuleGraph False) version of the graph.
--- ****************
-
-getValidLinkables
- :: GhcMode
- -> [Linkable] -- old linkables
- -> [Module] -- all home modules
- -> [SCC ModSummary] -- all modules in the program, dependency order
- -> IO ( [Linkable], -- still-valid linkables
- [Linkable] -- new linkables we just found on the disk
- -- presumably generated by separate run of ghc
- )
-
-getValidLinkables mode old_linkables all_home_mods module_graph
- = do { -- Process the SCCs in bottom-to-top order
- -- (foldM works left-to-right)
- ls <- foldM (getValidLinkablesSCC mode old_linkables all_home_mods)
- [] module_graph
- ; return (partition_it ls [] []) }
- where
- partition_it [] valid new = (valid,new)
- partition_it ((l,b):ls) valid new
- | b = partition_it ls valid (l:new)
- | otherwise = partition_it ls (l:valid) new
-
-
-getValidLinkablesSCC
- :: GhcMode
- -> [Linkable] -- old linkables
- -> [Module] -- all home modules
- -> [(Linkable,Bool)]
- -> SCC ModSummary
- -> IO [(Linkable,Bool)]
-
-getValidLinkablesSCC mode old_linkables all_home_mods new_linkables scc0
- = let
- scc = flattenSCC scc0
- scc_names = map ms_mod scc
- home_module m = m `elem` all_home_mods && m `notElem` scc_names
- scc_allhomeimps = nub (filter home_module (concatMap ms_imps scc))
- -- NB. ms_imps, not ms_allimps above. We don't want to
- -- force a module's SOURCE imports to be already compiled for
- -- its object linkable to be valid.
-
- -- The new_linkables is only the *valid* linkables below here
- has_object m = case findModuleLinkable_maybe (map fst new_linkables) m of
- Nothing -> False
- Just l -> isObjectLinkable l
-
- objects_allowed = mode == BatchCompile || all has_object scc_allhomeimps
- in do
-
- new_linkables'
- <- foldM (getValidLinkable old_linkables objects_allowed) [] scc
-
- -- since an scc can contain only all objects or no objects at all,
- -- we have to check whether we got all objects or not, and re-do
- -- the linkable check if not.
- new_linkables' <-
- if objects_allowed
- && not (all isObjectLinkable (map fst new_linkables'))
- then foldM (getValidLinkable old_linkables False) [] scc
- else return new_linkables'
-
- return (new_linkables ++ new_linkables')
-
-
-getValidLinkable :: [Linkable] -> Bool -> [(Linkable,Bool)] -> ModSummary
- -> IO [(Linkable,Bool)]
- -- True <=> linkable is new; i.e. freshly discovered on the disk
- -- presumably generated 'on the side'
- -- by a separate GHC run
-getValidLinkable old_linkables objects_allowed new_linkables summary
- -- 'objects_allowed' says whether we permit this module to
- -- have a .o-file linkable. We only permit it if all the
- -- modules it depends on also have .o files; a .o file can't
- -- link to a bytecode module
- = do let mod_name = ms_mod summary
-
- maybe_disk_linkable
- <- if (not objects_allowed)
- then return Nothing
-
- else findLinkable mod_name (ms_location summary)
-
- let old_linkable = findModuleLinkable_maybe old_linkables mod_name
-
- new_linkables' =
- case (old_linkable, maybe_disk_linkable) of
- (Nothing, Nothing) -> []
-
- -- new object linkable just appeared
- (Nothing, Just l) -> up_to_date l True
-
- (Just l, Nothing)
- | isObjectLinkable l -> []
- -- object linkable disappeared! In case we need to
- -- relink the module, disregard the old linkable and
- -- just interpret the module from now on.
- | otherwise -> up_to_date l False
- -- old byte code linkable
-
- (Just l, Just l')
- | not (isObjectLinkable l) -> up_to_date l False
- -- if the previous linkable was interpreted, then we
- -- ignore a newly compiled version, because the version
- -- numbers in the interface file will be out-of-sync with
- -- our internal ones.
- | linkableTime l' > linkableTime l -> up_to_date l' True
- | linkableTime l' == linkableTime l -> up_to_date l False
- | otherwise -> []
- -- on-disk linkable has been replaced by an older one!
- -- again, disregard the previous one.
-
- up_to_date l b
- | linkableTime l < ms_hs_date summary = []
- | otherwise = [(l,b)]
- -- why '<' rather than '<=' above? If the filesystem stores
+-- -----------------------------------------------------------------------------
+-- checkStability
+
+{-
+ Stability tells us which modules definitely do not need to be recompiled.
+ There are two main reasons for having stability:
+
+ - avoid doing a complete upsweep of the module graph in GHCi when
+ modules near the bottom of the tree have not changed.
+
+ - to tell GHCi when it can load object code: we can only load object code
+ for a module when we also load object code fo all of the imports of the
+ module. So we need to know that we will definitely not be recompiling
+ any of these modules, and we can use the object code.
+
+ NB. stability is of no importance to BatchCompile at all, only Interactive.
+ (ToDo: what about JustTypecheck?)
+
+ The stability check is as follows. Both stableObject and
+ stableBCO are used during the upsweep phase later.
+
+ -------------------
+ stable m = stableObject m || stableBCO m
+
+ stableObject m =
+ all stableObject (imports m)
+ && old linkable does not exist, or is == on-disk .o
+ && date(on-disk .o) > date(.hs)
+
+ stableBCO m =
+ all stable (imports m)
+ && date(BCO) > date(.hs)
+ -------------------
+
+ These properties embody the following ideas:
+
+ - if a module is stable:
+ - if it has been compiled in a previous pass (present in HPT)
+ then it does not need to be compiled or re-linked.
+ - if it has not been compiled in a previous pass,
+ then we only need to read its .hi file from disk and
+ link it to produce a ModDetails.
+
+ - if a modules is not stable, we will definitely be at least
+ re-linking, and possibly re-compiling it during the upsweep.
+ All non-stable modules can (and should) therefore be unlinked
+ before the upsweep.
+
+ - Note that objects are only considered stable if they only depend
+ on other objects. We can't link object code against byte code.
+-}
+
+checkStability
+ :: HomePackageTable -- HPT from last compilation
+ -> [SCC ModSummary] -- current module graph (cyclic)
+ -> [Module] -- all home modules
+ -> ([Module], -- stableObject
+ [Module]) -- stableBCO
+
+checkStability hpt sccs all_home_mods = foldl checkSCC ([],[]) sccs
+ where
+ checkSCC (stable_obj, stable_bco) scc0
+ | stableObjects = (scc_mods ++ stable_obj, stable_bco)
+ | stableBCOs = (stable_obj, scc_mods ++ stable_bco)
+ | otherwise = (stable_obj, stable_bco)
+ where
+ scc = flattenSCC scc0
+ scc_mods = map ms_mod scc
+ home_module m = m `elem` all_home_mods && m `notElem` scc_mods
+
+ scc_allimps = nub (filter home_module (concatMap ms_allimps scc))
+ -- all imports outside the current SCC, but in the home pkg
+
+ stable_obj_imps = map (`elem` stable_obj) scc_allimps
+ stable_bco_imps = map (`elem` stable_bco) scc_allimps
+
+ stableObjects =
+ and stable_obj_imps
+ && all object_ok scc
+
+ stableBCOs =
+ and (zipWith (||) stable_obj_imps stable_bco_imps)
+ && all bco_ok scc
+
+ object_ok ms
+ | Just t <- ms_obj_date ms = t >= ms_hs_date ms
+ && same_as_prev t
+ | otherwise = False
+ where
+ same_as_prev t = case lookupModuleEnv hpt (ms_mod ms) of
+ Nothing -> True
+ Just hmi | Just l <- hm_linkable hmi
+ -> isObjectLinkable l && t == linkableTime l
+ -- why '>=' rather than '>' above? If the filesystem stores