Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC Commits: 6b3044a0 by David Eichmann at 2026-05-30T11:58:48-04:00 Add code comments to allocator code - - - - - f4e04210 by Matthew Pickering at 2026-05-30T11:59:34-04:00 hadrian: Refactor system-cxx-std-lib rules I noticed a few things wrong with the hadrian rules for `system-cxx-std-lib` rules. * For `text` there is an ad-hoc check to depend on `system-cxx-std-lib` outside of `configurePackage`. * The `system-cxx-std-lib` dependency is not read from cabal files. * Recache is not called on the packge database after the `.conf` file is generated, a more natural place for this rule is `registerRules`. Treating this uniformly like other packages is complicated by it not having any source code or a cabal file. However we can do a bit better by reporting the dependency firstly in `PackageData` and then needing the `.conf` file in the same place as every other package in `configurePackage`. This commit increases the `shakeVersion`, to provide backwards compatibility to previous builds with different PackageData. Fixes #25303 Co-authored-by: Sven Tennie <sven.tennie@gmail.com> - - - - - 2224e4eb by Simon Jakobi at 2026-06-02T00:13:09-04:00 compiler: use nubOrd from containers Address #27103 by replacing GHC.Utils.Misc.ordNub[On] with Data.Containers.ListUtils.nubOrd[On]. Note that nubOrd suffers from a small inefficiency, a fix for which will be included in the next containers release: https://github.com/haskell/containers/issues/1202 - - - - - 13652abf by David Eichmann at 2026-06-02T00:13:10-04:00 Hadrian: disable response files for GHC/Haddock builders on non-Windows This makes debugging build errors easier on non-windows hosts. See issue #27230 - - - - - 20 changed files: - + changelog.d/hadrian-system-cxx-std-lib-25303 - compiler/GHC/CmmToAsm/BlockLayout.hs - compiler/GHC/Driver/Backpack.hs - compiler/GHC/Driver/Session/Units.hs - compiler/GHC/HsToCore/Usage.hs - compiler/GHC/Linker/Unit.hs - compiler/GHC/Rename/Pat.hs - compiler/GHC/Unit/Info.hs - compiler/GHC/Unit/State.hs - compiler/GHC/Utils/Misc.hs - ghc/GHCi/UI.hs - hadrian/src/Builder.hs - hadrian/src/Hadrian/Haskell/Cabal/Parse.hs - hadrian/src/Hadrian/Haskell/Cabal/Type.hs - hadrian/src/Hadrian/Utilities.hs - hadrian/src/Main.hs - hadrian/src/Rules/Generate.hs - hadrian/src/Rules/Register.hs - rts/sm/BlockAlloc.c - rts/sm/MBlock.c Changes: ===================================== changelog.d/hadrian-system-cxx-std-lib-25303 ===================================== @@ -0,0 +1,22 @@ +section: packaging +synopsis: Fix Hadrian rules for system-cxx-std-lib package dependency +issues: #25303 +mrs: !16013 +description: { + Hadrian's handling of the `system-cxx-std-lib` virtual package has been + fixed and made more uniform. + + Previously, `text` had an ad-hoc rule outside of `configurePackage` to + declare a dependency on `system-cxx-std-lib`, the dependency was not + discovered from cabal files, and the package database was not recached after + the `.conf` file was generated. + + The dependency is now read from cabal files via a new + `dependsOnSystemCxxStdLib` field in `PackageData`, and the `.conf` file + is needed inside `configurePackage` alongside all other package + dependencies, consistent with how every other package is handled. + + `shakeVersion` has been bumped to ensure existing build databases are + invalidated when upgrading, preventing binary deserialisation errors due to + the changed `PackageData` type. +} ===================================== compiler/GHC/CmmToAsm/BlockLayout.hs ===================================== @@ -36,6 +36,7 @@ import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Misc +import Data.Containers.ListUtils (nubOrd) import Data.List (sortOn, sortBy, nub) import Data.List.NonEmpty (nonEmpty) import qualified Data.List.NonEmpty as NE @@ -426,7 +427,7 @@ combineNeighbourhood edges chains applyEdges :: [CfgEdge] -> FrontierMap -> FrontierMap -> Set.Set (BlockId, BlockId) -> ([BlockChain], Set.Set (BlockId,BlockId)) applyEdges [] chainEnds _chainFronts combined = - (ordNub $ map snd $ mapElems chainEnds, combined) + (nubOrd $ map snd $ mapElems chainEnds, combined) applyEdges ((CfgEdge from to _w):edges) chainEnds chainFronts combined | Just (c1_e,c1) <- mapLookup from chainEnds , Just (c2_f,c2) <- mapLookup to chainFronts ===================================== compiler/GHC/Driver/Backpack.hs ===================================== @@ -76,6 +76,7 @@ import GHC.Data.FastString import qualified GHC.Data.EnumSet as EnumSet import qualified GHC.Data.ShortText as ST +import Data.Containers.ListUtils (nubOrd) import Data.List ( partition ) import System.Exit import Control.Monad @@ -763,14 +764,14 @@ hsunitModuleGraph do_link unit = do let inodes = instantiationNodes (homeUnitId $ hsc_home_unit hsc_env) (hsc_units hsc_env) -- TODO: Backpack mode does not properly support ExternalPackage nodes yet -- Module nodes do not get given package dependencies (see hsModuleToModSummary). - let pkg_nodes = ordNub $ map (\(_, iud) -> UnitNode [] (instUnitInstanceOf iud)) inodes + let pkg_nodes = nubOrd $ map (\(_, iud) -> UnitNode [] (instUnitInstanceOf iud)) inodes let graph_nodes = nodes ++ req_nodes ++ (map (uncurry InstantiationNode) $ inodes) ++ pkg_nodes key_nodes = map mkNodeKey graph_nodes all_nodes = graph_nodes ++ [LinkNode key_nodes (homeUnitId $ hsc_home_unit hsc_env) | do_link] -- This error message is not very good but .bkp mode is just for testing so -- better to be direct rather than pretty. when - (length key_nodes /= length (ordNub key_nodes)) + (length key_nodes /= length (nubOrd key_nodes)) (pprPanic "Duplicate nodes keys in backpack file" (ppr key_nodes)) -- 3. Return the kaboodle ===================================== compiler/GHC/Driver/Session/Units.hs ===================================== @@ -25,7 +25,6 @@ import qualified GHC.Unit.State as State import GHC.Types.SrcLoc import GHC.Types.SourceError -import GHC.Utils.Misc import GHC.Utils.Panic import GHC.Utils.Outputable as Outputable import GHC.Utils.Monad ( liftIO, mapMaybeM ) @@ -35,6 +34,7 @@ import System.IO import System.Exit import System.FilePath import Control.Monad +import Data.Containers.ListUtils (nubOrdOn) import Data.List ( partition, (\\) ) import qualified Data.Set as Set import GHC.Prelude @@ -204,7 +204,7 @@ checkDuplicateUnits dflags flags = where uids = map (second homeUnitId_) flags - deduplicated_uids = ordNubOn snd uids + deduplicated_uids = nubOrdOn snd uids duplicate_ids = Set.fromList (map snd uids \\ map snd deduplicated_uids) duplicate_flags = filter (flip Set.member duplicate_ids . snd) uids ===================================== compiler/GHC/HsToCore/Usage.hs ===================================== @@ -32,6 +32,7 @@ import GHC.Unit.Module.Deps import GHC.Data.Maybe import GHC.Data.FastString +import Data.Containers.ListUtils (nubOrdOn) import Data.List (sortBy) import Data.Map (Map) import qualified Data.Map as Map @@ -180,7 +181,7 @@ the TH splice. -- modules and direct object files for pkg dependencies mkObjectUsage :: Plugins -> FinderCache -> [LinkableUsage] -> PkgsLoaded -> IO [Usage] mkObjectUsage plugins fc th_links_needed th_pkgs_needed = do - let ls = ordNubOn linkableModule (th_links_needed ++ plugins_links_needed) + let ls = nubOrdOn linkableModule (th_links_needed ++ plugins_links_needed) ds = concatMap loaded_pkg_hs_objs $ eltsUDFM (plusUDFM th_pkgs_needed plugin_pkgs_needed) -- TODO possibly record loaded_pkg_non_hs_objs as well (plugins_links_needed, plugin_pkgs_needed) = loadedPluginDeps plugins concat <$> sequence (map linkableToUsage ls ++ map librarySpecToUsage ds) ===================================== compiler/GHC/Linker/Unit.hs ===================================== @@ -25,6 +25,7 @@ import qualified GHC.Data.ShortText as ST import GHC.Settings import Control.Monad +import Data.Containers.ListUtils (nubOrd) import Data.List (nub) import Data.Semigroup ( Semigroup(..) ) import System.Directory @@ -95,7 +96,7 @@ collectArchives namever ways pc = filterM doesFileExist [ searchPath </> ("lib" ++ lib ++ ".a") | searchPath <- searchPaths , lib <- libs ] - where searchPaths = ordNub . filter notNull . libraryDirsForWay ways $ pc + where searchPaths = nubOrd . filter notNull . libraryDirsForWay ways $ pc libs = unitHsLibs namever ways pc ++ (map ST.unpack . unitExtDepLibsStaticSys $ pc) getLibs :: GhcNameVersion -> Ways -> UnitEnv -> [UnitId] -> IO [(String,String)] ===================================== compiler/GHC/Rename/Pat.hs ===================================== @@ -79,6 +79,7 @@ import GHC.Core.TyCon ( isKindName ) import qualified GHC.LanguageExtensions as LangExt import Control.Monad ( when, ap, guard, unless ) +import Data.Containers.ListUtils (nubOrdOn) import Data.Foldable import Data.Function ( on ) import Data.Functor.Identity ( Identity (..) ) @@ -667,7 +668,7 @@ rnPatAndThen mk (OrPat _ pats) ; pats' <- rnLPatsAndThen mk pats ; let bndrs = collectPatsBinders CollVarTyVarBinders (NE.toList pats') ; liftCps $ setSrcSpan loc $ checkErr (null bndrs) $ - TcRnOrPatBindsVariables (NE.fromList (ordNubOn getOccName bndrs)) + TcRnOrPatBindsVariables (NE.fromList (nubOrdOn getOccName bndrs)) ; return (OrPat noExtField pats') } rnPatAndThen mk (SumPat _ pat alt arity) ===================================== compiler/GHC/Unit/Info.hs ===================================== @@ -49,6 +49,7 @@ import GHC.Unit.Database import GHC.Settings +import Data.Containers.ListUtils (nubOrd) import Data.Version import Data.Bifunctor import Data.List (isPrefixOf, stripPrefix) @@ -185,7 +186,7 @@ mkUnitPprInfo ufs i = UnitPprInfo -- | Find all the include directories in the given units collectIncludeDirs :: [UnitInfo] -> [FilePath] -collectIncludeDirs ps = map ST.unpack $ ordNub (filter (not . ST.null) (concatMap unitIncludeDirs ps)) +collectIncludeDirs ps = map ST.unpack $ nubOrd (filter (not . ST.null) (concatMap unitIncludeDirs ps)) -- | Find all the C-compiler options in the given units collectExtraCcOpts :: [UnitInfo] -> [String] @@ -193,7 +194,7 @@ collectExtraCcOpts ps = map ST.unpack (concatMap unitCcOptions ps) -- | Find all the library directories in the given units for the given ways collectLibraryDirs :: Ways -> [UnitInfo] -> [FilePath] -collectLibraryDirs ws = ordNub . filter notNull . concatMap (libraryDirsForWay ws) +collectLibraryDirs ws = nubOrd . filter notNull . concatMap (libraryDirsForWay ws) -- | Find all the frameworks in the given units collectFrameworks :: [UnitInfo] -> [String] @@ -201,7 +202,7 @@ collectFrameworks ps = map ST.unpack (concatMap unitExtDepFrameworks ps) -- | Find all the package framework paths in these and the preload packages collectFrameworksDirs :: [UnitInfo] -> [String] -collectFrameworksDirs ps = map ST.unpack (ordNub (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps))) +collectFrameworksDirs ps = map ST.unpack (nubOrd (filter (not . ST.null) (concatMap unitExtDepFrameworkDirs ps))) -- | Either the 'unitLibraryDirs' or 'unitLibraryDynDirs' as appropriate for the way. libraryDirsForWay :: Ways -> UnitInfo -> [String] ===================================== compiler/GHC/Unit/State.hs ===================================== @@ -112,6 +112,7 @@ import GHC.Utils.Exception import System.Directory import System.FilePath as FilePath import Control.Monad +import Data.Containers.ListUtils (nubOrd) import Data.Graph (stronglyConnComp, SCC(..)) import Data.Char ( toUpper ) import Data.List ( intersperse, partition, sortBy, sortOn, sort ) @@ -1705,7 +1706,7 @@ mkUnitState logger cfg = do basicLinkedUnits = fmap (RealUnit . Definite) $ filter (flip elemUniqMap pkg_db) $ unitConfigAutoLink cfg - preload3 = ordNub $ (basicLinkedUnits ++ preload1) + preload3 = nubOrd $ (basicLinkedUnits ++ preload1) -- Close the preload packages with their dependencies dep_preload <- mayThrowUnitErr ===================================== compiler/GHC/Utils/Misc.hs ===================================== @@ -59,7 +59,7 @@ module GHC.Utils.Misc ( replaceAt, dropTail, capitalise, -- * Sorting - sortWith, minWith, nubSort, ordNub, ordNubOn, + sortWith, minWith, nubSort, -- * Comparisons isEqual, @@ -570,23 +570,6 @@ minWith get_key xs = assert (not (null xs) ) nubSort :: Ord a => [a] -> [a] nubSort = Set.toAscList . Set.fromList --- | Remove duplicates but keep elements in order. --- O(n * log n) -ordNub :: Ord a => [a] -> [a] -ordNub xs = ordNubOn id xs - --- | Remove duplicates but keep elements in order. --- O(n * log n) -ordNubOn :: Ord b => (a -> b) -> [a] -> [a] -ordNubOn f xs - = go Set.empty xs - where - go _ [] = [] - go s (x:xs) - | Set.member (f x) s = go s xs - | otherwise = x : go (Set.insert (f x) s) xs - - {- ************************************************************************ * * ===================================== ghc/GHCi/UI.hs ===================================== @@ -128,6 +128,7 @@ import Control.Monad.Trans.Except import Data.Array import qualified Data.ByteString.Char8 as BS import Data.Char +import Data.Containers.ListUtils (nubOrd) import Data.Function import qualified Data.Foldable as Foldable import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef ) @@ -786,7 +787,7 @@ installInteractiveHomeUnits dflags = do -- This is mostly for a clear separation of concerns, -- to indicate we only care about unit dependencies from package dbs. & filter (not . selectHptFlag (HUG.allUnits $ hsc_HUG hsc_env)) - & ordNub + & nubOrd else packageFlags dflags0 @@ -871,7 +872,7 @@ installInteractiveHomeUnits dflags = do prefix = longestCommonPrefix stacks in - prefix ++ ordNub (concatMap (List.drop (length prefix)) stacks) + prefix ++ nubOrd (concatMap (List.drop (length prefix)) stacks) reportError :: GhciMonad m => GhciCommandMessage -> m () reportError err = do @@ -1249,7 +1250,7 @@ generatePromptFunctionFromString promptS modules_names line = processString ('%':'s':xs) = liftM2 (<>) (return modules_list) (processString xs) where - modules_list = hsep . map text . ordNub $ modules_names + modules_list = hsep . map text . nubOrd $ modules_names processString ('%':'l':xs) = liftM2 (<>) (return $ ppr line) (processString xs) processString ('%':'d':xs) = ===================================== hadrian/src/Builder.hs ===================================== @@ -39,7 +39,6 @@ import Packages import GHC.IO.Encoding (getFileSystemEncoding) import qualified Data.ByteString as BS import qualified GHC.Foreign as GHC -import GHC.ResponseFile import GHC.Toolchain (Target(..)) import qualified GHC.Toolchain as Toolchain @@ -346,7 +345,15 @@ instance H.Builder Builder where Haddock BuildPackage -> runHaddock path buildArgs buildInputs - Ghc _ _ -> runGhcWithResponse path buildArgs buildInputs buildOptions + Ghc _ _ -> + -- Use a response file for ghc invocations to avoid issues with command line + -- size limit on Windows (#26637). + -- NB: we can't put the buildArgs in a response file, because some flags require + -- empty arguments (such as the -dep-suffix flag), but that isn't supported + -- yet due to #26560. + withResponseFileOnWindows + (\buildInputs' -> cmd [path] buildArgs buildInputs' buildOptions) + buildInputs HsCpp -> captureStdout @@ -380,29 +387,15 @@ instance H.Builder Builder where _ -> cmd' [path] buildArgs buildOptions --- | Invoke @haddock@ given a path to it and a list of arguments. The arguments --- are passed in a response file. +-- | Invoke @haddock@ given a path to it and a list of arguments. On Windows, +-- the input file arguments are passed as a response file. runHaddock :: FilePath -- ^ path to @haddock@ -> [String] -> [FilePath] -- ^ input file paths -> Action () -runHaddock haddockPath flagArgs fileInputs = withResponseFile $ \tmp -> do - writeFile' tmp $ escapeArgs fileInputs - cmd [haddockPath] flagArgs ('@' : tmp) - --- | Use a response file for ghc invocations to avoid issues with command line --- size limit on Windows (#26637). -runGhcWithResponse :: FilePath -- ^ Path to ghc - -> [String] -- ^ Arguments passed on the command line - -> [FilePath] -- ^ Input file paths (passed via response file) - -> [CmdOption] - -> Action () -runGhcWithResponse ghcPath buildArgs buildInputs buildOptions = withResponseFile $ \tmp -> do - -- We can't put the buildArgs in a response file, because some flags require - -- empty arguments (such as the -dep-suffix flag), but that isn't supported - -- yet due to #26560. - writeFile' tmp (escapeArgs buildInputs) - cmd [ghcPath] buildArgs ('@' : tmp) buildOptions +runHaddock haddockPath flagArgs fileInputs = withResponseFileOnWindows + (cmd [haddockPath] flagArgs) + fileInputs -- TODO: Some builders are required only on certain platforms. For example, -- 'Objdump' is only required on OpenBSD and AIX. Add support for platform ===================================== hadrian/src/Hadrian/Haskell/Cabal/Parse.hs ===================================== @@ -81,10 +81,11 @@ parsePackageData pkg = do sorted = sort [ C.unPackageName p | C.Dependency p _ _ <- allDeps ] deps = nubOrd sorted \\ [name] depPkgs = mapMaybe findPackageByName deps + cxxStdLib = elem "system-cxx-std-lib" deps return $ PackageData name version (C.fromShortText (C.synopsis pd)) (C.fromShortText (C.description pd)) - depPkgs gpd + depPkgs cxxStdLib gpd where -- Collect an overapproximation of dependencies by ignoring conditionals collectDeps :: Maybe (C.CondTree v [C.Dependency] a) -> [C.Dependency] @@ -138,7 +139,9 @@ configurePackage :: Context -> Action () configurePackage context@Context {..} = do putProgressInfo $ "| Configure package " ++ quote (pkgName package) gpd <- pkgGenericDescription package - depPkgs <- packageDependencies <$> readPackageData package + pd <- readPackageData package + let depPkgs = packageDependencies pd + needSystemCxxStdLib = dependsOnSystemCxxStdLib pd -- Stage packages are those we have in this stage. stagePkgs <- stagePackages stage @@ -157,7 +160,12 @@ configurePackage context@Context {..} = do -- We'll need those packages in our package database. deps <- sequence [ pkgConfFile (context { package = pkg, iplace = forceBaseAfterGhcInternal pkg }) | pkg <- depPkgs, pkg `elem` stagePkgs ] - need $ extraPreConfigureDeps ++ deps + -- system-cxx-std-lib is magic.. it doesn't have a cabal file or source code, so we have + -- to treat it specially as `pkgConfFile` uses `readPackageData` to compute the version. + systemCxxStdLib <- sequence [ systemCxxStdLibConfPath (PackageDbLoc stage iplace) | needSystemCxxStdLib ] + need $ extraPreConfigureDeps + ++ deps + ++ systemCxxStdLib -- Figure out what hooks we need. let configureFile = replaceFileName (pkgCabalFile package) "configure" ===================================== hadrian/src/Hadrian/Haskell/Cabal/Type.hs ===================================== @@ -30,6 +30,7 @@ data PackageData = PackageData , synopsis :: String , description :: String , packageDependencies :: [Package] + , dependsOnSystemCxxStdLib :: Bool , genericPackageDescription :: GenericPackageDescription } deriving (Eq, Generic, Show) ===================================== hadrian/src/Hadrian/Utilities.hs ===================================== @@ -14,7 +14,7 @@ module Hadrian.Utilities ( -- * Paths BuildRoot (..), buildRoot, buildRootRules, isGeneratedSource, - KeepResponseFiles (..), keepResponseFiles, withResponseFile, + KeepResponseFiles (..), keepResponseFiles, withResponseFile, withResponseFileOnWindows, -- * File system operations copyFile, copyFileUntracked, createFileLink, fixFile, @@ -48,8 +48,11 @@ import Data.Typeable (TypeRep, typeOf) import Development.Shake hiding (Normal) import Development.Shake.Classes import Development.Shake.FilePath +import GHC.ResponseFile (escapeArgs) import System.Environment (lookupEnv) +import System.Info.Extra (isWindows) import System.IO (hClose, openTempFile) +import System.IO.Error (isPermissionError) import qualified Data.ByteString as BS import qualified Control.Exception.Base as IO @@ -57,8 +60,7 @@ import qualified Data.HashMap.Strict as Map import qualified System.Directory.Extra as IO import qualified System.Info.Extra as IO import qualified System.IO as IO -import System.IO.Error (isPermissionError) -import qualified System.FilePath.Posix as Posix +import qualified System.FilePath.Posix as Posix -- | Extract a value from a singleton list, or terminate with an error message -- if the list does not contain exactly one value. @@ -328,6 +330,21 @@ keepResponseFiles = do KeepResponseFiles keep <- userSetting (KeepResponseFiles False) return keep +-- | Run an action either with command arguments direcly or by, on Windows, +-- placing those arguments into a response file escaped with @GHC.ResponseFile.escapeArgs@. +-- +-- With @--keep-response-files@, the file is left on disk (if used) +withResponseFileOnWindows :: + ([String] -> Action a) -- ^ Action to perform given arguments (of the form @["\@reponseFilePath"]@ on Windows) + -> [String] -- ^ Command arguments + -> Action a +withResponseFileOnWindows action commandArgs = do + if isWindows + then withResponseFile $ \tmp -> do + writeFile' tmp (escapeArgs commandArgs) + action ['@' : tmp] + else action commandArgs + -- | Run an action with a response file path. -- -- With @--keep-response-files@, the file is left on disk. ===================================== hadrian/src/Main.hs ===================================== @@ -63,7 +63,13 @@ main = do shakeColor <- shouldUseColor let options :: ShakeOptions options = shakeOptions - { shakeChange = ChangeModtimeAndDigest + { -- Bump shakeVersion whenever a type stored in the Shake oracle + -- changes its Binary representation (e.g. fields added/removed + -- from PackageData or other oracle value types). This forces + -- Shake to wipe the stale database instead of crashing on + -- deserialisation. + shakeVersion = "2" + , shakeChange = ChangeModtimeAndDigest , shakeFiles = buildRoot -/- Base.shakeFilesDir , shakeProgress = Progress.hadrianProgress cwd , shakeRebuild = rebuild ===================================== hadrian/src/Rules/Generate.hs ===================================== @@ -242,9 +242,6 @@ copyRules = do prefix -/- "html/**" <~ return "utils/haddock/haddock-api/resources" prefix -/- "latex/**" <~ return "utils/haddock/haddock-api/resources" - forM_ [Inplace, Final] $ \iplace -> - root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do - copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file generateRules :: Rules () generateRules = do ===================================== hadrian/src/Rules/Register.hs ===================================== @@ -6,7 +6,6 @@ module Rules.Register ( import Base import Context -import Flavour import Oracles.Setting import Hadrian.BuildPath import Hadrian.Expression @@ -48,14 +47,6 @@ configurePackageRules = do isGmp <- (== "gmp") <$> interpretInContext ctx getBignumBackend when isGmp $ need [buildP -/- "include/ghc-gmp.h"] - when (pkg == text) $ do - simdutf <- textWithSIMDUTF <$> flavour - when simdutf $ do - -- This is required, otherwise you get Error: hadrian: - -- Encountered missing or private dependencies: - -- system-cxx-std-lib ==1.0 - cxxStdLib <- systemCxxStdLibConfPath $ PackageDbLoc stage Inplace - need [cxxStdLib] Cabal.configurePackage ctx root -/- "**/autogen/cabal_macros.h" %> \out -> do @@ -105,6 +96,12 @@ registerPackageRules rs stage iplace = do target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] [] writeFileLines stamp [] + -- Special rule for registering system-cxx-std-lib + root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- systemCxxStdLibConf %> \file -> do + copyFile ("mk" -/- "system-cxx-std-lib-1.0.conf") file + buildWithResources rs $ + target (Context stage compiler vanilla iplace) (GhcPkg Recache stage) [] [] + -- Register a package. root -/- relativePackageDbPath (PackageDbLoc stage iplace) -/- "*.conf" %> \conf -> do historyDisable ===================================== rts/sm/BlockAlloc.c ===================================== @@ -549,6 +549,8 @@ allocGroupOnNode (uint32_t node, W_ n) ln++; } + // If no free blocks exist then allocate a new megablock and keep just a + // chunk of it. if (ln == NUM_FREE_LISTS) { #if 0 /* useful for debugging fragmentation */ if ((W_)mblocks_allocated * BLOCKS_PER_MBLOCK * BLOCK_SIZE_W @@ -1020,6 +1022,9 @@ freeGroup(bdescr *p) } // coalesce backwards + // Note that p is not a megablock/megagroup, so there are still live blocks on + // this megablock. Hence we can't coalesce backwards past the first block + // descriptor of this megablock. if (p != FIRST_BDESCR(MBLOCK_ROUND_DOWN(p))) { bdescr *prev; ===================================== rts/sm/MBlock.c ===================================== @@ -95,6 +95,10 @@ typedef struct free_list { } free_list; static free_list *free_list_head; + +// The address in `mblock_address_space` just after the highest MBlock. This +// will be the address of the next new MBlock committed when the free list is +// empty. static W_ mblock_high_watermark; /* * it is quite important that these are in the same cache line as they @@ -103,22 +107,47 @@ static W_ mblock_high_watermark; */ struct mblock_address_range mblock_address_space = { 0, 0, {} }; +// Search for the first committed MBlock at or after startingAt. +// +// start_iter [in/out]: The free_list or a subset of it. Must contain all +// entries for MBlocks at or after startingAt. On return this is set to the +// free_list entry just after the returned MBlock. If no MBlock was found, This +// is set to NULL (the search will have reached the end of the free list). +// +// startingAt [in]: address from which to start searching. This must be to the +// start of an MBlock. +// +// return: The address of the committed MBlock. NULL if no committed MBLock was +// found. +// static void *getAllocatedMBlock(free_list **start_iter, W_ startingAt) { + // We simultaneously traverse the free list and the mblock_address_space. free_list *iter; W_ p = startingAt; for (iter = *start_iter; iter != NULL; iter = iter->next) { + // The current free MBlock, `iter`, is past the current MBlock, `p`. + // This means that `p` is committed (if it was free, then we would have + // found it on the free list). Stop searching. if (p < iter->address) break; + // Note that if `p > iter->address`, then we don't bump `p`. This just + // means we are skipping entries in the free list that correspond to + // MBlocks before `startingAt`. if (p == iter->address) + // Move to the next MBlock. The MBlock may be committed, + // uncommitted, or even past mblock_high_watermark. p += iter->size; } + // Output current free list entry. *start_iter = iter; + // If we reached mblock_high_watermark, then we didn't find any committed + // MBlocks. if (p >= mblock_high_watermark) return NULL; @@ -152,6 +181,11 @@ void * getNextMBlock(void **state STG_UNUSED, void *mblock) return getAllocatedMBlock(casted_state, (W_)mblock + MBLOCK_SIZE); } +// Used to implement getCommittedMBlocks. Search the free list for n contiguous +// free MBlocks, and commit those MBlocks, updating the free_list. Returns the +// address of the start of those MBlocks. Returns NULL if no n contiguous +// MBlocks were found in the free list. Unlike getFreshMBlocks, this doesn't +// attempt to allocate new MBlocks past mblock_high_watermark. static void *getReusableMBlocks(uint32_t n) { struct free_list *iter; @@ -163,7 +197,10 @@ static void *getReusableMBlocks(uint32_t n) if (iter->size < size) continue; + // We've found a large enough group of MBlocks. addr = (void*)iter->address; + + // Update the free list. iter->address += size; iter->size -= size; if (iter->size == 0) { @@ -190,6 +227,9 @@ static void *getReusableMBlocks(uint32_t n) return NULL; } +// Used to implement getCommittedMBlocks. Commit n new MBlocks starting at +// mblock_high_watermark. May exit with an out of memory error if we've passed +// mblock_address_space.end (this is unlikely). static void *getFreshMBlocks(uint32_t n) { W_ size = MBLOCK_SIZE * (W_)n; @@ -207,6 +247,8 @@ static void *getFreshMBlocks(uint32_t n) return addr; } +// Commit n new MBlocks. Tries to reuse freed MBlocks, else commits new +// MBlock(s) at mblock_high_watermark. static void *getCommittedMBlocks(uint32_t n) { void *p; @@ -220,6 +262,11 @@ static void *getCommittedMBlocks(uint32_t n) return p; } +// Decommit n contiguous MBlocks starting at the given address. +// +// addr [in]: address of the start of the n MBlocks (in mblock_address_space). +// +// n [in]: number of contiguous MBlocks to decommit. static void decommitMBlocks(char *addr, uint32_t n) { struct free_list *iter, *prev; @@ -228,17 +275,24 @@ static void decommitMBlocks(char *addr, uint32_t n) osDecommitMemory(addr, size); + // Update the free list. prev = NULL; for (iter = free_list_head; iter != NULL; iter = iter->next) { prev = iter; + // iter is still entirely behind and not contiguous with the MBlocks so + // continue traversing free_list. if (iter->address + iter->size < address) continue; + // The MBlocks are after and contiguous to iter. Simply modify the + // current entry to include n more MBlocks and possibly coalesce. if (iter->address + iter->size == address) { iter->size += size; + // If the current free_list entry now reaches mblock_high_watermark, + // remove the entry and decrement mblock_high_watermark. if (address + size == mblock_high_watermark) { mblock_high_watermark -= iter->size; if (iter->prev) { @@ -251,6 +305,8 @@ static void decommitMBlocks(char *addr, uint32_t n) return; } + // If the current free_list entry now reaches the next free_list + // entry, coalesce them. if (iter->next && iter->next->address == iter->address + iter->size) { struct free_list *next; @@ -269,6 +325,8 @@ static void decommitMBlocks(char *addr, uint32_t n) stgFree(next); } return; + + // The MBlocks are before and contiguous to iter. } else if (address + size == iter->address) { iter->address = address; iter->size += size; @@ -280,6 +338,9 @@ static void decommitMBlocks(char *addr, uint32_t n) ASSERT(iter->prev->address + iter->prev->size < iter->address); } return; + + // The MBlocks are before and not contiguous to iter. Insert a new entry + // just before iter. } else { struct free_list *new_iter; @@ -311,6 +372,7 @@ static void decommitMBlocks(char *addr, uint32_t n) if (address + size == mblock_high_watermark) { mblock_high_watermark -= size; } else { + // Add a new entry to the end of the free list. struct free_list *new_iter; new_iter = stgMallocBytes(sizeof(struct free_list), "freeMBlocks"); View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c80f15faa8059f87825f586b3752084... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c80f15faa8059f87825f586b3752084... You're receiving this email because of your account on gitlab.haskell.org.