1 /* -----------------------------------------------------------------------------
2 * $Id: StgProf.h,v 1.10 2000/05/12 13:01:04 simonmar Exp $
4 * (c) The GHC Team, 1998
6 * Macros for profiling operations in STG code
7 * ---------------------------------------------------------------------------*/
12 #if !defined(PROFILING)
14 #define CCS_ALLOC(ccs, amount) doNothing()
15 #define ENTER_CC_PAP_CL(r) doNothing()
16 #define ENTER_CCS_PAP_CL(r) doNothing()
18 #else /* PROFILING... */
20 /* -----------------------------------------------------------------------------
22 * ---------------------------------------------------------------------------*/
24 #define EMPTY_STACK NULL
25 #define EMPTY_TABLE NULL
27 /* Constants used to set sumbsumed flag on CostCentres */
29 #define CC_IS_CAF 'c' /* 'c' => *is* a CAF cc */
30 #define CC_IS_BORING 'B' /* 'B' => *not* a CAF/sub cc */
32 /* -----------------------------------------------------------------------------
34 * ---------------------------------------------------------------------------*/
39 typedef struct _CostCentre {
45 /* used for accumulating costs at the end of the run... */
46 unsigned long time_ticks;
47 unsigned long mem_alloc;
51 struct _CostCentre *link;
60 typedef struct _CostCentreStack {
64 struct _CostCentreStack *prevStack;
65 struct _IndexTable *indexTable;
67 unsigned long scc_count;
69 unsigned long time_ticks;
70 unsigned long mem_alloc;
71 unsigned long mem_resid;
73 unsigned long inherited_ticks;
74 unsigned long inherited_alloc;
85 typedef struct _IndexTable {
88 struct _IndexTable *next;
89 unsigned int back_edge;
93 /* -----------------------------------------------------------------------------
94 Pre-defined cost centres and cost centre stacks
95 -------------------------------------------------------------------------- */
97 extern CostCentreStack *CCCS; /* current CCS */
99 extern CostCentre CC_MAIN[];
100 extern CostCentreStack CCS_MAIN[]; /* Top CCS */
102 extern CostCentre CC_SYSTEM[];
103 extern CostCentreStack CCS_SYSTEM[]; /* RTS costs */
105 extern CostCentre CC_GC[];
106 extern CostCentreStack CCS_GC[]; /* Garbage collector costs */
108 extern CostCentre CC_SUBSUMED[];
109 extern CostCentreStack CCS_SUBSUMED[]; /* Costs are subsumed by caller */
111 extern CostCentre CC_OVERHEAD[];
112 extern CostCentreStack CCS_OVERHEAD[]; /* Profiling overhead */
114 extern CostCentre CC_DONT_CARE[];
115 extern CostCentreStack CCS_DONT_CARE[]; /* shouldn't ever get set */
117 extern unsigned int CC_ID; /* global ids */
118 extern unsigned int CCS_ID;
119 extern unsigned int HP_ID;
121 /* -----------------------------------------------------------------------------
123 * ---------------------------------------------------------------------------*/
125 CostCentreStack *EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn );
126 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
127 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
129 extern unsigned int entering_PAP;
131 /* -----------------------------------------------------------------------------
134 Cost centres are registered at startup by calling a registering
135 routine in each module. Each module registers its cost centres and
136 calls the registering routine for all imported modules. The RTS calls
137 the registering routine for the module Main. This registering must be
138 done before initialisation since the evaluation required for
139 initialisation may use the cost centres.
141 As the code for each module uses tail calls we use an auxiliary stack
142 (in the heap) to record imported modules still to be registered. At
143 the bottom of the stack is NULL which indicates that
144 @miniInterpretEnd@ should be resumed.
146 @START_REGISTER@ and @END_REGISTER@ are special macros used to
147 delimit the function. @END_REGISTER@ pops the next registering
148 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
149 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
152 -------------------------------------------------------------------------- */
154 extern CostCentre *CC_LIST; /* registered CC list */
155 extern CostCentreStack *CCS_LIST; /* registered CCS list */
157 #define REGISTER_CC(cc) \
159 extern CostCentre cc[]; \
160 if ((cc)->link == (CostCentre *)0) { \
161 (cc)->link = CC_LIST; \
163 (cc)->ccID = CC_ID++; \
166 #define REGISTER_CCS(ccs) \
168 extern CostCentreStack ccs[]; \
169 if ((ccs)->prevStack == (CostCentreStack *)0) { \
170 (ccs)->prevStack = CCS_LIST; \
172 (ccs)->ccsID = CCS_ID++; \
175 /* -----------------------------------------------------------------------------
176 * Declaring Cost Centres & Cost Centre Stacks.
177 * -------------------------------------------------------------------------- */
179 # define CC_DECLARE(cc_ident,name,module,caf,is_local) \
180 is_local CostCentre cc_ident[1] \
189 # define CCS_DECLARE(ccs_ident,cc_ident,is_local) \
190 is_local CostCentreStack ccs_ident[1] \
199 inherited_ticks : 0, \
200 inherited_alloc : 0, \
204 # define CC_EXTERN(cc_ident) \
205 extern CostCentre cc_ident[];
207 /* -----------------------------------------------------------------------------
208 * Time / Allocation Macros
209 * ---------------------------------------------------------------------------*/
211 #define CCS_TICK(ccs) (ccs)->time_ticks++
213 /* eliminate profiling overhead from allocation costs */
214 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
216 /* For grabbing the cost centre from a closure */
217 #define CCS_HDR(closure) ((StgClosure *)(closure))->header.prof.ccs
219 /* Restore the CCCS from a stack frame.
220 * (addr should always be Sp->header.prof.ccs)
222 #define RESTORE_CCCS(addr) (CCCS = (CostCentreStack *)(addr))
224 /* -----------------------------------------------------------------------------
225 * Pushing a new cost centre (i.e. for scc annotations)
226 * -------------------------------------------------------------------------- */
228 # define SET_CCC_X(cc,do_subcc_count,do_scc_count) \
230 CCCS = PushCostCentre(CCCS,cc); \
231 if (do_scc_count) { CCCS->scc_count++; } \
234 /* We sometimes don't increment the scc_count field, for example when
235 * this scc has been placed by the compiler on an expression it
236 * floated outside the main scc annotation.
239 # define SET_CCC(cc_ident,do_scc_count) \
240 SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
242 # define SET_CCS_TOP(cc_ident) \
243 SET_CCC_X(cc_ident,0,1)
245 /* -----------------------------------------------------------------------------
246 * Allocating new cost centres / cost centre stacks.
247 * -------------------------------------------------------------------------- */
249 #define ASSIGN_CC_ID(ccID) \
255 #define ASSIGN_CCS_ID(ccsID) \
261 #define ASSIGN_HP_ID(hpID) \
267 #define SET_STATS_TO_ZERO(stack) \
269 (stack)->scc_count = 0; \
270 (stack)->time_ticks = 0; \
271 (stack)->mem_alloc = 0; \
274 /* -----------------------------------------------------------------------------
275 * Setting the cost centre when we enter a closure
276 * -------------------------------------------------------------------------- */
278 #if defined(PROFILING_DETAIL_COUNTS)
279 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
281 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
284 /* On entry to top level CAFs we count the scc ...*/
286 #define ENTER_CCS_CAF_X(ccs) \
288 /* set CCCS to ident ccs */ \
289 CCCS = (CostCentreStack *)(ccs); \
290 /* inc scc count of CAF ccs */ \
294 #define ENTER_CCS_CAF(ccs_ident) ENTER_CCS_CAF_X(ccs_ident)
295 #define ENTER_CCS_CAF_CL(closure) ENTER_CCS_CAF_X(CCS_HDR(closure))
297 /* ----------------------------------------------------------------------------
300 * On entering a closure we only count the enter to thunks ...
301 * ------------------------------------------------------------------------- */
303 #define ENTER_CCS_T(ccs) \
305 CCCS = (CostCentreStack *)(ccs); \
306 CCCS_DETAIL_COUNT(CCCS->thunk_count); \
309 #define ENTER_CCS_TCL(closure) ENTER_CCS_T(CCS_HDR(closure))
311 /* -----------------------------------------------------------------------------
312 * Entering a function
314 * Here is our special "hybrid" case when we do *not* set the CCCS.
315 * (a) The closure is a function, not a thunk;
316 * (b) The CCS is CAF-ish.
317 * -------------------------------------------------------------------------- */
319 #define ENTER_CCS_F(stack) \
321 CostCentreStack *ccs = (CostCentreStack *) (stack); \
322 CCCS_DETAIL_COUNT(CCCS->function_count); \
323 CCCS = EnterFunCCS(CCCS,ccs); \
326 #define ENTER_CCS_FCL(closure) ENTER_CCS_F(CCS_HDR(closure))
328 /* Entering a top-level function: costs are subsumed by the caller
330 #define ENTER_CCS_FSUB() \
332 CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count); \
333 CCCS_DETAIL_COUNT(CCCS->function_count); \
337 #define ENTER_CCS_FCAF(stack) \
339 CostCentreStack *ccs = (CostCentreStack *) (stack); \
340 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
341 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
342 CCCS_DETAIL_COUNT(CCCS->function_count); \
346 #define ENTER_CCS_FLOAD(ccs) \
348 CCCS = (CostCentreStack *)(ccs); \
349 CCCS_DETAIL_COUNT(CCCS->function_count); \
352 /* These ENTER_CC_PAP things are only used in the RTS */
354 #define ENTER_CCS_PAP(stack) \
356 ENTER_CCS_F(stack); \
357 entering_PAP = rtsTrue; \
360 #define ENTER_CCS_PAP_CL(closure) \
361 ENTER_CCS_PAP((closure)->header.prof.ccs)
364 #define STATIC_CCS_REF(ccs) (ccs)
366 #endif /* PROFILING */
368 #endif /* STGPROF_H */