1 /* -----------------------------------------------------------------------------
2 * $Id: StgProf.h,v 1.18 2004/08/13 13:09:37 simonmar Exp $
4 * (c) The GHC Team, 1998
6 * Macros for profiling operations in STG code
7 * ---------------------------------------------------------------------------*/
12 /* -----------------------------------------------------------------------------
14 * ---------------------------------------------------------------------------*/
15 typedef struct _CostCentre {
21 /* used for accumulating costs at the end of the run... */
27 struct _CostCentre *link;
31 typedef struct _CostCentreStack {
35 struct _CostCentreStack *prevStack;
36 struct _IndexTable *indexTable;
42 StgWord inherited_ticks;
43 StgWord64 inherited_alloc;
49 /* -----------------------------------------------------------------------------
50 * The rest is PROFILING only...
51 * ---------------------------------------------------------------------------*/
53 #if defined(PROFILING)
55 /* -----------------------------------------------------------------------------
57 * ---------------------------------------------------------------------------*/
59 #define EMPTY_STACK NULL
60 #define EMPTY_TABLE NULL
62 /* Constants used to set sumbsumed flag on CostCentres */
64 #define CC_IS_CAF 'c' /* 'c' => *is* a CAF cc */
65 #define CC_IS_BORING 'B' /* 'B' => *not* a CAF/sub cc */
68 /* -----------------------------------------------------------------------------
70 * ---------------------------------------------------------------------------*/
72 typedef struct _IndexTable {
75 struct _IndexTable *next;
76 unsigned int back_edge;
80 /* -----------------------------------------------------------------------------
81 Pre-defined cost centres and cost centre stacks
82 -------------------------------------------------------------------------- */
84 extern CostCentreStack * RTS_VAR(CCCS); /* current CCS */
88 extern StgWord CC_MAIN[];
89 extern StgWord CCS_MAIN[]; /* Top CCS */
91 extern StgWord CC_SYSTEM[];
92 extern StgWord CCS_SYSTEM[]; /* RTS costs */
94 extern StgWord CC_GC[];
95 extern StgWord CCS_GC[]; /* Garbage collector costs */
97 extern StgWord CC_SUBSUMED[];
98 extern StgWord CCS_SUBSUMED[]; /* Costs are subsumed by caller */
100 extern StgWord CC_OVERHEAD[];
101 extern StgWord CCS_OVERHEAD[]; /* Profiling overhead */
103 extern StgWord CC_DONT_CARE[];
104 extern StgWord CCS_DONT_CARE[]; /* shouldn't ever get set */
108 extern CostCentre CC_MAIN[];
109 extern CostCentreStack CCS_MAIN[]; /* Top CCS */
111 extern CostCentre CC_SYSTEM[];
112 extern CostCentreStack CCS_SYSTEM[]; /* RTS costs */
114 extern CostCentre CC_GC[];
115 extern CostCentreStack CCS_GC[]; /* Garbage collector costs */
117 extern CostCentre CC_SUBSUMED[];
118 extern CostCentreStack CCS_SUBSUMED[]; /* Costs are subsumed by caller */
120 extern CostCentre CC_OVERHEAD[];
121 extern CostCentreStack CCS_OVERHEAD[]; /* Profiling overhead */
123 extern CostCentre CC_DONT_CARE[];
124 extern CostCentreStack CCS_DONT_CARE[]; /* shouldn't ever get set */
126 #endif // IN_STG_CODE
128 extern unsigned int RTS_VAR(CC_ID); /* global ids */
129 extern unsigned int RTS_VAR(CCS_ID);
130 extern unsigned int RTS_VAR(HP_ID);
132 extern unsigned int RTS_VAR(era);
134 /* -----------------------------------------------------------------------------
136 * ---------------------------------------------------------------------------*/
138 void EnterFunCCS ( CostCentreStack *ccsfn );
139 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
140 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
142 extern unsigned int RTS_VAR(entering_PAP);
144 /* -----------------------------------------------------------------------------
147 Cost centres are registered at startup by calling a registering
148 routine in each module. Each module registers its cost centres and
149 calls the registering routine for all imported modules. The RTS calls
150 the registering routine for the module Main. This registering must be
151 done before initialisation since the evaluation required for
152 initialisation may use the cost centres.
154 As the code for each module uses tail calls we use an auxiliary stack
155 (in the heap) to record imported modules still to be registered. At
156 the bottom of the stack is NULL which indicates that
157 @miniInterpretEnd@ should be resumed.
159 @START_REGISTER@ and @END_REGISTER@ are special macros used to
160 delimit the function. @END_REGISTER@ pops the next registering
161 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
162 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
165 -------------------------------------------------------------------------- */
167 extern CostCentre * RTS_VAR(CC_LIST); /* registered CC list */
168 extern CostCentreStack * RTS_VAR(CCS_LIST); /* registered CCS list */
170 #define REGISTER_CC(cc) \
172 extern CostCentre cc[]; \
173 if ((cc)->link == (CostCentre *)0) { \
174 (cc)->link = CC_LIST; \
176 (cc)->ccID = CC_ID++; \
179 #define REGISTER_CCS(ccs) \
181 extern CostCentreStack ccs[]; \
182 if ((ccs)->prevStack == (CostCentreStack *)0) { \
183 (ccs)->prevStack = CCS_LIST; \
185 (ccs)->ccsID = CCS_ID++; \
188 /* -----------------------------------------------------------------------------
189 * Declaring Cost Centres & Cost Centre Stacks.
190 * -------------------------------------------------------------------------- */
192 # define CC_DECLARE(cc_ident,name,module,caf,is_local) \
193 is_local CostCentre cc_ident[1] \
202 # define CCS_DECLARE(ccs_ident,cc_ident,is_local) \
203 is_local CostCentreStack ccs_ident[1] \
212 inherited_ticks : 0, \
213 inherited_alloc : 0, \
217 # define CC_EXTERN(cc_ident) \
218 extern CostCentre cc_ident[];
220 /* -----------------------------------------------------------------------------
221 * Time / Allocation Macros
222 * ---------------------------------------------------------------------------*/
224 /* eliminate profiling overhead from allocation costs */
225 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
227 /* For grabbing the cost centre from a closure */
228 #define CCS_HDR(closure) ((StgClosure *)(closure))->header.prof.ccs
230 /* Restore the CCCS from a stack frame.
231 * (addr should always be Sp->header.prof.ccs)
233 #define RESTORE_CCCS(addr) (*CCCS = (CostCentreStack *)(addr))
235 /* -----------------------------------------------------------------------------
236 * Pushing a new cost centre (i.e. for scc annotations)
237 * -------------------------------------------------------------------------- */
239 # define SET_CCC_X(cc,do_subcc_count,do_scc_count) \
241 CCCS = PushCostCentre(CCCS,cc); \
242 if (do_scc_count) { CCCS->scc_count++; } \
245 /* We sometimes don't increment the scc_count field, for example when
246 * this scc has been placed by the compiler on an expression it
247 * floated outside the main scc annotation.
250 # define SET_CCC(cc_ident,do_scc_count) \
251 SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
253 # define SET_CCS_TOP(cc_ident) \
254 SET_CCC_X(cc_ident,0,1)
256 /* -----------------------------------------------------------------------------
257 * Allocating new cost centres / cost centre stacks.
258 * -------------------------------------------------------------------------- */
260 #define ASSIGN_CC_ID(ccID) \
266 #define ASSIGN_CCS_ID(ccsID) \
272 #define ASSIGN_HP_ID(hpID) \
278 #define SET_STATS_TO_ZERO(stack) \
280 (stack)->scc_count = 0; \
281 (stack)->time_ticks = 0; \
282 (stack)->mem_alloc = 0; \
285 /* -----------------------------------------------------------------------------
286 * Setting the cost centre when we enter a closure
287 * -------------------------------------------------------------------------- */
289 #if defined(PROFILING_DETAIL_COUNTS)
290 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
292 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
295 /* On entry to top level CAFs we count the scc ...*/
297 #define ENTER_CCS_CAF_X(ccs) \
299 /* set CCCS to ident ccs */ \
300 CCCS = (CostCentreStack *)(ccs); \
301 /* inc scc count of CAF ccs */ \
305 #define ENTER_CCS_CAF(ccs_ident) ENTER_CCS_CAF_X(ccs_ident)
306 #define ENTER_CCS_CAF_CL(closure) ENTER_CCS_CAF_X(CCS_HDR(closure))
308 /* ----------------------------------------------------------------------------
311 * On entering a closure we only count the enter to thunks ...
312 * ------------------------------------------------------------------------- */
314 #define ENTER_CCS_T(ccs) \
316 *CCCS = (CostCentreStack *)(ccs); \
317 CCCS_DETAIL_COUNT(CCCS->thunk_count); \
320 #define ENTER_CCS_TCL(closure) ENTER_CCS_T(CCS_HDR(closure))
322 /* -----------------------------------------------------------------------------
323 * Entering a function
325 * Here is our special "hybrid" case when we do *not* set the CCCS.
326 * (a) The closure is a function, not a thunk;
327 * (b) The CCS is CAF-ish.
328 * -------------------------------------------------------------------------- */
330 #define ENTER_CCS_F(stack) EnterFunCCS(stack)
332 #define ENTER_CCS_FCL(closure) ENTER_CCS_F(CCS_HDR(closure))
334 /* Entering a top-level function: costs are subsumed by the caller
336 #define ENTER_CCS_FSUB() \
338 CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count); \
339 CCCS_DETAIL_COUNT(CCCS->function_count); \
343 #define ENTER_CCS_FCAF(stack) \
345 CostCentreStack *ccs = (CostCentreStack *) (stack); \
346 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
347 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
348 CCCS_DETAIL_COUNT(CCCS->function_count); \
352 #define ENTER_CCS_FLOAD(ccs) \
354 CCCS = (CostCentreStack *)(ccs); \
355 CCCS_DETAIL_COUNT(CCCS->function_count); \
358 /* These ENTER_CC_PAP things are only used in the RTS */
360 #define ENTER_CCS_PAP(stack) \
362 ENTER_CCS_F(stack); \
363 *entering_PAP = rtsTrue; \
366 #define ENTER_CCS_PAP_CL(closure) \
367 ENTER_CCS_PAP((closure)->header.prof.ccs)
369 /* -----------------------------------------------------------------------------
370 When not profiling, these macros do nothing...
371 -------------------------------------------------------------------------- */
372 #else /* !PROFILING */
374 #define CCS_ALLOC(ccs, amount) doNothing()
375 #define ENTER_CC_PAP_CL(r) doNothing()
376 #define ENTER_CCS_PAP_CL(r) doNothing()
378 #endif /* PROFILING */
380 #endif /* STGPROF_H */