ghc-heap 9.8.1 → 9.10.1
raw patch · 10 files changed
+1055/−6 lines, 10 filesdep +ghc-internalPVP ok
version bump matches the API change (PVP)
Dependencies added: ghc-internal
API changes (from Hackage documentation)
- GHC.Exts.Heap.ClosureTypes: instance GHC.Classes.Eq GHC.Exts.Heap.ClosureTypes.ClosureType
- GHC.Exts.Heap.ClosureTypes: instance GHC.Classes.Ord GHC.Exts.Heap.ClosureTypes.ClosureType
- GHC.Exts.Heap.ClosureTypes: instance GHC.Enum.Enum GHC.Exts.Heap.ClosureTypes.ClosureType
- GHC.Exts.Heap.ClosureTypes: instance GHC.Generics.Generic GHC.Exts.Heap.ClosureTypes.ClosureType
- GHC.Exts.Heap.ClosureTypes: instance GHC.Show.Show GHC.Exts.Heap.ClosureTypes.ClosureType
- GHC.Exts.Heap.Closures: instance Data.Foldable.Foldable GHC.Exts.Heap.Closures.GenClosure
- GHC.Exts.Heap.Closures: instance Data.Traversable.Traversable GHC.Exts.Heap.Closures.GenClosure
- GHC.Exts.Heap.Closures: instance GHC.Base.Functor GHC.Exts.Heap.Closures.GenClosure
- GHC.Exts.Heap.Closures: instance GHC.Generics.Generic (GHC.Exts.Heap.Closures.GenClosure b)
- GHC.Exts.Heap.Closures: instance GHC.Generics.Generic GHC.Exts.Heap.Closures.PrimType
- GHC.Exts.Heap.Closures: instance GHC.Generics.Generic GHC.Exts.Heap.Closures.TsoFlags
- GHC.Exts.Heap.Closures: instance GHC.Generics.Generic GHC.Exts.Heap.Closures.WhatNext
- GHC.Exts.Heap.Closures: instance GHC.Generics.Generic GHC.Exts.Heap.Closures.WhyBlocked
- GHC.Exts.Heap.Closures: instance GHC.Show.Show GHC.Exts.Heap.Closures.Box
- GHC.Exts.Heap.Closures: instance GHC.Show.Show GHC.Exts.Heap.Closures.PrimType
- GHC.Exts.Heap.Closures: instance GHC.Show.Show GHC.Exts.Heap.Closures.TsoFlags
- GHC.Exts.Heap.Closures: instance GHC.Show.Show GHC.Exts.Heap.Closures.WhatNext
- GHC.Exts.Heap.Closures: instance GHC.Show.Show GHC.Exts.Heap.Closures.WhyBlocked
- GHC.Exts.Heap.Closures: instance GHC.Show.Show b => GHC.Show.Show (GHC.Exts.Heap.Closures.GenClosure b)
- GHC.Exts.Heap.InfoTable.Types: instance GHC.Generics.Generic GHC.Exts.Heap.InfoTable.Types.StgInfoTable
- GHC.Exts.Heap.InfoTable.Types: instance GHC.Show.Show GHC.Exts.Heap.InfoTable.Types.StgInfoTable
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.CostCentre
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.CostCentreStack
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.IndexTable
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.StgTSOProfInfo
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Show.Show GHC.Exts.Heap.ProfInfo.Types.CostCentre
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Show.Show GHC.Exts.Heap.ProfInfo.Types.CostCentreStack
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Show.Show GHC.Exts.Heap.ProfInfo.Types.IndexTable
- GHC.Exts.Heap.ProfInfo.Types: instance GHC.Show.Show GHC.Exts.Heap.ProfInfo.Types.StgTSOProfInfo
+ GHC.Exts.Heap: UnknownTypeWordSizedPrimitive :: !Word -> GenClosure b
+ GHC.Exts.Heap.Closures: AtomicallyFrame :: !StgInfoTable -> !b -> !b -> GenStackFrame b
+ GHC.Exts.Heap.Closures: CatchFrame :: !StgInfoTable -> !b -> GenStackFrame b
+ GHC.Exts.Heap.Closures: CatchRetryFrame :: !StgInfoTable -> !Word -> !b -> !b -> GenStackFrame b
+ GHC.Exts.Heap.Closures: CatchStmFrame :: !StgInfoTable -> !b -> !b -> GenStackFrame b
+ GHC.Exts.Heap.Closures: GenStgStackClosure :: !StgInfoTable -> !Word32 -> ![GenStackFrame b] -> GenStgStackClosure b
+ GHC.Exts.Heap.Closures: RetBCO :: !StgInfoTable -> !b -> ![GenStackField b] -> GenStackFrame b
+ GHC.Exts.Heap.Closures: RetBig :: !StgInfoTable -> ![GenStackField b] -> GenStackFrame b
+ GHC.Exts.Heap.Closures: RetFun :: !StgInfoTable -> !Word -> !b -> ![GenStackField b] -> GenStackFrame b
+ GHC.Exts.Heap.Closures: RetSmall :: !StgInfoTable -> ![GenStackField b] -> GenStackFrame b
+ GHC.Exts.Heap.Closures: StackBox :: !b -> GenStackField b
+ GHC.Exts.Heap.Closures: StackWord :: !Word -> GenStackField b
+ GHC.Exts.Heap.Closures: StopFrame :: !StgInfoTable -> GenStackFrame b
+ GHC.Exts.Heap.Closures: UnderflowFrame :: !StgInfoTable -> !GenStgStackClosure b -> GenStackFrame b
+ GHC.Exts.Heap.Closures: UnknownTypeWordSizedPrimitive :: !Word -> GenClosure b
+ GHC.Exts.Heap.Closures: UpdateFrame :: !StgInfoTable -> !b -> GenStackFrame b
+ GHC.Exts.Heap.Closures: [alt_code] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [atomicallyFrameCode] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [bcoArgs] :: GenStackFrame b -> ![GenStackField b]
+ GHC.Exts.Heap.Closures: [bco] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [catchFrameCode] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [first_code] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [handler] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [info_tbl] :: GenStackFrame b -> !StgInfoTable
+ GHC.Exts.Heap.Closures: [nextChunk] :: GenStackFrame b -> !GenStgStackClosure b
+ GHC.Exts.Heap.Closures: [result] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [retFunFun] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: [retFunPayload] :: GenStackFrame b -> ![GenStackField b]
+ GHC.Exts.Heap.Closures: [retFunSize] :: GenStackFrame b -> !Word
+ GHC.Exts.Heap.Closures: [running_alt_code] :: GenStackFrame b -> !Word
+ GHC.Exts.Heap.Closures: [ssc_info] :: GenStgStackClosure b -> !StgInfoTable
+ GHC.Exts.Heap.Closures: [ssc_stack] :: GenStgStackClosure b -> ![GenStackFrame b]
+ GHC.Exts.Heap.Closures: [ssc_stack_size] :: GenStgStackClosure b -> !Word32
+ GHC.Exts.Heap.Closures: [stack_payload] :: GenStackFrame b -> ![GenStackField b]
+ GHC.Exts.Heap.Closures: [updatee] :: GenStackFrame b -> !b
+ GHC.Exts.Heap.Closures: data GenStackField b
+ GHC.Exts.Heap.Closures: data GenStackFrame b
+ GHC.Exts.Heap.Closures: data GenStgStackClosure b
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Base.Functor GHC.Exts.Heap.Closures.GenClosure
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Base.Functor GHC.Exts.Heap.Closures.GenStackField
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Base.Functor GHC.Exts.Heap.Closures.GenStackFrame
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Base.Functor GHC.Exts.Heap.Closures.GenStgStackClosure
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Foldable.Foldable GHC.Exts.Heap.Closures.GenClosure
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Foldable.Foldable GHC.Exts.Heap.Closures.GenStackField
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Foldable.Foldable GHC.Exts.Heap.Closures.GenStackFrame
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Foldable.Foldable GHC.Exts.Heap.Closures.GenStgStackClosure
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Traversable.Traversable GHC.Exts.Heap.Closures.GenClosure
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Traversable.Traversable GHC.Exts.Heap.Closures.GenStackField
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Traversable.Traversable GHC.Exts.Heap.Closures.GenStackFrame
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Data.Traversable.Traversable GHC.Exts.Heap.Closures.GenStgStackClosure
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic (GHC.Exts.Heap.Closures.GenClosure b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic (GHC.Exts.Heap.Closures.GenStackField b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic (GHC.Exts.Heap.Closures.GenStackFrame b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic (GHC.Exts.Heap.Closures.GenStgStackClosure b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.Closures.PrimType
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.Closures.TsoFlags
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.Closures.WhatNext
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.Closures.WhyBlocked
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show GHC.Exts.Heap.Closures.Box
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show GHC.Exts.Heap.Closures.PrimType
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show GHC.Exts.Heap.Closures.TsoFlags
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show GHC.Exts.Heap.Closures.WhatNext
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show GHC.Exts.Heap.Closures.WhyBlocked
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show b => GHC.Internal.Show.Show (GHC.Exts.Heap.Closures.GenClosure b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show b => GHC.Internal.Show.Show (GHC.Exts.Heap.Closures.GenStackField b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show b => GHC.Internal.Show.Show (GHC.Exts.Heap.Closures.GenStackFrame b)
+ GHC.Exts.Heap.Closures: instance GHC.Internal.Show.Show b => GHC.Internal.Show.Show (GHC.Exts.Heap.Closures.GenStgStackClosure b)
+ GHC.Exts.Heap.Closures: type StackField = GenStackField Box
+ GHC.Exts.Heap.Closures: type StackFrame = GenStackFrame Box
+ GHC.Exts.Heap.Closures: type StgStackClosure = GenStgStackClosure Box
+ GHC.Exts.Heap.InfoTable.Types: instance GHC.Classes.Eq GHC.Exts.Heap.InfoTable.Types.StgInfoTable
+ GHC.Exts.Heap.InfoTable.Types: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.InfoTable.Types.StgInfoTable
+ GHC.Exts.Heap.InfoTable.Types: instance GHC.Internal.Show.Show GHC.Exts.Heap.InfoTable.Types.StgInfoTable
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.CostCentre
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.CostCentreStack
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.IndexTable
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Generics.Generic GHC.Exts.Heap.ProfInfo.Types.StgTSOProfInfo
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Show.Show GHC.Exts.Heap.ProfInfo.Types.CostCentre
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Show.Show GHC.Exts.Heap.ProfInfo.Types.CostCentreStack
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Show.Show GHC.Exts.Heap.ProfInfo.Types.IndexTable
+ GHC.Exts.Heap.ProfInfo.Types: instance GHC.Internal.Show.Show GHC.Exts.Heap.ProfInfo.Types.StgTSOProfInfo
+ GHC.Exts.Stack: decodeStack :: StackSnapshot -> IO StgStackClosure
+ GHC.Exts.Stack: stackFrameSize :: StackFrame -> Int
+ GHC.Exts.Stack.Constants: ByteOffset :: Int -> ByteOffset
+ GHC.Exts.Stack.Constants: WordOffset :: Int -> WordOffset
+ GHC.Exts.Stack.Constants: [offsetInBytes] :: ByteOffset -> Int
+ GHC.Exts.Stack.Constants: [offsetInWords] :: WordOffset -> Int
+ GHC.Exts.Stack.Constants: byteOffsetToWordOffset :: ByteOffset -> WordOffset
+ GHC.Exts.Stack.Constants: bytesInWord :: Int
+ GHC.Exts.Stack.Constants: bytesToWords :: Int -> Int
+ GHC.Exts.Stack.Constants: instance GHC.Classes.Eq GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Classes.Eq GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: instance GHC.Classes.Ord GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Classes.Ord GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Enum.Enum GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Enum.Enum GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Num.Num GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Num.Num GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Real.Integral GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Real.Integral GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Real.Real GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Real.Real GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Show.Show GHC.Exts.Stack.Constants.ByteOffset
+ GHC.Exts.Stack.Constants: instance GHC.Internal.Show.Show GHC.Exts.Stack.Constants.WordOffset
+ GHC.Exts.Stack.Constants: newtype ByteOffset
+ GHC.Exts.Stack.Constants: newtype WordOffset
+ GHC.Exts.Stack.Constants: offsetStgAtomicallyFrameCode :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgAtomicallyFrameResult :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgBCOFrameArity :: ByteOffset
+ GHC.Exts.Stack.Constants: offsetStgBCOFrameInstrs :: ByteOffset
+ GHC.Exts.Stack.Constants: offsetStgBCOFrameLiterals :: ByteOffset
+ GHC.Exts.Stack.Constants: offsetStgBCOFramePtrs :: ByteOffset
+ GHC.Exts.Stack.Constants: offsetStgBCOFrameSize :: ByteOffset
+ GHC.Exts.Stack.Constants: offsetStgCatchFrameHandler :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgCatchRetryFrameAltCode :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgCatchRetryFrameRunningAltCode :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgCatchRetryFrameRunningFirstCode :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgCatchSTMFrameCode :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgCatchSTMFrameHandler :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgClosurePayload :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgRetFunFrameFun :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgRetFunFramePayload :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgRetFunFrameSize :: WordOffset
+ GHC.Exts.Stack.Constants: offsetStgUpdateFrameUpdatee :: WordOffset
+ GHC.Exts.Stack.Constants: sizeStgAtomicallyFrame :: Int
+ GHC.Exts.Stack.Constants: sizeStgCatchFrame :: Int
+ GHC.Exts.Stack.Constants: sizeStgCatchRetryFrame :: Int
+ GHC.Exts.Stack.Constants: sizeStgCatchSTMFrame :: Int
+ GHC.Exts.Stack.Constants: sizeStgClosure :: Int
+ GHC.Exts.Stack.Constants: sizeStgRetFunFrame :: Int
+ GHC.Exts.Stack.Constants: sizeStgUpdateFrame :: Int
+ GHC.Exts.Stack.Decode: decodeStack :: StackSnapshot -> IO StgStackClosure
+ GHC.Exts.Stack.Decode: instance GHC.Internal.Show.Show GHC.Exts.Stack.Decode.Pointerness
Files
- GHC/Exts/Heap.hs +3/−2
- GHC/Exts/Heap/ClosureTypes.hs +4/−0
- GHC/Exts/Heap/Closures.hs +110/−1
- GHC/Exts/Heap/InfoTable/Types.hsc +1/−1
- GHC/Exts/Stack.hs +37/−0
- GHC/Exts/Stack/Constants.hsc +126/−0
- GHC/Exts/Stack/Decode.hs +431/−0
- cbits/Stack.cmm +182/−0
- cbits/Stack_c.c +151/−0
- ghc-heap.cabal +10/−2
GHC/Exts/Heap.hs view
@@ -317,8 +317,9 @@ _ -> fail $ "Expected at least 3 ptrs to MVAR, found " ++ show (length pts) - BLOCKING_QUEUE ->- pure $ OtherClosure itbl pts rawHeapWords+ BLOCKING_QUEUE+ | [_link, bh, _owner, msg] <- pts ->+ pure $ BlockingQueueClosure itbl _link bh _owner msg WEAK -> case pts of pts0 : pts1 : pts2 : pts3 : rest -> pure $ WeakClosure
GHC/Exts/Heap/ClosureTypes.hs view
@@ -7,6 +7,9 @@ ) where import Prelude -- See note [Why do we import Prelude here?]+#if __GLASGOW_HASKELL__ >= 909+import GHC.Internal.ClosureTypes+#else import GHC.Generics {- ---------------------------------------------@@ -83,6 +86,7 @@ | CONTINUATION | N_CLOSURE_TYPES deriving (Enum, Eq, Ord, Show, Generic)+#endif -- | Return the size of the closures header in words closureTypeHeaderSize :: ClosureType -> Int
GHC/Exts/Heap/Closures.hs view
@@ -18,6 +18,14 @@ , allClosures , closureSize + -- * Stack+ , StgStackClosure+ , GenStgStackClosure(..)+ , StackFrame+ , GenStackFrame(..)+ , StackField+ , GenStackField(..)+ -- * Boxes , Box(..) , areBoxesEqual@@ -95,7 +103,6 @@ ------------------------------------------------------------------------ -- Closures- type Closure = GenClosure Box -- | This is the representation of a Haskell value on the heap. It reflects@@ -354,8 +361,110 @@ | UnsupportedClosure { info :: !StgInfoTable }++ -- | A primitive word from a bitmap encoded stack frame payload+ --+ -- The type itself cannot be restored (i.e. it might represent a Word8#+ -- or an Int#).+ | UnknownTypeWordSizedPrimitive+ { wordVal :: !Word } deriving (Show, Generic, Functor, Foldable, Traversable) +type StgStackClosure = GenStgStackClosure Box++-- | A decoded @StgStack@ with `StackFrame`s+--+-- Stack related data structures (`GenStgStackClosure`, `GenStackField`,+-- `GenStackFrame`) are defined separately from `GenClosure` as their related+-- functions are very different. Though, both are closures in the sense of RTS+-- structures, their decoding logic differs: While it's safe to keep a reference+-- to a heap closure, the garbage collector does not update references to stack+-- located closures.+--+-- Additionally, stack frames don't appear outside of the stack. Thus, keeping+-- `GenStackFrame` and `GenClosure` separated, makes these types more precise+-- (in the sense what values to expect.)+data GenStgStackClosure b = GenStgStackClosure+ { ssc_info :: !StgInfoTable+ , ssc_stack_size :: !Word32 -- ^ stack size in *words*+ , ssc_stack :: ![GenStackFrame b]+ }+ deriving (Foldable, Functor, Generic, Show, Traversable)++type StackField = GenStackField Box++-- | Bitmap-encoded payload on the stack+data GenStackField b+ -- | A non-pointer field+ = StackWord !Word+ -- | A pointer field+ | StackBox !b+ deriving (Foldable, Functor, Generic, Show, Traversable)++type StackFrame = GenStackFrame Box++-- | A single stack frame+data GenStackFrame b =+ UpdateFrame+ { info_tbl :: !StgInfoTable+ , updatee :: !b+ }++ | CatchFrame+ { info_tbl :: !StgInfoTable+ , handler :: !b+ }++ | CatchStmFrame+ { info_tbl :: !StgInfoTable+ , catchFrameCode :: !b+ , handler :: !b+ }++ | CatchRetryFrame+ { info_tbl :: !StgInfoTable+ , running_alt_code :: !Word+ , first_code :: !b+ , alt_code :: !b+ }++ | AtomicallyFrame+ { info_tbl :: !StgInfoTable+ , atomicallyFrameCode :: !b+ , result :: !b+ }++ | UnderflowFrame+ { info_tbl :: !StgInfoTable+ , nextChunk :: !(GenStgStackClosure b)+ }++ | StopFrame+ { info_tbl :: !StgInfoTable }++ | RetSmall+ { info_tbl :: !StgInfoTable+ , stack_payload :: ![GenStackField b]+ }++ | RetBig+ { info_tbl :: !StgInfoTable+ , stack_payload :: ![GenStackField b]+ }++ | RetFun+ { info_tbl :: !StgInfoTable+ , retFunSize :: !Word+ , retFunFun :: !b+ , retFunPayload :: ![GenStackField b]+ }++ | RetBCO+ { info_tbl :: !StgInfoTable+ , bco :: !b -- ^ always a BCOClosure+ , bcoArgs :: ![GenStackField b]+ }+ deriving (Foldable, Functor, Generic, Show, Traversable) data PrimType = PInt
GHC/Exts/Heap/InfoTable/Types.hsc view
@@ -37,4 +37,4 @@ tipe :: ClosureType, srtlen :: HalfWord, code :: Maybe ItblCodes -- Just <=> TABLES_NEXT_TO_CODE- } deriving (Show, Generic)+ } deriving (Eq, Show, Generic)
+ GHC/Exts/Stack.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE CPP #-}+#if MIN_TOOL_VERSION_ghc(9,9,0)+{-# LANGUAGE RecordWildCards #-}++module GHC.Exts.Stack+ ( -- * Stack inspection+ decodeStack,+ stackFrameSize,+ )+where++import GHC.Exts.Heap.Closures+import GHC.Exts.Stack.Constants+import GHC.Exts.Stack.Decode+import Prelude++-- | Get the size of the `StackFrame` in words.+--+-- Includes header and payload. Does not follow pointers.+stackFrameSize :: StackFrame -> Int+stackFrameSize (UpdateFrame {}) = sizeStgUpdateFrame+stackFrameSize (CatchFrame {}) = sizeStgCatchFrame+stackFrameSize (CatchStmFrame {}) = sizeStgCatchSTMFrame+stackFrameSize (CatchRetryFrame {}) = sizeStgCatchRetryFrame+stackFrameSize (AtomicallyFrame {}) = sizeStgAtomicallyFrame+stackFrameSize (RetSmall {..}) = sizeStgClosure + length stack_payload+stackFrameSize (RetBig {..}) = sizeStgClosure + length stack_payload+stackFrameSize (RetFun {..}) = sizeStgRetFunFrame + length retFunPayload+-- The one additional word is a pointer to the StgBCO in the closure's payload+stackFrameSize (RetBCO {..}) = sizeStgClosure + 1 + length bcoArgs+-- The one additional word is a pointer to the next stack chunk+stackFrameSize (UnderflowFrame {}) = sizeStgClosure + 1+stackFrameSize _ = error "Unexpected stack frame type"++#else+module GHC.Exts.Stack where+#endif
+ GHC/Exts/Stack/Constants.hsc view
@@ -0,0 +1,126 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module GHC.Exts.Stack.Constants where++#if MIN_TOOL_VERSION_ghc(9,9,0)++import Prelude++#include "Rts.h"+#undef BLOCK_SIZE+#undef MBLOCK_SIZE+#undef BLOCKS_PER_MBLOCK+#include "DerivedConstants.h"++newtype ByteOffset = ByteOffset { offsetInBytes :: Int }+ deriving newtype (Eq, Show, Integral, Real, Num, Enum, Ord)++newtype WordOffset = WordOffset { offsetInWords :: Int }+ deriving newtype (Eq, Show, Integral, Real, Num, Enum, Ord)++offsetStgCatchFrameHandler :: WordOffset+offsetStgCatchFrameHandler = byteOffsetToWordOffset $+ (#const OFFSET_StgCatchFrame_handler) + (#size StgHeader)++sizeStgCatchFrame :: Int+sizeStgCatchFrame = bytesToWords $+ (#const SIZEOF_StgCatchFrame_NoHdr) + (#size StgHeader)++offsetStgCatchSTMFrameCode :: WordOffset+offsetStgCatchSTMFrameCode = byteOffsetToWordOffset $+ (#const OFFSET_StgCatchSTMFrame_code) + (#size StgHeader)++offsetStgCatchSTMFrameHandler :: WordOffset+offsetStgCatchSTMFrameHandler = byteOffsetToWordOffset $+ (#const OFFSET_StgCatchSTMFrame_handler) + (#size StgHeader)++sizeStgCatchSTMFrame :: Int+sizeStgCatchSTMFrame = bytesToWords $+ (#const SIZEOF_StgCatchSTMFrame_NoHdr) + (#size StgHeader)++offsetStgUpdateFrameUpdatee :: WordOffset+offsetStgUpdateFrameUpdatee = byteOffsetToWordOffset $+ (#const OFFSET_StgUpdateFrame_updatee) + (#size StgHeader)++sizeStgUpdateFrame :: Int+sizeStgUpdateFrame = bytesToWords $+ (#const SIZEOF_StgUpdateFrame_NoHdr) + (#size StgHeader)++offsetStgAtomicallyFrameCode :: WordOffset+offsetStgAtomicallyFrameCode = byteOffsetToWordOffset $+ (#const OFFSET_StgAtomicallyFrame_code) + (#size StgHeader)++offsetStgAtomicallyFrameResult :: WordOffset+offsetStgAtomicallyFrameResult = byteOffsetToWordOffset $+ (#const OFFSET_StgAtomicallyFrame_result) + (#size StgHeader)++sizeStgAtomicallyFrame :: Int+sizeStgAtomicallyFrame = bytesToWords $+ (#const SIZEOF_StgAtomicallyFrame_NoHdr) + (#size StgHeader)++offsetStgCatchRetryFrameRunningAltCode :: WordOffset+offsetStgCatchRetryFrameRunningAltCode = byteOffsetToWordOffset $+ (#const OFFSET_StgCatchRetryFrame_running_alt_code) + (#size StgHeader)++offsetStgCatchRetryFrameRunningFirstCode :: WordOffset+offsetStgCatchRetryFrameRunningFirstCode = byteOffsetToWordOffset $+ (#const OFFSET_StgCatchRetryFrame_first_code) + (#size StgHeader)++offsetStgCatchRetryFrameAltCode :: WordOffset+offsetStgCatchRetryFrameAltCode = byteOffsetToWordOffset $+ (#const OFFSET_StgCatchRetryFrame_alt_code) + (#size StgHeader)++sizeStgCatchRetryFrame :: Int+sizeStgCatchRetryFrame = bytesToWords $+ (#const SIZEOF_StgCatchRetryFrame_NoHdr) + (#size StgHeader)++offsetStgRetFunFrameSize :: WordOffset+-- StgRetFun has no header, but only a pointer to the info table at the beginning.+offsetStgRetFunFrameSize = byteOffsetToWordOffset (#const OFFSET_StgRetFun_size)++offsetStgRetFunFrameFun :: WordOffset+offsetStgRetFunFrameFun = byteOffsetToWordOffset (#const OFFSET_StgRetFun_fun)++offsetStgRetFunFramePayload :: WordOffset+offsetStgRetFunFramePayload = byteOffsetToWordOffset (#const OFFSET_StgRetFun_payload)++sizeStgRetFunFrame :: Int+sizeStgRetFunFrame = bytesToWords (#const SIZEOF_StgRetFun)++offsetStgBCOFrameInstrs :: ByteOffset+offsetStgBCOFrameInstrs = (#const OFFSET_StgBCO_instrs) + (#size StgHeader)++offsetStgBCOFrameLiterals :: ByteOffset+offsetStgBCOFrameLiterals = (#const OFFSET_StgBCO_literals) + (#size StgHeader)++offsetStgBCOFramePtrs :: ByteOffset+offsetStgBCOFramePtrs = (#const OFFSET_StgBCO_ptrs) + (#size StgHeader)++offsetStgBCOFrameArity :: ByteOffset+offsetStgBCOFrameArity = (#const OFFSET_StgBCO_arity) + (#size StgHeader)++offsetStgBCOFrameSize :: ByteOffset+offsetStgBCOFrameSize = (#const OFFSET_StgBCO_size) + (#size StgHeader)++offsetStgClosurePayload :: WordOffset+offsetStgClosurePayload = byteOffsetToWordOffset $+ (#const OFFSET_StgClosure_payload) + (#size StgHeader)++sizeStgClosure :: Int+sizeStgClosure = bytesToWords (#size StgHeader)++byteOffsetToWordOffset :: ByteOffset -> WordOffset+byteOffsetToWordOffset = WordOffset . bytesToWords . fromInteger . toInteger++bytesToWords :: Int -> Int+bytesToWords b =+ if b `mod` bytesInWord == 0 then+ fromIntegral $ b `div` bytesInWord+ else+ error "Unexpected struct alignment!"++bytesInWord :: Int+bytesInWord = (#const SIZEOF_VOID_P)++#endif
+ GHC/Exts/Stack/Decode.hs view
@@ -0,0 +1,431 @@+{-# LANGUAGE CPP #-}+#if MIN_TOOL_VERSION_ghc(9,9,0)+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GHCForeignImportPrim #-}+{-# LANGUAGE MagicHash #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE UnboxedTuples #-}+{-# LANGUAGE UnliftedFFITypes #-}++module GHC.Exts.Stack.Decode+ ( decodeStack,+ )+where++import Control.Monad+import Data.Bits+import Data.Maybe+import Foreign+import GHC.Exts+import GHC.Exts.Heap (Box (..))+import GHC.Exts.Heap.ClosureTypes+import GHC.Exts.Heap.Closures+ ( StackFrame,+ GenStackFrame (..),+ StgStackClosure,+ GenStgStackClosure (..),+ StackField,+ GenStackField(..)+ )+import GHC.Exts.Heap.Constants (wORD_SIZE_IN_BITS)+import GHC.Exts.Heap.InfoTable+import GHC.Exts.Stack.Constants+import GHC.Stack.CloneStack+import GHC.Word+import Prelude++{- Note [Decoding the stack]+ ~~~~~~~~~~~~~~~~~~~~~~~~~++The stack is represented by a chain of StgStack closures. Each of these closures+is subject to garbage collection. I.e. they can be moved in memory (in a+simplified perspective) at any time.++The array of closures inside an StgStack (that makeup the execution stack; the+stack frames) is moved as bare memory by the garbage collector. References+(pointers) to stack frames are not updated by the garbage collector.++As the StgStack closure is moved as whole, the relative offsets inside it stay+the same. (Though, the absolute addresses change!)++Decoding+========++Stack frames are defined by their `StackSnapshot#` (`StgStack*` in RTS) and+their relative offset. This tuple is described by `StackFrameLocation`.++`StackFrame` is an ADT for decoded stack frames. Regarding payload and fields we+have to deal with three cases:++- If the payload can only be a closure, we put it in a `Box` for later decoding+ by the heap closure functions.++- If the payload can either be a closure or a word-sized value (this happens for+ bitmap-encoded payloads), we use a `StackField` which is a sum type to+ represent either a `Word` or a `Box`.++- Fields that are just simple (i.e. non-closure) values are decoded as such.++The decoding happens in two phases:++1. The whole stack is decoded into `StackFrameLocation`s.++2. All `StackFrameLocation`s are decoded into `StackFrame`s.++`StackSnapshot#` parameters are updated by the garbage collector and thus safe+to hand around.++The head of the stack frame array has offset (index) 0. To traverse the stack+frames the latest stack frame's offset is incremented by the closure size. The+unit of the offset is machine words (32bit or 64bit.)++IO+==++Unfortunately, ghc-heap decodes `Closure`s in `IO`. This leads to `StackFrames`+also being decoded in `IO`, due to references to `Closure`s.++Technical details+=================++- All access to StgStack/StackSnapshot# closures is made through Cmm code. This+ keeps the closure from being moved by the garbage collector during the+ operation.++- As StgStacks are mainly used in Cmm and C code, much of the decoding logic is+ implemented in Cmm and C. It's just easier to reuse existing helper macros and+ functions, than reinventing them in Haskell.++- Offsets and sizes of closures are imported from DerivedConstants.h via HSC.+ This keeps the code very portable.+-}++foreign import prim "getUnderflowFrameNextChunkzh"+ getUnderflowFrameNextChunk# ::+ StackSnapshot# -> Word# -> StackSnapshot#++getUnderflowFrameNextChunk :: StackSnapshot# -> WordOffset -> StackSnapshot+getUnderflowFrameNextChunk stackSnapshot# index =+ StackSnapshot (getUnderflowFrameNextChunk# stackSnapshot# (wordOffsetToWord# index))++foreign import prim "getWordzh"+ getWord# ::+ StackSnapshot# -> Word# -> Word#++getWord :: StackSnapshot# -> WordOffset -> Word+getWord stackSnapshot# index =+ W# (getWord# stackSnapshot# (wordOffsetToWord# index))++foreign import prim "isArgGenBigRetFunTypezh" isArgGenBigRetFunType# :: StackSnapshot# -> Word# -> Int#++isArgGenBigRetFunType :: StackSnapshot# -> WordOffset -> Bool+isArgGenBigRetFunType stackSnapshot# index =+ I# (isArgGenBigRetFunType# stackSnapshot# (wordOffsetToWord# index)) > 0++-- | Gets contents of a `LargeBitmap` (@StgLargeBitmap@)+--+-- The first two arguments identify the location of the frame on the stack.+-- Returned is the `Addr#` of the @StgWord[]@ (bitmap) and it's size.+type LargeBitmapGetter = StackSnapshot# -> Word# -> (# Addr#, Word# #)++foreign import prim "getLargeBitmapzh" getLargeBitmap# :: LargeBitmapGetter++foreign import prim "getBCOLargeBitmapzh" getBCOLargeBitmap# :: LargeBitmapGetter++foreign import prim "getRetFunLargeBitmapzh" getRetFunLargeBitmap# :: LargeBitmapGetter++-- | Gets contents of a small bitmap (fitting in one @StgWord@)+--+-- The first two arguments identify the location of the frame on the stack.+-- Returned is the bitmap and it's size.+type SmallBitmapGetter = StackSnapshot# -> Word# -> (# Word#, Word# #)++foreign import prim "getSmallBitmapzh" getSmallBitmap# :: SmallBitmapGetter++foreign import prim "getRetFunSmallBitmapzh" getRetFunSmallBitmap# :: SmallBitmapGetter++foreign import prim "getInfoTableAddrzh" getInfoTableAddr# :: StackSnapshot# -> Word# -> Addr#++foreign import prim "getStackInfoTableAddrzh" getStackInfoTableAddr# :: StackSnapshot# -> Addr#++getInfoTableOnStack :: StackSnapshot# -> WordOffset -> IO StgInfoTable+getInfoTableOnStack stackSnapshot# index =+ let infoTablePtr = Ptr (getInfoTableAddr# stackSnapshot# (wordOffsetToWord# index))+ in peekItbl infoTablePtr++getInfoTableForStack :: StackSnapshot# -> IO StgInfoTable+getInfoTableForStack stackSnapshot# =+ peekItbl $+ Ptr (getStackInfoTableAddr# stackSnapshot#)++foreign import prim "getStackClosurezh"+ getStackClosure# ::+ StackSnapshot# -> Word# -> Any++foreign import prim "getStackFieldszh"+ getStackFields# ::+ StackSnapshot# -> Word32#++getStackFields :: StackSnapshot# -> Word32+getStackFields stackSnapshot# =+ case getStackFields# stackSnapshot# of+ sSize# -> W32# sSize#++-- | `StackFrameLocation` of the top-most stack frame+stackHead :: StackSnapshot# -> StackFrameLocation+stackHead s# = (StackSnapshot s#, 0) -- GHC stacks are never empty++-- | Advance to the next stack frame (if any)+--+-- The last `Int#` in the result tuple is meant to be treated as bool+-- (has_next).+foreign import prim "advanceStackFrameLocationzh"+ advanceStackFrameLocation# ::+ StackSnapshot# -> Word# -> (# StackSnapshot#, Word#, Int# #)++-- | Advance to the next stack frame (if any)+advanceStackFrameLocation :: StackFrameLocation -> Maybe StackFrameLocation+advanceStackFrameLocation ((StackSnapshot stackSnapshot#), index) =+ let !(# s', i', hasNext #) = advanceStackFrameLocation# stackSnapshot# (wordOffsetToWord# index)+ in if I# hasNext > 0+ then Just (StackSnapshot s', primWordToWordOffset i')+ else Nothing+ where+ primWordToWordOffset :: Word# -> WordOffset+ primWordToWordOffset w# = fromIntegral (W# w#)++getClosureBox :: StackSnapshot# -> WordOffset -> Box+getClosureBox stackSnapshot# index =+ case getStackClosure# stackSnapshot# (wordOffsetToWord# index) of+ -- c needs to be strictly evaluated, otherwise a thunk gets boxed (and+ -- will later be decoded as such)+ !c -> Box c++-- | Representation of @StgLargeBitmap@ (RTS)+data LargeBitmap = LargeBitmap+ { largeBitmapSize :: Word,+ largebitmapWords :: Ptr Word+ }++-- | Is a bitmap entry a closure pointer or a primitive non-pointer?+data Pointerness = Pointer | NonPointer+ deriving (Show)++decodeLargeBitmap :: LargeBitmapGetter -> StackSnapshot# -> WordOffset -> WordOffset -> IO [StackField]+decodeLargeBitmap getterFun# stackSnapshot# index relativePayloadOffset = do+ let largeBitmap = case getterFun# stackSnapshot# (wordOffsetToWord# index) of+ (# wordsAddr#, size# #) -> LargeBitmap (W# size#) (Ptr wordsAddr#)+ bitmapWords <- largeBitmapToList largeBitmap+ pure $ decodeBitmaps+ stackSnapshot#+ (index + relativePayloadOffset)+ (bitmapWordsPointerness (largeBitmapSize largeBitmap) bitmapWords)+ where+ largeBitmapToList :: LargeBitmap -> IO [Word]+ largeBitmapToList LargeBitmap {..} =+ cWordArrayToList largebitmapWords $+ (usedBitmapWords . fromIntegral) largeBitmapSize++ cWordArrayToList :: Ptr Word -> Int -> IO [Word]+ cWordArrayToList ptr size = mapM (peekElemOff ptr) [0 .. (size - 1)]++ usedBitmapWords :: Int -> Int+ usedBitmapWords 0 = error "Invalid large bitmap size 0."+ usedBitmapWords size = (size `div` fromIntegral wORD_SIZE_IN_BITS) + 1++ bitmapWordsPointerness :: Word -> [Word] -> [Pointerness]+ bitmapWordsPointerness size _ | size <= 0 = []+ bitmapWordsPointerness _ [] = []+ bitmapWordsPointerness size (w : wds) =+ bitmapWordPointerness (min size (fromIntegral wORD_SIZE_IN_BITS)) w+ ++ bitmapWordsPointerness (size - fromIntegral wORD_SIZE_IN_BITS) wds++bitmapWordPointerness :: Word -> Word -> [Pointerness]+bitmapWordPointerness 0 _ = []+bitmapWordPointerness bSize bitmapWord =+ ( if (bitmapWord .&. 1) /= 0+ then NonPointer+ else Pointer+ )+ : bitmapWordPointerness+ (bSize - 1)+ (bitmapWord `shiftR` 1)++decodeBitmaps :: StackSnapshot# -> WordOffset -> [Pointerness] -> [StackField]+decodeBitmaps stack# index ps =+ zipWith toPayload ps [index ..]+ where+ toPayload :: Pointerness -> WordOffset -> StackField+ toPayload p i = case p of+ NonPointer -> StackWord (getWord stack# i)+ Pointer -> StackBox (getClosureBox stack# i)++decodeSmallBitmap :: SmallBitmapGetter -> StackSnapshot# -> WordOffset -> WordOffset -> [StackField]+decodeSmallBitmap getterFun# stackSnapshot# index relativePayloadOffset =+ let (bitmap, size) = case getterFun# stackSnapshot# (wordOffsetToWord# index) of+ (# b#, s# #) -> (W# b#, W# s#)+ in decodeBitmaps+ stackSnapshot#+ (index + relativePayloadOffset)+ (bitmapWordPointerness size bitmap)++unpackStackFrame :: StackFrameLocation -> IO StackFrame+unpackStackFrame (StackSnapshot stackSnapshot#, index) = do+ info <- getInfoTableOnStack stackSnapshot# index+ unpackStackFrame' info+ where+ unpackStackFrame' :: StgInfoTable -> IO StackFrame+ unpackStackFrame' info =+ case tipe info of+ RET_BCO -> do+ let bco' = getClosureBox stackSnapshot# (index + offsetStgClosurePayload)+ -- The arguments begin directly after the payload's one element+ bcoArgs' <- decodeLargeBitmap getBCOLargeBitmap# stackSnapshot# index (offsetStgClosurePayload + 1)+ pure+ RetBCO+ { info_tbl = info,+ bco = bco',+ bcoArgs = bcoArgs'+ }+ RET_SMALL ->+ let payload' = decodeSmallBitmap getSmallBitmap# stackSnapshot# index offsetStgClosurePayload+ in+ pure $+ RetSmall+ { info_tbl = info,+ stack_payload = payload'+ }+ RET_BIG -> do+ payload' <- decodeLargeBitmap getLargeBitmap# stackSnapshot# index offsetStgClosurePayload+ pure $+ RetBig+ { info_tbl = info,+ stack_payload = payload'+ }+ RET_FUN -> do+ let retFunSize' = getWord stackSnapshot# (index + offsetStgRetFunFrameSize)+ retFunFun' = getClosureBox stackSnapshot# (index + offsetStgRetFunFrameFun)+ retFunPayload' <-+ if isArgGenBigRetFunType stackSnapshot# index == True+ then decodeLargeBitmap getRetFunLargeBitmap# stackSnapshot# index offsetStgRetFunFramePayload+ else pure $ decodeSmallBitmap getRetFunSmallBitmap# stackSnapshot# index offsetStgRetFunFramePayload+ pure $+ RetFun+ { info_tbl = info,+ retFunSize = retFunSize',+ retFunFun = retFunFun',+ retFunPayload = retFunPayload'+ }+ UPDATE_FRAME ->+ let updatee' = getClosureBox stackSnapshot# (index + offsetStgUpdateFrameUpdatee)+ in+ pure $+ UpdateFrame+ { info_tbl = info,+ updatee = updatee'+ }+ CATCH_FRAME -> do+ let handler' = getClosureBox stackSnapshot# (index + offsetStgCatchFrameHandler)+ pure $+ CatchFrame+ { info_tbl = info,+ handler = handler'+ }+ UNDERFLOW_FRAME -> do+ let nextChunk' = getUnderflowFrameNextChunk stackSnapshot# index+ stackClosure <- decodeStack nextChunk'+ pure $+ UnderflowFrame+ { info_tbl = info,+ nextChunk = stackClosure+ }+ STOP_FRAME -> pure $ StopFrame {info_tbl = info}+ ATOMICALLY_FRAME -> do+ let atomicallyFrameCode' = getClosureBox stackSnapshot# (index + offsetStgAtomicallyFrameCode)+ result' = getClosureBox stackSnapshot# (index + offsetStgAtomicallyFrameResult)+ pure $+ AtomicallyFrame+ { info_tbl = info,+ atomicallyFrameCode = atomicallyFrameCode',+ result = result'+ }+ CATCH_RETRY_FRAME ->+ let running_alt_code' = getWord stackSnapshot# (index + offsetStgCatchRetryFrameRunningAltCode)+ first_code' = getClosureBox stackSnapshot# (index + offsetStgCatchRetryFrameRunningFirstCode)+ alt_code' = getClosureBox stackSnapshot# (index + offsetStgCatchRetryFrameAltCode)+ in+ pure $+ CatchRetryFrame+ { info_tbl = info,+ running_alt_code = running_alt_code',+ first_code = first_code',+ alt_code = alt_code'+ }+ CATCH_STM_FRAME ->+ let catchFrameCode' = getClosureBox stackSnapshot# (index + offsetStgCatchSTMFrameCode)+ handler' = getClosureBox stackSnapshot# (index + offsetStgCatchSTMFrameHandler)+ in+ pure $+ CatchStmFrame+ { info_tbl = info,+ catchFrameCode = catchFrameCode',+ handler = handler'+ }+ x -> error $ "Unexpected closure type on stack: " ++ show x++-- | Unbox 'Int#' from 'Int'+toInt# :: Int -> Int#+toInt# (I# i) = i++-- | Convert `Int` to `Word#`+intToWord# :: Int -> Word#+intToWord# i = int2Word# (toInt# i)++wordOffsetToWord# :: WordOffset -> Word#+wordOffsetToWord# wo = intToWord# (fromIntegral wo)++-- | Location of a stackframe on the stack+--+-- It's defined by the `StackSnapshot` (@StgStack@) and the offset to the bottom+-- of the stack.+type StackFrameLocation = (StackSnapshot, WordOffset)++-- | Decode `StackSnapshot` to a `StgStackClosure`+--+-- The return value is the representation of the @StgStack@ itself.+--+-- See /Note [Decoding the stack]/.+decodeStack :: StackSnapshot -> IO StgStackClosure+decodeStack (StackSnapshot stack#) = do+ info <- getInfoTableForStack stack#+ case tipe info of+ STACK -> do+ let stack_size' = getStackFields stack#+ sfls = stackFrameLocations stack#+ stack' <- mapM unpackStackFrame sfls+ pure $+ GenStgStackClosure+ { ssc_info = info,+ ssc_stack_size = stack_size',+ ssc_stack = stack'+ }+ _ -> error $ "Expected STACK closure, got " ++ show info+ where+ stackFrameLocations :: StackSnapshot# -> [StackFrameLocation]+ stackFrameLocations s# =+ stackHead s#+ : go (advanceStackFrameLocation (stackHead s#))+ where+ go :: Maybe StackFrameLocation -> [StackFrameLocation]+ go Nothing = []+ go (Just r) = r : go (advanceStackFrameLocation r)++#else+module GHC.Exts.Stack.Decode where+#endif
+ cbits/Stack.cmm view
@@ -0,0 +1,182 @@+// Uncomment to enable assertions during development+// #define DEBUG 1++#include "Cmm.h"++// StgStack_marking was not available in the Stage0 compiler at the time of+// writing. Because, it has been added to derivedConstants when Stack.cmm was+// developed.+#if defined(StgStack_marking)++// Returns the next stackframe's StgStack* and offset in it. And, an indicator+// if this frame is the last one (`hasNext` bit.)+// (StgStack*, StgWord, StgWord) advanceStackFrameLocationzh(StgStack* stack, StgWord offsetWords)+advanceStackFrameLocationzh (P_ stack, W_ offsetWords) {+ W_ frameSize;+ (frameSize) = ccall stackFrameSize(stack, offsetWords);++ P_ nextClosurePtr;+ nextClosurePtr = (StgStack_sp(stack) + WDS(offsetWords) + WDS(frameSize));++ P_ stackArrayPtr;+ stackArrayPtr = stack + SIZEOF_StgHeader + OFFSET_StgStack_stack;++ P_ stackBottom;+ W_ stackSize, stackSizeInBytes;+ stackSize = TO_W_(StgStack_stack_size(stack));+ stackSizeInBytes = WDS(stackSize);+ stackBottom = stackSizeInBytes + stackArrayPtr;++ P_ newStack;+ W_ newOffsetWords, hasNext;+ if(nextClosurePtr < stackBottom) (likely: True) {+ newStack = stack;+ newOffsetWords = offsetWords + frameSize;+ hasNext = 1;+ } else {+ P_ underflowFrameStack;+ (underflowFrameStack) = ccall getUnderflowFrameStack(stack, offsetWords);+ if (underflowFrameStack == NULL) (likely: True) {+ newStack = NULL;+ newOffsetWords = NULL;+ hasNext = NULL;+ } else {+ newStack = underflowFrameStack;+ newOffsetWords = NULL;+ hasNext = 1;+ }+ }++ return (newStack, newOffsetWords, hasNext);+}++// (StgWord, StgWord) getSmallBitmapzh(StgStack* stack, StgWord offsetWords)+getSmallBitmapzh(P_ stack, W_ offsetWords) {+ P_ c;+ c = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ W_ bitmap, size;+ (bitmap) = ccall getBitmapWord(c);+ (size) = ccall getBitmapSize(c);++ return (bitmap, size);+}+++// (StgWord, StgWord) getRetFunSmallBitmapzh(StgStack* stack, StgWord offsetWords)+getRetFunSmallBitmapzh(P_ stack, W_ offsetWords) {+ P_ c;+ c = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ W_ bitmap, size, specialType;+ (bitmap) = ccall getRetFunBitmapWord(c);+ (size) = ccall getRetFunBitmapSize(c);++ return (bitmap, size);+}++// (StgWord*, StgWord) getLargeBitmapzh(StgStack* stack, StgWord offsetWords)+getLargeBitmapzh(P_ stack, W_ offsetWords) {+ P_ c, words;+ W_ size;+ c = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ (words) = ccall getLargeBitmap(MyCapability(), c);+ (size) = ccall getLargeBitmapSize(c);++ return (words, size);+}++// (StgWord*, StgWord) getBCOLargeBitmapzh(StgStack* stack, StgWord offsetWords)+getBCOLargeBitmapzh(P_ stack, W_ offsetWords) {+ P_ c, words;+ W_ size;+ c = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ (words) = ccall getBCOLargeBitmap(MyCapability(), c);+ (size) = ccall getBCOLargeBitmapSize(c);++ return (words, size);+}++// (StgWord*, StgWord) getRetFunLargeBitmapzh(StgStack* stack, StgWord offsetWords)+getRetFunLargeBitmapzh(P_ stack, W_ offsetWords) {+ P_ c, words;+ W_ size;+ c = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ (words) = ccall getRetFunLargeBitmap(MyCapability(), c);+ (size) = ccall getRetFunSize(c);++ return (words, size);+}++// (StgWord) getWordzh(StgStack* stack, StgWord offsetWords)+getWordzh(P_ stack, W_ offsetWords) {+ P_ wordAddr;+ wordAddr = (StgStack_sp(stack) + WDS(offsetWords));+ return (W_[wordAddr]);+}++// (StgStack*) getUnderflowFrameNextChunkzh(StgStack* stack, StgWord offsetWords)+getUnderflowFrameNextChunkzh(P_ stack, W_ offsetWords) {+ P_ closurePtr;+ closurePtr = (StgStack_sp(stack) + WDS(offsetWords));+ ASSERT(LOOKS_LIKE_CLOURE_PTR(closurePtr));++ P_ next_chunk;+ (next_chunk) = ccall getUnderflowFrameNextChunk(closurePtr);+ ASSERT(LOOKS_LIKE_CLOURE_PTR(next_chunk));+ return (next_chunk);+}++// (StgWord) getRetFunTypezh(StgStack* stack, StgWord offsetWords)+isArgGenBigRetFunTypezh(P_ stack, W_ offsetWords) {+ P_ c;+ c = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ W_ type;+ (type) = ccall isArgGenBigRetFunType(c);+ return (type);+}++// (StgInfoTable*) getInfoTableAddrzh(StgStack* stack, StgWord offsetWords)+getInfoTableAddrzh(P_ stack, W_ offsetWords) {+ P_ p, info;+ p = StgStack_sp(stack) + WDS(offsetWords);+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(p));+ info = %GET_STD_INFO(UNTAG(p));++ return (info);+}++// (StgInfoTable*) getStackInfoTableAddrzh(StgStack* stack)+getStackInfoTableAddrzh(P_ stack) {+ P_ info;+ info = %GET_STD_INFO(UNTAG(stack));+ return (info);+}++// (StgClosure*) getStackClosurezh(StgStack* stack, StgWord offsetWords)+getStackClosurezh(P_ stack, W_ offsetWords) {+ P_ ptr;+ ptr = StgStack_sp(stack) + WDS(offsetWords);++ P_ closure;+ (closure) = ccall getStackClosure(ptr);+ return (closure);+}++// (bits32) getStackFieldszh(StgStack* stack)+getStackFieldszh(P_ stack){+ bits32 size;+ size = StgStack_stack_size(stack);+ return (size);+}+#endif
+ cbits/Stack_c.c view
@@ -0,0 +1,151 @@+#include "MachDeps.h"+#include "Rts.h"+#include "RtsAPI.h"+#include "rts/Messages.h"+#include "rts/Types.h"+#include "rts/storage/ClosureTypes.h"+#include "rts/storage/Closures.h"+#include "rts/storage/FunTypes.h"+#include "rts/storage/InfoTables.h"++StgWord stackFrameSize(StgStack *stack, StgWord offset) {+ StgClosure *c = (StgClosure *)stack->sp + offset;+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));+ return stack_frame_sizeW(c);+}++StgStack *getUnderflowFrameStack(StgStack *stack, StgWord offset) {+ StgClosure *frame = (StgClosure *)stack->sp + offset;+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(frame));+ const StgRetInfoTable *info = get_ret_itbl((StgClosure *)frame);++ if (info->i.type == UNDERFLOW_FRAME) {+ return ((StgUnderflowFrame *)frame)->next_chunk;+ } else {+ return NULL;+ }+}++// Only exists to make the get_itbl macro available in Haskell code (via FFI).+const StgInfoTable *getItbl(StgClosure *closure) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(closure));+ return get_itbl(closure);+};++StgWord getBitmapSize(StgClosure *c) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ const StgInfoTable *info = get_itbl(c);+ StgWord bitmap = info->layout.bitmap;+ return BITMAP_SIZE(bitmap);+}++StgWord getRetFunBitmapSize(StgRetFun *ret_fun) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(ret_fun));++ const StgFunInfoTable *fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ switch (fun_info->f.fun_type) {+ case ARG_GEN:+ return BITMAP_SIZE(fun_info->f.b.bitmap);+ case ARG_GEN_BIG:+ return GET_FUN_LARGE_BITMAP(fun_info)->size;+ default:+ return BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);+ }+}++StgWord getBitmapWord(StgClosure *c) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ const StgInfoTable *info = get_itbl(c);+ StgWord bitmap = info->layout.bitmap;+ StgWord bitmapWord = BITMAP_BITS(bitmap);+ return bitmapWord;+}++StgWord getRetFunBitmapWord(StgRetFun *ret_fun) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(ret_fun));++ const StgFunInfoTable *fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ switch (fun_info->f.fun_type) {+ case ARG_GEN:+ return BITMAP_BITS(fun_info->f.b.bitmap);+ case ARG_GEN_BIG:+ // Cannot do more than warn and exit.+ errorBelch("Unexpected ARG_GEN_BIG StgRetFun closure %p", ret_fun);+ stg_exit(EXIT_INTERNAL_ERROR);+ default:+ return BITMAP_BITS(stg_arg_bitmaps[fun_info->f.fun_type]);+ }+}++StgWord getLargeBitmapSize(StgClosure *c) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ const StgInfoTable *info = get_itbl(c);+ StgLargeBitmap *bitmap = GET_LARGE_BITMAP(info);+ return bitmap->size;+}++StgWord getRetFunSize(StgRetFun *ret_fun) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(ret_fun));++ const StgFunInfoTable *fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ switch (fun_info->f.fun_type) {+ case ARG_GEN:+ return BITMAP_SIZE(fun_info->f.b.bitmap);+ case ARG_GEN_BIG:+ return GET_FUN_LARGE_BITMAP(fun_info)->size;+ default:+ return BITMAP_SIZE(stg_arg_bitmaps[fun_info->f.fun_type]);+ }+}++StgWord getBCOLargeBitmapSize(StgClosure *c) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ StgBCO *bco = (StgBCO *)*c->payload;++ return BCO_BITMAP_SIZE(bco);+}++StgWord *getLargeBitmap(Capability *cap, StgClosure *c) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));+ const StgInfoTable *info = get_itbl(c);+ StgLargeBitmap *bitmap = GET_LARGE_BITMAP(info);++ return bitmap->bitmap;+}++StgWord *getRetFunLargeBitmap(Capability *cap, StgRetFun *ret_fun) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(ret_fun));++ const StgFunInfoTable *fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ StgLargeBitmap *bitmap = GET_FUN_LARGE_BITMAP(fun_info);++ return bitmap->bitmap;+}++StgWord *getBCOLargeBitmap(Capability *cap, StgClosure *c) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(c));++ StgBCO *bco = (StgBCO *)*c->payload;+ StgLargeBitmap *bitmap = BCO_BITMAP(bco);++ return bitmap->bitmap;+}++StgStack *getUnderflowFrameNextChunk(StgUnderflowFrame *frame) {+ return frame->next_chunk;+}++StgWord isArgGenBigRetFunType(StgRetFun *ret_fun) {+ ASSERT(LOOKS_LIKE_CLOSURE_PTR(ret_fun));++ const StgFunInfoTable *fun_info = get_fun_itbl(UNTAG_CLOSURE(ret_fun->fun));+ return fun_info->f.fun_type == ARG_GEN_BIG;+}++StgClosure *getStackClosure(StgClosure **c) { return *c; }
ghc-heap.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: ghc-heap-version: 9.8.1+version: 9.10.1 license: BSD-3-Clause license-file: LICENSE maintainer: libraries@haskell.org@@ -25,11 +25,16 @@ build-depends: base >= 4.9.0 && < 5.0 , ghc-prim > 0.2 && < 0.12 , rts == 1.0.*- , containers >= 0.6.2.1 && < 0.7+ , containers >= 0.6.2.1 && < 0.8 + if impl(ghc >= 9.9)+ build-depends: ghc-internal >= 9.1001 && < 9.1002+ ghc-options: -Wall if !os(ghcjs) cmm-sources: cbits/HeapPrim.cmm+ cbits/Stack.cmm+ c-sources: cbits/Stack_c.c default-extensions: NoImplicitPrelude @@ -48,3 +53,6 @@ GHC.Exts.Heap.ProfInfo.PeekProfInfo GHC.Exts.Heap.ProfInfo.PeekProfInfo_ProfilingDisabled GHC.Exts.Heap.ProfInfo.PeekProfInfo_ProfilingEnabled+ GHC.Exts.Stack.Constants+ GHC.Exts.Stack+ GHC.Exts.Stack.Decode