1 -----------------------------------------------------------------------------
3 -- Code generation for profiling
5 -- (c) The University of Glasgow 2004-2006
7 -----------------------------------------------------------------------------
10 initCostCentres, ccType, ccsType,
11 mkCCostCentre, mkCCostCentreStack,
13 -- Cost-centre Profiling
14 dynProfHdr, profDynAlloc, profAlloc, staticProfHdr, initUpdFrameProf,
15 enterCostCentre, enterCostCentrePAP, enterCostCentreThunk,
21 saveCurrentCostCentre, restoreCurrentCostCentre,
23 -- Lag/drag/void stuff
24 ldvEnter, ldvEnterClosure, ldvRecordCreate
27 #include "HsVersions.h"
28 #include "../includes/MachDeps.h"
29 -- For WORD_SIZE_IN_BITS only.
30 #include "../includes/rts/Constants.h"
31 -- For LDV_CREATE_MASK, LDV_STATE_USE
33 #include "../includes/DerivedConstants.h"
34 -- For REP_xxx constants, which are MachReps
48 import qualified Module
54 import Constants -- Lots of field offsets
60 -----------------------------------------------------------------------------
62 -- Cost-centre-stack Profiling
64 -----------------------------------------------------------------------------
66 -- Expression representing the current cost centre stack
67 ccsType :: CmmType -- Type of a cost-centre stack
70 ccType :: CmmType -- Type of a cost centre
74 curCCS = CmmLoad curCCSAddr ccsType
76 -- Address of current CCS variable, for storing into
78 curCCSAddr = CmmLit (CmmLabel (mkCmmDataLabel rtsPackageId (fsLit "CCCS")))
80 mkCCostCentre :: CostCentre -> CmmLit
81 mkCCostCentre cc = CmmLabel (mkCCLabel cc)
83 mkCCostCentreStack :: CostCentreStack -> CmmLit
84 mkCCostCentreStack ccs = CmmLabel (mkCCSLabel ccs)
86 costCentreFrom :: CmmExpr -- A closure pointer
87 -> CmmExpr -- The cost centre from that closure
88 costCentreFrom cl = CmmLoad (cmmOffsetB cl oFFSET_StgHeader_ccs) ccsType
90 staticProfHdr :: CostCentreStack -> [CmmLit]
91 -- The profiling header words in a static closure
92 -- Was SET_STATIC_PROF_HDR
93 staticProfHdr ccs = ifProfilingL [mkCCostCentreStack ccs,
96 dynProfHdr :: CmmExpr -> [CmmExpr]
97 -- Profiling header words in a dynamic closure
98 dynProfHdr ccs = ifProfilingL [ccs, dynLdvInit]
100 initUpdFrameProf :: CmmExpr -> FCode ()
101 -- Initialise the profiling field of an update frame
102 initUpdFrameProf frame_amode
103 = ifProfiling $ -- frame->header.prof.ccs = CCCS
104 emit (mkStore (cmmOffsetB frame_amode oFFSET_StgHeader_ccs) curCCS)
105 -- frame->header.prof.hp.rs = NULL (or frame-header.prof.hp.ldvw = 0)
106 -- is unnecessary because it is not used anyhow.
108 ---------------------------------------------------------------------------
109 -- Saving and restoring the current cost centre
110 ---------------------------------------------------------------------------
112 {- Note [Saving the current cost centre]
113 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
114 The current cost centre is like a global register. Like other
115 global registers, it's a caller-saves one. But consider
116 case (f x) of (p,q) -> rhs
117 Since 'f' may set the cost centre, we must restore it
118 before resuming rhs. So we want code like this:
119 local_cc = CCC -- save
121 CCC = local_cc -- restore
122 That is, we explicitly "save" the current cost centre in
123 a LocalReg, local_cc; and restore it after the call. The
124 C-- infrastructure will arrange to save local_cc across the
127 The same goes for join points;
130 We want this kind of code:
131 local_cc = CCC -- save
134 CCC = local_cc -- restore
137 saveCurrentCostCentre :: FCode (Maybe LocalReg)
138 -- Returns Nothing if profiling is off
139 saveCurrentCostCentre
140 | not opt_SccProfilingOn
143 = do { local_cc <- newTemp ccType
144 ; emit (mkAssign (CmmLocal local_cc) curCCS)
145 ; return (Just local_cc) }
147 restoreCurrentCostCentre :: Maybe LocalReg -> FCode ()
148 restoreCurrentCostCentre Nothing
150 restoreCurrentCostCentre (Just local_cc)
151 = emit (mkStore curCCSAddr (CmmReg (CmmLocal local_cc)))
154 -------------------------------------------------------------------------------
155 -- Recording allocation in a cost centre
156 -------------------------------------------------------------------------------
158 -- | Record the allocation of a closure. The CmmExpr is the cost
159 -- centre stack to which to attribute the allocation.
160 profDynAlloc :: ClosureInfo -> CmmExpr -> FCode ()
161 profDynAlloc cl_info ccs
163 profAlloc (CmmLit (mkIntCLit (closureSize cl_info))) ccs
165 -- | Record the allocation of a closure (size is given by a CmmExpr)
166 -- The size must be in words, because the allocation counter in a CCS counts
168 profAlloc :: CmmExpr -> CmmExpr -> FCode ()
171 emit (addToMemE alloc_rep
172 (cmmOffsetB ccs oFFSET_CostCentreStack_mem_alloc)
173 (CmmMachOp (MO_UU_Conv wordWidth (typeWidth alloc_rep)) $
174 [CmmMachOp mo_wordSub [words,
175 CmmLit (mkIntCLit profHdrSize)]]))
176 -- subtract the "profiling overhead", which is the
177 -- profiling header in a closure.
179 alloc_rep = REP_CostCentreStack_mem_alloc
181 -- ----------------------------------------------------------------------
182 -- Setting the cost centre in a new closure
184 chooseDynCostCentres :: CostCentreStack
187 -> FCode (CmmExpr, CmmExpr)
188 -- Called when allocating a closure
189 -- Tells which cost centre to put in the object, and which
190 -- to blame the cost of allocation on
191 chooseDynCostCentres ccs args body = do
192 -- Cost-centre we record in the object
193 use_ccs <- emitCCS ccs
195 -- Cost-centre on whom we blame the allocation
197 | null args && isBox body = CmmLit (mkCCostCentreStack overheadCCS)
198 | otherwise = use_ccs
200 return (use_ccs, blame_ccs)
203 -- Some CostCentreStacks are a sequence of pushes on top of CCCS.
204 -- These pushes must be performed before we can refer to the stack in
206 emitCCS :: CostCentreStack -> FCode CmmExpr
207 emitCCS ccs = push_em (ccsExpr ccs') (reverse cc's)
209 (cc's, ccs') = decomposeCCS ccs
211 push_em ccs [] = return ccs
212 push_em ccs (cc:rest) = do
213 tmp <- newTemp ccsType
214 pushCostCentre tmp ccs cc
215 push_em (CmmReg (CmmLocal tmp)) rest
217 ccsExpr :: CostCentreStack -> CmmExpr
219 | isCurrentCCS ccs = curCCS
220 | otherwise = CmmLit (mkCCostCentreStack ccs)
223 isBox :: StgExpr -> Bool
224 -- If it's an utterly trivial RHS, then it must be
225 -- one introduced by boxHigherOrderArgs for profiling,
226 -- so we charge it to "OVERHEAD".
227 -- This looks like a GROSS HACK to me --SDM
228 isBox (StgApp _ []) = True
232 -- -----------------------------------------------------------------------
233 -- Setting the current cost centre on entry to a closure
235 -- For lexically scoped profiling we have to load the cost centre from
236 -- the closure entered, if the costs are not supposed to be inherited.
237 -- This is done immediately on entering the fast entry point.
239 -- Load current cost centre from closure, if not inherited.
240 -- Node is guaranteed to point to it, if profiling and not inherited.
245 -> StgExpr -- The RHS of the closure
248 -- We used to have a special case for bindings of form
250 -- where g has arity 2. The RHS is a thunk, but we don't
251 -- need to update it; and we want to subsume costs.
252 -- We don't have these sort of PAPs any more, so the special
253 -- case has gone away.
255 enterCostCentre closure_info ccs body
257 ASSERT2(not (noCCSAttached ccs), ppr (closureName closure_info) <+> ppr ccs)
258 enter_cost_centre closure_info ccs body
260 enter_cost_centre :: ClosureInfo -> CostCentreStack -> StgExpr -> FCode ()
261 enter_cost_centre closure_info ccs body
263 = ASSERT(isToplevClosure closure_info)
267 | isDerivedFromCurrentCCS ccs
269 if re_entrant && not is_box
271 enter_ccs_fun node_ccs
273 emit (mkStore curCCSAddr node_ccs)
275 -- don't forget to bump the scc count. This closure might have been
276 -- of the form let x = _scc_ "x" e in ...x..., which the SCCfinal
277 -- pass has turned into simply let x = e in ...x... and attached
278 -- the _scc_ as PushCostCentre(x,CCCS) on the x closure. So that
279 -- we don't lose the scc counter, bump it in the entry code for x.
280 -- ToDo: for a multi-push we should really bump the counter for
281 -- each of the intervening CCSs, not just the top one.
282 ; when (not (isCurrentCCS ccs)) $
283 emit (bumpSccCount curCCS)
287 = ASSERT(isToplevClosure closure_info)
288 ASSERT(not re_entrant)
289 do { -- This is just a special case of the isDerivedFromCurrentCCS
290 -- case above. We could delete this, but it's a micro
291 -- optimisation and saves a bit of code.
292 emit (mkStore curCCSAddr enc_ccs)
293 ; emit (bumpSccCount node_ccs)
297 = panic "enterCostCentre"
299 enc_ccs = CmmLit (mkCCostCentreStack ccs)
300 re_entrant = closureReEntrant closure_info
301 node_ccs = costCentreFrom (cmmOffsetB (CmmReg nodeReg) (-node_tag))
304 -- if this is a function, then node will be tagged; we must subract the tag
305 node_tag = funTag closure_info
307 -- set the current CCS when entering a PAP
308 enterCostCentrePAP :: CmmExpr -> FCode ()
309 enterCostCentrePAP closure =
311 enter_ccs_fun (costCentreFrom closure)
314 enterCostCentreThunk :: CmmExpr -> FCode ()
315 enterCostCentreThunk closure =
317 emit $ mkStore curCCSAddr (costCentreFrom closure)
319 enter_ccs_fun :: CmmExpr -> FCode ()
320 enter_ccs_fun stack = emitRtsCall rtsPackageId (fsLit "EnterFunCCS") [(stack,AddrHint)] False
323 enter_ccs_fsub :: FCode ()
324 enter_ccs_fsub = enteringPAP 0
326 -- When entering a PAP, EnterFunCCS is called by both the PAP entry
327 -- code and the function entry code; we don't want the function's
328 -- entry code to also update CCCS in the event that it was called via
329 -- a PAP, so we set the flag entering_PAP to indicate that we are
330 -- entering via a PAP.
331 enteringPAP :: Integer -> FCode ()
333 = emit (mkStore (CmmLit (CmmLabel (mkCmmDataLabel rtsPackageId (fsLit "entering_PAP"))))
334 (CmmLit (CmmInt n cIntWidth)))
336 ifProfiling :: FCode () -> FCode ()
338 | opt_SccProfilingOn = code
341 ifProfilingL :: [a] -> [a]
343 | opt_SccProfilingOn = xs
347 ---------------------------------------------------------------
348 -- Initialising Cost Centres & CCSs
349 ---------------------------------------------------------------
351 initCostCentres :: CollectedCCs -> FCode CmmAGraph
352 -- Emit the declarations, and return code to register them
353 initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs)
354 = getCode $ whenC opt_SccProfilingOn $
355 do { mapM_ emitCostCentreDecl local_CCs
356 ; mapM_ emitCostCentreStackDecl singleton_CCSs
357 ; emit $ catAGraphs $ map mkRegisterCC local_CCs
358 ; emit $ catAGraphs $ map mkRegisterCCS singleton_CCSs }
361 emitCostCentreDecl :: CostCentre -> FCode ()
362 emitCostCentreDecl cc = do
363 { label <- mkStringCLit (costCentreUserName cc)
364 ; modl <- mkStringCLit (Module.moduleNameString
365 (Module.moduleName (cc_mod cc)))
366 -- All cost centres will be in the main package, since we
367 -- don't normally use -auto-all or add SCCs to other packages.
368 -- Hence don't emit the package name in the module here.
369 ; let lits = [ zero, -- StgInt ccID,
370 label, -- char *label,
371 modl, -- char *module,
372 zero, -- StgWord time_ticks
373 zero64, -- StgWord64 mem_alloc
374 subsumed, -- StgInt is_caf
375 zero -- struct _CostCentre *link
377 ; emitDataLits (mkCCLabel cc) lits
380 subsumed | isCafCC cc = mkIntCLit (ord 'c') -- 'c' == is a CAF
381 | otherwise = mkIntCLit (ord 'B') -- 'B' == is boring
383 emitCostCentreStackDecl :: CostCentreStack -> FCode ()
384 emitCostCentreStackDecl ccs
385 = case maybeSingletonCCS ccs of
386 Just cc -> emitDataLits (mkCCSLabel ccs) (mk_lits cc)
387 Nothing -> pprPanic "emitCostCentreStackDecl" (ppr ccs)
391 replicate (sizeof_ccs_words - 2) zero
392 -- Note: to avoid making any assumptions about how the
393 -- C compiler (that compiles the RTS, in particular) does
394 -- layouts of structs containing long-longs, simply
395 -- pad out the struct with zero words until we hit the
396 -- size of the overall struct (which we get via DerivedConstants.h)
401 zero64 = CmmInt 0 W64
403 sizeof_ccs_words :: Int
405 -- round up to the next word.
409 (ws,ms) = SIZEOF_CostCentreStack `divMod` wORD_SIZE
411 -- ---------------------------------------------------------------------------
412 -- Registering CCs and CCSs
414 -- (cc)->link = CC_LIST;
416 -- (cc)->ccID = CC_ID++;
418 mkRegisterCC :: CostCentre -> CmmAGraph
420 = withTemp cInt $ \tmp ->
422 mkStore (cmmOffsetB cc_lit oFFSET_CostCentre_link)
423 (CmmLoad cC_LIST bWord),
424 mkStore cC_LIST cc_lit,
425 mkAssign (CmmLocal tmp) (CmmLoad cC_ID cInt),
426 mkStore (cmmOffsetB cc_lit oFFSET_CostCentre_ccID) (CmmReg (CmmLocal tmp)),
427 mkStore cC_ID (cmmRegOffB (CmmLocal tmp) 1)
430 cc_lit = CmmLit (CmmLabel (mkCCLabel cc))
432 -- (ccs)->prevStack = CCS_LIST;
434 -- (ccs)->ccsID = CCS_ID++;
436 mkRegisterCCS :: CostCentreStack -> CmmAGraph
438 = withTemp cInt $ \ tmp ->
440 mkStore (cmmOffsetB ccs_lit oFFSET_CostCentreStack_prevStack)
441 (CmmLoad cCS_LIST bWord),
442 mkStore cCS_LIST ccs_lit,
443 mkAssign (CmmLocal tmp) (CmmLoad cCS_ID cInt),
444 mkStore (cmmOffsetB ccs_lit oFFSET_CostCentreStack_ccsID) (CmmReg (CmmLocal tmp)),
445 mkStore cCS_ID (cmmRegOffB (CmmLocal tmp) 1)
448 ccs_lit = CmmLit (CmmLabel (mkCCSLabel ccs))
451 cC_LIST, cC_ID :: CmmExpr
452 cC_LIST = CmmLit (CmmLabel (mkCmmDataLabel rtsPackageId (fsLit "CC_LIST")))
453 cC_ID = CmmLit (CmmLabel (mkCmmDataLabel rtsPackageId (fsLit "CC_ID")))
455 cCS_LIST, cCS_ID :: CmmExpr
456 cCS_LIST = CmmLit (CmmLabel (mkCmmDataLabel rtsPackageId (fsLit "CCS_LIST")))
457 cCS_ID = CmmLit (CmmLabel (mkCmmDataLabel rtsPackageId (fsLit "CCS_ID")))
459 -- ---------------------------------------------------------------------------
460 -- Set the current cost centre stack
462 emitSetCCC :: CostCentre -> FCode ()
464 | not opt_SccProfilingOn = nopC
466 tmp <- newTemp ccsType -- TODO FIXME NOW
467 ASSERT( sccAbleCostCentre cc )
468 pushCostCentre tmp curCCS cc
469 emit (mkStore curCCSAddr (CmmReg (CmmLocal tmp)))
470 when (isSccCountCostCentre cc) $
471 emit (bumpSccCount curCCS)
473 pushCostCentre :: LocalReg -> CmmExpr -> CostCentre -> FCode ()
474 pushCostCentre result ccs cc
475 = emitRtsCallWithResult result AddrHint
477 (fsLit "PushCostCentre") [(ccs,AddrHint),
478 (CmmLit (mkCCostCentre cc), AddrHint)]
481 bumpSccCount :: CmmExpr -> CmmAGraph
483 = addToMem REP_CostCentreStack_scc_count
484 (cmmOffsetB ccs oFFSET_CostCentreStack_scc_count) 1
486 -----------------------------------------------------------------------------
488 -- Lag/drag/void stuff
490 -----------------------------------------------------------------------------
493 -- Initial value for the LDV field in a static closure
495 staticLdvInit :: CmmLit
496 staticLdvInit = zeroCLit
499 -- Initial value of the LDV field in a dynamic closure
501 dynLdvInit :: CmmExpr
502 dynLdvInit = -- (era << LDV_SHIFT) | LDV_STATE_CREATE
503 CmmMachOp mo_wordOr [
504 CmmMachOp mo_wordShl [loadEra, CmmLit (mkIntCLit lDV_SHIFT) ],
505 CmmLit (mkWordCLit lDV_STATE_CREATE)
509 -- Initialise the LDV word of a new closure
511 ldvRecordCreate :: CmmExpr -> FCode ()
512 ldvRecordCreate closure = emit $ mkStore (ldvWord closure) dynLdvInit
515 -- Called when a closure is entered, marks the closure as having been "used".
516 -- The closure is not an 'inherently used' one.
517 -- The closure is not IND or IND_OLDGEN because neither is considered for LDV
520 ldvEnterClosure :: ClosureInfo -> FCode ()
521 ldvEnterClosure closure_info = ldvEnter (cmmOffsetB (CmmReg nodeReg) (-tag))
522 where tag = funTag closure_info
523 -- don't forget to substract node's tag
525 ldvEnter :: CmmExpr -> FCode ()
526 -- Argument is a closure pointer
530 -- LDVW((c)) = (LDVW((c)) & LDV_CREATE_MASK) |
531 -- era | LDV_STATE_USE }
532 emit (mkCmmIfThenElse (CmmMachOp mo_wordUGt [loadEra, CmmLit zeroCLit])
533 (mkStore ldv_wd new_ldv_wd)
536 -- don't forget to substract node's tag
537 ldv_wd = ldvWord cl_ptr
538 new_ldv_wd = cmmOrWord (cmmAndWord (CmmLoad ldv_wd bWord)
539 (CmmLit (mkWordCLit lDV_CREATE_MASK)))
540 (cmmOrWord loadEra (CmmLit (mkWordCLit lDV_STATE_USE)))
543 loadEra = CmmMachOp (MO_UU_Conv cIntWidth wordWidth)
544 [CmmLoad (mkLblExpr (mkCmmDataLabel rtsPackageId (fsLit "era"))) cInt]
546 ldvWord :: CmmExpr -> CmmExpr
547 -- Takes the address of a closure, and returns
548 -- the address of the LDV word in the closure
549 ldvWord closure_ptr = cmmOffsetB closure_ptr oFFSET_StgHeader_ldvw
551 -- LDV constants, from ghc/includes/Constants.h
553 lDV_SHIFT = LDV_SHIFT
554 --lDV_STATE_MASK :: StgWord
555 --lDV_STATE_MASK = LDV_STATE_MASK
556 lDV_CREATE_MASK :: StgWord
557 lDV_CREATE_MASK = LDV_CREATE_MASK
558 --lDV_LAST_MASK :: StgWord
559 --lDV_LAST_MASK = LDV_LAST_MASK
560 lDV_STATE_CREATE :: StgWord
561 lDV_STATE_CREATE = LDV_STATE_CREATE
562 lDV_STATE_USE :: StgWord
563 lDV_STATE_USE = LDV_STATE_USE