%
% (c) The University of Glasgow 2006
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
Storage manager representation of closures
\begin{code}
module SMRep (
StgWord, fromStgWord, toStgWord,
StgHalfWord, fromStgHalfWord, toStgHalfWord,
hALF_WORD_SIZE, hALF_WORD_SIZE_IN_BITS,
WordOff, ByteOff,
roundUpToWords,
#if __GLASGOW_HASKELL__ > 706
UArrayStgWord, listArray, toByteArray,
#endif
SMRep(..),
IsStatic,
ClosureTypeInfo(..), ArgDescr(..), Liveness,
ConstrDescription,
mkHeapRep, blackHoleRep, indStaticRep, mkStackRep, mkRTSRep,
isStaticRep, isConRep, isThunkRep, isFunRep, isStaticNoCafCon,
isStackRep,
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 DynFlags
import Outputable
import Platform
import FastString
import qualified Data.Array.Base as Array
#if __GLASGOW_HASKELL__ > 706
import GHC.Base ( ByteArray# )
import Data.Ix
#endif
import Data.Char( ord )
import Data.Word
import Data.Bits
\end{code}
%************************************************************************
%* *
Words and bytes
%* *
%************************************************************************
\begin{code}
type WordOff = Int
type ByteOff = Int
roundUpToWords :: DynFlags -> ByteOff -> ByteOff
roundUpToWords dflags n = (n + (wORD_SIZE dflags 1)) .&. (complement (wORD_SIZE dflags 1))
\end{code}
StgWord is a type representing an StgWord on the target platform.
\begin{code}
newtype StgWord = StgWord Word64
deriving (Eq,
#if __GLASGOW_HASKELL__ < 706
Num,
#endif
#if __GLASGOW_HASKELL__ <= 706
Array.IArray Array.UArray,
#endif
Bits)
fromStgWord :: StgWord -> Integer
fromStgWord (StgWord i) = toInteger i
toStgWord :: DynFlags -> Integer -> StgWord
toStgWord dflags i
= case platformWordSize (targetPlatform dflags) of
4 -> StgWord (fromIntegral (fromInteger i :: Word32))
8 -> StgWord (fromInteger i :: Word64)
w -> panic ("toStgWord: Unknown platformWordSize: " ++ show w)
instance Outputable StgWord where
ppr (StgWord i) = integer (toInteger i)
newtype StgHalfWord = StgHalfWord Word32
deriving Eq
fromStgHalfWord :: StgHalfWord -> Integer
fromStgHalfWord (StgHalfWord w) = toInteger w
toStgHalfWord :: DynFlags -> Integer -> StgHalfWord
toStgHalfWord dflags i
= case platformWordSize (targetPlatform dflags) of
4 -> StgHalfWord (fromIntegral (fromInteger i :: Word16))
8 -> StgHalfWord (fromInteger i :: Word32)
w -> panic ("toStgHalfWord: Unknown platformWordSize: " ++ show w)
instance Outputable StgHalfWord where
ppr (StgHalfWord w) = integer (toInteger w)
hALF_WORD_SIZE :: DynFlags -> ByteOff
hALF_WORD_SIZE dflags = platformWordSize (targetPlatform dflags) `shiftR` 1
hALF_WORD_SIZE_IN_BITS :: DynFlags -> Int
hALF_WORD_SIZE_IN_BITS dflags = platformWordSize (targetPlatform dflags) `shiftL` 2
\end{code}
%************************************************************************
%* *
Immutable arrays of StgWords
%* *
%************************************************************************
\begin{code}
#if __GLASGOW_HASKELL__ > 706
newtype UArrayStgWord i = UArrayStgWord (Array.UArray i Word64)
listArray :: Ix i => (i, i) -> [StgWord] -> UArrayStgWord i
listArray (i,j) words
= UArrayStgWord $ Array.listArray (i,j) (map unStgWord words)
where unStgWord (StgWord w64) = w64
toByteArray :: UArrayStgWord i -> ByteArray#
toByteArray (UArrayStgWord (Array.UArray _ _ _ b)) = b
#endif
\end{code}
%************************************************************************
%* *
\subsubsection[SMRep-datatype]{@SMRep@---storage manager representation}
%* *
%************************************************************************
\begin{code}
data SMRep
= HeapRep
IsStatic
!WordOff
!WordOff
ClosureTypeInfo
| StackRep
Liveness
| RTSRep
Int
SMRep
type IsStatic = Bool
data ClosureTypeInfo
= Constr ConstrTag ConstrDescription
| Fun FunArity ArgDescr
| Thunk
| ThunkSelector SelectorOffset
| BlackHole
| IndStatic
type ConstrTag = Int
type ConstrDescription = [Word8]
type FunArity = Int
type SelectorOffset = Int
type Liveness = [Bool]
data ArgDescr
= ArgSpec
!Int
| ArgGen
Liveness
mkHeapRep :: DynFlags -> IsStatic -> WordOff -> WordOff -> ClosureTypeInfo
-> SMRep
mkHeapRep dflags 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 dflags (hdr_size + payload_size))
hdr_size = closureTypeHdrSize dflags cl_type_info
payload_size = ptr_wds + nonptr_wds
mkRTSRep :: Int -> SMRep -> SMRep
mkRTSRep = RTSRep
mkStackRep :: [Bool] -> SMRep
mkStackRep liveness = StackRep liveness
blackHoleRep :: SMRep
blackHoleRep = HeapRep False 0 0 BlackHole
indStaticRep :: SMRep
indStaticRep = HeapRep True 1 0 IndStatic
isStaticRep :: SMRep -> IsStatic
isStaticRep (HeapRep is_static _ _ _) = is_static
isStaticRep (StackRep {}) = False
isStaticRep (RTSRep _ rep) = isStaticRep rep
isStackRep :: SMRep -> Bool
isStackRep StackRep{} = True
isStackRep (RTSRep _ rep) = isStackRep rep
isStackRep _ = False
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 (HeapRep _ _ _ IndStatic{}) = True
isThunkRep _ = False
isFunRep :: SMRep -> Bool
isFunRep (HeapRep _ _ _ Fun{}) = True
isFunRep _ = False
isStaticNoCafCon :: SMRep -> Bool
isStaticNoCafCon (HeapRep True 0 _ Constr{}) = True
isStaticNoCafCon _ = False
fixedHdrSize :: DynFlags -> WordOff
fixedHdrSize dflags = sTD_HDR_SIZE dflags + profHdrSize dflags
profHdrSize :: DynFlags -> WordOff
profHdrSize dflags
| gopt Opt_SccProfilingOn dflags = pROF_HDR_SIZE dflags
| otherwise = 0
minClosureSize :: DynFlags -> WordOff
minClosureSize dflags = fixedHdrSize dflags + mIN_PAYLOAD_SIZE dflags
arrWordsHdrSize :: DynFlags -> ByteOff
arrWordsHdrSize dflags
= fixedHdrSize dflags * wORD_SIZE dflags + sIZEOF_StgArrWords_NoHdr dflags
arrPtrsHdrSize :: DynFlags -> ByteOff
arrPtrsHdrSize dflags
= fixedHdrSize dflags * wORD_SIZE dflags + sIZEOF_StgMutArrPtrs_NoHdr dflags
thunkHdrSize :: DynFlags -> WordOff
thunkHdrSize dflags = fixedHdrSize dflags + smp_hdr
where smp_hdr = sIZEOF_StgSMPThunkHeader dflags `quot` wORD_SIZE dflags
nonHdrSize :: SMRep -> WordOff
nonHdrSize (HeapRep _ p np _) = p + np
nonHdrSize (StackRep bs) = length bs
nonHdrSize (RTSRep _ rep) = nonHdrSize rep
heapClosureSize :: DynFlags -> SMRep -> WordOff
heapClosureSize dflags (HeapRep _ p np ty)
= closureTypeHdrSize dflags ty + p + np
heapClosureSize _ _ = panic "SMRep.heapClosureSize"
closureTypeHdrSize :: DynFlags -> ClosureTypeInfo -> WordOff
closureTypeHdrSize dflags ty = case ty of
Thunk{} -> thunkHdrSize dflags
ThunkSelector{} -> thunkHdrSize dflags
BlackHole{} -> thunkHdrSize dflags
IndStatic{} -> thunkHdrSize dflags
_ -> fixedHdrSize dflags
#include "../includes/rts/storage/ClosureTypes.h"
#include "../includes/rts/storage/FunTypes.h"
rtsClosureType :: SMRep -> Int
rtsClosureType rep
= case rep of
RTSRep ty _ -> ty
HeapRep False 1 0 Constr{} -> CONSTR_1_0
HeapRep False 0 1 Constr{} -> CONSTR_0_1
HeapRep False 2 0 Constr{} -> CONSTR_2_0
HeapRep False 1 1 Constr{} -> CONSTR_1_1
HeapRep False 0 2 Constr{} -> CONSTR_0_2
HeapRep False _ _ Constr{} -> CONSTR
HeapRep False 1 0 Fun{} -> FUN_1_0
HeapRep False 0 1 Fun{} -> FUN_0_1
HeapRep False 2 0 Fun{} -> FUN_2_0
HeapRep False 1 1 Fun{} -> FUN_1_1
HeapRep False 0 2 Fun{} -> FUN_0_2
HeapRep False _ _ Fun{} -> FUN
HeapRep False 1 0 Thunk{} -> THUNK_1_0
HeapRep False 0 1 Thunk{} -> THUNK_0_1
HeapRep False 2 0 Thunk{} -> THUNK_2_0
HeapRep False 1 1 Thunk{} -> THUNK_1_1
HeapRep False 0 2 Thunk{} -> THUNK_0_2
HeapRep False _ _ Thunk{} -> THUNK
HeapRep False _ _ ThunkSelector{} -> THUNK_SELECTOR
HeapRep True 0 _ Constr{} -> CONSTR_NOCAF_STATIC
HeapRep True _ _ Constr{} -> CONSTR_STATIC
HeapRep True _ _ Fun{} -> FUN_STATIC
HeapRep True _ _ Thunk{} -> THUNK_STATIC
HeapRep False _ _ BlackHole{} -> BLACKHOLE
HeapRep False _ _ IndStatic{} -> IND_STATIC
_ -> panic "rtsClosureType"
rET_SMALL, rET_BIG, aRG_GEN, aRG_GEN_BIG :: Int
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") <+> ppr n
ppr (ArgGen ls) = ptext (sLit "ArgGen") <+> ppr ls
pprTypeInfo :: ClosureTypeInfo -> SDoc
pprTypeInfo (Constr tag descr)
= ptext (sLit "Con") <+>
braces (sep [ ptext (sLit "tag:") <+> ppr tag
, ptext (sLit "descr:") <> text (show descr) ])
pprTypeInfo (Fun arity args)
= ptext (sLit "Fun") <+>
braces (sep [ ptext (sLit "arity:") <+> ppr arity
, ptext (sLit ("fun_type:")) <+> ppr args ])
pprTypeInfo (ThunkSelector offset)
= ptext (sLit "ThunkSel") <+> ppr offset
pprTypeInfo Thunk = ptext (sLit "Thunk")
pprTypeInfo BlackHole = ptext (sLit "BlackHole")
pprTypeInfo IndStatic = ptext (sLit "IndStatic")
stringToWord8s :: String -> [Word8]
stringToWord8s s = map (fromIntegral . ord) s
pprWord8String :: [Word8] -> SDoc
pprWord8String ws = text (show ws)
\end{code}