| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
GHC.Unit.External.Index
Description
The UnitIndex is a UnitEnv wide data structure that shares
external unit information across the UnitState of all home units
(e.g., HomeUnitEnv) in a particular UnitEnv.
It caches already read unit databases, all processed UnitInfos and
the WireMap.
This module is meant to be imported as Index.
A short overview of how the different types here related to UnitState, UnitEnv
and the HomeUnitEnv.
┌─────────┐ │ UnitEnv │ └────┬────┘ ├───────────────────────┐ │ │ ┌────▼──────┐ ┌─────▼─────┐ │HomeUnitEnv│ │ UnitIndex ├────────────────┐ └────┬──────┘ └───────────┘ │ │ │ │ Reads cached unit DBs │ ┌────▼──────┐ ┌─────────────────────┐ │ │ UnitState ├──────────>ExternalUnitDatabases◄──────┤ └────┬──┬───┘ └─────────────────────┘ │ │ └───────────────────────┐ │ │ Writes new UnitInfos │ │ │ during initialisation │ │ ┌────▼────────┐ ┌────────v──────────┐ │ │ UnitInfoMap │ │ GlobalUnitInfoMap ◄────────┘ └────┬────────┘ └────────^──────────┘ │ │ └──────────────────────────┘ UnitInfoMap references GlobalUnitInfoMap values (All UnitInfos are shared)
Open arrow A ───> B: A uses B.
Closed arrow A ◄─── B: A is a field of B.
Also, see Note [Sharing UnitInfos across the UnitEnv] for more technical discussion
about sharing UnitInfos.
Synopsis
- newtype UnitIndexCache = UnitIndexCache {}
- initUnitIndexCache :: IO UnitIndexCache
- readUnitIndex :: UnitIndexCache -> IO UnitIndex
- modifyUnitIndexCache :: UnitIndexCache -> (UnitIndex -> UnitIndex) -> IO ()
- clearUnitIndexCache :: UnitIndexCache -> IO ()
- cacheExternalUnitDatabase :: UnitIndexCache -> UnitDatabase UnitId -> IO ()
- readExternalUnitDatabases :: UnitIndexCache -> IO (ExternalUnitDatabases UnitId)
- readExternalUnitDatabase :: UnitIndexCache -> OsPath -> IO (Maybe (UnitDatabase UnitId))
- data UnitIndex
- emptyUnitIndex :: UnitIndex
- wiringMap :: UnitIndex -> WireMap
- unwiringMap :: UnitIndex -> UnwireMap
- globalUnits :: UnitIndex -> GlobalUnitInfoMap
- externalUnitDatabases :: UnitIndex -> ExternalUnitDatabases UnitId
- setWireMap :: WireMap -> UnitIndex -> UnitIndex
- wireMapExists :: UnitIndex -> Bool
- addUnitInfoMap :: UnitInfoMap -> UnitIndex -> UnitIndex
- data GlobalUnitInfoMap
- lookupGlobalUnitInfoMap :: GlobalUnitKey -> GlobalUnitInfoMap -> Maybe UnitInfo
- emptyGlobalUnitInfoMap :: GlobalUnitInfoMap
- mkGlobalUnitInfoMap :: [(UnitId, UnitInfo)] -> GlobalUnitInfoMap
- data GlobalUnitKey
- type UnitAbiHash = ShortText
- mkGlobalUnitKey :: UnitId -> UnitAbiHash -> GlobalUnitKey
- globalUnitKeyFromUnitInfo :: UnitInfo -> GlobalUnitKey
- setupWiredInUnits :: Logger -> UnitPrecedenceMap -> [UnitInfo] -> VisibilityMap -> UnitIndexCache -> IO WireMap
- updateWiredInUnitIndex :: WireMap -> [UnitInfo] -> UnitIndexCache -> IO [UnitInfo]
- unwireUnit :: UnitIndex -> Unit -> Unit
- updateWiredInUnits :: WireMap -> GlobalUnitInfoMap -> [UnitInfo] -> [Either UnitInfo UnitInfo]
- updateWiredInUnitsInUnitInfo :: WireMap -> GlobalUnitInfoMap -> UnitInfo -> Either UnitInfo UnitInfo
- updateWiredInUnitIdInModule :: WireMap -> Module -> Module
- readOrGetUnitDatabase :: Logger -> UnitIndexCache -> UnitDbConfig -> OsPath -> IO (UnitDatabase UnitId)
- readUnitDatabases :: Logger -> UnitIndexCache -> UnitDbConfig -> IO [UnitDatabase UnitId]
The UnitIndexCache.
newtype UnitIndexCache Source #
Mutable version of UnitIndex.
The UnitIndexCache ensures that all calls to initUnits will
share the UnitInfo if it is possible.
To share the UnitInfo, the UnitInfo needs to be fully-resolved, i.e., its wired-in
dependencies and modules need to be replaced with the UnitId of the wired-in unit.
Thus, the UnitIndexCache caches both the global WireMap and the UnitInfoMap.
The WireMap is globally valid, as other parts of the compiler rely on the fact
that only one instance of wired-in units is used.
Memory Invariant: The UnitIndexCache is the root object for retaining fully-resolved
UnitInfo. UnitState is expected to reference only UnitInfos from the UnitIndexCache.
There is exactly one fully-resolved UnitInfo alive for each external unit per unit database.
A second instance may or may not be stored in the externalUnitDatabases, which represent the
in-memory cache of the on-disk unit databases.
Constructors
| UnitIndexCache | |
modifyUnitIndexCache :: UnitIndexCache -> (UnitIndex -> UnitIndex) -> IO () Source #
clearUnitIndexCache :: UnitIndexCache -> IO () Source #
cacheExternalUnitDatabase :: UnitIndexCache -> UnitDatabase UnitId -> IO () Source #
readExternalUnitDatabase :: UnitIndexCache -> OsPath -> IO (Maybe (UnitDatabase UnitId)) Source #
UnitIndex
unwiringMap :: UnitIndex -> UnwireMap Source #
globalUnits :: UnitIndex -> GlobalUnitInfoMap Source #
Access the global map of fully-resolved UnitInfos.
A UnitInfo is fully-resolved, if its dependencies were updated to reference the
wired-in packages (e.g., wiringMap) and the wired-in packages are updated.
Further, the UnitInfo is based on the ExternalUnitDatabases results, resolving
variables such as ${pkgroot} in paths.
See Note [Sharing UnitInfos across the UnitEnv] for why this is helpful.
externalUnitDatabases :: UnitIndex -> ExternalUnitDatabases UnitId Source #
Access the already processed unit databases.
addUnitInfoMap :: UnitInfoMap -> UnitIndex -> UnitIndex Source #
GlobalUnitInfoMap
data GlobalUnitInfoMap Source #
Like a UnitInfoMap but stores all UnitInfos.
It is keyed by the UnitId and the UnitInfos UnitAbiHash.
In modern cabal, there should never be a conflict of UnitIds, as cabal
hashes the Abi, dependency hashes, source hashes and more.
However, a user can choose a conflicting UnitId, causing a conflict after all.
We use the UnitAbiHash for disambiguation. If both UnitId and UnitAbiHash are
identical in separate unit databases, we can assume they are the same unit, according
to the documentation of GHC.
lookupGlobalUnitInfoMap :: GlobalUnitKey -> GlobalUnitInfoMap -> Maybe UnitInfo Source #
Lookup the UnitInfo in the GlobalUnitInfoMap.
This does not check whether the GlobalUnitKey refers to a unit that needs to be resolved
in the WireMap.
For example, if the UnitId is ghc-internal-version (and ghc-internal is a wired-in package),
then lookupGlobalUnitInfoMap won't find it, as in the GlobalUnitInfoMap, the key is ghc-internal.
mkGlobalUnitInfoMap :: [(UnitId, UnitInfo)] -> GlobalUnitInfoMap Source #
GlobalUnitKey
data GlobalUnitKey Source #
A GlobalUnitKey is a key that can globally identify a UnitInfo, not just
in the UnitInfoMap.
The UnitId and UnitAbiHash uniquely identify a UnitInfo.
type UnitAbiHash = ShortText Source #
mkGlobalUnitKey :: UnitId -> UnitAbiHash -> GlobalUnitKey Source #
Wired-in units
setupWiredInUnits :: Logger -> UnitPrecedenceMap -> [UnitInfo] -> VisibilityMap -> UnitIndexCache -> IO WireMap Source #
Find the wired-in units in the given '[UnitInfo]' if there isn't already
one in the UnitIndexCache. If there is, simply return the existing WireMap.
Otherwise, update the wiringMap in the UnitIndexCache
updateWiredInUnitIndex :: WireMap -> [UnitInfo] -> UnitIndexCache -> IO [UnitInfo] Source #
Resolve the wired-in units in the '[UnitInfo]'.
If the fully-resolved can be found in UnitIndexCache, then we use it.
If the resolved UnitInfo is new, we immediately cache it in the UnitIndexCache.
We return the fully-resolved UnitInfo list in the same order as provided.
updateWiredInUnits :: WireMap -> GlobalUnitInfoMap -> [UnitInfo] -> [Either UnitInfo UnitInfo] Source #
updateWiredInUnitsInUnitInfo :: WireMap -> GlobalUnitInfoMap -> UnitInfo -> Either UnitInfo UnitInfo Source #
Reading external unit databases into the UnitIndexCache
readOrGetUnitDatabase :: Logger -> UnitIndexCache -> UnitDbConfig -> OsPath -> IO (UnitDatabase UnitId) Source #
Get the cached UnitDatabase or read the UnitDatabase at the given location.
readUnitDatabases :: Logger -> UnitIndexCache -> UnitDbConfig -> IO [UnitDatabase UnitId] Source #