module StgCmmProf (
initCostCentres, ccType, ccsType,
mkCCostCentre, mkCCostCentreStack,
dynProfHdr, profDynAlloc, profAlloc, staticProfHdr, initUpdFrameProf,
enterCostCentreThunk,
costCentreFrom,
curCCS, storeCurCCS,
emitSetCCC,
saveCurrentCostCentre, restoreCurrentCostCentre,
ldvEnter, ldvEnterClosure, ldvRecordCreate
) where
#include "HsVersions.h"
#include "../includes/MachDeps.h"
#include "../includes/rts/Constants.h"
#include "../includes/dist-derivedconstants/header/DerivedConstants.h"
import StgCmmClosure
import StgCmmUtils
import StgCmmMonad
import SMRep
import MkGraph
import Cmm
import CmmUtils
import CLabel
import qualified Module
import CostCentre
import StaticFlags
import FastString
import Module
import Constants
import Outputable
import Control.Monad
import Data.Char (ord)
ccsType :: CmmType
ccsType = bWord
ccType :: CmmType
ccType = bWord
curCCS :: CmmExpr
curCCS = CmmReg (CmmGlobal CCCS)
storeCurCCS :: CmmExpr -> CmmAGraph
storeCurCCS e = mkAssign (CmmGlobal CCCS) e
mkCCostCentre :: CostCentre -> CmmLit
mkCCostCentre cc = CmmLabel (mkCCLabel cc)
mkCCostCentreStack :: CostCentreStack -> CmmLit
mkCCostCentreStack ccs = CmmLabel (mkCCSLabel ccs)
costCentreFrom :: CmmExpr
-> CmmExpr
costCentreFrom cl = CmmLoad (cmmOffsetB cl oFFSET_StgHeader_ccs) ccsType
staticProfHdr :: CostCentreStack -> [CmmLit]
staticProfHdr ccs = ifProfilingL [mkCCostCentreStack ccs,
staticLdvInit]
dynProfHdr :: CmmExpr -> [CmmExpr]
dynProfHdr ccs = ifProfilingL [ccs, dynLdvInit]
initUpdFrameProf :: CmmExpr -> FCode ()
initUpdFrameProf frame_amode
= ifProfiling $
emitStore (cmmOffsetB frame_amode oFFSET_StgHeader_ccs) curCCS
saveCurrentCostCentre :: FCode (Maybe LocalReg)
saveCurrentCostCentre
| not opt_SccProfilingOn
= return Nothing
| otherwise
= do { local_cc <- newTemp ccType
; emitAssign (CmmLocal local_cc) curCCS
; return (Just local_cc) }
restoreCurrentCostCentre :: Maybe LocalReg -> FCode ()
restoreCurrentCostCentre Nothing
= return ()
restoreCurrentCostCentre (Just local_cc)
= emit (storeCurCCS (CmmReg (CmmLocal local_cc)))
profDynAlloc :: SMRep -> CmmExpr -> FCode ()
profDynAlloc rep ccs
= ifProfiling $
profAlloc (CmmLit (mkIntCLit (heapClosureSize rep))) ccs
profAlloc :: CmmExpr -> CmmExpr -> FCode ()
profAlloc words ccs
= ifProfiling $
emit (addToMemE alloc_rep
(cmmOffsetB ccs oFFSET_CostCentreStack_mem_alloc)
(CmmMachOp (MO_UU_Conv wordWidth (typeWidth alloc_rep)) $
[CmmMachOp mo_wordSub [words,
CmmLit (mkIntCLit profHdrSize)]]))
where
alloc_rep = REP_CostCentreStack_mem_alloc
enterCostCentreThunk :: CmmExpr -> FCode ()
enterCostCentreThunk closure =
ifProfiling $ do
emit $ storeCurCCS (costCentreFrom closure)
ifProfiling :: FCode () -> FCode ()
ifProfiling code
| opt_SccProfilingOn = code
| otherwise = nopC
ifProfilingL :: [a] -> [a]
ifProfilingL xs
| opt_SccProfilingOn = xs
| otherwise = []
initCostCentres :: CollectedCCs -> FCode ()
initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs)
= whenC opt_SccProfilingOn $
do { mapM_ emitCostCentreDecl local_CCs
; mapM_ emitCostCentreStackDecl singleton_CCSs }
emitCostCentreDecl :: CostCentre -> FCode ()
emitCostCentreDecl cc = do
{ label <- newByteStringCLit (bytesFS $ costCentreUserNameFS cc)
; modl <- newByteStringCLit (bytesFS $ Module.moduleNameFS
$ Module.moduleName
$ cc_mod cc)
; dflags <- getDynFlags
; loc <- newStringCLit (showPpr dflags (costCentreSrcSpan cc))
; let lits = [ zero,
label,
modl,
loc,
zero64,
zero,
is_caf,
zero
]
; emitDataLits (mkCCLabel cc) lits
}
where
is_caf | isCafCC cc = mkIntCLit (ord 'c')
| otherwise = zero
emitCostCentreStackDecl :: CostCentreStack -> FCode ()
emitCostCentreStackDecl ccs
= case maybeSingletonCCS ccs of
Just cc -> emitDataLits (mkCCSLabel ccs) (mk_lits cc)
Nothing -> pprPanic "emitCostCentreStackDecl" (ppr ccs)
where
mk_lits cc = zero :
mkCCostCentre cc :
replicate (sizeof_ccs_words 2) zero
zero :: CmmLit
zero = mkIntCLit 0
zero64 :: CmmLit
zero64 = CmmInt 0 W64
sizeof_ccs_words :: Int
sizeof_ccs_words
| ms == 0 = ws
| otherwise = ws + 1
where
(ws,ms) = SIZEOF_CostCentreStack `divMod` wORD_SIZE
emitSetCCC :: CostCentre -> Bool -> Bool -> FCode ()
emitSetCCC cc tick push
| not opt_SccProfilingOn = nopC
| otherwise = do
tmp <- newTemp ccsType
pushCostCentre tmp curCCS cc
when tick $ emit (bumpSccCount (CmmReg (CmmLocal tmp)))
when push $ emit (storeCurCCS (CmmReg (CmmLocal tmp)))
pushCostCentre :: LocalReg -> CmmExpr -> CostCentre -> FCode ()
pushCostCentre result ccs cc
= emitRtsCallWithResult result AddrHint
rtsPackageId
(fsLit "PushCostCentre") [(ccs,AddrHint),
(CmmLit (mkCCostCentre cc), AddrHint)]
False
bumpSccCount :: CmmExpr -> CmmAGraph
bumpSccCount ccs
= addToMem REP_CostCentreStack_scc_count
(cmmOffsetB ccs oFFSET_CostCentreStack_scc_count) 1
staticLdvInit :: CmmLit
staticLdvInit = zeroCLit
dynLdvInit :: CmmExpr
dynLdvInit =
CmmMachOp mo_wordOr [
CmmMachOp mo_wordShl [loadEra, CmmLit (mkIntCLit lDV_SHIFT) ],
CmmLit (mkWordCLit lDV_STATE_CREATE)
]
ldvRecordCreate :: CmmExpr -> FCode ()
ldvRecordCreate closure = emit $ mkStore (ldvWord closure) dynLdvInit
ldvEnterClosure :: ClosureInfo -> FCode ()
ldvEnterClosure closure_info = ldvEnter (cmmOffsetB (CmmReg nodeReg) (tag))
where tag = funTag closure_info
ldvEnter :: CmmExpr -> FCode ()
ldvEnter cl_ptr
= ifProfiling $
emit =<< mkCmmIfThenElse (CmmMachOp mo_wordUGt [loadEra, CmmLit zeroCLit])
(mkStore ldv_wd new_ldv_wd)
mkNop
where
ldv_wd = ldvWord cl_ptr
new_ldv_wd = cmmOrWord (cmmAndWord (CmmLoad ldv_wd bWord)
(CmmLit (mkWordCLit lDV_CREATE_MASK)))
(cmmOrWord loadEra (CmmLit (mkWordCLit lDV_STATE_USE)))
loadEra :: CmmExpr
loadEra = CmmMachOp (MO_UU_Conv cIntWidth wordWidth)
[CmmLoad (mkLblExpr (mkCmmDataLabel rtsPackageId (fsLit "era"))) cInt]
ldvWord :: CmmExpr -> CmmExpr
ldvWord closure_ptr = cmmOffsetB closure_ptr oFFSET_StgHeader_ldvw
lDV_SHIFT :: Int
lDV_SHIFT = LDV_SHIFT
lDV_CREATE_MASK :: StgWord
lDV_CREATE_MASK = LDV_CREATE_MASK
lDV_STATE_CREATE :: StgWord
lDV_STATE_CREATE = LDV_STATE_CREATE
lDV_STATE_USE :: StgWord
lDV_STATE_USE = LDV_STATE_USE