1 /* -----------------------------------------------------------------------------
2 * $Id: StgProf.h,v 1.17 2003/11/12 17:27:04 sof 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... */
22 unsigned long time_ticks;
27 struct _CostCentre *link;
31 typedef struct _CostCentreStack {
35 struct _CostCentreStack *prevStack;
36 struct _IndexTable *indexTable;
38 unsigned int selected;
42 unsigned long time_ticks;
46 unsigned long inherited_ticks;
47 ullong inherited_alloc;
53 /* -----------------------------------------------------------------------------
54 * The rest is PROFILING only...
55 * ---------------------------------------------------------------------------*/
57 #if defined(PROFILING)
59 /* -----------------------------------------------------------------------------
61 * ---------------------------------------------------------------------------*/
63 #define EMPTY_STACK NULL
64 #define EMPTY_TABLE NULL
66 /* Constants used to set sumbsumed flag on CostCentres */
68 #define CC_IS_CAF 'c' /* 'c' => *is* a CAF cc */
69 #define CC_IS_BORING 'B' /* 'B' => *not* a CAF/sub cc */
72 /* -----------------------------------------------------------------------------
74 * ---------------------------------------------------------------------------*/
76 typedef struct _IndexTable {
79 struct _IndexTable *next;
80 unsigned int back_edge;
84 /* -----------------------------------------------------------------------------
85 Pre-defined cost centres and cost centre stacks
86 -------------------------------------------------------------------------- */
88 extern CostCentreStack *CCCS; /* current CCS */
90 extern CostCentre CC_MAIN[];
91 extern CostCentreStack CCS_MAIN[]; /* Top CCS */
93 extern CostCentre CC_SYSTEM[];
94 extern CostCentreStack CCS_SYSTEM[]; /* RTS costs */
96 extern CostCentre CC_GC[];
97 extern CostCentreStack CCS_GC[]; /* Garbage collector costs */
99 extern CostCentre CC_SUBSUMED[];
100 extern CostCentreStack CCS_SUBSUMED[]; /* Costs are subsumed by caller */
102 extern CostCentre CC_OVERHEAD[];
103 extern CostCentreStack CCS_OVERHEAD[]; /* Profiling overhead */
105 extern CostCentre CC_DONT_CARE[];
106 extern CostCentreStack CCS_DONT_CARE[]; /* shouldn't ever get set */
108 extern unsigned int CC_ID; /* global ids */
109 extern unsigned int CCS_ID;
110 extern unsigned int HP_ID;
112 /* -----------------------------------------------------------------------------
114 * ---------------------------------------------------------------------------*/
116 CostCentreStack *EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn );
117 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
118 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
120 extern unsigned int entering_PAP;
122 /* -----------------------------------------------------------------------------
125 Cost centres are registered at startup by calling a registering
126 routine in each module. Each module registers its cost centres and
127 calls the registering routine for all imported modules. The RTS calls
128 the registering routine for the module Main. This registering must be
129 done before initialisation since the evaluation required for
130 initialisation may use the cost centres.
132 As the code for each module uses tail calls we use an auxiliary stack
133 (in the heap) to record imported modules still to be registered. At
134 the bottom of the stack is NULL which indicates that
135 @miniInterpretEnd@ should be resumed.
137 @START_REGISTER@ and @END_REGISTER@ are special macros used to
138 delimit the function. @END_REGISTER@ pops the next registering
139 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
140 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
143 -------------------------------------------------------------------------- */
145 extern CostCentre *CC_LIST; /* registered CC list */
146 extern CostCentreStack *CCS_LIST; /* registered CCS list */
148 #define REGISTER_CC(cc) \
150 extern CostCentre cc[]; \
151 if ((cc)->link == (CostCentre *)0) { \
152 (cc)->link = CC_LIST; \
154 (cc)->ccID = CC_ID++; \
157 #define REGISTER_CCS(ccs) \
159 extern CostCentreStack ccs[]; \
160 if ((ccs)->prevStack == (CostCentreStack *)0) { \
161 (ccs)->prevStack = CCS_LIST; \
163 (ccs)->ccsID = CCS_ID++; \
166 /* -----------------------------------------------------------------------------
167 * Declaring Cost Centres & Cost Centre Stacks.
168 * -------------------------------------------------------------------------- */
170 # define CC_DECLARE(cc_ident,name,module,caf,is_local) \
171 is_local CostCentre cc_ident[1] \
180 # define CCS_DECLARE(ccs_ident,cc_ident,is_local) \
181 is_local CostCentreStack ccs_ident[1] \
190 inherited_ticks : 0, \
191 inherited_alloc : 0, \
195 # define CC_EXTERN(cc_ident) \
196 extern CostCentre cc_ident[];
198 /* -----------------------------------------------------------------------------
199 * Time / Allocation Macros
200 * ---------------------------------------------------------------------------*/
202 /* eliminate profiling overhead from allocation costs */
203 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
205 /* For grabbing the cost centre from a closure */
206 #define CCS_HDR(closure) ((StgClosure *)(closure))->header.prof.ccs
208 /* Restore the CCCS from a stack frame.
209 * (addr should always be Sp->header.prof.ccs)
211 #define RESTORE_CCCS(addr) (CCCS = (CostCentreStack *)(addr))
213 /* -----------------------------------------------------------------------------
214 * Pushing a new cost centre (i.e. for scc annotations)
215 * -------------------------------------------------------------------------- */
217 # define SET_CCC_X(cc,do_subcc_count,do_scc_count) \
219 CCCS = PushCostCentre(CCCS,cc); \
220 if (do_scc_count) { CCCS->scc_count++; } \
223 /* We sometimes don't increment the scc_count field, for example when
224 * this scc has been placed by the compiler on an expression it
225 * floated outside the main scc annotation.
228 # define SET_CCC(cc_ident,do_scc_count) \
229 SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
231 # define SET_CCS_TOP(cc_ident) \
232 SET_CCC_X(cc_ident,0,1)
234 /* -----------------------------------------------------------------------------
235 * Allocating new cost centres / cost centre stacks.
236 * -------------------------------------------------------------------------- */
238 #define ASSIGN_CC_ID(ccID) \
244 #define ASSIGN_CCS_ID(ccsID) \
250 #define ASSIGN_HP_ID(hpID) \
256 #define SET_STATS_TO_ZERO(stack) \
258 (stack)->scc_count = 0; \
259 (stack)->time_ticks = 0; \
260 (stack)->mem_alloc = 0; \
263 /* -----------------------------------------------------------------------------
264 * Setting the cost centre when we enter a closure
265 * -------------------------------------------------------------------------- */
267 #if defined(PROFILING_DETAIL_COUNTS)
268 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
270 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
273 /* On entry to top level CAFs we count the scc ...*/
275 #define ENTER_CCS_CAF_X(ccs) \
277 /* set CCCS to ident ccs */ \
278 CCCS = (CostCentreStack *)(ccs); \
279 /* inc scc count of CAF ccs */ \
283 #define ENTER_CCS_CAF(ccs_ident) ENTER_CCS_CAF_X(ccs_ident)
284 #define ENTER_CCS_CAF_CL(closure) ENTER_CCS_CAF_X(CCS_HDR(closure))
286 /* ----------------------------------------------------------------------------
289 * On entering a closure we only count the enter to thunks ...
290 * ------------------------------------------------------------------------- */
292 #define ENTER_CCS_T(ccs) \
294 CCCS = (CostCentreStack *)(ccs); \
295 CCCS_DETAIL_COUNT(CCCS->thunk_count); \
298 #define ENTER_CCS_TCL(closure) ENTER_CCS_T(CCS_HDR(closure))
300 /* -----------------------------------------------------------------------------
301 * Entering a function
303 * Here is our special "hybrid" case when we do *not* set the CCCS.
304 * (a) The closure is a function, not a thunk;
305 * (b) The CCS is CAF-ish.
306 * -------------------------------------------------------------------------- */
308 #define ENTER_CCS_F(stack) \
310 CostCentreStack *ccs = (CostCentreStack *) (stack); \
311 CCCS_DETAIL_COUNT(CCCS->function_count); \
312 CCCS = EnterFunCCS(CCCS,ccs); \
315 #define ENTER_CCS_FCL(closure) ENTER_CCS_F(CCS_HDR(closure))
317 /* Entering a top-level function: costs are subsumed by the caller
319 #define ENTER_CCS_FSUB() \
321 CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count); \
322 CCCS_DETAIL_COUNT(CCCS->function_count); \
326 #define ENTER_CCS_FCAF(stack) \
328 CostCentreStack *ccs = (CostCentreStack *) (stack); \
329 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
330 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
331 CCCS_DETAIL_COUNT(CCCS->function_count); \
335 #define ENTER_CCS_FLOAD(ccs) \
337 CCCS = (CostCentreStack *)(ccs); \
338 CCCS_DETAIL_COUNT(CCCS->function_count); \
341 /* These ENTER_CC_PAP things are only used in the RTS */
343 #define ENTER_CCS_PAP(stack) \
345 ENTER_CCS_F(stack); \
346 entering_PAP = rtsTrue; \
349 #define ENTER_CCS_PAP_CL(closure) \
350 ENTER_CCS_PAP((closure)->header.prof.ccs)
352 /* -----------------------------------------------------------------------------
353 When not profiling, these macros do nothing...
354 -------------------------------------------------------------------------- */
355 #else /* !PROFILING */
357 #define CCS_ALLOC(ccs, amount) doNothing()
358 #define ENTER_CC_PAP_CL(r) doNothing()
359 #define ENTER_CCS_PAP_CL(r) doNothing()
361 #endif /* PROFILING */
363 #endif /* STGPROF_H */