%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
Storage manager representation of closures
This is here, rather than in ClosureInfo, just to keep nhc happy.
Other modules should access this info through ClosureInfo.
\begin{code}
module SMRep (
StgWord, StgHalfWord,
hALF_WORD_SIZE, hALF_WORD_SIZE_IN_BITS,
WordOff, ByteOff,
roundUpToWords,
SMRep(..),
IsStatic,
ClosureTypeInfo(..), ArgDescr(..), Liveness,
ConstrDescription,
mkHeapRep, blackHoleRep, mkStackRep, mkRTSRep,
isStaticRep, isConRep, isThunkRep, isFunRep, isStaticNoCafCon,
heapClosureSize,
fixedHdrSize, arrWordsHdrSize, arrPtrsHdrSize,
profHdrSize, thunkHdrSize, nonHdrSize,
rtsClosureType, rET_SMALL, rET_BIG,
aRG_GEN, aRG_GEN_BIG,
pprWord8String, stringToWord8s
) where
#include "../HsVersions.h"
#include "../includes/MachDeps.h"
import StaticFlags
import Constants
import Outputable
import FastString
import Data.Char( ord )
import Data.Word
import Data.Bits
\end{code}
%************************************************************************
%* *
Words and bytes
%* *
%************************************************************************
\begin{code}
type WordOff = Int
type ByteOff = Int
roundUpToWords :: ByteOff -> ByteOff
roundUpToWords n = (n + (wORD_SIZE 1)) .&. (complement (wORD_SIZE 1))
\end{code}
StgWord is a type representing an StgWord on the target platform.
\begin{code}
#if SIZEOF_HSWORD == 4
type StgWord = Word32
type StgHalfWord = Word16
hALF_WORD_SIZE :: ByteOff
hALF_WORD_SIZE = 2
hALF_WORD_SIZE_IN_BITS :: Int
hALF_WORD_SIZE_IN_BITS = 16
#elif SIZEOF_HSWORD == 8
type StgWord = Word64
type StgHalfWord = Word32
hALF_WORD_SIZE :: ByteOff
hALF_WORD_SIZE = 4
hALF_WORD_SIZE_IN_BITS :: Int
hALF_WORD_SIZE_IN_BITS = 32
#else
#error unknown SIZEOF_HSWORD
#endif
\end{code}
%************************************************************************
%* *
\subsubsection[SMRep-datatype]{@SMRep@---storage manager representation}
%* *
%************************************************************************
\begin{code}
data SMRep
= HeapRep
IsStatic
!WordOff
!WordOff
ClosureTypeInfo
| StackRep
Liveness
| RTSRep
StgHalfWord
SMRep
type IsStatic = Bool
data ClosureTypeInfo
= Constr ConstrTag ConstrDescription
| Fun FunArity ArgDescr
| Thunk
| ThunkSelector SelectorOffset
| BlackHole
type ConstrTag = StgHalfWord
type ConstrDescription = [Word8]
type FunArity = StgHalfWord
type SelectorOffset = StgWord
type Liveness = [Bool]
data ArgDescr
= ArgSpec
!StgHalfWord
| ArgGen
Liveness
mkHeapRep :: IsStatic -> WordOff -> WordOff -> ClosureTypeInfo -> SMRep
mkHeapRep is_static ptr_wds nonptr_wds cl_type_info
= HeapRep is_static
ptr_wds
(nonptr_wds + slop_wds)
cl_type_info
where
slop_wds
| is_static = 0
| otherwise = max 0 (minClosureSize (hdr_size + payload_size))
hdr_size = closureTypeHdrSize cl_type_info
payload_size = ptr_wds + nonptr_wds
mkRTSRep :: StgHalfWord -> SMRep -> SMRep
mkRTSRep = RTSRep
mkStackRep :: [Bool] -> SMRep
mkStackRep liveness = StackRep liveness
blackHoleRep :: SMRep
blackHoleRep = HeapRep False 0 0 BlackHole
isStaticRep :: SMRep -> IsStatic
isStaticRep (HeapRep is_static _ _ _) = is_static
isStaticRep (StackRep {}) = False
isStaticRep (RTSRep _ rep) = isStaticRep rep
isConRep :: SMRep -> Bool
isConRep (HeapRep _ _ _ Constr{}) = True
isConRep _ = False
isThunkRep :: SMRep -> Bool
isThunkRep (HeapRep _ _ _ Thunk{}) = True
isThunkRep (HeapRep _ _ _ ThunkSelector{}) = True
isThunkRep (HeapRep _ _ _ BlackHole{}) = True
isThunkRep _ = False
isFunRep :: SMRep -> Bool
isFunRep (HeapRep _ _ _ Fun{}) = True
isFunRep _ = False
isStaticNoCafCon :: SMRep -> Bool
isStaticNoCafCon (HeapRep True 0 _ Constr{}) = True
isStaticNoCafCon _ = False
fixedHdrSize :: WordOff
fixedHdrSize = sTD_HDR_SIZE + profHdrSize
profHdrSize :: WordOff
profHdrSize | opt_SccProfilingOn = pROF_HDR_SIZE
| otherwise = 0
minClosureSize :: WordOff
minClosureSize = fixedHdrSize + mIN_PAYLOAD_SIZE
arrWordsHdrSize :: ByteOff
arrWordsHdrSize = fixedHdrSize*wORD_SIZE + sIZEOF_StgArrWords_NoHdr
arrPtrsHdrSize :: ByteOff
arrPtrsHdrSize = fixedHdrSize*wORD_SIZE + sIZEOF_StgMutArrPtrs_NoHdr
thunkHdrSize :: WordOff
thunkHdrSize = fixedHdrSize + smp_hdr
where smp_hdr = sIZEOF_StgSMPThunkHeader `quot` wORD_SIZE
nonHdrSize :: SMRep -> WordOff
nonHdrSize (HeapRep _ p np _) = p + np
nonHdrSize (StackRep bs) = length bs
nonHdrSize (RTSRep _ rep) = nonHdrSize rep
heapClosureSize :: SMRep -> WordOff
heapClosureSize (HeapRep _ p np ty) = closureTypeHdrSize ty + p + np
heapClosureSize _ = panic "SMRep.heapClosureSize"
closureTypeHdrSize :: ClosureTypeInfo -> WordOff
closureTypeHdrSize ty = case ty of
Thunk{} -> thunkHdrSize
ThunkSelector{} -> thunkHdrSize
BlackHole{} -> thunkHdrSize
_ -> fixedHdrSize
#include "../includes/rts/storage/ClosureTypes.h"
#include "../includes/rts/storage/FunTypes.h"
rtsClosureType :: SMRep -> StgHalfWord
rtsClosureType (RTSRep ty _) = ty
rtsClosureType (HeapRep False 1 0 Constr{}) = CONSTR_1_0
rtsClosureType (HeapRep False 0 1 Constr{}) = CONSTR_0_1
rtsClosureType (HeapRep False 2 0 Constr{}) = CONSTR_2_0
rtsClosureType (HeapRep False 1 1 Constr{}) = CONSTR_1_1
rtsClosureType (HeapRep False 0 2 Constr{}) = CONSTR_0_2
rtsClosureType (HeapRep False _ _ Constr{}) = CONSTR
rtsClosureType (HeapRep False 1 0 Fun{}) = FUN_1_0
rtsClosureType (HeapRep False 0 1 Fun{}) = FUN_0_1
rtsClosureType (HeapRep False 2 0 Fun{}) = FUN_2_0
rtsClosureType (HeapRep False 1 1 Fun{}) = FUN_1_1
rtsClosureType (HeapRep False 0 2 Fun{}) = FUN_0_2
rtsClosureType (HeapRep False _ _ Fun{}) = FUN
rtsClosureType (HeapRep False 1 0 Thunk{}) = THUNK_1_0
rtsClosureType (HeapRep False 0 1 Thunk{}) = THUNK_0_1
rtsClosureType (HeapRep False 2 0 Thunk{}) = THUNK_2_0
rtsClosureType (HeapRep False 1 1 Thunk{}) = THUNK_1_1
rtsClosureType (HeapRep False 0 2 Thunk{}) = THUNK_0_2
rtsClosureType (HeapRep False _ _ Thunk{}) = THUNK
rtsClosureType (HeapRep False _ _ ThunkSelector{}) = THUNK_SELECTOR
rtsClosureType (HeapRep True 0 _ Constr{}) = CONSTR_NOCAF_STATIC
rtsClosureType (HeapRep True _ _ Constr{}) = CONSTR_STATIC
rtsClosureType (HeapRep True _ _ Fun{}) = FUN_STATIC
rtsClosureType (HeapRep True _ _ Thunk{}) = THUNK_STATIC
rtsClosureType (HeapRep False _ _ BlackHole{}) = BLACKHOLE
rtsClosureType _ = panic "rtsClosureType"
rET_SMALL, rET_BIG, aRG_GEN, aRG_GEN_BIG :: StgHalfWord
rET_SMALL = RET_SMALL
rET_BIG = RET_BIG
aRG_GEN = ARG_GEN
aRG_GEN_BIG = ARG_GEN_BIG
\end{code}
Note [Static NoCaf constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If we know that a top-level binding 'x' is not Caffy (ie no CAFs are
reachable from 'x'), then a statically allocated constructor (Just x)
is also not Caffy, and the garbage collector need not follow its
argument fields. Exploiting this would require two static info tables
for Just, for the two cases where the argument was Caffy or non-Caffy.
Currently we don't do this; instead we treat nullary constructors
as non-Caffy, and the others as potentially Caffy.
%************************************************************************
%* *
Pretty printing of SMRep and friends
%* *
%************************************************************************
\begin{code}
instance Outputable ClosureTypeInfo where
ppr = pprTypeInfo
instance Outputable SMRep where
ppr (HeapRep static ps nps tyinfo)
= hang (header <+> lbrace) 2 (ppr tyinfo <+> rbrace)
where
header = ptext (sLit "HeapRep")
<+> if static then ptext (sLit "static") else empty
<+> pp_n "ptrs" ps <+> pp_n "nonptrs" nps
pp_n :: String -> Int -> SDoc
pp_n _ 0 = empty
pp_n s n = int n <+> text s
ppr (StackRep bs) = ptext (sLit "StackRep") <+> ppr bs
ppr (RTSRep ty rep) = ptext (sLit "tag:") <> ppr ty <+> ppr rep
instance Outputable ArgDescr where
ppr (ArgSpec n) = ptext (sLit "ArgSpec") <+> integer (toInteger n)
ppr (ArgGen ls) = ptext (sLit "ArgGen") <+> ppr ls
pprTypeInfo :: ClosureTypeInfo -> SDoc
pprTypeInfo (Constr tag descr)
= ptext (sLit "Con") <+>
braces (sep [ ptext (sLit "tag:") <+> integer (toInteger tag)
, ptext (sLit "descr:") <> text (show descr) ])
pprTypeInfo (Fun arity args)
= ptext (sLit "Fun") <+>
braces (sep [ ptext (sLit "arity:") <+> integer (toInteger arity)
, ptext (sLit ("fun_type:")) <+> ppr args ])
pprTypeInfo (ThunkSelector offset)
= ptext (sLit "ThunkSel") <+> integer (toInteger offset)
pprTypeInfo Thunk = ptext (sLit "Thunk")
pprTypeInfo BlackHole = ptext (sLit "BlackHole")
stringToWord8s :: String -> [Word8]
stringToWord8s s = map (fromIntegral . ord) s
pprWord8String :: [Word8] -> SDoc
pprWord8String ws = text (show ws)
\end{code}