1 -----------------------------------------------------------------------------
3 -- Code generation for profiling
5 -- (c) The University of Glasgow 2004
7 -----------------------------------------------------------------------------
10 mkCCostCentre, mkCCostCentreStack,
12 -- Cost-centre Profiling
13 dynProfHdr, profDynAlloc, profAlloc, staticProfHdr, initUpdFrameProf,
14 enterCostCentre, enterCostCentrePAP, enterCostCentreThunk,
18 emitCostCentreDecl, emitCostCentreStackDecl,
19 emitRegisterCC, emitRegisterCCS,
22 -- Lag/drag/void stuff
23 ldvEnter, ldvRecordCreate
26 #include "HsVersions.h"
27 #include "../includes/Constants.h"
28 -- For LDV_CREATE_MASK, LDV_STATE_USE
30 #include "../includes/DerivedConstants.h"
31 -- For REP_xxx constants, which are MachReps
33 import ClosureInfo ( ClosureInfo, closureSize,
34 closureName, isToplevClosure, closureReEntrant, )
37 import SMRep ( StgWord, profHdrSize )
41 import CmmUtils ( zeroCLit, mkIntCLit, mkLblExpr )
42 import CLabel ( mkCCLabel, mkCCSLabel, mkRtsDataLabel )
44 import Module ( moduleUserString )
47 import StgSyn ( GenStgExpr(..), StgExpr )
48 import CmdLineOpts ( opt_SccProfilingOn )
49 import FastString ( FastString, mkFastString, LitString )
50 import Constants -- Lots of field offsets
57 -----------------------------------------------------------------------------
59 -- Cost-centre-stack Profiling
61 -----------------------------------------------------------------------------
63 -- Expression representing the current cost centre stack
65 curCCS = CmmLoad curCCSAddr wordRep
67 -- Address of current CCS variable, for storing into
69 curCCSAddr = CmmLit (CmmLabel (mkRtsDataLabel SLIT("CCCS")))
71 mkCCostCentre :: CostCentre -> CmmLit
72 mkCCostCentre cc = CmmLabel (mkCCLabel cc)
74 mkCCostCentreStack :: CostCentreStack -> CmmLit
75 mkCCostCentreStack ccs = CmmLabel (mkCCSLabel ccs)
77 costCentreFrom :: CmmExpr -- A closure pointer
78 -> CmmExpr -- The cost centre from that closure
79 costCentreFrom cl = CmmLoad (cmmOffsetB cl oFFSET_StgHeader_ccs) wordRep
81 staticProfHdr :: CostCentreStack -> [CmmLit]
82 -- The profiling header words in a static closure
83 -- Was SET_STATIC_PROF_HDR
84 staticProfHdr ccs = ifProfilingL [mkCCostCentreStack ccs,
87 dynProfHdr :: CmmExpr -> [CmmExpr]
88 -- Profiling header words in a dynamic closure
89 dynProfHdr ccs = ifProfilingL [ccs, dynLdvInit]
91 initUpdFrameProf :: CmmExpr -> Code
92 -- Initialise the profiling field of an update frame
93 initUpdFrameProf frame_amode
94 = ifProfiling $ -- frame->header.prof.ccs = CCCS
95 stmtC (CmmStore (cmmOffsetB frame_amode oFFSET_StgHeader_ccs) curCCS)
96 -- frame->header.prof.hp.rs = NULL (or frame-header.prof.hp.ldvw = 0)
97 -- is unnecessary because it is not used anyhow.
99 -- -----------------------------------------------------------------------------
100 -- Recording allocation in a cost centre
102 -- | Record the allocation of a closure. The CmmExpr is the cost
103 -- centre stack to which to attribute the allocation.
104 profDynAlloc :: ClosureInfo -> CmmExpr -> Code
105 profDynAlloc cl_info ccs
107 profAlloc (CmmLit (mkIntCLit (closureSize cl_info))) ccs
109 -- | Record the allocation of a closure (size is given by a CmmExpr)
110 -- The size must be in words, because the allocation counter in a CCS counts
112 profAlloc :: CmmExpr -> CmmExpr -> Code
115 stmtC (addToMemE alloc_rep
116 (cmmOffsetB ccs oFFSET_CostCentreStack_mem_alloc)
117 (CmmMachOp (MO_U_Conv wordRep alloc_rep) $
118 [CmmMachOp mo_wordSub [words,
119 CmmLit (mkIntCLit profHdrSize)]]))
120 -- subtract the "profiling overhead", which is the
121 -- profiling header in a closure.
123 alloc_rep = REP_CostCentreStack_mem_alloc
125 -- ----------------------------------------------------------------------
126 -- Setting the cost centre in a new closure
128 chooseDynCostCentres :: CostCentreStack
131 -> FCode (CmmExpr, CmmExpr)
132 -- Called when alllcating a closure
133 -- Tells which cost centre to put in the object, and which
134 -- to blame the cost of allocation on
135 chooseDynCostCentres ccs args body = do
136 -- Cost-centre we record in the object
137 use_ccs <- emitCCS ccs
139 -- Cost-centre on whom we blame the allocation
141 | null args && isBox body = CmmLit (mkCCostCentreStack overheadCCS)
142 | otherwise = use_ccs
144 return (use_ccs, blame_ccs)
147 -- Some CostCentreStacks are a sequence of pushes on top of CCCS.
148 -- These pushes must be performed before we can refer to the stack in
150 emitCCS :: CostCentreStack -> FCode CmmExpr
151 emitCCS ccs = push_em (ccsExpr ccs') (reverse cc's)
153 (cc's, ccs') = decomposeCCS ccs
155 push_em ccs [] = return ccs
156 push_em ccs (cc:rest) = do
157 tmp <- newTemp wordRep
158 pushCostCentre tmp ccs cc
159 push_em (CmmReg tmp) rest
161 ccsExpr :: CostCentreStack -> CmmExpr
163 | isCurrentCCS ccs = curCCS
164 | otherwise = CmmLit (mkCCostCentreStack ccs)
167 isBox :: StgExpr -> Bool
168 -- If it's an utterly trivial RHS, then it must be
169 -- one introduced by boxHigherOrderArgs for profiling,
170 -- so we charge it to "OVERHEAD".
171 -- This looks like a GROSS HACK to me --SDM
172 isBox (StgApp fun []) = True
176 -- -----------------------------------------------------------------------
177 -- Setting the current cost centre on entry to a closure
179 -- For lexically scoped profiling we have to load the cost centre from
180 -- the closure entered, if the costs are not supposed to be inherited.
181 -- This is done immediately on entering the fast entry point.
183 -- Load current cost centre from closure, if not inherited.
184 -- Node is guaranteed to point to it, if profiling and not inherited.
189 -> StgExpr -- The RHS of the closure
192 -- We used to have a special case for bindings of form
194 -- where g has arity 2. The RHS is a thunk, but we don't
195 -- need to update it; and we want to subsume costs.
196 -- We don't have these sort of PAPs any more, so the special
197 -- case has gone away.
199 enterCostCentre closure_info ccs body
201 ASSERT2(not (noCCSAttached ccs), ppr (closureName closure_info) <+> ppr ccs)
202 enter_cost_centre closure_info ccs body
204 enter_cost_centre closure_info ccs body
206 = ASSERT(isToplevClosure closure_info)
210 | isDerivedFromCurrentCCS ccs
212 if re_entrant && not is_box
214 enter_ccs_fun node_ccs
216 stmtC (CmmStore curCCSAddr node_ccs)
218 -- don't forget to bump the scc count. This closure might have been
219 -- of the form let x = _scc_ "x" e in ...x..., which the SCCfinal
220 -- pass has turned into simply let x = e in ...x... and attached
221 -- the _scc_ as PushCostCentre(x,CCCS) on the x closure. So that
222 -- we don't lose the scc counter, bump it in the entry code for x.
223 -- ToDo: for a multi-push we should really bump the counter for
224 -- each of the intervening CCSs, not just the top one.
225 ; when (not (isCurrentCCS ccs)) $
226 stmtC (bumpSccCount curCCS)
230 = ASSERT(isToplevClosure closure_info)
231 ASSERT(not re_entrant)
232 do { -- This is just a special case of the isDerivedFromCurrentCCS
233 -- case above. We could delete this, but it's a micro
234 -- optimisation and saves a bit of code.
235 stmtC (CmmStore curCCSAddr enc_ccs)
236 ; stmtC (bumpSccCount node_ccs)
240 = panic "enterCostCentre"
242 enc_ccs = CmmLit (mkCCostCentreStack ccs)
243 re_entrant = closureReEntrant closure_info
244 node_ccs = costCentreFrom (CmmReg nodeReg)
247 -- set the current CCS when entering a PAP
248 enterCostCentrePAP :: CmmExpr -> Code
249 enterCostCentrePAP closure =
251 enter_ccs_fun (costCentreFrom closure)
254 enterCostCentreThunk :: CmmExpr -> Code
255 enterCostCentreThunk closure =
257 stmtC $ CmmStore curCCSAddr (costCentreFrom closure)
259 enter_ccs_fun stack = emitRtsCall SLIT("EnterFunCCS") [(stack,PtrHint)]
261 enter_ccs_fsub = enteringPAP 0
263 -- When entering a PAP, EnterFunCCS is called by both the PAP entry
264 -- code and the function entry code; we don't want the function's
265 -- entry code to also update CCCS in the event that it was called via
266 -- a PAP, so we set the flag entering_PAP to indicate that we are
267 -- entering via a PAP.
268 enteringPAP :: Integer -> Code
270 = stmtC (CmmStore (CmmLit (CmmLabel (mkRtsDataLabel SLIT("entering_PAP"))))
271 (CmmLit (CmmInt n cIntRep)))
273 ifProfiling :: Code -> Code
275 | opt_SccProfilingOn = code
278 ifProfilingL :: [a] -> [a]
280 | opt_SccProfilingOn = xs
284 -- ---------------------------------------------------------------------------
285 -- Initialising Cost Centres & CCSs
290 emitCostCentreDecl cc = do
291 { label <- mkStringCLit (costCentreUserName cc)
292 ; modl <- mkStringCLit (moduleUserString (cc_mod cc))
294 lits = [ zero, -- StgInt ccID,
295 label, -- char *label,
296 modl, -- char *module,
297 zero, -- StgWord time_ticks
298 zero64, -- StgWord64 mem_alloc
299 subsumed, -- StgInt is_caf
300 zero -- struct _CostCentre *link
302 ; emitDataLits (mkCCLabel cc) lits
305 subsumed | isCafCC cc = mkIntCLit (ord 'c') -- 'c' == is a CAF
306 | otherwise = mkIntCLit (ord 'B') -- 'B' == is boring
309 emitCostCentreStackDecl
312 emitCostCentreStackDecl ccs
313 | Just cc <- maybeSingletonCCS ccs = do
317 zero, -- struct _CostCentreStack *prevStack;
318 zero, -- struct _IndexTable *indexTable;
319 zero, -- StgWord selected;
320 zero64, -- StgWord64 scc_count;
321 zero, -- StgWord time_ticks;
322 zero64, -- StgWord64 mem_alloc;
323 zero, -- StgWord inherited_ticks;
324 zero64, -- StgWord64 inherited_alloc;
325 zero -- CostCentre *root;
327 ; emitDataLits (mkCCSLabel ccs) lits
329 | otherwise = pprPanic "emitCostCentreStackDecl" (ppr ccs)
332 zero64 = CmmInt 0 I64
335 -- ---------------------------------------------------------------------------
336 -- Registering CCs and CCSs
338 -- (cc)->link = CC_LIST;
340 -- (cc)->ccID = CC_ID++;
342 emitRegisterCC :: CostCentre -> Code
343 emitRegisterCC cc = do
344 { tmp <- newTemp cIntRep
346 CmmStore (cmmOffsetB cc_lit oFFSET_CostCentre_link)
347 (CmmLoad cC_LIST wordRep),
348 CmmStore cC_LIST cc_lit,
349 CmmAssign tmp (CmmLoad cC_ID cIntRep),
350 CmmStore (cmmOffsetB cc_lit oFFSET_CostCentre_ccID) (CmmReg tmp),
351 CmmStore cC_ID (cmmRegOffB tmp 1)
355 cc_lit = CmmLit (CmmLabel (mkCCLabel cc))
357 -- (ccs)->prevStack = CCS_LIST;
359 -- (ccs)->ccsID = CCS_ID++;
361 emitRegisterCCS :: CostCentreStack -> Code
362 emitRegisterCCS ccs = do
363 { tmp <- newTemp cIntRep
365 CmmStore (cmmOffsetB ccs_lit oFFSET_CostCentreStack_prevStack)
366 (CmmLoad cCS_LIST wordRep),
367 CmmStore cCS_LIST ccs_lit,
368 CmmAssign tmp (CmmLoad cCS_ID cIntRep),
369 CmmStore (cmmOffsetB ccs_lit oFFSET_CostCentreStack_ccsID) (CmmReg tmp),
370 CmmStore cCS_ID (cmmRegOffB tmp 1)
374 ccs_lit = CmmLit (CmmLabel (mkCCSLabel ccs))
377 cC_LIST = CmmLit (CmmLabel (mkRtsDataLabel SLIT("CC_LIST")))
378 cC_ID = CmmLit (CmmLabel (mkRtsDataLabel SLIT("CC_ID")))
380 cCS_LIST = CmmLit (CmmLabel (mkRtsDataLabel SLIT("CCS_LIST")))
381 cCS_ID = CmmLit (CmmLabel (mkRtsDataLabel SLIT("CCS_ID")))
383 -- ---------------------------------------------------------------------------
384 -- Set the current cost centre stack
386 emitSetCCC :: CostCentre -> Code
388 | not opt_SccProfilingOn = nopC
390 tmp <- newTemp wordRep
391 ASSERT( sccAbleCostCentre cc )
392 pushCostCentre tmp curCCS cc
393 stmtC (CmmStore curCCSAddr (CmmReg tmp))
394 when (isSccCountCostCentre cc) $
395 stmtC (bumpSccCount curCCS)
397 pushCostCentre :: CmmReg -> CmmExpr -> CostCentre -> Code
398 pushCostCentre result ccs cc
399 = emitRtsCallWithResult result PtrHint
400 SLIT("PushCostCentre") [(ccs,PtrHint),
401 (CmmLit (mkCCostCentre cc), PtrHint)]
403 bumpSccCount :: CmmExpr -> CmmStmt
405 = addToMem REP_CostCentreStack_scc_count
406 (cmmOffsetB ccs oFFSET_CostCentreStack_scc_count) 1
408 -----------------------------------------------------------------------------
410 -- Lag/drag/void stuff
412 -----------------------------------------------------------------------------
415 -- Initial value for the LDV field in a static closure
417 staticLdvInit :: CmmLit
418 staticLdvInit = zeroCLit
421 -- Initial value of the LDV field in a dynamic closure
423 dynLdvInit :: CmmExpr
424 dynLdvInit = -- (era << LDV_SHIFT) | LDV_STATE_CREATE
425 CmmMachOp mo_wordOr [
426 CmmMachOp mo_wordShl [loadEra, CmmLit (mkIntCLit lDV_SHIFT) ],
427 CmmLit (mkWordCLit lDV_STATE_CREATE)
431 -- Initialise the LDV word of a new closure
433 ldvRecordCreate :: CmmExpr -> Code
434 ldvRecordCreate closure = stmtC $ CmmStore (ldvWord closure) dynLdvInit
437 -- Called when a closure is entered, marks the closure as having been "used".
438 -- The closure is not an 'inherently used' one.
439 -- The closure is not IND or IND_OLDGEN because neither is considered for LDV
442 ldvEnter :: CmmExpr -> Code
443 -- Argument is a closure pointer
447 -- LDVW((c)) = (LDVW((c)) & LDV_CREATE_MASK) |
448 -- era | LDV_STATE_USE }
449 emitIf (CmmMachOp mo_wordUGt [loadEra, CmmLit zeroCLit])
450 (stmtC (CmmStore ldv_wd new_ldv_wd))
452 ldv_wd = ldvWord cl_ptr
453 new_ldv_wd = cmmOrWord (cmmAndWord (CmmLoad ldv_wd wordRep)
454 (CmmLit (mkWordCLit lDV_CREATE_MASK)))
455 (cmmOrWord loadEra (CmmLit (mkWordCLit lDV_STATE_USE)))
458 loadEra = CmmMachOp (MO_U_Conv cIntRep wordRep)
459 [CmmLoad (mkLblExpr (mkRtsDataLabel SLIT("era"))) cIntRep]
461 ldvWord :: CmmExpr -> CmmExpr
462 -- Takes the address of a closure, and returns
463 -- the address of the LDV word in the closure
464 ldvWord closure_ptr = cmmOffsetB closure_ptr oFFSET_StgHeader_ldvw
466 -- LDV constants, from ghc/includes/Constants.h
467 lDV_SHIFT = (LDV_SHIFT :: Int)
468 --lDV_STATE_MASK = (LDV_STATE_MASK :: StgWord)
469 lDV_CREATE_MASK = (LDV_CREATE_MASK :: StgWord)
470 --lDV_LAST_MASK = (LDV_LAST_MASK :: StgWord)
471 lDV_STATE_CREATE = (LDV_STATE_CREATE :: StgWord)
472 lDV_STATE_USE = (LDV_STATE_USE :: StgWord)