1 /* -----------------------------------------------------------------------------
2 * $Id: StgProf.h,v 1.9 2000/04/03 15:54:49 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;
68 unsigned long sub_scc_count;
69 unsigned long sub_cafcc_count;
71 unsigned long time_ticks;
72 unsigned long mem_alloc;
73 unsigned long mem_resid;
84 typedef struct _IndexTable {
87 struct _IndexTable *next;
88 unsigned int back_edge;
92 /* -----------------------------------------------------------------------------
93 Pre-defined cost centres and cost centre stacks
94 -------------------------------------------------------------------------- */
96 extern CostCentreStack *CCCS; /* current CCS */
98 extern CostCentre CC_MAIN[];
99 extern CostCentreStack CCS_MAIN[]; /* Top CCS */
101 extern CostCentre CC_SYSTEM[];
102 extern CostCentreStack CCS_SYSTEM[]; /* RTS costs */
104 extern CostCentre CC_GC[];
105 extern CostCentreStack CCS_GC[]; /* Garbage collector costs */
107 extern CostCentre CC_SUBSUMED[];
108 extern CostCentreStack CCS_SUBSUMED[]; /* Costs are subsumed by caller */
110 extern CostCentre CC_OVERHEAD[];
111 extern CostCentreStack CCS_OVERHEAD[]; /* Profiling overhead */
113 extern CostCentre CC_DONT_CARE[];
114 extern CostCentreStack CCS_DONT_CARE[]; /* shouldn't ever get set */
116 extern unsigned int CC_ID; /* global ids */
117 extern unsigned int CCS_ID;
118 extern unsigned int HP_ID;
120 /* -----------------------------------------------------------------------------
122 * ---------------------------------------------------------------------------*/
124 CostCentreStack *EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn );
125 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
126 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
128 extern unsigned int entering_PAP;
130 /* -----------------------------------------------------------------------------
133 Cost centres are registered at startup by calling a registering
134 routine in each module. Each module registers its cost centres and
135 calls the registering routine for all imported modules. The RTS calls
136 the registering routine for the module Main. This registering must be
137 done before initialisation since the evaluation required for
138 initialisation may use the cost centres.
140 As the code for each module uses tail calls we use an auxiliary stack
141 (in the heap) to record imported modules still to be registered. At
142 the bottom of the stack is NULL which indicates that
143 @miniInterpretEnd@ should be resumed.
145 @START_REGISTER@ and @END_REGISTER@ are special macros used to
146 delimit the function. @END_REGISTER@ pops the next registering
147 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
148 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
151 -------------------------------------------------------------------------- */
153 extern CostCentre *CC_LIST; /* registered CC list */
154 extern CostCentreStack *CCS_LIST; /* registered CCS list */
156 #define REGISTER_CC(cc) \
158 extern CostCentre cc[]; \
159 if ((cc)->link == (CostCentre *)0) { \
160 (cc)->link = CC_LIST; \
162 (cc)->ccID = CC_ID++; \
165 #define REGISTER_CCS(ccs) \
167 extern CostCentreStack ccs[]; \
168 if ((ccs)->prevStack == (CostCentreStack *)0) { \
169 (ccs)->prevStack = CCS_LIST; \
171 (ccs)->ccsID = CCS_ID++; \
174 /* -----------------------------------------------------------------------------
175 * Declaring Cost Centres & Cost Centre Stacks.
176 * -------------------------------------------------------------------------- */
178 # define CC_DECLARE(cc_ident,name,module,caf,is_local) \
179 is_local CostCentre cc_ident[1] \
188 # define CCS_DECLARE(ccs_ident,cc_ident,is_local) \
189 is_local CostCentreStack ccs_ident[1] \
196 sub_cafcc_count : 0, \
203 # define CC_EXTERN(cc_ident) \
204 extern CostCentre cc_ident[];
206 /* -----------------------------------------------------------------------------
207 * Time / Allocation Macros
208 * ---------------------------------------------------------------------------*/
210 #define CCS_TICK(ccs) (ccs)->time_ticks++
212 /* eliminate profiling overhead from allocation costs */
213 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
215 /* For grabbing the cost centre from a closure */
216 #define CCS_HDR(closure) ((StgClosure *)(closure))->header.prof.ccs
218 /* Restore the CCCS from a stack frame.
219 * (addr should always be Sp->header.prof.ccs)
221 #define RESTORE_CCCS(addr) (CCCS = (CostCentreStack *)(addr))
223 /* -----------------------------------------------------------------------------
224 * Pushing a new cost centre (i.e. for scc annotations)
225 * -------------------------------------------------------------------------- */
227 # define SET_CCC_X(cc,do_subcc_count,do_scc_count) \
229 if (do_subcc_count) { CCCS->sub_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)->sub_cafcc_count = 0; \
272 (stack)->mem_alloc = 0; \
275 /* -----------------------------------------------------------------------------
276 * Setting the cost centre when we enter a closure
277 * -------------------------------------------------------------------------- */
279 #if defined(PROFILING_DETAIL_COUNTS)
280 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
282 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
285 /* On entry to top level CAFs we count the scc ...*/
287 #define ENTER_CCS_CAF_X(ccs) \
289 /* inc subcaf count of CCCS */ \
290 CCCS->sub_cafcc_count++; \
291 /* set CCCS to ident ccs */ \
292 CCCS = (CostCentreStack *)(ccs); \
293 /* inc scc count of CAF ccs */ \
297 #define ENTER_CCS_CAF(ccs_ident) ENTER_CCS_CAF_X(ccs_ident)
298 #define ENTER_CCS_CAF_CL(closure) ENTER_CCS_CAF_X(CCS_HDR(closure))
300 /* ----------------------------------------------------------------------------
303 * On entering a closure we only count the enter to thunks ...
304 * ------------------------------------------------------------------------- */
306 #define ENTER_CCS_T(ccs) \
308 CCCS = (CostCentreStack *)(ccs); \
309 CCCS_DETAIL_COUNT(CCCS->thunk_count); \
312 #define ENTER_CCS_TCL(closure) ENTER_CCS_T(CCS_HDR(closure))
314 /* -----------------------------------------------------------------------------
315 * Entering a function
317 * Here is our special "hybrid" case when we do *not* set the CCCS.
318 * (a) The closure is a function, not a thunk;
319 * (b) The CCS is CAF-ish.
320 * -------------------------------------------------------------------------- */
322 #define ENTER_CCS_F(stack) \
324 CostCentreStack *ccs = (CostCentreStack *) (stack); \
325 CCCS_DETAIL_COUNT(CCCS->function_count); \
326 CCCS = EnterFunCCS(CCCS,ccs); \
329 #define ENTER_CCS_FCL(closure) ENTER_CCS_F(CCS_HDR(closure))
331 /* Entering a top-level function: costs are subsumed by the caller
333 #define ENTER_CCS_FSUB() \
335 CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count); \
336 CCCS_DETAIL_COUNT(CCCS->function_count); \
340 #define ENTER_CCS_FCAF(stack) \
342 CostCentreStack *ccs = (CostCentreStack *) (stack); \
343 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
344 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
345 CCCS_DETAIL_COUNT(CCCS->function_count); \
349 #define ENTER_CCS_FLOAD(ccs) \
351 CCCS = (CostCentreStack *)(ccs); \
352 CCCS_DETAIL_COUNT(CCCS->function_count); \
355 /* These ENTER_CC_PAP things are only used in the RTS */
357 #define ENTER_CCS_PAP(stack) \
359 ENTER_CCS_F(stack); \
360 entering_PAP = rtsTrue; \
363 #define ENTER_CCS_PAP_CL(closure) \
364 ENTER_CCS_PAP((closure)->header.prof.ccs)
367 #define STATIC_CCS_REF(ccs) (ccs)
369 #endif /* PROFILING */
371 #endif /* STGPROF_H */