2 -- Lots of missing type sigs etc
4 -----------------------------------------------------------------------------
6 -- Code generation for profiling
8 -- (c) The University of Glasgow 2004-2006
10 -----------------------------------------------------------------------------
13 initCostCentres, ccType, ccsType,
14 mkCCostCentre, mkCCostCentreStack,
16 -- Cost-centre Profiling
17 dynProfHdr, profDynAlloc, profAlloc, staticProfHdr, initUpdFrameProf,
18 enterCostCentre, enterCostCentrePAP, enterCostCentreThunk,
24 saveCurrentCostCentre, restoreCurrentCostCentre,
26 -- Lag/drag/void stuff
27 ldvEnter, ldvEnterClosure, ldvRecordCreate
30 #include "HsVersions.h"
32 -- For WORD_SIZE_IN_BITS only.
33 #include "../includes/Constants.h"
34 -- For LDV_CREATE_MASK, LDV_STATE_USE
36 #include "../includes/DerivedConstants.h"
37 -- For REP_xxx constants, which are MachReps
47 import TyCon ( PrimRep(..) )
52 import qualified Module
57 import Constants -- Lots of field offsets
64 -----------------------------------------------------------------------------
66 -- Cost-centre-stack Profiling
68 -----------------------------------------------------------------------------
70 -- Expression representing the current cost centre stack
71 ccsType :: CmmType -- Type of a cost-centre stack
74 ccType :: CmmType -- Type of a cost centre
78 curCCS = CmmLoad curCCSAddr ccsType
80 -- Address of current CCS variable, for storing into
82 curCCSAddr = CmmLit (CmmLabel (mkRtsDataLabel (sLit "CCCS")))
84 mkCCostCentre :: CostCentre -> CmmLit
85 mkCCostCentre cc = CmmLabel (mkCCLabel cc)
87 mkCCostCentreStack :: CostCentreStack -> CmmLit
88 mkCCostCentreStack ccs = CmmLabel (mkCCSLabel ccs)
90 costCentreFrom :: CmmExpr -- A closure pointer
91 -> CmmExpr -- The cost centre from that closure
92 costCentreFrom cl = CmmLoad (cmmOffsetB cl oFFSET_StgHeader_ccs) ccsType
94 staticProfHdr :: CostCentreStack -> [CmmLit]
95 -- The profiling header words in a static closure
96 -- Was SET_STATIC_PROF_HDR
97 staticProfHdr ccs = ifProfilingL [mkCCostCentreStack ccs,
100 dynProfHdr :: CmmExpr -> [CmmExpr]
101 -- Profiling header words in a dynamic closure
102 dynProfHdr ccs = ifProfilingL [ccs, dynLdvInit]
104 initUpdFrameProf :: CmmExpr -> FCode ()
105 -- Initialise the profiling field of an update frame
106 initUpdFrameProf frame_amode
107 = ifProfiling $ -- frame->header.prof.ccs = CCCS
108 emit (mkStore (cmmOffsetB frame_amode oFFSET_StgHeader_ccs) curCCS)
109 -- frame->header.prof.hp.rs = NULL (or frame-header.prof.hp.ldvw = 0)
110 -- is unnecessary because it is not used anyhow.
112 ---------------------------------------------------------------------------
113 -- Saving and restoring the current cost centre
114 ---------------------------------------------------------------------------
116 {- Note [Saving the current cost centre]
117 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
118 The current cost centre is like a global register. Like other
119 global registers, it's a caller-saves one. But consider
120 case (f x) of (p,q) -> rhs
121 Since 'f' may set the cost centre, we must restore it
122 before resuming rhs. So we want code like this:
123 local_cc = CCC -- save
125 CCC = local_cc -- restore
126 That is, we explicitly "save" the current cost centre in
127 a LocalReg, local_cc; and restore it after the call. The
128 C-- infrastructure will arrange to save local_cc across the
131 The same goes for join points;
134 We want this kind of code:
135 local_cc = CCC -- save
138 CCC = local_cc -- restore
141 saveCurrentCostCentre :: FCode (Maybe LocalReg)
142 -- Returns Nothing if profiling is off
143 saveCurrentCostCentre
144 | not opt_SccProfilingOn
147 = do { local_cc <- newTemp ccType
148 ; emit (mkAssign (CmmLocal local_cc) curCCS)
149 ; return (Just local_cc) }
151 restoreCurrentCostCentre :: Maybe LocalReg -> FCode ()
152 restoreCurrentCostCentre Nothing
154 restoreCurrentCostCentre (Just local_cc)
155 = emit (mkStore curCCSAddr (CmmReg (CmmLocal local_cc)))
158 -------------------------------------------------------------------------------
159 -- Recording allocation in a cost centre
160 -------------------------------------------------------------------------------
162 -- | Record the allocation of a closure. The CmmExpr is the cost
163 -- centre stack to which to attribute the allocation.
164 profDynAlloc :: ClosureInfo -> CmmExpr -> FCode ()
165 profDynAlloc cl_info ccs
167 profAlloc (CmmLit (mkIntCLit (closureSize cl_info))) ccs
169 -- | Record the allocation of a closure (size is given by a CmmExpr)
170 -- The size must be in words, because the allocation counter in a CCS counts
172 profAlloc :: CmmExpr -> CmmExpr -> FCode ()
175 emit (addToMemE alloc_rep
176 (cmmOffsetB ccs oFFSET_CostCentreStack_mem_alloc)
177 (CmmMachOp (MO_UU_Conv wordWidth (typeWidth alloc_rep)) $
178 [CmmMachOp mo_wordSub [words,
179 CmmLit (mkIntCLit profHdrSize)]]))
180 -- subtract the "profiling overhead", which is the
181 -- profiling header in a closure.
183 alloc_rep = REP_CostCentreStack_mem_alloc
185 -- ----------------------------------------------------------------------
186 -- Setting the cost centre in a new closure
188 chooseDynCostCentres :: CostCentreStack
191 -> FCode (CmmExpr, CmmExpr)
192 -- Called when allocating a closure
193 -- Tells which cost centre to put in the object, and which
194 -- to blame the cost of allocation on
195 chooseDynCostCentres ccs args body = do
196 -- Cost-centre we record in the object
197 use_ccs <- emitCCS ccs
199 -- Cost-centre on whom we blame the allocation
201 | null args && isBox body = CmmLit (mkCCostCentreStack overheadCCS)
202 | otherwise = use_ccs
204 return (use_ccs, blame_ccs)
207 -- Some CostCentreStacks are a sequence of pushes on top of CCCS.
208 -- These pushes must be performed before we can refer to the stack in
210 emitCCS :: CostCentreStack -> FCode CmmExpr
211 emitCCS ccs = push_em (ccsExpr ccs') (reverse cc's)
213 (cc's, ccs') = decomposeCCS ccs
215 push_em ccs [] = return ccs
216 push_em ccs (cc:rest) = do
217 tmp <- newTemp ccsType
218 pushCostCentre tmp ccs cc
219 push_em (CmmReg (CmmLocal tmp)) rest
221 ccsExpr :: CostCentreStack -> CmmExpr
223 | isCurrentCCS ccs = curCCS
224 | otherwise = CmmLit (mkCCostCentreStack ccs)
227 isBox :: StgExpr -> Bool
228 -- If it's an utterly trivial RHS, then it must be
229 -- one introduced by boxHigherOrderArgs for profiling,
230 -- so we charge it to "OVERHEAD".
231 -- This looks like a GROSS HACK to me --SDM
232 isBox (StgApp fun []) = True
236 -- -----------------------------------------------------------------------
237 -- Setting the current cost centre on entry to a closure
239 -- For lexically scoped profiling we have to load the cost centre from
240 -- the closure entered, if the costs are not supposed to be inherited.
241 -- This is done immediately on entering the fast entry point.
243 -- Load current cost centre from closure, if not inherited.
244 -- Node is guaranteed to point to it, if profiling and not inherited.
249 -> StgExpr -- The RHS of the closure
252 -- We used to have a special case for bindings of form
254 -- where g has arity 2. The RHS is a thunk, but we don't
255 -- need to update it; and we want to subsume costs.
256 -- We don't have these sort of PAPs any more, so the special
257 -- case has gone away.
259 enterCostCentre closure_info ccs body
261 ASSERT2(not (noCCSAttached ccs), ppr (closureName closure_info) <+> ppr ccs)
262 enter_cost_centre closure_info ccs body
264 enter_cost_centre closure_info ccs body
266 = ASSERT(isToplevClosure closure_info)
270 | isDerivedFromCurrentCCS ccs
272 if re_entrant && not is_box
274 enter_ccs_fun node_ccs
276 emit (mkStore curCCSAddr node_ccs)
278 -- don't forget to bump the scc count. This closure might have been
279 -- of the form let x = _scc_ "x" e in ...x..., which the SCCfinal
280 -- pass has turned into simply let x = e in ...x... and attached
281 -- the _scc_ as PushCostCentre(x,CCCS) on the x closure. So that
282 -- we don't lose the scc counter, bump it in the entry code for x.
283 -- ToDo: for a multi-push we should really bump the counter for
284 -- each of the intervening CCSs, not just the top one.
285 ; when (not (isCurrentCCS ccs)) $
286 emit (bumpSccCount curCCS)
290 = ASSERT(isToplevClosure closure_info)
291 ASSERT(not re_entrant)
292 do { -- This is just a special case of the isDerivedFromCurrentCCS
293 -- case above. We could delete this, but it's a micro
294 -- optimisation and saves a bit of code.
295 emit (mkStore curCCSAddr enc_ccs)
296 ; emit (bumpSccCount node_ccs)
300 = panic "enterCostCentre"
302 enc_ccs = CmmLit (mkCCostCentreStack ccs)
303 re_entrant = closureReEntrant closure_info
304 node_ccs = costCentreFrom (cmmOffsetB (CmmReg nodeReg) (-node_tag))
307 -- if this is a function, then node will be tagged; we must subract the tag
308 node_tag = funTag closure_info
310 -- set the current CCS when entering a PAP
311 enterCostCentrePAP :: CmmExpr -> FCode ()
312 enterCostCentrePAP closure =
314 enter_ccs_fun (costCentreFrom closure)
317 enterCostCentreThunk :: CmmExpr -> FCode ()
318 enterCostCentreThunk closure =
320 emit $ mkStore curCCSAddr (costCentreFrom closure)
322 enter_ccs_fun stack = emitRtsCall (sLit "EnterFunCCS") [(stack,AddrHint)] False
325 enter_ccs_fsub = enteringPAP 0
327 -- When entering a PAP, EnterFunCCS is called by both the PAP entry
328 -- code and the function entry code; we don't want the function's
329 -- entry code to also update CCCS in the event that it was called via
330 -- a PAP, so we set the flag entering_PAP to indicate that we are
331 -- entering via a PAP.
332 enteringPAP :: Integer -> FCode ()
334 = emit (mkStore (CmmLit (CmmLabel (mkRtsDataLabel (sLit "entering_PAP"))))
335 (CmmLit (CmmInt n cIntWidth)))
337 ifProfiling :: FCode () -> FCode ()
339 | opt_SccProfilingOn = code
342 ifProfilingL :: [a] -> [a]
344 | opt_SccProfilingOn = xs
348 ---------------------------------------------------------------
349 -- Initialising Cost Centres & CCSs
350 ---------------------------------------------------------------
352 initCostCentres :: CollectedCCs -> FCode CmmAGraph
353 -- Emit the declarations, and return code to register them
354 initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs)
355 = getCode $ whenC opt_SccProfilingOn $
356 do { mapM_ emitCostCentreDecl local_CCs
357 ; mapM_ emitCostCentreStackDecl singleton_CCSs
358 ; emit $ catAGraphs $ map mkRegisterCC local_CCs
359 ; emit $ catAGraphs $ map mkRegisterCCS singleton_CCSs }
362 emitCostCentreDecl :: CostCentre -> FCode ()
363 emitCostCentreDecl cc = do
364 { label <- mkStringCLit (costCentreUserName cc)
365 ; modl <- mkStringCLit (Module.moduleNameString
366 (Module.moduleName (cc_mod cc)))
367 -- All cost centres will be in the main package, since we
368 -- don't normally use -auto-all or add SCCs to other packages.
369 -- Hence don't emit the package name in the module here.
370 ; let lits = [ zero, -- StgInt ccID,
371 label, -- char *label,
372 modl, -- char *module,
373 zero, -- StgWord time_ticks
374 zero64, -- StgWord64 mem_alloc
375 subsumed, -- StgInt is_caf
376 zero -- struct _CostCentre *link
378 ; emitDataLits (mkCCLabel cc) lits
381 subsumed | isCafCC cc = mkIntCLit (ord 'c') -- 'c' == is a CAF
382 | otherwise = mkIntCLit (ord 'B') -- 'B' == is boring
384 emitCostCentreStackDecl :: CostCentreStack -> FCode ()
385 emitCostCentreStackDecl ccs
386 = case maybeSingletonCCS ccs of
387 Just cc -> emitDataLits (mkCCSLabel ccs) (mk_lits cc)
388 Nothing -> pprPanic "emitCostCentreStackDecl" (ppr ccs)
392 replicate (sizeof_ccs_words - 2) zero
393 -- Note: to avoid making any assumptions about how the
394 -- C compiler (that compiles the RTS, in particular) does
395 -- layouts of structs containing long-longs, simply
396 -- pad out the struct with zero words until we hit the
397 -- size of the overall struct (which we get via DerivedConstants.h)
400 zero64 = CmmInt 0 W64
402 sizeof_ccs_words :: Int
404 -- round up to the next word.
408 (ws,ms) = SIZEOF_CostCentreStack `divMod` wORD_SIZE
410 -- ---------------------------------------------------------------------------
411 -- Registering CCs and CCSs
413 -- (cc)->link = CC_LIST;
415 -- (cc)->ccID = CC_ID++;
417 mkRegisterCC :: CostCentre -> CmmAGraph
419 = withTemp cInt $ \tmp ->
421 mkStore (cmmOffsetB cc_lit oFFSET_CostCentre_link)
422 (CmmLoad cC_LIST bWord),
423 mkStore cC_LIST cc_lit,
424 mkAssign (CmmLocal tmp) (CmmLoad cC_ID cInt),
425 mkStore (cmmOffsetB cc_lit oFFSET_CostCentre_ccID) (CmmReg (CmmLocal tmp)),
426 mkStore cC_ID (cmmRegOffB (CmmLocal tmp) 1)
429 cc_lit = CmmLit (CmmLabel (mkCCLabel cc))
431 -- (ccs)->prevStack = CCS_LIST;
433 -- (ccs)->ccsID = CCS_ID++;
435 mkRegisterCCS :: CostCentreStack -> CmmAGraph
437 = withTemp cInt $ \ tmp ->
439 mkStore (cmmOffsetB ccs_lit oFFSET_CostCentreStack_prevStack)
440 (CmmLoad cCS_LIST bWord),
441 mkStore cCS_LIST ccs_lit,
442 mkAssign (CmmLocal tmp) (CmmLoad cCS_ID cInt),
443 mkStore (cmmOffsetB ccs_lit oFFSET_CostCentreStack_ccsID) (CmmReg (CmmLocal tmp)),
444 mkStore cCS_ID (cmmRegOffB (CmmLocal tmp) 1)
447 ccs_lit = CmmLit (CmmLabel (mkCCSLabel ccs))
450 cC_LIST = CmmLit (CmmLabel (mkRtsDataLabel (sLit "CC_LIST")))
451 cC_ID = CmmLit (CmmLabel (mkRtsDataLabel (sLit "CC_ID")))
453 cCS_LIST = CmmLit (CmmLabel (mkRtsDataLabel (sLit "CCS_LIST")))
454 cCS_ID = CmmLit (CmmLabel (mkRtsDataLabel (sLit "CCS_ID")))
456 -- ---------------------------------------------------------------------------
457 -- Set the current cost centre stack
459 emitSetCCC :: CostCentre -> FCode ()
461 | not opt_SccProfilingOn = nopC
463 tmp <- newTemp ccsType -- TODO FIXME NOW
464 ASSERT( sccAbleCostCentre cc )
465 pushCostCentre tmp curCCS cc
466 emit (mkStore curCCSAddr (CmmReg (CmmLocal tmp)))
467 when (isSccCountCostCentre cc) $
468 emit (bumpSccCount curCCS)
470 pushCostCentre :: LocalReg -> CmmExpr -> CostCentre -> FCode ()
471 pushCostCentre result ccs cc
472 = emitRtsCallWithResult result AddrHint
473 (sLit "PushCostCentre") [(ccs,AddrHint),
474 (CmmLit (mkCCostCentre cc), AddrHint)]
477 bumpSccCount :: CmmExpr -> CmmAGraph
479 = addToMem REP_CostCentreStack_scc_count
480 (cmmOffsetB ccs oFFSET_CostCentreStack_scc_count) 1
482 -----------------------------------------------------------------------------
484 -- Lag/drag/void stuff
486 -----------------------------------------------------------------------------
489 -- Initial value for the LDV field in a static closure
491 staticLdvInit :: CmmLit
492 staticLdvInit = zeroCLit
495 -- Initial value of the LDV field in a dynamic closure
497 dynLdvInit :: CmmExpr
498 dynLdvInit = -- (era << LDV_SHIFT) | LDV_STATE_CREATE
499 CmmMachOp mo_wordOr [
500 CmmMachOp mo_wordShl [loadEra, CmmLit (mkIntCLit lDV_SHIFT) ],
501 CmmLit (mkWordCLit lDV_STATE_CREATE)
505 -- Initialise the LDV word of a new closure
507 ldvRecordCreate :: CmmExpr -> FCode ()
508 ldvRecordCreate closure = emit $ mkStore (ldvWord closure) dynLdvInit
511 -- Called when a closure is entered, marks the closure as having been "used".
512 -- The closure is not an 'inherently used' one.
513 -- The closure is not IND or IND_OLDGEN because neither is considered for LDV
516 ldvEnterClosure :: ClosureInfo -> FCode ()
517 ldvEnterClosure closure_info = ldvEnter (cmmOffsetB (CmmReg nodeReg) (-tag))
518 where tag = funTag closure_info
519 -- don't forget to substract node's tag
521 ldvEnter :: CmmExpr -> FCode ()
522 -- Argument is a closure pointer
526 -- LDVW((c)) = (LDVW((c)) & LDV_CREATE_MASK) |
527 -- era | LDV_STATE_USE }
528 emit (mkCmmIfThenElse (CmmMachOp mo_wordUGt [loadEra, CmmLit zeroCLit])
529 (mkStore ldv_wd new_ldv_wd)
532 -- don't forget to substract node's tag
533 ldv_wd = ldvWord cl_ptr
534 new_ldv_wd = cmmOrWord (cmmAndWord (CmmLoad ldv_wd bWord)
535 (CmmLit (mkWordCLit lDV_CREATE_MASK)))
536 (cmmOrWord loadEra (CmmLit (mkWordCLit lDV_STATE_USE)))
539 loadEra = CmmMachOp (MO_UU_Conv cIntWidth wordWidth)
540 [CmmLoad (mkLblExpr (mkRtsDataLabel (sLit "era"))) cInt]
542 ldvWord :: CmmExpr -> CmmExpr
543 -- Takes the address of a closure, and returns
544 -- the address of the LDV word in the closure
545 ldvWord closure_ptr = cmmOffsetB closure_ptr oFFSET_StgHeader_ldvw
547 -- LDV constants, from ghc/includes/Constants.h
548 lDV_SHIFT = (LDV_SHIFT :: Int)
549 --lDV_STATE_MASK = (LDV_STATE_MASK :: StgWord)
550 lDV_CREATE_MASK = (LDV_CREATE_MASK :: StgWord)
551 --lDV_LAST_MASK = (LDV_LAST_MASK :: StgWord)
552 lDV_STATE_CREATE = (LDV_STATE_CREATE :: StgWord)
553 lDV_STATE_USE = (LDV_STATE_USE :: StgWord)