2c9cb32ec0a0bd3ec72f8918c536721945a35336
[ghc.git] / compiler / cmm / SMRep.lhs
1 %
2 % (c) The University of Glasgow 2006
3 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 %
5
6 Storage manager representation of closures
7
8 This is here, rather than in ClosureInfo, just to keep nhc happy.
9 Other modules should access this info through ClosureInfo.
10
11 \begin{code}
12 module SMRep (
13         -- * Words and bytes
14         StgWord, StgHalfWord,
15         hALF_WORD_SIZE, hALF_WORD_SIZE_IN_BITS,
16         WordOff, ByteOff,
17         roundUpToWords,
18
19         -- * Closure repesentation
20         SMRep(..), -- CmmInfo sees the rep; no one else does
21         IsStatic,
22         ClosureTypeInfo(..), ArgDescr(..), Liveness,
23         ConstrDescription,
24
25         -- ** Construction
26         mkHeapRep, blackHoleRep, mkStackRep, mkRTSRep,
27
28         -- ** Predicates
29         isStaticRep, isConRep, isThunkRep, isFunRep, isStaticNoCafCon,
30
31         -- ** Size-related things
32         heapClosureSize,
33         fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize,
34         profHdrSize, thunkHdrSize, nonHdrSize,
35
36         -- ** RTS closure types
37         rtsClosureType, rET_SMALL, rET_BIG,
38         aRG_GEN, aRG_GEN_BIG,
39
40         -- * Operations over [Word8] strings that don't belong here
41         pprWord8String, stringToWord8s
42     ) where
43
44 #include "../HsVersions.h"
45 #include "../includes/MachDeps.h"
46
47 import DynFlags
48 import Outputable
49 import FastString
50
51 import Data.Char( ord )
52 import Data.Word
53 import Data.Bits
54 \end{code}
55
56
57 %************************************************************************
58 %*                                                                      *
59                 Words and bytes
60 %*                                                                      *
61 %************************************************************************
62
63 \begin{code}
64 type WordOff = Int -- Word offset, or word count
65 type ByteOff = Int -- Byte offset, or byte count
66
67 roundUpToWords :: DynFlags -> ByteOff -> ByteOff
68 roundUpToWords dflags n = (n + (wORD_SIZE dflags - 1)) .&. (complement (wORD_SIZE dflags - 1))
69 \end{code}
70
71 StgWord is a type representing an StgWord on the target platform.
72
73 \begin{code}
74 #if SIZEOF_HSWORD == 4
75 type StgWord     = Word32
76 type StgHalfWord = Word16
77 hALF_WORD_SIZE :: ByteOff
78 hALF_WORD_SIZE = 2
79 hALF_WORD_SIZE_IN_BITS :: Int
80 hALF_WORD_SIZE_IN_BITS = 16
81 #elif SIZEOF_HSWORD == 8
82 type StgWord     = Word64
83 type StgHalfWord = Word32
84 hALF_WORD_SIZE :: ByteOff
85 hALF_WORD_SIZE = 4
86 hALF_WORD_SIZE_IN_BITS :: Int
87 hALF_WORD_SIZE_IN_BITS = 32
88 #else
89 #error unknown SIZEOF_HSWORD
90 #endif
91 \end{code}
92
93
94 %************************************************************************
95 %*                                                                      *
96 \subsubsection[SMRep-datatype]{@SMRep@---storage manager representation}
97 %*                                                                      *
98 %************************************************************************
99
100 \begin{code}
101 -- | A description of the layout of a closure.  Corresponds directly
102 -- to the closure types in includes/rts/storage/ClosureTypes.h.
103 data SMRep
104   = HeapRep              -- GC routines consult sizes in info tbl
105         IsStatic
106         !WordOff         --  # ptr words
107         !WordOff         --  # non-ptr words INCLUDING SLOP (see mkHeapRep below)
108         ClosureTypeInfo  -- type-specific info
109
110   | StackRep            -- Stack frame (RET_SMALL or RET_BIG)
111         Liveness
112
113   | RTSRep              -- The RTS needs to declare info tables with specific
114         StgHalfWord     -- type tags, so this form lets us override the default
115         SMRep           -- tag for an SMRep.
116
117 -- | True <=> This is a static closure.  Affects how we garbage-collect it.
118 -- Static closure have an extra static link field at the end.
119 type IsStatic = Bool
120
121 -- From an SMRep you can get to the closure type defined in
122 -- includes/rts/storage/ClosureTypes.h. Described by the function
123 -- rtsClosureType below.
124
125 data ClosureTypeInfo
126   = Constr        ConstrTag ConstrDescription
127   | Fun           FunArity ArgDescr
128   | Thunk
129   | ThunkSelector SelectorOffset
130   | BlackHole
131
132 type ConstrTag         = StgHalfWord
133 type ConstrDescription = [Word8] -- result of dataConIdentity
134 type FunArity          = StgHalfWord
135 type SelectorOffset    = StgWord
136
137 -------------------------
138 -- We represent liveness bitmaps as a Bitmap (whose internal
139 -- representation really is a bitmap).  These are pinned onto case return
140 -- vectors to indicate the state of the stack for the garbage collector.
141 --
142 -- In the compiled program, liveness bitmaps that fit inside a single
143 -- word (StgWord) are stored as a single word, while larger bitmaps are
144 -- stored as a pointer to an array of words.
145
146 type Liveness = [Bool]   -- One Bool per word; True  <=> non-ptr or dead
147                          --                    False <=> ptr
148
149 -------------------------
150 -- An ArgDescr describes the argument pattern of a function
151
152 data ArgDescr
153   = ArgSpec             -- Fits one of the standard patterns
154         !StgHalfWord    -- RTS type identifier ARG_P, ARG_N, ...
155
156   | ArgGen              -- General case
157         Liveness        -- Details about the arguments
158
159
160 -----------------------------------------------------------------------------
161 -- Construction
162
163 mkHeapRep :: DynFlags -> IsStatic -> WordOff -> WordOff -> ClosureTypeInfo
164           -> SMRep
165 mkHeapRep dflags is_static ptr_wds nonptr_wds cl_type_info
166   = HeapRep is_static
167             ptr_wds
168             (nonptr_wds + slop_wds)
169             cl_type_info
170   where
171      slop_wds
172       | is_static = 0
173       | otherwise = max 0 (minClosureSize dflags - (hdr_size + payload_size))
174
175      hdr_size     = closureTypeHdrSize dflags cl_type_info
176      payload_size = ptr_wds + nonptr_wds
177
178 mkRTSRep :: StgHalfWord -> SMRep -> SMRep
179 mkRTSRep = RTSRep
180
181 mkStackRep :: [Bool] -> SMRep
182 mkStackRep liveness = StackRep liveness
183
184 blackHoleRep :: SMRep
185 blackHoleRep = HeapRep False 0 0 BlackHole
186
187 -----------------------------------------------------------------------------
188 -- Predicates
189
190 isStaticRep :: SMRep -> IsStatic
191 isStaticRep (HeapRep is_static _ _ _) = is_static
192 isStaticRep (StackRep {})             = False
193 isStaticRep (RTSRep _ rep)            = isStaticRep rep
194
195 isConRep :: SMRep -> Bool
196 isConRep (HeapRep _ _ _ Constr{}) = True
197 isConRep _                        = False
198
199 isThunkRep :: SMRep -> Bool
200 isThunkRep (HeapRep _ _ _ Thunk{})         = True
201 isThunkRep (HeapRep _ _ _ ThunkSelector{}) = True
202 isThunkRep (HeapRep _ _ _ BlackHole{})     = True
203 isThunkRep _                               = False
204
205 isFunRep :: SMRep -> Bool
206 isFunRep (HeapRep _ _ _ Fun{}) = True
207 isFunRep _                     = False
208
209 isStaticNoCafCon :: SMRep -> Bool
210 -- This should line up exactly with CONSTR_NOCAF_STATIC above
211 -- See Note [Static NoCaf constructors]
212 isStaticNoCafCon (HeapRep True 0 _ Constr{}) = True
213 isStaticNoCafCon _                           = False
214
215
216 -----------------------------------------------------------------------------
217 -- Size-related things
218
219 -- | Size of a closure header (StgHeader in includes/rts/storage/Closures.h)
220 fixedHdrSize :: DynFlags -> WordOff
221 fixedHdrSize dflags = sTD_HDR_SIZE dflags + profHdrSize dflags
222
223 -- | Size of the profiling part of a closure header
224 -- (StgProfHeader in includes/rts/storage/Closures.h)
225 profHdrSize  :: DynFlags -> WordOff
226 profHdrSize dflags
227  | dopt Opt_SccProfilingOn dflags = pROF_HDR_SIZE dflags
228  | otherwise                      = 0
229
230 -- | The garbage collector requires that every closure is at least as
231 --   big as this.
232 minClosureSize :: DynFlags -> WordOff
233 minClosureSize dflags = fixedHdrSize dflags + mIN_PAYLOAD_SIZE dflags
234
235 arrWordsHdrSize :: DynFlags -> ByteOff
236 arrWordsHdrSize dflags
237  = fixedHdrSize dflags * wORD_SIZE dflags + sIZEOF_StgArrWords_NoHdr dflags
238
239 arrPtrsHdrSize :: DynFlags -> ByteOff
240 arrPtrsHdrSize dflags
241  = fixedHdrSize dflags * wORD_SIZE dflags + sIZEOF_StgMutArrPtrs_NoHdr dflags
242
243 -- Thunks have an extra header word on SMP, so the update doesn't
244 -- splat the payload.
245 thunkHdrSize :: DynFlags -> WordOff
246 thunkHdrSize dflags = fixedHdrSize dflags + smp_hdr
247         where smp_hdr = sIZEOF_StgSMPThunkHeader dflags `quot` wORD_SIZE dflags
248
249
250 nonHdrSize :: SMRep -> WordOff
251 nonHdrSize (HeapRep _ p np _) = p + np
252 nonHdrSize (StackRep bs)      = length bs
253 nonHdrSize (RTSRep _ rep)     = nonHdrSize rep
254
255 heapClosureSize :: DynFlags -> SMRep -> WordOff
256 heapClosureSize dflags (HeapRep _ p np ty)
257  = closureTypeHdrSize dflags ty + p + np
258 heapClosureSize _ _ = panic "SMRep.heapClosureSize"
259
260 closureTypeHdrSize :: DynFlags -> ClosureTypeInfo -> WordOff
261 closureTypeHdrSize dflags ty = case ty of
262                   Thunk{}         -> thunkHdrSize dflags
263                   ThunkSelector{} -> thunkHdrSize dflags
264                   BlackHole{}     -> thunkHdrSize dflags
265                   _               -> fixedHdrSize dflags
266         -- All thunks use thunkHdrSize, even if they are non-updatable.
267         -- this is because we don't have separate closure types for
268         -- updatable vs. non-updatable thunks, so the GC can't tell the
269         -- difference.  If we ever have significant numbers of non-
270         -- updatable thunks, it might be worth fixing this.
271
272 -----------------------------------------------------------------------------
273 -- deriving the RTS closure type from an SMRep
274
275 #include "../includes/rts/storage/ClosureTypes.h"
276 #include "../includes/rts/storage/FunTypes.h"
277 -- Defines CONSTR, CONSTR_1_0 etc
278
279 -- | Derives the RTS closure type from an 'SMRep'
280 rtsClosureType :: SMRep -> StgHalfWord
281 rtsClosureType (RTSRep ty _)  = ty
282
283 rtsClosureType (HeapRep False 1 0 Constr{}) = CONSTR_1_0
284 rtsClosureType (HeapRep False 0 1 Constr{}) = CONSTR_0_1
285 rtsClosureType (HeapRep False 2 0 Constr{}) = CONSTR_2_0
286 rtsClosureType (HeapRep False 1 1 Constr{}) = CONSTR_1_1
287 rtsClosureType (HeapRep False 0 2 Constr{}) = CONSTR_0_2
288 rtsClosureType (HeapRep False _ _ Constr{}) = CONSTR
289
290 rtsClosureType (HeapRep False 1 0 Fun{}) = FUN_1_0
291 rtsClosureType (HeapRep False 0 1 Fun{}) = FUN_0_1
292 rtsClosureType (HeapRep False 2 0 Fun{}) = FUN_2_0
293 rtsClosureType (HeapRep False 1 1 Fun{}) = FUN_1_1
294 rtsClosureType (HeapRep False 0 2 Fun{}) = FUN_0_2
295 rtsClosureType (HeapRep False _ _ Fun{}) = FUN
296
297 rtsClosureType (HeapRep False 1 0 Thunk{}) = THUNK_1_0
298 rtsClosureType (HeapRep False 0 1 Thunk{}) = THUNK_0_1
299 rtsClosureType (HeapRep False 2 0 Thunk{}) = THUNK_2_0
300 rtsClosureType (HeapRep False 1 1 Thunk{}) = THUNK_1_1
301 rtsClosureType (HeapRep False 0 2 Thunk{}) = THUNK_0_2
302 rtsClosureType (HeapRep False _ _ Thunk{}) = THUNK
303
304 rtsClosureType (HeapRep False _ _ ThunkSelector{}) =  THUNK_SELECTOR
305
306 -- Approximation: we use the CONSTR_NOCAF_STATIC type for static constructors
307 -- that have no pointer words only.
308 rtsClosureType (HeapRep True 0 _ Constr{}) = CONSTR_NOCAF_STATIC  -- See isStaticNoCafCon below
309 rtsClosureType (HeapRep True _ _ Constr{}) = CONSTR_STATIC
310 rtsClosureType (HeapRep True _ _ Fun{})    = FUN_STATIC
311 rtsClosureType (HeapRep True _ _ Thunk{})  = THUNK_STATIC
312
313 rtsClosureType (HeapRep False _ _ BlackHole{}) =  BLACKHOLE
314
315 rtsClosureType _ = panic "rtsClosureType"
316
317 -- We export these ones
318 rET_SMALL, rET_BIG, aRG_GEN, aRG_GEN_BIG :: StgHalfWord
319 rET_SMALL   = RET_SMALL
320 rET_BIG     = RET_BIG
321 aRG_GEN     = ARG_GEN
322 aRG_GEN_BIG = ARG_GEN_BIG
323 \end{code}
324
325 Note [Static NoCaf constructors]
326 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
327 If we know that a top-level binding 'x' is not Caffy (ie no CAFs are
328 reachable from 'x'), then a statically allocated constructor (Just x)
329 is also not Caffy, and the garbage collector need not follow its
330 argument fields.  Exploiting this would require two static info tables
331 for Just, for the two cases where the argument was Caffy or non-Caffy.
332
333 Currently we don't do this; instead we treat nullary constructors
334 as non-Caffy, and the others as potentially Caffy.
335
336
337 %************************************************************************
338 %*                                                                      *
339              Pretty printing of SMRep and friends
340 %*                                                                      *
341 %************************************************************************
342
343 \begin{code}
344 instance Outputable ClosureTypeInfo where
345    ppr = pprTypeInfo
346
347 instance Outputable SMRep where
348    ppr (HeapRep static ps nps tyinfo)
349      = hang (header <+> lbrace) 2 (ppr tyinfo <+> rbrace)
350      where
351        header = ptext (sLit "HeapRep")
352                 <+> if static then ptext (sLit "static") else empty
353                 <+> pp_n "ptrs" ps <+> pp_n "nonptrs" nps
354        pp_n :: String -> Int -> SDoc
355        pp_n _ 0 = empty
356        pp_n s n = int n <+> text s
357
358    ppr (StackRep bs) = ptext (sLit "StackRep") <+> ppr bs
359
360    ppr (RTSRep ty rep) = ptext (sLit "tag:") <> ppr ty <+> ppr rep
361
362 instance Outputable ArgDescr where
363   ppr (ArgSpec n) = ptext (sLit "ArgSpec") <+> integer (toInteger n)
364   ppr (ArgGen ls) = ptext (sLit "ArgGen") <+> ppr ls
365
366 pprTypeInfo :: ClosureTypeInfo -> SDoc
367 pprTypeInfo (Constr tag descr)
368   = ptext (sLit "Con") <+>
369     braces (sep [ ptext (sLit "tag:") <+> integer (toInteger tag)
370                 , ptext (sLit "descr:") <> text (show descr) ])
371
372 pprTypeInfo (Fun arity args)
373   = ptext (sLit "Fun") <+>
374     braces (sep [ ptext (sLit "arity:") <+> integer (toInteger arity)
375                 , ptext (sLit ("fun_type:")) <+> ppr args ])
376
377 pprTypeInfo (ThunkSelector offset)
378   = ptext (sLit "ThunkSel") <+> integer (toInteger offset)
379
380 pprTypeInfo Thunk     = ptext (sLit "Thunk")
381 pprTypeInfo BlackHole = ptext (sLit "BlackHole")
382
383 -- XXX Does not belong here!!
384 stringToWord8s :: String -> [Word8]
385 stringToWord8s s = map (fromIntegral . ord) s
386
387 pprWord8String :: [Word8] -> SDoc
388 -- Debug printing.  Not very clever right now.
389 pprWord8String ws = text (show ws)
390 \end{code}