[Git][ghc/ghc][master] 9 commits: rts/CloneStack: Bounds check array write
Marge Bot (@marge-bot)
gitlab at gitlab.haskell.org
Sat Mar 9 22:38:23 UTC 2024
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
c554b4da by Ben Gamari at 2024-03-09T09:39:20-05:00
rts/CloneStack: Bounds check array write
- - - - -
15c590a5 by Ben Gamari at 2024-03-09T09:39:20-05:00
rts/CloneStack: Don't expose helper functions in header
- - - - -
e831ce31 by Ben Gamari at 2024-03-09T09:39:20-05:00
base: Move internals of GHC.InfoProv into GHC.InfoProv.Types
Such that we can add new helpers into GHC.InfoProv.Types without
breakage.
- - - - -
6948e24d by Ben Gamari at 2024-03-09T09:39:20-05:00
rts: Lazily decode IPE tables
Previously we would eagerly allocate `InfoTableEnt`s for each
info table registered in the info table provenance map. However, this
costs considerable memory and initialization time. Instead we now
lazily decode these tables. This allows us to use one-third the memory
*and* opens the door to taking advantage of sharing opportunities within
a module.
This required considerable reworking since lookupIPE now must be passed
its result buffer.
- - - - -
9204a04e by Ben Gamari at 2024-03-09T09:39:20-05:00
rts/IPE: Don't expose helper in header
- - - - -
308926ff by Ben Gamari at 2024-03-09T09:39:20-05:00
rts/IPE: Share module_name within a Node
This allows us to shave a 64-bit word off of the packed IPE entry size.
- - - - -
bebdea05 by Ben Gamari at 2024-03-09T09:39:20-05:00
IPE: Expose unit ID in InfoTableProv
Here we add the unit ID to the info table provenance structure.
- - - - -
6519c9ad by Ben Gamari at 2024-03-09T09:39:35-05:00
rts: Refactor GHC.Stack.CloneStack.decode
Don't allocate a Ptr constructor per frame.
- - - - -
ed0b69dc by Ben Gamari at 2024-03-09T09:39:35-05:00
base: Do not expose whereFrom# from GHC.Exts
- - - - -
30 changed files:
- compiler/GHC/Builtin/primops.txt.pp
- compiler/GHC/StgToCmm/InfoTableProv.hs
- libraries/base/changelog.md
- libraries/base/src/GHC/Base.hs
- libraries/base/src/GHC/Exts.hs
- libraries/ghc-internal/ghc-internal.cabal
- libraries/ghc-internal/src/GHC/Internal/Base.hs
- libraries/ghc-internal/src/GHC/Internal/Exts.hs
- + libraries/ghc-internal/src/GHC/Internal/InfoProv.hs
- libraries/ghc-internal/src/GHC/Internal/InfoProv.hsc → libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
- libraries/ghc-internal/src/GHC/Internal/Stack/CloneStack.hs
- rts/CloneStack.c
- rts/CloneStack.h
- rts/IPE.c
- rts/IPE.h
- rts/PrimOps.cmm
- rts/Trace.c
- rts/include/rts/IPE.h
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- testsuite/tests/profiling/should_run/staticcallstack001.stdout
- testsuite/tests/profiling/should_run/staticcallstack002.stdout
- testsuite/tests/rts/ipe/T24005/t24005.stdout
- testsuite/tests/rts/ipe/ipeEventLog.stderr
- testsuite/tests/rts/ipe/ipeEventLog_fromMap.c
- testsuite/tests/rts/ipe/ipeEventLog_fromMap.stderr
- testsuite/tests/rts/ipe/ipeMap.c
- testsuite/tests/rts/ipe/ipe_lib.c
Changes:
=====================================
compiler/GHC/Builtin/primops.txt.pp
=====================================
@@ -3849,10 +3849,9 @@ primop ClearCCSOp "clearCCS#" GenPrimOp
section "Info Table Origin"
------------------------------------------------------------------------
primop WhereFromOp "whereFrom#" GenPrimOp
- a -> State# s -> (# State# s, Addr# #)
- { Returns the @InfoProvEnt @ for the info table of the given object
- (value is @NULL@ if the table does not exist or there is no information
- about the closure).}
+ a -> Addr# -> State# s -> (# State# s, Int# #)
+ { Fills the given buffer with the @InfoProvEnt@ for the info table of the
+ given object. Returns @1#@ on success and @0#@ otherwise.}
with
out_of_line = True
=====================================
compiler/GHC/StgToCmm/InfoTableProv.hs
=====================================
@@ -83,9 +83,11 @@ emitIpeBufferListNode this_mod ents = do
platform = stgToCmmPlatform cfg
int n = mkIntCLit platform n
- (cg_ipes, strtab) = flip runState emptyStringTable $ do
- module_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr this_mod)
- mapM (toCgIPE platform ctx module_name) ents
+ ((cg_ipes, unit_id, module_name), strtab) = flip runState emptyStringTable $ do
+ unit_id <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr $ moduleName this_mod)
+ module_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr $ moduleUnit this_mod)
+ cg_ipes <- mapM (toCgIPE platform ctx) ents
+ return (cg_ipes, unit_id, module_name)
tables :: [CmmStatic]
tables = map (CmmStaticLit . CmmLabel . ipeInfoTablePtr) cg_ipes
@@ -136,6 +138,12 @@ emitIpeBufferListNode this_mod ents = do
-- 'string_table_size' field (decompressed size)
, int $ BS.length uncompressed_strings
+
+ -- 'module_name' field
+ , CmmInt (fromIntegral module_name) W32
+
+ -- 'unit_id' field
+ , CmmInt (fromIntegral unit_id) W32
]
-- Emit the list of info table pointers
@@ -173,10 +181,8 @@ toIpeBufferEntries byte_order cg_ipes =
, ipeClosureDesc cg_ipe
, ipeTypeDesc cg_ipe
, ipeLabel cg_ipe
- , ipeModuleName cg_ipe
, ipeSrcFile cg_ipe
, ipeSrcSpan cg_ipe
- , 0 -- padding
]
word32Builder :: Word32 -> BSB.Builder
@@ -184,8 +190,8 @@ toIpeBufferEntries byte_order cg_ipes =
BigEndian -> BSB.word32BE
LittleEndian -> BSB.word32LE
-toCgIPE :: Platform -> SDocContext -> StrTabOffset -> InfoProvEnt -> State StringTable CgInfoProvEnt
-toCgIPE platform ctx module_name ipe = do
+toCgIPE :: Platform -> SDocContext -> InfoProvEnt -> State StringTable CgInfoProvEnt
+toCgIPE platform ctx ipe = do
table_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (pprCLabel platform (infoTablePtr ipe))
closure_desc <- lookupStringTable $ ST.pack $ show (infoProvEntClosureType ipe)
type_desc <- lookupStringTable $ ST.pack $ infoTableType ipe
@@ -205,7 +211,6 @@ toCgIPE platform ctx module_name ipe = do
, ipeClosureDesc = closure_desc
, ipeTypeDesc = type_desc
, ipeLabel = label
- , ipeModuleName = module_name
, ipeSrcFile = src_file
, ipeSrcSpan = src_span
}
@@ -216,7 +221,6 @@ data CgInfoProvEnt = CgInfoProvEnt
, ipeClosureDesc :: !StrTabOffset
, ipeTypeDesc :: !StrTabOffset
, ipeLabel :: !StrTabOffset
- , ipeModuleName :: !StrTabOffset
, ipeSrcFile :: !StrTabOffset
, ipeSrcSpan :: !StrTabOffset
}
=====================================
libraries/base/changelog.md
=====================================
@@ -47,6 +47,8 @@
matches a `data` or `data instance` declaration) with all of its
constructors in scope and the levity of `t` is statically known,
then the constraint `DataToTag t` can always be solved.
+ * `GHC.Exts` no longer exports the GHC-internal `whereFrom#` primop ([CLC proposal #214](https://github.com/haskell/core-libraries-committee/issues/214))
+ * `GHC.InfoProv.InfoProv` now provides a `ipUnitId :: String` field encoding the unit ID of the unit defining the info table ([CLC proposal #214](https://github.com/haskell/core-libraries-committee/issues/214))
([CLC proposal #104](https://github.com/haskell/core-libraries-committee/issues/104))
* Add `sortOn` to `Data.List.NonEmpty`
=====================================
libraries/base/src/GHC/Base.hs
=====================================
@@ -139,7 +139,12 @@ module GHC.Base
) where
import GHC.Internal.Base
-import GHC.Prim hiding (dataToTagLarge#, dataToTagSmall#)
+import GHC.Prim hiding (dataToTagLarge#, dataToTagSmall#, whereFrom#)
+ -- Hide dataToTagLarge# because it is expected to break for
+ -- GHC-internal reasons in the near future, and shouldn't
+ -- be exposed from base (not even GHC.Exts)
+ -- whereFrom# is similarly internal.
+
import GHC.Prim.Ext
import GHC.Prim.PtrEq
import GHC.Internal.Err
=====================================
libraries/base/src/GHC/Exts.hs
=====================================
@@ -111,10 +111,11 @@ module GHC.Exts
import GHC.Internal.Exts
import GHC.Internal.ArrayArray
-import GHC.Prim hiding ( coerce, dataToTagSmall#, dataToTagLarge# )
+import GHC.Prim hiding ( coerce, dataToTagSmall#, dataToTagLarge#, whereFrom# )
-- Hide dataToTag# ops because they are expected to break for
-- GHC-internal reasons in the near future, and shouldn't
-- be exposed from base (not even GHC.Exts)
+ -- whereFrom# is similarly internal.
import GHC.Prim.Ext
=====================================
libraries/ghc-internal/ghc-internal.cabal
=====================================
@@ -197,6 +197,7 @@ Library
GHC.Internal.GHCi.Helpers
GHC.Internal.Generics
GHC.Internal.InfoProv
+ GHC.Internal.InfoProv.Types
GHC.Internal.IO
GHC.Internal.IO.Buffer
GHC.Internal.IO.BufferedIO
=====================================
libraries/ghc-internal/src/GHC/Internal/Base.hs
=====================================
@@ -315,7 +315,7 @@ import GHC.Classes hiding (
import GHC.CString
import GHC.Magic
import GHC.Magic.Dict
-import GHC.Prim hiding (dataToTagSmall#, dataToTagLarge#)
+import GHC.Prim hiding (dataToTagSmall#, dataToTagLarge#, whereFrom#)
-- Hide dataToTag# ops because they are expected to break for
-- GHC-internal reasons in the near future, and shouldn't
-- be exposed from base (not even GHC.Exts)
=====================================
libraries/ghc-internal/src/GHC/Internal/Exts.hs
=====================================
@@ -133,10 +133,11 @@ module GHC.Internal.Exts
maxTupleSize,
) where
-import GHC.Prim hiding ( coerce, dataToTagSmall#, dataToTagLarge# )
- -- Hide dataToTag# ops because they are expected to break for
+import GHC.Prim hiding ( coerce, dataToTagSmall#, dataToTagLarge#, whereFrom# )
+ -- Hide dataToTagLarge# because it is expected to break for
-- GHC-internal reasons in the near future, and shouldn't
-- be exposed from base (not even GHC.Exts)
+ -- whereFrom# is similarly internal.
import GHC.Types
hiding ( IO -- Exported from "GHC.IO"
=====================================
libraries/ghc-internal/src/GHC/Internal/InfoProv.hs
=====================================
@@ -0,0 +1,53 @@
+{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE UnboxedTuples #-}
+{-# LANGUAGE MagicHash #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE TypeApplications #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module : GHC.Internal.InfoProv
+-- Copyright : (c) The University of Glasgow 2011
+-- License : see libraries/base/LICENSE
+--
+-- Maintainer : ghc-devs at haskell.org
+-- Stability : internal
+-- Portability : non-portable (GHC Extensions)
+--
+-- Access to GHC's info-table provenance metadata.
+--
+-- /The API of this module is unstable and not meant to be consumed by the general public./
+-- If you absolutely must depend on it, make sure to use a tight upper
+-- bound, e.g., @base < 4.X@ rather than @base < 5@, because the interface can
+-- change rapidly without much warning.
+--
+-- @since base-4.18.0.0
+-----------------------------------------------------------------------------
+
+module GHC.Internal.InfoProv
+ ( InfoProv(..)
+ , ipLoc
+ , whereFrom
+ -- * Internals
+ , InfoProvEnt
+ , ipeProv
+ , peekInfoProv
+ ) where
+
+import GHC.Internal.Base
+import GHC.Internal.InfoProv.Types
+
+-- | Get information about where a value originated from.
+-- This information is stored statically in a binary when @-finfo-table-map@ is
+-- enabled. The source positions will be greatly improved by also enabled debug
+-- information with @-g3 at . Finally you can enable @-fdistinct-constructor-tables@ to
+-- get more precise information about data constructor allocations.
+--
+-- The information is collect by looking at the info table address of a specific closure and
+-- then consulting a specially generated map (by @-finfo-table-map@) to find out where we think
+-- the best source position to describe that info table arose from.
+--
+-- @since base-4.16.0.0
+whereFrom :: a -> IO (Maybe InfoProv)
+whereFrom obj = getIPE obj Nothing $ \p ->
+ Just `fmap` peekInfoProv (ipeProv p)
=====================================
libraries/ghc-internal/src/GHC/Internal/InfoProv.hsc → libraries/ghc-internal/src/GHC/Internal/InfoProv/Types.hsc
=====================================
@@ -1,79 +1,80 @@
+{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE NoImplicitPrelude #-}
-{-# LANGUAGE TypeApplications #-}
------------------------------------------------------------------------------
--- |
--- Module : GHC.Internal.InfoProv
--- Copyright : (c) The University of Glasgow 2011
--- License : see libraries/base/LICENSE
---
--- Maintainer : ghc-devs at haskell.org
--- Stability : internal
--- Portability : non-portable (GHC Extensions)
---
--- Access to GHC's info-table provenance metadata.
---
--- /The API of this module is unstable and not meant to be consumed by the general public./
--- If you absolutely must depend on it, make sure to use a tight upper
--- bound, e.g., @base < 4.X@ rather than @base < 5@, because the interface can
--- change rapidly without much warning.
---
--- @since base-4.18.0.0
------------------------------------------------------------------------------
+#include "Rts.h"
-module GHC.Internal.InfoProv
+module GHC.Internal.InfoProv.Types
( InfoProv(..)
, ipLoc
, ipeProv
- , whereFrom
- -- * Internals
, InfoProvEnt
, peekInfoProv
+ , getIPE
+ , StgInfoTable
+ , lookupIPE
) where
-#include "Rts.h"
-
import GHC.Internal.Base
+import GHC.Internal.Data.Maybe
import GHC.Internal.Enum
-import GHC.Internal.Show
-import GHC.Internal.Ptr (Ptr(..), plusPtr, nullPtr)
+import GHC.Internal.Show (Show)
+import GHC.Internal.Ptr (Ptr(..), plusPtr)
+import GHC.Internal.Foreign.C.String.Encoding (CString, peekCString)
+import GHC.Internal.Foreign.C.Types (CBool(..))
+import GHC.Internal.Foreign.Marshal.Alloc (allocaBytes)
import GHC.Internal.IO.Encoding (utf8)
import GHC.Internal.Foreign.Storable (peekByteOff)
-import GHC.Internal.Foreign.C.String.Encoding
-import GHC.Internal.Text.Read (readMaybe)
-import GHC.Internal.Data.Maybe (maybe)
-import GHC.Internal.ClosureTypes ( ClosureType(..) )
+import GHC.Internal.ClosureTypes
+import GHC.Internal.Text.Read
+import GHC.Prim (whereFrom##)
data InfoProv = InfoProv {
ipName :: String,
ipDesc :: ClosureType,
ipTyDesc :: String,
ipLabel :: String,
+ -- | @since base-4.20.0.0
+ ipUnitId :: String,
ipMod :: String,
ipSrcFile :: String,
ipSrcSpan :: String
} deriving (Eq, Show)
-data InfoProvEnt
-
ipLoc :: InfoProv -> String
ipLoc ipe = ipSrcFile ipe ++ ":" ++ ipSrcSpan ipe
-getIPE :: a -> IO (Ptr InfoProvEnt)
-getIPE obj = IO $ \s ->
- case whereFrom## obj s of
- (## s', addr ##) -> (## s', Ptr addr ##)
+data InfoProvEnt
+
+data StgInfoTable
+
+foreign import ccall "lookupIPE" c_lookupIPE :: Ptr StgInfoTable -> Ptr InfoProvEnt -> IO CBool
+
+lookupIPE :: Ptr StgInfoTable -> IO (Maybe InfoProv)
+lookupIPE itbl = allocaBytes (#size InfoProvEnt) $ \p -> do
+ res <- c_lookupIPE itbl p
+ case res of
+ 1 -> Just `fmap` peekInfoProv (ipeProv p)
+ _ -> return Nothing
+
+getIPE :: a -> r -> (Ptr InfoProvEnt -> IO r) -> IO r
+getIPE obj fail k = allocaBytes (#size InfoProvEnt) $ \p -> IO $ \s ->
+ case whereFrom## obj (unPtr p) s of
+ (## s', 1## ##) -> unIO (k p) s'
+ (## s', _ ##) -> (## s', fail ##)
+ where
+ unPtr (Ptr p) = p
ipeProv :: Ptr InfoProvEnt -> Ptr InfoProv
ipeProv p = (#ptr InfoProvEnt, prov) p
-peekIpName, peekIpDesc, peekIpLabel, peekIpModule, peekIpSrcFile, peekIpSrcSpan, peekIpTyDesc :: Ptr InfoProv -> IO CString
+peekIpName, peekIpDesc, peekIpLabel, peekIpUnitId, peekIpModule, peekIpSrcFile, peekIpSrcSpan, peekIpTyDesc :: Ptr InfoProv -> IO CString
peekIpName p = (# peek InfoProv, table_name) p
peekIpDesc p = (# peek InfoProv, closure_desc) p
peekIpLabel p = (# peek InfoProv, label) p
+peekIpUnitId p = (# peek InfoProv, unit_id) p
peekIpModule p = (# peek InfoProv, module) p
peekIpSrcFile p = (# peek InfoProv, src_file) p
peekIpSrcSpan p = (# peek InfoProv, src_span) p
@@ -85,6 +86,7 @@ peekInfoProv infop = do
desc <- peekCString utf8 =<< peekIpDesc infop
tyDesc <- peekCString utf8 =<< peekIpTyDesc infop
label <- peekCString utf8 =<< peekIpLabel infop
+ unit_id <- peekCString utf8 =<< peekIpUnitId infop
mod <- peekCString utf8 =<< peekIpModule infop
file <- peekCString utf8 =<< peekIpSrcFile infop
span <- peekCString utf8 =<< peekIpSrcSpan infop
@@ -95,31 +97,9 @@ peekInfoProv infop = do
ipDesc = maybe INVALID_OBJECT toEnum . readMaybe @Int $ desc,
ipTyDesc = tyDesc,
ipLabel = label,
+ ipUnitId = unit_id,
ipMod = mod,
ipSrcFile = file,
ipSrcSpan = span
}
--- | Get information about where a value originated from.
--- This information is stored statically in a binary when @-finfo-table-map@ is
--- enabled. The source positions will be greatly improved by also enabled debug
--- information with @-g3 at . Finally you can enable @-fdistinct-constructor-tables@ to
--- get more precise information about data constructor allocations.
---
--- The information is collect by looking at the info table address of a specific closure and
--- then consulting a specially generated map (by @-finfo-table-map@) to find out where we think
--- the best source position to describe that info table arose from.
---
--- @since base-4.16.0.0
-whereFrom :: a -> IO (Maybe InfoProv)
-whereFrom obj = do
- ipe <- getIPE obj
- -- The primop returns the null pointer in two situations at the moment
- -- 1. The lookup fails for whatever reason
- -- 2. -finfo-table-map is not enabled.
- -- It would be good to distinguish between these two cases somehow.
- if ipe == nullPtr
- then return Nothing
- else do
- infoProv <- peekInfoProv (ipeProv ipe)
- return $ Just infoProv
=====================================
libraries/ghc-internal/src/GHC/Internal/Stack/CloneStack.hs
=====================================
@@ -25,21 +25,23 @@ module GHC.Internal.Stack.CloneStack (
import GHC.Internal.MVar
import GHC.Internal.Data.Maybe (catMaybes)
import GHC.Internal.Base
+import GHC.Internal.Foreign.Storable
import GHC.Internal.Conc.Sync
-import GHC.Internal.Exts () -- (Int (I#), RealWorld, StackSnapshot#, ThreadId#, Array#, sizeofArray#, indexArray#, State#, StablePtr#)
-import GHC.Internal.InfoProv (InfoProv (..), InfoProvEnt, ipLoc, ipeProv, peekInfoProv)
+import GHC.Internal.IO (unsafeInterleaveIO)
+import GHC.Internal.InfoProv.Types (InfoProv (..), ipLoc, lookupIPE, StgInfoTable)
import GHC.Internal.Num
+import GHC.Internal.Real (div)
import GHC.Internal.Stable
import GHC.Internal.Text.Show
import GHC.Internal.Ptr
-import GHC.Internal.ClosureTypes ( ClosureType(..) )
+import GHC.Internal.ClosureTypes
-- | A frozen snapshot of the state of an execution stack.
--
-- @since base-4.17.0.0
data StackSnapshot = StackSnapshot !StackSnapshot#
-foreign import prim "stg_decodeStackzh" decodeStack# :: StackSnapshot# -> State# RealWorld -> (# State# RealWorld, Array# (Ptr InfoProvEnt) #)
+foreign import prim "stg_decodeStackzh" decodeStack# :: StackSnapshot# -> State# RealWorld -> (# State# RealWorld, ByteArray# #)
foreign import prim "stg_cloneMyStackzh" cloneMyStack# :: State# RealWorld -> (# State# RealWorld, StackSnapshot# #)
@@ -231,39 +233,35 @@ data StackEntry = StackEntry
--
-- @since base-4.17.0.0
decode :: StackSnapshot -> IO [StackEntry]
-decode stackSnapshot = do
- stackEntries <- getDecodedStackArray stackSnapshot
- ipes <- mapM unmarshal stackEntries
- return $ catMaybes ipes
-
- where
- unmarshal :: Ptr InfoProvEnt -> IO (Maybe StackEntry)
- unmarshal ipe = if ipe == nullPtr then
- pure Nothing
- else do
- infoProv <- (peekInfoProv . ipeProv) ipe
- pure $ Just (toStackEntry infoProv)
- toStackEntry :: InfoProv -> StackEntry
- toStackEntry infoProv =
- StackEntry
- { functionName = ipLabel infoProv,
- moduleName = ipMod infoProv,
- srcLoc = ipLoc infoProv,
- closureType = ipDesc $ infoProv
- }
-
-getDecodedStackArray :: StackSnapshot -> IO [Ptr InfoProvEnt]
+decode stackSnapshot = catMaybes `fmap` getDecodedStackArray stackSnapshot
+
+toStackEntry :: InfoProv -> StackEntry
+toStackEntry infoProv =
+ StackEntry
+ { functionName = ipLabel infoProv,
+ moduleName = ipMod infoProv,
+ srcLoc = ipLoc infoProv,
+ closureType = ipDesc infoProv
+ }
+
+getDecodedStackArray :: StackSnapshot -> IO [Maybe StackEntry]
getDecodedStackArray (StackSnapshot s) =
IO $ \s0 -> case decodeStack# s s0 of
- (# s1, a #) -> (# s1, (go a ((I# (sizeofArray# a)) - 1)) #)
+ (# s1, arr #) ->
+ let n = I# (sizeofByteArray# arr) `div` wordSize - 1
+ in unIO (go arr n) s1
where
- go :: Array# (Ptr InfoProvEnt) -> Int -> [Ptr InfoProvEnt]
- go stack 0 = [stackEntryAt stack 0]
- go stack i = (stackEntryAt stack i) : go stack (i - 1)
+ go :: ByteArray# -> Int -> IO [Maybe StackEntry]
+ go _stack (-1) = return []
+ go stack i = do
+ infoProv <- lookupIPE (stackEntryAt stack i)
+ rest <- unsafeInterleaveIO $ go stack (i-1)
+ return ((toStackEntry `fmap` infoProv) : rest)
+
+ stackEntryAt :: ByteArray# -> Int -> Ptr StgInfoTable
+ stackEntryAt stack (I# i) = Ptr (indexAddrArray# stack i)
- stackEntryAt :: Array# (Ptr InfoProvEnt) -> Int -> Ptr InfoProvEnt
- stackEntryAt stack (I# i) = case indexArray# stack i of
- (# se #) -> se
+ wordSize = sizeOf (nullPtr :: Ptr ())
prettyStackEntry :: StackEntry -> String
prettyStackEntry (StackEntry {moduleName=mod_nm, functionName=fun_nm, srcLoc=loc}) =
=====================================
rts/CloneStack.c
=====================================
@@ -25,6 +25,12 @@
#include <string.h>
+
+static StgWord getStackFrameCount(StgStack* stack);
+static StgWord getStackChunkClosureCount(StgStack* stack);
+static StgArrBytes* allocateByteArray(Capability *cap, StgWord bytes);
+static void copyPtrsToArray(StgArrBytes* arr, StgStack* stack);
+
static StgStack* cloneStackChunk(Capability* capability, const StgStack* stack)
{
StgWord spOffset = stack->sp - stack->stack;
@@ -109,12 +115,12 @@ void sendCloneStackMessage(StgTSO *tso STG_UNUSED, HsStablePtr mvar STG_UNUSED)
// array is the count of stack frames.
// Each InfoProvEnt* is looked up by lookupIPE(). If there's no IPE for a stack
// frame it's represented by null.
-StgMutArrPtrs* decodeClonedStack(Capability *cap, StgStack* stack) {
+StgArrBytes* decodeClonedStack(Capability *cap, StgStack* stack) {
StgWord closureCount = getStackFrameCount(stack);
- StgMutArrPtrs* array = allocateMutableArray(closureCount);
+ StgArrBytes* array = allocateByteArray(cap, sizeof(StgInfoTable*) * closureCount);
- copyPtrsToArray(cap, array, stack);
+ copyPtrsToArray(array, stack);
return array;
}
@@ -150,52 +156,34 @@ StgWord getStackChunkClosureCount(StgStack* stack) {
return closureCount;
}
-// Allocate and initialize memory for a MutableArray# (Haskell representation).
-StgMutArrPtrs* allocateMutableArray(StgWord closureCount) {
+// Allocate and initialize memory for a ByteArray# (Haskell representation).
+StgArrBytes* allocateByteArray(Capability *cap, StgWord bytes) {
// Idea stolen from PrimOps.cmm:stg_newArrayzh()
- StgWord size = closureCount + mutArrPtrsCardTableSize(closureCount);
- StgWord words = sizeofW(StgMutArrPtrs) + size;
-
- StgMutArrPtrs* array = (StgMutArrPtrs*) allocate(myTask()->cap, words);
+ StgWord words = sizeofW(StgArrBytes) + bytes;
- SET_HDR(array, &stg_MUT_ARR_PTRS_DIRTY_info, CCS_SYSTEM);
- array->ptrs = closureCount;
- array->size = size;
+ StgArrBytes* array = (StgArrBytes*) allocate(cap, words);
+ SET_HDR(array, &stg_ARR_WORDS_info, CCS_SYSTEM);
+ array->bytes = bytes;
return array;
}
-
-void copyPtrsToArray(Capability *cap, StgMutArrPtrs* arr, StgStack* stack) {
+static void copyPtrsToArray(StgArrBytes* arr, StgStack* stack) {
StgWord index = 0;
StgStack *last_stack = stack;
+ const StgInfoTable **result = (const StgInfoTable **) arr->payload;
while (true) {
StgPtr sp = last_stack->sp;
StgPtr spBottom = last_stack->stack + last_stack->stack_size;
for (; sp < spBottom; sp += stack_frame_sizeW((StgClosure *)sp)) {
- const StgInfoTable* infoTable = get_itbl((StgClosure *)sp);
-
- // Add the IPE that was looked up by lookupIPE() to the MutableArray#.
- // The "Info Table Provernance Entry Map" (IPE) idea is to use a pointer
- // (address) to the info table to lookup entries, this is fulfilled in
- // non-"Tables Next to Code" builds.
- // When "Tables Next to Code" is used, the assembly label of the info table
- // is between the info table and it's code. There's no other label in the
- // assembly code which could be used instead, thus lookupIPE() is actually
- // called with the code pointer of the info table.
- // (As long as it's used consistently, this doesn't really matter - IPE uses
- // the pointer only to connect an info table to it's provenance entry in the
- // IPE map.)
-#if defined(TABLES_NEXT_TO_CODE)
- InfoProvEnt* ipe = lookupIPE((StgInfoTable*) infoTable->code);
-#else
- InfoProvEnt* ipe = lookupIPE(infoTable);
-#endif
- arr->payload[index] = createPtrClosure(cap, ipe);
-
+ const StgInfoTable* infoTable = ((StgClosure *)sp)->header.info;
+ result[index] = infoTable;
index++;
}
+ // Ensure that we didn't overflow the result array
+ ASSERT(index-1 < arr->bytes / sizeof(StgInfoTable*));
+
// check whether the stack ends in an underflow frame
StgUnderflowFrame *frame = (StgUnderflowFrame *) (last_stack->stack
+ last_stack->stack_size - sizeofW(StgUnderflowFrame));
@@ -206,12 +194,3 @@ void copyPtrsToArray(Capability *cap, StgMutArrPtrs* arr, StgStack* stack) {
}
}
}
-
-// Create a GHC.Ptr (Haskell constructor: `Ptr InfoProvEnt`) pointing to the
-// IPE.
-StgClosure* createPtrClosure(Capability *cap, InfoProvEnt* ipe) {
- StgClosure *p = (StgClosure *) allocate(cap, CONSTR_sizeW(0,1));
- SET_HDR(p, &ghczminternal_GHCziInternalziPtr_Ptr_con_info, CCS_SYSTEM);
- p->payload[0] = (StgClosure*) ipe;
- return TAG_CLOSURE(1, p);
-}
=====================================
rts/CloneStack.h
=====================================
@@ -15,7 +15,7 @@ StgStack* cloneStack(Capability* capability, const StgStack* stack);
void sendCloneStackMessage(StgTSO *tso, HsStablePtr mvar);
-StgMutArrPtrs* decodeClonedStack(Capability *cap, StgStack* stack);
+StgArrBytes* decodeClonedStack(Capability *cap, StgStack* stack);
#include "BeginPrivate.h"
@@ -23,10 +23,4 @@ StgMutArrPtrs* decodeClonedStack(Capability *cap, StgStack* stack);
void handleCloneStackMessage(MessageCloneStack *msg);
#endif
-StgWord getStackFrameCount(StgStack* stack);
-StgWord getStackChunkClosureCount(StgStack* stack);
-void copyPtrsToArray(Capability *cap, StgMutArrPtrs* arr, StgStack* stack);
-StgClosure* createPtrClosure(Capability* cap, InfoProvEnt* ipe);
-StgMutArrPtrs* allocateMutableArray(StgWord size);
-
#include "EndPrivate.h"
=====================================
rts/IPE.c
=====================================
@@ -52,16 +52,23 @@ of InfoProvEnt are represented in IpeBufferEntry as 32-bit offsets into the
string table. This allows us to halve the size of the buffer entries on
64-bit machines while significantly reducing the number of needed
relocations, reducing linking cost. Moreover, the code generator takes care
-to deduplicate strings when generating the string table. When we insert a
-set of IpeBufferEntrys into the IPE hash-map we convert them to InfoProvEnts,
-which contain proper string pointers.
+to deduplicate strings when generating the string table.
Building the hash map is done lazily, i.e. on first lookup or traversal. For
this all IPE lists of all IpeBufferListNode are traversed to insert all IPEs.
+This involves allocating a IpeMapEntry for each IPE entry, pointing to the
+entry's containing IpeBufferListNode and its index in that node.
+
+When the user looks up an IPE entry, we convert it to the user-facing
+InfoProvEnt representation.
-After the content of a IpeBufferListNode has been inserted, it's freed.
*/
+typedef struct {
+ IpeBufferListNode *node;
+ uint32_t idx;
+} IpeMapEntry;
+
#if defined(THREADED_RTS)
static Mutex ipeMapLock;
#endif
@@ -71,6 +78,9 @@ static HashTable *ipeMap = NULL;
// Accessed atomically
static IpeBufferListNode *ipeBufferList = NULL;
+static void decompressIPEBufferListNodeIfCompressed(IpeBufferListNode*);
+static void updateIpeMap(void);
+
#if defined(THREADED_RTS)
void initIpe(void) { initMutex(&ipeMapLock); }
@@ -85,18 +95,23 @@ void exitIpe(void) { }
#endif // THREADED_RTS
-static InfoProvEnt ipeBufferEntryToIpe(const char *strings, const StgInfoTable *tbl, const IpeBufferEntry ent)
+static InfoProvEnt ipeBufferEntryToIpe(const IpeBufferListNode *node, uint32_t idx)
{
+ CHECK(idx < node->count);
+ CHECK(!node->compressed);
+ const char *strings = node->string_table;
+ const IpeBufferEntry *ent = &node->entries[idx];
return (InfoProvEnt) {
- .info = tbl,
+ .info = node->tables[idx],
.prov = {
- .table_name = &strings[ent.table_name],
- .closure_desc = &strings[ent.closure_desc],
- .ty_desc = &strings[ent.ty_desc],
- .label = &strings[ent.label],
- .module = &strings[ent.module_name],
- .src_file = &strings[ent.src_file],
- .src_span = &strings[ent.src_span]
+ .table_name = &strings[ent->table_name],
+ .closure_desc = &strings[ent->closure_desc],
+ .ty_desc = &strings[ent->ty_desc],
+ .label = &strings[ent->label],
+ .unit_id = &strings[node->unit_id],
+ .module = &strings[node->module_name],
+ .src_file = &strings[ent->src_file],
+ .src_span = &strings[ent->src_span]
}
};
}
@@ -105,29 +120,22 @@ static InfoProvEnt ipeBufferEntryToIpe(const char *strings, const StgInfoTable *
#if defined(TRACING)
static void traceIPEFromHashTable(void *data STG_UNUSED, StgWord key STG_UNUSED,
const void *value) {
- InfoProvEnt *ipe = (InfoProvEnt *)value;
- traceIPE(ipe);
+ const IpeMapEntry *map_ent = (const IpeMapEntry *)value;
+ const InfoProvEnt ipe = ipeBufferEntryToIpe(map_ent->node, map_ent->idx);
+ traceIPE(&ipe);
}
void dumpIPEToEventLog(void) {
// Dump pending entries
- IpeBufferListNode *cursor = RELAXED_LOAD(&ipeBufferList);
- while (cursor != NULL) {
- IpeBufferEntry *entries;
- const char *strings;
+ IpeBufferListNode *node = RELAXED_LOAD(&ipeBufferList);
+ while (node != NULL) {
+ decompressIPEBufferListNodeIfCompressed(node);
- // Decompress if compressed
- decompressIPEBufferListNodeIfCompressed(cursor, &entries, &strings);
-
- for (uint32_t i = 0; i < cursor->count; i++) {
- const InfoProvEnt ent = ipeBufferEntryToIpe(
- strings,
- cursor->tables[i],
- entries[i]
- );
+ for (uint32_t i = 0; i < node->count; i++) {
+ const InfoProvEnt ent = ipeBufferEntryToIpe(node, i);
traceIPE(&ent);
}
- cursor = cursor->next;
+ node = node->next;
}
// Dump entries already in hashmap
@@ -168,9 +176,15 @@ void registerInfoProvList(IpeBufferListNode *node) {
}
}
-InfoProvEnt *lookupIPE(const StgInfoTable *info) {
+bool lookupIPE(const StgInfoTable *info, InfoProvEnt *out) {
updateIpeMap();
- return lookupHashTable(ipeMap, (StgWord)info);
+ IpeMapEntry *map_ent = (IpeMapEntry *) lookupHashTable(ipeMap, (StgWord)info);
+ if (map_ent) {
+ *out = ipeBufferEntryToIpe(map_ent->node, map_ent->idx);
+ return true;
+ } else {
+ return false;
+ }
}
void updateIpeMap(void) {
@@ -188,47 +202,40 @@ void updateIpeMap(void) {
}
while (pending != NULL) {
- IpeBufferListNode *current_node = pending;
- IpeBufferEntry *entries;
- const char *strings;
+ IpeBufferListNode *node = pending;
// Decompress if compressed
- decompressIPEBufferListNodeIfCompressed(current_node, &entries, &strings);
-
- // Convert the on-disk IPE buffer entry representation (IpeBufferEntry)
- // into the runtime representation (InfoProvEnt)
- InfoProvEnt *ip_ents = stgMallocBytes(
- sizeof(InfoProvEnt) * current_node->count,
- "updateIpeMap: ip_ents"
- );
- for (uint32_t i = 0; i < current_node->count; i++) {
- const IpeBufferEntry ent = entries[i];
- const StgInfoTable *tbl = current_node->tables[i];
- ip_ents[i] = ipeBufferEntryToIpe(strings, tbl, ent);
- insertHashTable(ipeMap, (StgWord) tbl, &ip_ents[i]);
+ decompressIPEBufferListNodeIfCompressed(node);
+
+ // Insert entries into ipeMap
+ IpeMapEntry *map_ents = stgMallocBytes(node->count * sizeof(IpeMapEntry), "updateIpeMap: ip_ents");
+ for (uint32_t i = 0; i < node->count; i++) {
+ const StgInfoTable *tbl = node->tables[i];
+ map_ents[i].node = node;
+ map_ents[i].idx = i;
+ insertHashTable(ipeMap, (StgWord) tbl, &map_ents[i]);
}
- pending = current_node->next;
+ pending = node->next;
}
RELEASE_LOCK(&ipeMapLock);
}
/* Decompress the IPE data and strings table referenced by an IPE buffer list
-node if it is compressed. No matter whether the data is compressed, the pointers
-referenced by the 'entries_dst' and 'string_table_dst' parameters will point at
-the decompressed IPE data and string table for the given node, respectively,
-upon return from this function.
-*/
-void decompressIPEBufferListNodeIfCompressed(IpeBufferListNode *node, IpeBufferEntry **entries_dst, const char **string_table_dst) {
+ * node if it is compressed. After returning node->compressed with be 0 and the
+ * string_table and entries fields will have their uncompressed values.
+ */
+void decompressIPEBufferListNodeIfCompressed(IpeBufferListNode *node) {
if (node->compressed == 1) {
+ node->compressed = 0;
+
// The IPE list buffer node indicates that the strings table and
// entries list has been compressed. If zstd is not available, fail.
// If zstd is available, decompress.
#if HAVE_LIBZSTD == 0
barf("An IPE buffer list node has been compressed, but the "
- "decompression library (zstd) is not available."
-);
+ "decompression library (zstd) is not available.");
#else
size_t compressed_sz = ZSTD_findFrameCompressedSize(
node->string_table,
@@ -244,7 +251,7 @@ void decompressIPEBufferListNodeIfCompressed(IpeBufferListNode *node, IpeBufferE
node->string_table,
compressed_sz
);
- *string_table_dst = decompressed_strings;
+ node->string_table = (const char *) decompressed_strings;
// Decompress the IPE data
compressed_sz = ZSTD_findFrameCompressedSize(
@@ -261,12 +268,8 @@ void decompressIPEBufferListNodeIfCompressed(IpeBufferListNode *node, IpeBufferE
node->entries,
compressed_sz
);
- *entries_dst = decompressed_entries;
+ node->entries = decompressed_entries;
#endif // HAVE_LIBZSTD == 0
- } else {
- // Not compressed, no need to decompress
- *entries_dst = node->entries;
- *string_table_dst = node->string_table;
}
}
=====================================
rts/IPE.h
=====================================
@@ -14,9 +14,7 @@
#include "BeginPrivate.h"
void dumpIPEToEventLog(void);
-void updateIpeMap(void);
void initIpe(void);
void exitIpe(void);
-void decompressIPEBufferListNodeIfCompressed(IpeBufferListNode*, IpeBufferEntry**, const char**);
#include "EndPrivate.h"
=====================================
rts/PrimOps.cmm
=====================================
@@ -2533,13 +2533,13 @@ stg_closureSizzezh (P_ clos)
return (len);
}
-stg_whereFromzh (P_ clos)
+stg_whereFromzh (P_ clos, W_ buf)
{
- P_ ipe;
+ CBool success;
W_ info;
info = GET_INFO(UNTAG(clos));
- (ipe) = foreign "C" lookupIPE(info "ptr");
- return (ipe);
+ (success) = foreign "C" lookupIPE(info, buf);
+ return (TO_W_(success));
}
/* -----------------------------------------------------------------------------
=====================================
rts/Trace.c
=====================================
@@ -689,9 +689,10 @@ void traceIPE(const InfoProvEnt *ipe)
ACQUIRE_LOCK(&trace_utx);
tracePreface();
- debugBelch("IPE: table_name %s, closure_desc %s, ty_desc %s, label %s, module %s, srcloc %s:%s\n",
+ debugBelch("IPE: table_name %s, closure_desc %s, ty_desc %s, label %s, unit %s, module %s, srcloc %s:%s\n",
ipe->prov.table_name, ipe->prov.closure_desc, ipe->prov.ty_desc,
- ipe->prov.label, ipe->prov.module, ipe->prov.src_file, ipe->prov.src_span);
+ ipe->prov.label, ipe->prov.unit_id, ipe->prov.module,
+ ipe->prov.src_file, ipe->prov.src_span);
RELEASE_LOCK(&trace_utx);
} else
=====================================
rts/include/rts/IPE.h
=====================================
@@ -18,6 +18,7 @@ typedef struct InfoProv_ {
const char *closure_desc;
const char *ty_desc;
const char *label;
+ const char *unit_id;
const char *module;
const char *src_file;
const char *src_span;
@@ -56,10 +57,8 @@ typedef struct {
StringIdx closure_desc;
StringIdx ty_desc;
StringIdx label;
- StringIdx module_name;
StringIdx src_file;
StringIdx src_span;
- uint32_t _padding;
} IpeBufferEntry;
GHC_STATIC_ASSERT(sizeof(IpeBufferEntry) % (WORD_SIZE_IN_BITS / 8) == 0, "sizeof(IpeBufferEntry) must be a multiple of the word size");
@@ -77,13 +76,18 @@ typedef struct IpeBufferListNode_ {
// When TNTC is enabled, these will point to the entry code
// not the info table itself.
const StgInfoTable **tables;
-
IpeBufferEntry *entries;
StgWord entries_size; // decompressed size
const char *string_table;
StgWord string_table_size; // decompressed size
+
+ // Shared by all entries
+ StringIdx unit_id;
+ StringIdx module_name;
} IpeBufferListNode;
void registerInfoProvList(IpeBufferListNode *node);
-InfoProvEnt *lookupIPE(const StgInfoTable *info);
+
+// Returns true on success, initializes `out`.
+bool lookupIPE(const StgInfoTable *info, InfoProvEnt *out);
=====================================
testsuite/tests/interface-stability/base-exports.stdout
=====================================
@@ -4755,7 +4755,6 @@ module GHC.Base where
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
when :: forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -6857,7 +6856,6 @@ module GHC.Exts where
void# :: (# #)
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -8105,7 +8103,7 @@ module GHC.IORef where
module GHC.InfoProv where
-- Safety: Safe
type InfoProv :: *
- data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+ data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
type InfoProvEnt :: *
data InfoProvEnt
ipLoc :: InfoProv -> GHC.Internal.Base.String
@@ -12521,7 +12519,7 @@ instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.RTSFlags -- Defined in
instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.TickyFlags -- Defined in ‘GHC.Internal.RTS.Flags’
instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.TraceFlags -- Defined in ‘GHC.Internal.RTS.Flags’
instance GHC.Internal.Show.Show GHC.Internal.IOPort.IOPortException -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Internal.Show.Show GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Internal.Show.Show GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Internal.Show.Show GHC.Internal.Stack.CloneStack.StackEntry -- Defined in ‘GHC.Internal.Stack.CloneStack’
instance GHC.Internal.Show.Show GHC.Internal.StaticPtr.StaticPtrInfo -- Defined in ‘GHC.Internal.StaticPtr’
instance GHC.Internal.Show.Show GHC.Internal.Stats.GCDetails -- Defined in ‘GHC.Internal.Stats’
@@ -12717,7 +12715,7 @@ instance GHC.Classes.Eq GHC.Internal.IO.IOMode.IOMode -- Defined in ‘GHC.Inter
instance GHC.Classes.Eq GHC.Internal.RTS.Flags.IoSubSystem -- Defined in ‘GHC.Internal.RTS.Flags’
instance forall i e. GHC.Classes.Eq (GHC.Internal.IOArray.IOArray i e) -- Defined in ‘GHC.Internal.IOArray’
instance forall a. GHC.Classes.Eq (GHC.Internal.IOPort.IOPort a) -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Classes.Eq GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Classes.Eq GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Classes.Eq GHC.Num.Integer.Integer -- Defined in ‘GHC.Num.Integer’
instance GHC.Classes.Eq GHC.Num.BigNat.BigNat -- Defined in ‘GHC.Num.BigNat’
instance GHC.Classes.Eq GHC.Num.Natural.Natural -- Defined in ‘GHC.Num.Natural’
=====================================
testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
=====================================
@@ -4755,7 +4755,6 @@ module GHC.Base where
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
when :: forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -6826,7 +6825,6 @@ module GHC.Exts where
void# :: (# #)
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -8074,7 +8072,7 @@ module GHC.IORef where
module GHC.InfoProv where
-- Safety: Safe
type InfoProv :: *
- data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+ data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
type InfoProvEnt :: *
data InfoProvEnt
ipLoc :: InfoProv -> GHC.Internal.Base.String
@@ -15551,7 +15549,7 @@ instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.RTSFlags -- Defined in
instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.TickyFlags -- Defined in ‘GHC.Internal.RTS.Flags’
instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.TraceFlags -- Defined in ‘GHC.Internal.RTS.Flags’
instance GHC.Internal.Show.Show GHC.Internal.IOPort.IOPortException -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Internal.Show.Show GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Internal.Show.Show GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Internal.Show.Show GHC.Internal.JS.Prim.JSException -- Defined in ‘GHC.Internal.JS.Prim’
instance GHC.Internal.Show.Show GHC.Internal.JS.Prim.WouldBlockException -- Defined in ‘GHC.Internal.JS.Prim’
instance GHC.Internal.Show.Show GHC.Internal.Stack.CloneStack.StackEntry -- Defined in ‘GHC.Internal.Stack.CloneStack’
@@ -15743,7 +15741,7 @@ instance GHC.Classes.Eq GHC.Internal.IO.IOMode.IOMode -- Defined in ‘GHC.Inter
instance GHC.Classes.Eq GHC.Internal.RTS.Flags.IoSubSystem -- Defined in ‘GHC.Internal.RTS.Flags’
instance forall i e. GHC.Classes.Eq (GHC.Internal.IOArray.IOArray i e) -- Defined in ‘GHC.Internal.IOArray’
instance forall a. GHC.Classes.Eq (GHC.Internal.IOPort.IOPort a) -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Classes.Eq GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Classes.Eq GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Classes.Eq GHC.Num.Integer.Integer -- Defined in ‘GHC.Num.Integer’
instance GHC.Classes.Eq GHC.Internal.JS.Foreign.Callback.OnBlocked -- Defined in ‘GHC.Internal.JS.Foreign.Callback’
instance GHC.Classes.Eq GHC.Num.BigNat.BigNat -- Defined in ‘GHC.Num.BigNat’
=====================================
testsuite/tests/interface-stability/base-exports.stdout-mingw32
=====================================
@@ -4758,7 +4758,6 @@ module GHC.Base where
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
when :: forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -7006,7 +7005,6 @@ module GHC.Exts where
void# :: (# #)
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -8329,7 +8327,7 @@ module GHC.IORef where
module GHC.InfoProv where
-- Safety: Safe
type InfoProv :: *
- data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+ data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
type InfoProvEnt :: *
data InfoProvEnt
ipLoc :: InfoProv -> GHC.Internal.Base.String
@@ -12799,7 +12797,7 @@ instance GHC.Internal.Show.Show GHC.Internal.IO.Windows.Handle.CONSOLE_READCONSO
instance GHC.Internal.Show.Show (GHC.Internal.IO.Windows.Handle.Io GHC.Internal.IO.Windows.Handle.NativeHandle) -- Defined in ‘GHC.Internal.IO.Windows.Handle’
instance GHC.Internal.Show.Show (GHC.Internal.IO.Windows.Handle.Io GHC.Internal.IO.Windows.Handle.ConsoleHandle) -- Defined in ‘GHC.Internal.IO.Windows.Handle’
instance GHC.Internal.Show.Show GHC.Internal.IOPort.IOPortException -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Internal.Show.Show GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Internal.Show.Show GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Internal.Show.Show GHC.Internal.Stack.CloneStack.StackEntry -- Defined in ‘GHC.Internal.Stack.CloneStack’
instance GHC.Internal.Show.Show GHC.Internal.StaticPtr.StaticPtrInfo -- Defined in ‘GHC.Internal.StaticPtr’
instance GHC.Internal.Show.Show GHC.Internal.Stats.GCDetails -- Defined in ‘GHC.Internal.Stats’
@@ -12993,7 +12991,7 @@ instance GHC.Classes.Eq GHC.Internal.RTS.Flags.IoSubSystem -- Defined in ‘GHC.
instance GHC.Classes.Eq GHC.Internal.IO.Windows.Handle.TempFileOptions -- Defined in ‘GHC.Internal.IO.Windows.Handle’
instance forall i e. GHC.Classes.Eq (GHC.Internal.IOArray.IOArray i e) -- Defined in ‘GHC.Internal.IOArray’
instance forall a. GHC.Classes.Eq (GHC.Internal.IOPort.IOPort a) -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Classes.Eq GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Classes.Eq GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Classes.Eq GHC.Num.Integer.Integer -- Defined in ‘GHC.Num.Integer’
instance GHC.Classes.Eq GHC.Num.BigNat.BigNat -- Defined in ‘GHC.Num.BigNat’
instance GHC.Classes.Eq GHC.Num.Natural.Natural -- Defined in ‘GHC.Num.Natural’
=====================================
testsuite/tests/interface-stability/base-exports.stdout-ws-32
=====================================
@@ -4755,7 +4755,6 @@ module GHC.Base where
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
when :: forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -6857,7 +6856,6 @@ module GHC.Exts where
void# :: (# #)
waitRead# :: forall d. Int# -> State# d -> State# d
waitWrite# :: forall d. Int# -> State# d -> State# d
- whereFrom# :: forall a d. a -> State# d -> (# State# d, Addr# #)
word16ToInt16# :: Word16# -> Int16#
word16ToWord# :: Word16# -> Word#
word2Double# :: Word# -> Double#
@@ -8105,7 +8103,7 @@ module GHC.IORef where
module GHC.InfoProv where
-- Safety: Safe
type InfoProv :: *
- data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
+ data InfoProv = InfoProv {ipName :: GHC.Internal.Base.String, ipDesc :: GHC.Internal.ClosureTypes.ClosureType, ipTyDesc :: GHC.Internal.Base.String, ipLabel :: GHC.Internal.Base.String, ipUnitId :: GHC.Internal.Base.String, ipMod :: GHC.Internal.Base.String, ipSrcFile :: GHC.Internal.Base.String, ipSrcSpan :: GHC.Internal.Base.String}
type InfoProvEnt :: *
data InfoProvEnt
ipLoc :: InfoProv -> GHC.Internal.Base.String
@@ -12521,7 +12519,7 @@ instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.RTSFlags -- Defined in
instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.TickyFlags -- Defined in ‘GHC.Internal.RTS.Flags’
instance GHC.Internal.Show.Show GHC.Internal.RTS.Flags.TraceFlags -- Defined in ‘GHC.Internal.RTS.Flags’
instance GHC.Internal.Show.Show GHC.Internal.IOPort.IOPortException -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Internal.Show.Show GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Internal.Show.Show GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Internal.Show.Show GHC.Internal.Stack.CloneStack.StackEntry -- Defined in ‘GHC.Internal.Stack.CloneStack’
instance GHC.Internal.Show.Show GHC.Internal.StaticPtr.StaticPtrInfo -- Defined in ‘GHC.Internal.StaticPtr’
instance GHC.Internal.Show.Show GHC.Internal.Stats.GCDetails -- Defined in ‘GHC.Internal.Stats’
@@ -12717,7 +12715,7 @@ instance GHC.Classes.Eq GHC.Internal.IO.IOMode.IOMode -- Defined in ‘GHC.Inter
instance GHC.Classes.Eq GHC.Internal.RTS.Flags.IoSubSystem -- Defined in ‘GHC.Internal.RTS.Flags’
instance forall i e. GHC.Classes.Eq (GHC.Internal.IOArray.IOArray i e) -- Defined in ‘GHC.Internal.IOArray’
instance forall a. GHC.Classes.Eq (GHC.Internal.IOPort.IOPort a) -- Defined in ‘GHC.Internal.IOPort’
-instance GHC.Classes.Eq GHC.Internal.InfoProv.InfoProv -- Defined in ‘GHC.Internal.InfoProv’
+instance GHC.Classes.Eq GHC.Internal.InfoProv.Types.InfoProv -- Defined in ‘GHC.Internal.InfoProv.Types’
instance GHC.Classes.Eq GHC.Num.Integer.Integer -- Defined in ‘GHC.Num.Integer’
instance GHC.Classes.Eq GHC.Num.BigNat.BigNat -- Defined in ‘GHC.Num.BigNat’
instance GHC.Classes.Eq GHC.Num.Natural.Natural -- Defined in ‘GHC.Num.Natural’
=====================================
testsuite/tests/profiling/should_run/staticcallstack001.stdout
=====================================
@@ -1,3 +1,3 @@
-Just (InfoProv {ipName = "D_Main_4_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "16:13-27"})
-Just (InfoProv {ipName = "D_Main_2_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "caf", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "13:1-9"})
-Just (InfoProv {ipName = "sat_s11M_info", ipDesc = THUNK, ipTyDesc = "D", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "18:23-32"})
+Just (InfoProv {ipName = "D_Main_4_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "16:13-27"})
+Just (InfoProv {ipName = "D_Main_2_con_info", ipDesc = CONSTR_1_0, ipTyDesc = "D", ipLabel = "caf", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "13:1-9"})
+Just (InfoProv {ipName = "sat_s23z_info", ipDesc = THUNK, ipTyDesc = "D", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack001.hs", ipSrcSpan = "18:23-32"})
=====================================
testsuite/tests/profiling/should_run/staticcallstack002.stdout
=====================================
@@ -1,4 +1,4 @@
-Just (InfoProv {ipName = "sat_s11p_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "10:23-39"})
-Just (InfoProv {ipName = "sat_s11F_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "11:23-42"})
-Just (InfoProv {ipName = "sat_s11V_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "12:23-46"})
-Just (InfoProv {ipName = "sat_s12b_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "13:23-44"})
+Just (InfoProv {ipName = "sat_s237_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "10:23-39"})
+Just (InfoProv {ipName = "sat_s23r_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "11:23-42"})
+Just (InfoProv {ipName = "sat_s23L_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "12:23-46"})
+Just (InfoProv {ipName = "sat_s245_info", ipDesc = THUNK, ipTyDesc = "Any", ipLabel = "main", ipUnitId = "main", ipMod = "Main", ipSrcFile = "staticcallstack002.hs", ipSrcSpan = "13:23-44"})
=====================================
testsuite/tests/rts/ipe/T24005/t24005.stdout
=====================================
@@ -1,2 +1,2 @@
-Just (InfoProv {ipName = "C:Show_Main_1_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowA", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "25:10-15"})
-Just (InfoProv {ipName = "C:Show_Main_0_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowB", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "29:10-29"})
+Just (InfoProv {ipName = "C:Show_Main_1_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowA", ipUnitId = "main", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "25:10-15"})
+Just (InfoProv {ipName = "C:Show_Main_0_con_info", ipDesc = CONSTR, ipTyDesc = "Show", ipLabel = "$fShowB", ipUnitId = "main", ipMod = "Main", ipSrcFile = "t24005.hs", ipSrcSpan = "29:10-29"})
=====================================
testsuite/tests/rts/ipe/ipeEventLog.stderr
=====================================
@@ -1,20 +1,20 @@
-7f5278bc0740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7f5278bc0740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_001, srcloc src_file_001:src_span_001
-7f5278bc0740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_002, srcloc src_file_002:src_span_002
-7f5278bc0740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_003, srcloc src_file_003:src_span_003
-7f5278bc0740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_004, srcloc src_file_004:src_span_004
-7f5278bc0740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_005, srcloc src_file_005:src_span_005
-7f5278bc0740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_006, srcloc src_file_006:src_span_006
-7f5278bc0740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_007, srcloc src_file_007:src_span_007
-7f5278bc0740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_008, srcloc src_file_008:src_span_008
-7f5278bc0740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_009, srcloc src_file_009:src_span_009
-7f5278bc0740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7f5278bc0740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_001, srcloc src_file_001:src_span_001
-7f5278bc0740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_002, srcloc src_file_002:src_span_002
-7f5278bc0740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_003, srcloc src_file_003:src_span_003
-7f5278bc0740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_004, srcloc src_file_004:src_span_004
-7f5278bc0740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_005, srcloc src_file_005:src_span_005
-7f5278bc0740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_006, srcloc src_file_006:src_span_006
-7f5278bc0740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_007, srcloc src_file_007:src_span_007
-7f5278bc0740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_008, srcloc src_file_008:src_span_008
-7f5278bc0740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_009, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
=====================================
testsuite/tests/rts/ipe/ipeEventLog_fromMap.c
=====================================
@@ -19,7 +19,8 @@ int main(int argc, char *argv[]) {
registerInfoProvList(list2);
// Query an IPE to initialize the underlying hash map.
- lookupIPE(list1->tables[0]);
+ InfoProvEnt ipe;
+ lookupIPE(list1->tables[0], &ipe);
// Trace all IPE events.
dumpIPEToEventLog();
=====================================
testsuite/tests/rts/ipe/ipeEventLog_fromMap.stderr
=====================================
@@ -1,68 +1,20 @@
-7f86c4be8740: created capset 0 of type 2
-7f86c4be8740: created capset 1 of type 3
-7f86c4be8740: cap 0: initialised
-7f86c4be8740: assigned cap 0 to capset 0
-7f86c4be8740: assigned cap 0 to capset 1
-7f86c4be8740: cap 0: created thread 1[""]
-7f86c4be8740: cap 0: running thread 1[""] (ThreadRunGHC)
-7f86c4be8740: cap 0: thread 1[""] stopped (stack overflow, size 109)
-7f86c4be8740: cap 0: running thread 1[""] (ThreadRunGHC)
-7f86c4be8740: cap 0: created thread 2[""]
-7f86c4be8740: cap 0: thread 2 has label IOManager on cap 0
-7f86c4be8740: cap 0: thread 1[""] stopped (yielding)
-7f86b67fc640: cap 0: running thread 2["IOManager on cap 0"] (ThreadRunGHC)
-7f86b67fc640: cap 0: thread 2["IOManager on cap 0"] stopped (yielding)
-7f86c4be8740: cap 0: running thread 1[""] (ThreadRunGHC)
-7f86c4be8740: cap 0: created thread 3[""]
-7f86c4be8740: cap 0: thread 3 has label TimerManager
-7f86c4be8740: cap 0: thread 1[""] stopped (finished)
-7f86c4be8740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_009, srcloc src_file_009:src_span_009
-7f86c4be8740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_008, srcloc src_file_008:src_span_008
-7f86c4be8740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_007, srcloc src_file_007:src_span_007
-7f86c4be8740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_006, srcloc src_file_006:src_span_006
-7f86c4be8740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_005, srcloc src_file_005:src_span_005
-7f86c4be8740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_004, srcloc src_file_004:src_span_004
-7f86c4be8740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_003, srcloc src_file_003:src_span_003
-7f86c4be8740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_002, srcloc src_file_002:src_span_002
-7f86c4be8740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_001, srcloc src_file_001:src_span_001
-7f86c4be8740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7f86c4be8740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, module module_009, srcloc src_file_009:src_span_009
-7f86c4be8740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, module module_008, srcloc src_file_008:src_span_008
-7f86c4be8740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, module module_007, srcloc src_file_007:src_span_007
-7f86c4be8740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, module module_006, srcloc src_file_006:src_span_006
-7f86c4be8740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, module module_005, srcloc src_file_005:src_span_005
-7f86c4be8740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, module module_004, srcloc src_file_004:src_span_004
-7f86c4be8740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, module module_003, srcloc src_file_003:src_span_003
-7f86c4be8740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, module module_002, srcloc src_file_002:src_span_002
-7f86c4be8740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, module module_001, srcloc src_file_001:src_span_001
-7f86c4be8740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, module module_000, srcloc src_file_000:src_span_000
-7f86c4be8740: cap 0: created thread 4[""]
-7f86b67fc640: cap 0: running thread 2["IOManager on cap 0"] (ThreadRunGHC)
-7f86b67fc640: cap 0: thread 2["IOManager on cap 0"] stopped (suspended while making a foreign call)
-7f86b5ffb640: cap 0: running thread 3["TimerManager"] (ThreadRunGHC)
-7f86b5ffb640: cap 0: thread 3["TimerManager"] stopped (suspended while making a foreign call)
-7f86c4be8740: cap 0: running thread 4[""] (ThreadRunGHC)
-7f86c4be8740: cap 0: thread 4[""] stopped (yielding)
-7f86c4be8740: cap 0: running thread 4[""] (ThreadRunGHC)
-7f86c4be8740: cap 0: thread 4[""] stopped (finished)
-7f86b57fa640: cap 0: requesting sequential GC
-7f86b57fa640: cap 0: starting GC
-7f86b57fa640: cap 0: GC working
-7f86b57fa640: cap 0: GC idle
-7f86b57fa640: cap 0: GC done
-7f86b57fa640: cap 0: GC idle
-7f86b57fa640: cap 0: GC done
-7f86b57fa640: cap 0: GC idle
-7f86b57fa640: cap 0: GC done
-7f86b57fa640: cap 0: Memory Return (Current: 6) (Needed: 8) (Returned: 0)
-7f86b57fa640: cap 0: all caps stopped for GC
-7f86b57fa640: cap 0: finished GC
-7f86b5ffb640: cap 0: running thread 3["TimerManager"] (ThreadRunGHC)
-7f86b5ffb640: cap 0: thread 3["TimerManager"] stopped (finished)
-7f86b67fc640: cap 0: running thread 2["IOManager on cap 0"] (ThreadRunGHC)
-7f86b67fc640: cap 0: thread 2["IOManager on cap 0"] stopped (finished)
-7f86c4be8740: removed cap 0 from capset 0
-7f86c4be8740: removed cap 0 from capset 1
-7f86c4be8740: cap 0: shutting down
-7f86c4be8740: deleted capset 0
-7f86c4be8740: deleted capset 1
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
+7ffff7a4d740: IPE: table_name table_name_009, closure_desc closure_desc_009, ty_desc ty_desc_009, label label_009, unit unit_id_000, module module_000, srcloc src_file_009:src_span_009
+7ffff7a4d740: IPE: table_name table_name_008, closure_desc closure_desc_008, ty_desc ty_desc_008, label label_008, unit unit_id_000, module module_000, srcloc src_file_008:src_span_008
+7ffff7a4d740: IPE: table_name table_name_007, closure_desc closure_desc_007, ty_desc ty_desc_007, label label_007, unit unit_id_000, module module_000, srcloc src_file_007:src_span_007
+7ffff7a4d740: IPE: table_name table_name_006, closure_desc closure_desc_006, ty_desc ty_desc_006, label label_006, unit unit_id_000, module module_000, srcloc src_file_006:src_span_006
+7ffff7a4d740: IPE: table_name table_name_005, closure_desc closure_desc_005, ty_desc ty_desc_005, label label_005, unit unit_id_000, module module_000, srcloc src_file_005:src_span_005
+7ffff7a4d740: IPE: table_name table_name_004, closure_desc closure_desc_004, ty_desc ty_desc_004, label label_004, unit unit_id_000, module module_000, srcloc src_file_004:src_span_004
+7ffff7a4d740: IPE: table_name table_name_003, closure_desc closure_desc_003, ty_desc ty_desc_003, label label_003, unit unit_id_000, module module_000, srcloc src_file_003:src_span_003
+7ffff7a4d740: IPE: table_name table_name_002, closure_desc closure_desc_002, ty_desc ty_desc_002, label label_002, unit unit_id_000, module module_000, srcloc src_file_002:src_span_002
+7ffff7a4d740: IPE: table_name table_name_001, closure_desc closure_desc_001, ty_desc ty_desc_001, label label_001, unit unit_id_000, module module_000, srcloc src_file_001:src_span_001
+7ffff7a4d740: IPE: table_name table_name_000, closure_desc closure_desc_000, ty_desc ty_desc_000, label label_000, unit unit_id_000, module module_000, srcloc src_file_000:src_span_000
=====================================
testsuite/tests/rts/ipe/ipeMap.c
=====================================
@@ -28,14 +28,19 @@ int main(int argc, char *argv[]) {
hs_exit();
}
+static InfoProvEnt lookupIPE_(const char *where, const StgInfoTable *itbl) {
+ InfoProvEnt ent;
+ if (!lookupIPE(itbl, &ent)) {
+ barf("%s: Expected to find IPE entry", where);
+ }
+ return ent;
+}
+
void shouldFindNothingInAnEmptyIPEMap(Capability *cap) {
HaskellObj fortyTwo = UNTAG_CLOSURE(rts_mkInt(cap, 42));
-
- InfoProvEnt *result = lookupIPE(get_itbl(fortyTwo));
-
- if (result != NULL) {
- errorBelch("Found entry in an empty IPE map!");
- exit(1);
+ InfoProvEnt ent;
+ if (lookupIPE(get_itbl(fortyTwo), &ent)) {
+ barf("Found entry in an empty IPE map!");
}
}
@@ -48,6 +53,9 @@ HaskellObj shouldFindOneIfItHasBeenRegistered(Capability *cap) {
StringTable st;
init_string_table(&st);
+ node->unit_id = add_string(&st, "unit-id");
+ node->module_name = add_string(&st, "TheModule");
+
HaskellObj fortyTwo = UNTAG_CLOSURE(rts_mkInt(cap, 42));
node->next = NULL;
node->compressed = 0;
@@ -60,20 +68,16 @@ HaskellObj shouldFindOneIfItHasBeenRegistered(Capability *cap) {
registerInfoProvList(node);
- InfoProvEnt *result = lookupIPE(get_itbl(fortyTwo));
+ InfoProvEnt result = lookupIPE_("shouldFindOneIfItHasBeenRegistered", get_itbl(fortyTwo));
- if (result == NULL) {
- errorBelch("shouldFindOneIfItHasBeenRegistered: Found no entry in IPE map!");
- exit(1);
- }
-
- assertStringsEqual(result->prov.table_name, "table_name_042");
- assertStringsEqual(result->prov.closure_desc, "closure_desc_042");
- assertStringsEqual(result->prov.ty_desc, "ty_desc_042");
- assertStringsEqual(result->prov.label, "label_042");
- assertStringsEqual(result->prov.module, "module_042");
- assertStringsEqual(result->prov.src_file, "src_file_042");
- assertStringsEqual(result->prov.src_span, "src_span_042");
+ assertStringsEqual(result.prov.table_name, "table_name_042");
+ assertStringsEqual(result.prov.closure_desc, "closure_desc_042");
+ assertStringsEqual(result.prov.ty_desc, "ty_desc_042");
+ assertStringsEqual(result.prov.label, "label_042");
+ assertStringsEqual(result.prov.unit_id, "unit-id");
+ assertStringsEqual(result.prov.module, "TheModule");
+ assertStringsEqual(result.prov.src_file, "src_file_042");
+ assertStringsEqual(result.prov.src_span, "src_span_042");
return fortyTwo;
}
@@ -88,6 +92,9 @@ void shouldFindTwoIfTwoHaveBeenRegistered(Capability *cap,
StringTable st;
init_string_table(&st);
+ node->unit_id = add_string(&st, "unit-id");
+ node->module_name = add_string(&st, "TheModule");
+
HaskellObj twentyThree = UNTAG_CLOSURE(rts_mkInt8(cap, 23));
node->next = NULL;
node->compressed = 0;
@@ -100,22 +107,11 @@ void shouldFindTwoIfTwoHaveBeenRegistered(Capability *cap,
registerInfoProvList(node);
- InfoProvEnt *resultFortyTwo =
- lookupIPE(get_itbl(fortyTwo));
- InfoProvEnt *resultTwentyThree =
- lookupIPE(get_itbl(twentyThree));
+ InfoProvEnt resultFortyTwo = lookupIPE_("shouldFindTwoIfTwoHaveBeenRegistered", get_itbl(fortyTwo));
+ assertStringsEqual(resultFortyTwo.prov.table_name, "table_name_042");
- if (resultFortyTwo == NULL) {
- errorBelch("shouldFindTwoIfTwoHaveBeenRegistered(42): Found no entry in IPE map!");
- exit(1);
- }
- if (resultTwentyThree == NULL) {
- errorBelch("shouldFindTwoIfTwoHaveBeenRegistered(23): Found no entry in IPE map!");
- exit(1);
- }
-
- assertStringsEqual(resultFortyTwo->prov.table_name, "table_name_042");
- assertStringsEqual(resultTwentyThree->prov.table_name, "table_name_023");
+ InfoProvEnt resultTwentyThree = lookupIPE_("shouldFindTwoIfTwoHaveBeenRegistered", get_itbl(twentyThree));
+ assertStringsEqual(resultTwentyThree.prov.table_name, "table_name_023");
}
void shouldFindTwoFromTheSameList(Capability *cap) {
@@ -142,20 +138,11 @@ void shouldFindTwoFromTheSameList(Capability *cap) {
registerInfoProvList(node);
- InfoProvEnt *resultOne = lookupIPE(get_itbl(one));
- InfoProvEnt *resultTwo = lookupIPE(get_itbl(two));
-
- if (resultOne == NULL) {
- errorBelch("shouldFindTwoFromTheSameList(1): Found no entry in IPE map!");
- exit(1);
- }
- if (resultTwo == NULL) {
- errorBelch("shouldFindTwoFromTheSameList(2): Found no entry in IPE map!");
- exit(1);
- }
+ InfoProvEnt resultOne = lookupIPE_("shouldFindTwoFromTheSameList", get_itbl(one));
+ assertStringsEqual(resultOne.prov.table_name, "table_name_001");
- assertStringsEqual(resultOne->prov.table_name, "table_name_001");
- assertStringsEqual(resultTwo->prov.table_name, "table_name_002");
+ InfoProvEnt resultTwo = lookupIPE_("shouldFindTwoFromTheSameList", get_itbl(two));
+ assertStringsEqual(resultTwo.prov.table_name, "table_name_002");
}
void shouldDealWithAnEmptyList(Capability *cap, HaskellObj fortyTwo) {
@@ -166,15 +153,8 @@ void shouldDealWithAnEmptyList(Capability *cap, HaskellObj fortyTwo) {
registerInfoProvList(node);
- InfoProvEnt *resultFortyTwo =
- lookupIPE(get_itbl(fortyTwo));
-
- if (resultFortyTwo == NULL) {
- errorBelch("shouldDealWithAnEmptyList: Found no entry in IPE map!");
- exit(1);
- }
-
- assertStringsEqual(resultFortyTwo->prov.table_name, "table_name_042");
+ InfoProvEnt resultFortyTwo = lookupIPE_("shouldDealWithAnEmptyList", get_itbl(fortyTwo));
+ assertStringsEqual(resultFortyTwo.prov.table_name, "table_name_042");
}
void assertStringsEqual(const char *s1, const char *s2) {
=====================================
testsuite/tests/rts/ipe/ipe_lib.c
=====================================
@@ -48,11 +48,6 @@ IpeBufferEntry makeAnyProvEntry(Capability *cap, StringTable *st, int i) {
snprintf(label, labelLength, "label_%03i", i);
provEnt.label = add_string(st, label);
- unsigned int moduleLength = strlen("module_") + 3 /* digits */ + 1 /* null character */;
- char *module = malloc(sizeof(char) * moduleLength);
- snprintf(module, moduleLength, "module_%03i", i);
- provEnt.module_name = add_string(st, module);
-
unsigned int srcFileLength = strlen("src_file_") + 3 /* digits */ + 1 /* null character */;
char *srcFile = malloc(sizeof(char) * srcFileLength);
snprintf(srcFile, srcFileLength, "src_file_%03i", i);
@@ -77,6 +72,16 @@ IpeBufferListNode *makeAnyProvEntries(Capability *cap, int start, int end) {
StringTable st;
init_string_table(&st);
+ unsigned int unitIdLength = strlen("unit_id_") + 3 /* digits */ + 1 /* null character */;
+ char *unitId = malloc(sizeof(char) * unitIdLength);
+ snprintf(unitId, unitIdLength, "unit_id_%03i", start);
+ node->unit_id = add_string(&st, unitId);
+
+ unsigned int moduleLength = strlen("module_") + 3 /* digits */ + 1 /* null character */;
+ char *module = malloc(sizeof(char) * moduleLength);
+ snprintf(module, moduleLength, "module_%03i", start);
+ node->module_name = add_string(&st, module);
+
// Make the entries and fill the buffers
for (int i=start; i < end; i++) {
HaskellObj closure = rts_mkInt(cap, 42);
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2e592857b6e028fbad83712ceda6a0860191d379...ed0b69dc069a23692bff89cfcab1ad9d61999506
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/2e592857b6e028fbad83712ceda6a0860191d379...ed0b69dc069a23692bff89cfcab1ad9d61999506
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/20240309/2446b8f6/attachment-0001.html>
More information about the ghc-commits
mailing list