1 /* -----------------------------------------------------------------------------
2 * $Id: StgProf.h,v 1.2 1998/12/02 13:21:39 simonm Exp $
4 * (c) The GHC Team, 1998
6 * Macros for profiling operations in STG code
7 * ---------------------------------------------------------------------------*/
12 #if defined(PROFILING)
14 /* -----------------------------------------------------------------------------
17 Cost centres are registered at startup by calling a registering
18 routine in each module. Each module registers its cost centres and
19 calls the registering routine for all imported modules. The RTS calls
20 the registering routine for the module Main. This registering must be
21 done before initialisation since the evaluation required for
22 initialisation may use the cost centres.
24 As the code for each module uses tail calls we use an auxiliary stack
25 (in the heap) to record imported modules still to be registered. At
26 the bottom of the stack is NULL which indicates that
27 @miniInterpretEnd@ should be resumed.
29 @START_REGISTER@ and @END_REGISTER@ are special macros used to
30 delimit the function. @END_REGISTER@ pops the next registering
31 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
32 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
35 -------------------------------------------------------------------------- */
37 extern F_ *register_stack;
39 extern CostCentre *CC_LIST; /* registered CC list */
40 extern CostCentreStack *CCS_LIST; /* registered CCS list */
42 # define PUSH_REGISTER_STACK(reg_function) \
43 *(register_stack++) = (F_)reg_function
45 # define POP_REGISTER_STACK() \
48 # define START_REGISTER_CCS(reg_mod_name) \
49 static int _module_registered = 0; \
52 if (! _module_registered) { \
53 _module_registered = 1
55 # define REGISTER_IMPORT(reg_mod_name) \
56 do { EF_(reg_mod_name); \
57 PUSH_REGISTER_STACK(reg_mod_name) ; \
60 # define END_REGISTER_CCS() \
62 JMP_(POP_REGISTER_STACK()); \
65 #define REGISTER_CC(cc) \
67 extern CostCentre cc[]; \
68 if ((cc)->link == (CostCentre *)0) { \
69 (cc)->link = CC_LIST; \
71 (cc)->ccID = CC_ID++; \
74 #define REGISTER_CCS(ccs) \
76 extern CostCentreStack ccs[]; \
77 if ((ccs)->prevStack == (CostCentreStack *)0) { \
78 (ccs)->prevStack = CCS_LIST; \
80 (ccs)->ccsID = CCS_ID++; \
83 /* -----------------------------------------------------------------------------
84 * Declaring Cost Centres & Cost Centre Stacks.
85 * -------------------------------------------------------------------------- */
87 # define CC_DECLARE(cc_ident,name,module,group,subsumed,is_local) \
88 is_local CostCentre cc_ident[1] \
96 # define CCS_DECLARE(ccs_ident,cc_ident,subsumed,is_local) \
97 is_local CostCentreStack ccs_ident[1] \
104 sub_cafcc_count : 0, \
105 sub_dictcc_count : 0, \
108 is_subsumed : subsumed, \
111 # define CC_EXTERN(cc_ident) \
112 extern CostCentre cc_ident[];
114 /* -----------------------------------------------------------------------------
115 * Time / Allocation Macros
116 * ---------------------------------------------------------------------------*/
118 #define CCS_TICK(ccs) (ccs)->time_ticks++
120 /* eliminate profiling overhead from allocation costs */
121 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
123 /* For grabbing the cost centre from a closure */
124 #define CCS_HDR(closure) ((StgClosure *)(closure))->header.prof.ccs
126 /* Restore the CCCS from a stack fram.
127 * (addr should always be Sp->header.prof.ccs)
129 #define RESTORE_CCCS(addr) (CCCS = (CostCentreStack *)(addr))
131 /* -----------------------------------------------------------------------------
132 * Pushing a new cost centre (i.e. for scc annotations)
133 * -------------------------------------------------------------------------- */
135 # define SET_CCC_X(cc,do_subcc_count,do_subdict_count,do_scc_count) \
137 if (do_subcc_count) { CCCS->sub_scc_count++; } \
138 if (do_subdict_count) { CCCS->sub_dictcc_count++; } \
139 CCCS = PushCostCentre(CCCS,cc); \
140 if (do_scc_count) { CCCS->scc_count++; } \
143 /* We sometimes don't increment the scc_count field, for example when
144 * this scc has been placed by the compiler on an expression it
145 * floated outside the main scc annotation.
148 # define SET_CCC(cc_ident,do_scc_count) \
149 SET_CCC_X(cc_ident,do_scc_count,0,do_scc_count)
151 # define SET_DICT_CCC(cc_ident,do_scc_count) \
152 SET_CCC_X(cc_ident,0,do_scc_count,do_scc_count)
154 # define SET_CCS_TOP(cc_ident) \
155 SET_CCC_X(cc_ident,0,0,1)
157 /* -----------------------------------------------------------------------------
158 * Allocating new cost centres / cost centre stacks.
159 * -------------------------------------------------------------------------- */
161 #define ASSIGN_CC_ID(ccID) \
167 #define ASSIGN_CCS_ID(ccsID) \
173 #define ASSIGN_HP_ID(hpID) \
179 #define SET_STATS_TO_ZERO(stack) \
181 (stack)->scc_count = 0; \
182 (stack)->time_ticks = 0; \
183 (stack)->sub_cafcc_count = 0; \
184 (stack)->sub_dictcc_count = 0; \
185 (stack)->mem_alloc = 0; \
188 /* -----------------------------------------------------------------------------
189 * Setting the cost centre when we enter a closure
190 * -------------------------------------------------------------------------- */
192 #if defined(PROFILING_DETAIL_COUNTS)
193 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
195 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
198 #define IS_CAF_OR_DICT_OR_SUB_CCS(ccs) \
199 /* tests for lower case character */ \
200 ((ccs)->is_subsumed & ' ')
203 /* On entry to top level CAFs we count the scc ...*/
205 #define ENTER_CCS_CAF_X(ccs) \
207 /* inc subcaf count of CCCS */ \
208 CCCS->sub_cafcc_count++; \
209 /* set CCCS to ident ccs */ \
210 CCCS = (CostCentreStack *)(ccs); \
211 /* inc scc count of CAF ccs */ \
215 #define ENTER_CCS_CAF(ccs_ident) ENTER_CCS_CAF_X(ccs_ident)
216 #define ENTER_CCS_CAF_CL(closure) ENTER_CCS_CAF_X(CCS_HDR(closure))
218 /* ----------------------------------------------------------------------------
221 * On entering a closure we only count the enter to thunks ...
222 * ------------------------------------------------------------------------- */
224 #define ENTER_CCS_T(ccs) \
226 CCCS = (CostCentreStack *)(ccs); \
227 CCCS_DETAIL_COUNT(CCCS->thunk_count); \
230 #define ENTER_CCS_TCL(closure) ENTER_CCS_T(CCS_HDR(closure))
232 /* -----------------------------------------------------------------------------
233 * Entering a function
235 * Here is our special "hybrid" case when we do *not* set the CCCS.
236 * (a) The closure is a function, not a thunk;
237 * (b) The CCS is CAF/DICT-ish.
238 * -------------------------------------------------------------------------- */
240 #define ENTER_CCS_F(stack) \
242 CostCentreStack *ccs = (CostCentreStack *) (stack); \
243 if ( ! IS_CAF_OR_DICT_OR_SUB_CCS(ccs) ) { \
246 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
247 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
249 CCCS_DETAIL_COUNT(CCCS->function_count); \
252 #define ENTER_CCS_FCL(closure) ENTER_CCS_F(CCS_HDR(closure))
254 /* Entering a top-level function: costs are subsumed by the caller
256 #define ENTER_CCS_FSUB() \
258 CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count); \
259 CCCS_DETAIL_COUNT(CCCS->function_count); \
262 #define ENTER_CCS_FCAF(stack) \
264 CostCentreStack *ccs = (CostCentreStack *) (stack); \
265 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
266 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
267 CCCS_DETAIL_COUNT(CCCS->function_count); \
270 #define ENTER_CCS_FLOAD(ccs) \
272 CCCS = (CostCentreStack *)(ccs); \
273 CCCS_DETAIL_COUNT(CCCS->function_count); \
276 /* These ENTER_CC_PAP things are only used in the RTS */
278 #define ENTER_CCS_PAP(stack) \
280 CostCentreStack *ccs = (CostCentreStack *) (stack); \
281 if ( ! IS_CAF_OR_DICT_OR_SUB_CCS(ccs) ) { \
284 CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
285 CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
287 CCCS_DETAIL_COUNT(CCCS->pap_count); \
290 #define ENTER_CCS_PAP_CL(closure) \
291 ENTER_CCS_PAP((closure)->header.prof.ccs)
294 #define STATIC_CCS_REF(ccs) (ccs)
296 #endif /* PROFILING */
298 #endif /* STGPROF_H */