Wolfgang Jeltsch pushed to branch wip/sort-usages at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • compiler/GHC/HsToCore/Usage.hs
    ... ... @@ -12,7 +12,6 @@ import GHC.Tc.Types
    12 12
     import GHC.Iface.Load
    
    13 13
     
    
    14 14
     import GHC.Utils.Outputable
    
    15
    -import GHC.Utils.Misc
    
    16 15
     import GHC.Utils.Fingerprint
    
    17 16
     import GHC.Utils.Panic
    
    18 17
     import GHC.Utils.Monad
    
    ... ... @@ -33,7 +32,7 @@ import GHC.Data.Maybe
    33 32
     import GHC.Data.FastString
    
    34 33
     
    
    35 34
     import Data.Containers.ListUtils (nubOrdOn)
    
    36
    -import Data.List (sortBy, sortOn)
    
    35
    +import Data.List (sortBy)
    
    37 36
     import Data.Map (Map)
    
    38 37
     import qualified Data.Map as Map
    
    39 38
     import qualified Data.Set as Set
    
    ... ... @@ -70,8 +69,8 @@ data UsageConfig = UsageConfig
    70 69
       { uc_safe_implicit_imps_req :: !Bool -- ^ Are all implicit imports required to be safe for this Safe Haskell mode?
    
    71 70
       }
    
    72 71
     
    
    73
    --- | Build the list of 'Usage's that drives recompilation checking.
    
    74
    --- The resulting list is deterministically sorted (see 'usageFingerprint').
    
    72
    +-- | Build the list of 'Usage's that drive recompilation checking.
    
    73
    +-- The resulting list is deterministically sorted.
    
    75 74
     mkUsageInfo :: UsageConfig -> Plugins -> FinderCache -> UnitEnv
    
    76 75
                 -> Module -> ImportedMods -> [ImportUserSpec] -> NameSet
    
    77 76
                 -> [FilePath] -> [FilePath] -> [(Module, Fingerprint)] -> [LinkableUsage] -> PkgsLoaded
    
    ... ... @@ -102,13 +101,14 @@ mkUsageInfo uc plugins fc unit_env
    102 101
                                         }
    
    103 102
                                    | (mod, hash) <- merged ]
    
    104 103
                                 ++ object_usages
    
    105
    -
    
    106
    -    -- Sort all the Usages to ensure a deterministic ordering.
    
    107
    -    let sorted_usages = sortOn usageFingerprint usages
    
    108
    -    sorted_usages `seqList` return sorted_usages
    
    109
    -    -- seq the list of Usages returned: occasionally these
    
    110
    -    -- don't get evaluated for a while and we can end up hanging on to
    
    111
    -    -- the entire collection of Ifaces.
    
    104
    +    return (sortBy stableUsageCmp usages)
    
    105
    +    -- Note that the sorting serves two purposes:
    
    106
    +    --   * It makes the order of usages deterministic.
    
    107
    +    --   * It evaluates the spine of 'usages' and reduces all of its elements to
    
    108
    +    --     at least WHNF und thus has at least the effect of 'seqList'.
    
    109
    +    -- The latter is important because occasionally the returned list is not
    
    110
    +    -- evaluated for a while, so that with too much laziness here we could end
    
    111
    +    -- up hanging on to the entire collection of 'Iface's.
    
    112 112
     
    
    113 113
     {- Note [Plugin dependencies]
    
    114 114
     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    

  • compiler/GHC/Unit/Module/Deps.hs
    1 1
     {-# LANGUAGE PatternSynonyms #-}
    
    2 2
     {-# LANGUAGE DerivingVia #-}
    
    3
    +
    
    4
    +{-# OPTIONS_GHC -Wwarn=incomplete-record-selectors #-}
    
    5
    +
    
    3 6
     -- | Dependencies and Usage of a module
    
    4 7
     module GHC.Unit.Module.Deps
    
    5 8
        ( Dependencies(dep_direct_mods
    
    ... ... @@ -17,7 +20,7 @@ module GHC.Unit.Module.Deps
    17 20
        , noDependencies
    
    18 21
        , pprDeps
    
    19 22
        , Usage (..)
    
    20
    -   , usageFingerprint
    
    23
    +   , stableUsageCmp
    
    21 24
        , HomeModImport (..)
    
    22 25
        , HomeModImportedAvails (..)
    
    23 26
        , ImportAvails (..)
    
    ... ... @@ -53,6 +56,7 @@ import GHC.Utils.Outputable
    53 56
     import Control.DeepSeq
    
    54 57
     import Data.Bifunctor
    
    55 58
     import qualified Data.Foldable as Foldable
    
    59
    +import Data.Function (on)
    
    56 60
     import Data.List (sortBy, sort, partition)
    
    57 61
     import Data.Set (Set)
    
    58 62
     import qualified Data.Set as Set
    
    ... ... @@ -498,16 +502,46 @@ instance Binary Usage where
    498 502
     
    
    499 503
               i -> error ("Binary.get(Usage): " ++ show i)
    
    500 504
     
    
    501
    --- | Extract the distinguishing fingerprint carried by a particular 'Usage'
    
    502
    --- constructor.  Every constructor stores a hash capturing the bit of state
    
    503
    --- that drives recompilation decisions, so we can sort on it directly.
    
    504
    -usageFingerprint :: Usage -> Fingerprint
    
    505
    -usageFingerprint UsagePackageModule{ usg_mod_hash = fp } = fp
    
    506
    -usageFingerprint UsageHomeModule{ usg_mod_hash = fp } = fp
    
    507
    -usageFingerprint UsageFile{ usg_file_hash = fp } = fp
    
    508
    -usageFingerprint UsageDirectory{ usg_dir_hash = fp } = fp
    
    509
    -usageFingerprint UsageHomeModuleBytecode{ usg_bytecode_hash = fp } = fp
    
    510
    -usageFingerprint UsageMergedRequirement{ usg_mod_hash = fp } = fp
    
    505
    +-- | Compares 'Usage's by constructor and, if the constructors are the same, by
    
    506
    +--   identifying strings, to achieve a predictable ordering.
    
    507
    +stableUsageCmp :: Usage -> Usage -> Ordering
    
    508
    +stableUsageCmp
    
    509
    +    usage1@UsagePackageModule {}
    
    510
    +    usage2@UsagePackageModule {}
    
    511
    +    = (compare `on` usg_mod) usage1 usage2
    
    512
    +stableUsageCmp
    
    513
    +    usage1@UsageHomeModule {}
    
    514
    +    usage2@UsageHomeModule {}
    
    515
    +    = (compare `on` Module <$> usg_unit_id <*> usg_mod_name) usage1 usage2
    
    516
    +stableUsageCmp
    
    517
    +    usage1@UsageFile {}
    
    518
    +    usage2@UsageFile {}
    
    519
    +    = (lexicalCompareFS `on` usg_file_path) usage1 usage2
    
    520
    +stableUsageCmp
    
    521
    +    usage1@UsageDirectory {}
    
    522
    +    usage2@UsageDirectory {}
    
    523
    +    = (lexicalCompareFS `on` usg_dir_path) usage1 usage2
    
    524
    +stableUsageCmp
    
    525
    +    usage1@UsageHomeModuleBytecode {}
    
    526
    +    usage2@UsageHomeModuleBytecode {}
    
    527
    +    = (compare `on` Module <$> usg_unit_id <*> usg_mod_name) usage1 usage2
    
    528
    +stableUsageCmp
    
    529
    +    usage1@UsageMergedRequirement {}
    
    530
    +    usage2@UsageMergedRequirement {}
    
    531
    +    = (compare `on` usg_mod) usage1 usage2
    
    532
    +stableUsageCmp
    
    533
    +    usage1
    
    534
    +    usage2
    
    535
    +    = (compare `on` constructorIndex) usage1 usage2
    
    536
    +    where
    
    537
    +
    
    538
    +    constructorIndex :: Usage -> Int
    
    539
    +    constructorIndex UsagePackageModule      {} = 0
    
    540
    +    constructorIndex UsageHomeModule         {} = 1
    
    541
    +    constructorIndex UsageFile               {} = 2
    
    542
    +    constructorIndex UsageDirectory          {} = 3
    
    543
    +    constructorIndex UsageHomeModuleBytecode {} = 4
    
    544
    +    constructorIndex UsageMergedRequirement  {} = 5
    
    511 545
     
    
    512 546
     -- | Records the imports that we depend on from a home module,
    
    513 547
     -- for recompilation checking.
    

  • testsuite/tests/driver/recomp016/recomp016.stdout
    ... ... @@ -9,4 +9,4 @@ second run
    9 9
     [2 of 5] Compiling B                ( B.hs, B.o ) [Source file changed]
    
    10 10
     [3 of 5] Compiling C                ( C.hs, C.o ) [B changed]
    
    11 11
     [4 of 5] Compiling D                ( D.hs, D.o ) [C changed]
    
    12
    -[5 of 5] Compiling E                ( E.hs, E.o ) [D changed]
    12
    +[5 of 5] Compiling E                ( E.hs, E.o ) [B changed]