summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSven Tennie <sven.tennie@gmail.com>2023-05-05 19:53:54 +0000
committerSven Tennie <sven.tennie@gmail.com>2023-05-05 19:59:53 +0000
commit2f714b698664045e77476905517120f27c0aee30 (patch)
tree30c22c6ed0796ec33c7169e327ef0a16953d53b6
parentfce1eec46191b09e7b538e1388dbabe96622dfe4 (diff)
downloadhaskell-2f714b698664045e77476905517120f27c0aee30.tar.gz
Improve docs
-rw-r--r--libraries/ghc-heap/GHC/Exts/Heap/Closures.hs28
-rw-r--r--libraries/ghc-heap/GHC/Exts/Stack/Decode.hs35
2 files changed, 30 insertions, 33 deletions
diff --git a/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs b/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
index 33ed9e57f5..568c2bf2b1 100644
--- a/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
+++ b/libraries/ghc-heap/GHC/Exts/Heap/Closures.hs
@@ -371,15 +371,20 @@ data GenClosure b
{ wordVal :: !Word }
deriving (Show, Generic, Functor, Foldable, Traversable)
--- | A decoded @StgStack@ with `StackFrame`s
---
--- This is separate from its `Closure` incarnation, as unification would
--- require two kinds of boxes for bitmap encoded stack content: One for
--- primitives and one for closures. This turned out to be a nightmare with lots
--- of pattern matches and leaking data structures to enable access to primitives
--- on the stack...
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*
@@ -387,16 +392,17 @@ data GenStgStackClosure b = GenStgStackClosure
, ssc_stack_marking :: !Word8
, ssc_stack :: ![GenStackFrame b]
}
- deriving (Show, Generic)
+ 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 (Show, Generic)
+ deriving (Foldable, Functor, Generic, Show, Traversable)
type StackFrame = GenStackFrame Box
@@ -460,10 +466,10 @@ data GenStackFrame b =
| RetBCO
{ info_tbl :: !StgInfoTable
- , bco :: !b -- is always a BCOClosure
+ , bco :: !b -- ^ always a BCOClosure
, bcoArgs :: ![GenStackField b]
}
- deriving (Show, Generic)
+ deriving (Foldable, Functor, Generic, Show, Traversable)
-- | Fun types according to @FunTypes.h@
-- This `Enum` must be aligned with the values in @FunTypes.h@.
diff --git a/libraries/ghc-heap/GHC/Exts/Stack/Decode.hs b/libraries/ghc-heap/GHC/Exts/Stack/Decode.hs
index 9c90cfdb87..9034db6de7 100644
--- a/libraries/ghc-heap/GHC/Exts/Stack/Decode.hs
+++ b/libraries/ghc-heap/GHC/Exts/Stack/Decode.hs
@@ -57,21 +57,28 @@ 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. Where it points to heap located
-closures or primitive Words (in bitmap encoded payloads), `Closure` is used to
-describe the referenced payload.
+`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 which have
-`Closure`s as fields/references.
+2. All `StackFrameLocation`s are decoded into `StackFrame`s.
`StackSnapshot#` parameters are updated by the garbage collector and thus safe
to hand around.
@@ -80,22 +87,6 @@ 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.)
-Boxes
-=====
-
-`Closure` makes extensive usage of `Box`es. Unfortunately, we cannot simply apply the
-same here:
-
-- Bitmap encoded payloads can be either words or closure pointers.
-
-- Underflow frames point to `StgStack` closures.
-
-These three cases are hard to encode in boxes. Additionally, introducing new box
-types would break existing box usages. Thus, the stack is decoded unboxed, while
-the referenced `Closure`s use boxes. This seems to be a good compromise between
-optimization (with boxes) and simplicity (by leaving out the mentioned special
-cases.)
-
IO
==