[project @ 2004-02-12 02:04:59 by mthomas]
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgProf.h,v 1.17 2003/11/12 17:27:04 sof Exp $
3  *
4  * (c) The GHC Team, 1998
5  *
6  * Macros for profiling operations in STG code
7  * ---------------------------------------------------------------------------*/
8
9 #ifndef STGPROF_H
10 #define STGPROF_H
11
12 /* -----------------------------------------------------------------------------
13  * Data Structures 
14  * ---------------------------------------------------------------------------*/  
15 typedef struct _CostCentre {
16   int ccID;
17
18   char *label;
19   char *module;
20  
21   /* used for accumulating costs at the end of the run... */
22   unsigned long time_ticks;
23   ullong        mem_alloc;
24
25   char is_caf;
26
27   struct _CostCentre *link;
28 } CostCentre;
29
30
31 typedef struct _CostCentreStack {
32   int ccsID;
33
34   CostCentre *cc;
35   struct _CostCentreStack *prevStack;
36   struct _IndexTable *indexTable;
37
38   unsigned int selected;
39
40   ullong scc_count;
41
42   unsigned long time_ticks;
43
44   ullong mem_alloc;
45
46   unsigned long inherited_ticks;
47   ullong inherited_alloc;
48
49   CostCentre *root;
50 } CostCentreStack;
51
52
53 /* -----------------------------------------------------------------------------
54  * The rest is PROFILING only...
55  * ---------------------------------------------------------------------------*/
56
57 #if defined(PROFILING)
58   
59 /* -----------------------------------------------------------------------------
60  * Constants
61  * ---------------------------------------------------------------------------*/
62
63 #define EMPTY_STACK NULL
64 #define EMPTY_TABLE NULL
65
66 /* Constants used to set sumbsumed flag on CostCentres */
67
68 #define CC_IS_CAF      'c'            /* 'c'  => *is* a CAF cc           */
69 #define CC_IS_BORING   'B'            /* 'B'  => *not* a CAF/sub cc      */
70
71
72 /* -----------------------------------------------------------------------------
73  * Data Structures
74  * ---------------------------------------------------------------------------*/
75
76 typedef struct _IndexTable {
77   CostCentre *cc;
78   CostCentreStack *ccs;
79   struct _IndexTable *next;
80   unsigned int back_edge;
81 } IndexTable;
82
83      
84 /* -----------------------------------------------------------------------------
85    Pre-defined cost centres and cost centre stacks
86    -------------------------------------------------------------------------- */
87
88 extern CostCentreStack *CCCS;           /* current CCS */
89  
90 extern CostCentre      CC_MAIN[];       
91 extern CostCentreStack CCS_MAIN[];      /* Top CCS */
92
93 extern CostCentre      CC_SYSTEM[];     
94 extern CostCentreStack CCS_SYSTEM[];    /* RTS costs */
95
96 extern CostCentre      CC_GC[];
97 extern CostCentreStack CCS_GC[];         /* Garbage collector costs */
98
99 extern CostCentre      CC_SUBSUMED[];   
100 extern CostCentreStack CCS_SUBSUMED[];   /* Costs are subsumed by caller */
101
102 extern CostCentre      CC_OVERHEAD[];
103 extern CostCentreStack CCS_OVERHEAD[];   /* Profiling overhead */
104
105 extern CostCentre      CC_DONT_CARE[];
106 extern CostCentreStack CCS_DONT_CARE[];  /* shouldn't ever get set */
107
108 extern unsigned int CC_ID;      /* global ids */
109 extern unsigned int CCS_ID;
110 extern unsigned int HP_ID;
111
112 /* -----------------------------------------------------------------------------
113  * Functions 
114  * ---------------------------------------------------------------------------*/
115
116 CostCentreStack *EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn );
117 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
118 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
119
120 extern unsigned int entering_PAP;
121
122 /* -----------------------------------------------------------------------------
123  * Registering CCs
124  
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.
131  
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.
136  
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
141  the register stack.
142
143  -------------------------------------------------------------------------- */
144
145 extern CostCentre *CC_LIST;               /* registered CC list */
146 extern CostCentreStack *CCS_LIST;         /* registered CCS list */
147
148 #define REGISTER_CC(cc)                                 \
149         do {                                            \
150         extern CostCentre cc[];                         \
151         if ((cc)->link == (CostCentre *)0) {            \
152             (cc)->link = CC_LIST;                       \
153             CC_LIST = (cc);                             \
154             (cc)->ccID = CC_ID++;                       \
155         }} while(0)
156
157 #define REGISTER_CCS(ccs)                               \
158         do {                                            \
159         extern CostCentreStack ccs[];                   \
160         if ((ccs)->prevStack == (CostCentreStack *)0) { \
161           (ccs)->prevStack = CCS_LIST;                  \
162           CCS_LIST = (ccs);                             \
163           (ccs)->ccsID = CCS_ID++;                      \
164         }} while(0)
165
166 /* -----------------------------------------------------------------------------
167  * Declaring Cost Centres & Cost Centre Stacks.
168  * -------------------------------------------------------------------------- */
169
170 # define CC_DECLARE(cc_ident,name,module,caf,is_local)          \
171      is_local CostCentre cc_ident[1]                            \
172         = {{ 0,                                                 \
173              name,                                              \
174              module,                                            \
175              0,                                                 \
176              0,                                                 \
177              caf,                                               \
178              0 }};
179
180 # define CCS_DECLARE(ccs_ident,cc_ident,is_local)               \
181      is_local CostCentreStack ccs_ident[1]                      \
182        = {{ ccsID               : 0,                            \
183             cc                  : cc_ident,                     \
184             prevStack           : NULL,                         \
185             indexTable          : NULL,                         \
186             selected            : 0,                            \
187             scc_count           : 0,                            \
188             time_ticks          : 0,                            \
189             mem_alloc           : 0,                            \
190             inherited_ticks     : 0,                            \
191             inherited_alloc     : 0,                            \
192             root                : 0,                            \
193        }};
194
195 # define CC_EXTERN(cc_ident) \
196     extern CostCentre cc_ident[];
197
198 /* -----------------------------------------------------------------------------
199  * Time / Allocation Macros
200  * ---------------------------------------------------------------------------*/
201
202 /* eliminate profiling overhead from allocation costs */
203 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
204
205 /* For grabbing the cost centre from a closure */
206 #define CCS_HDR(closure)   ((StgClosure *)(closure))->header.prof.ccs
207
208 /* Restore the CCCS from a stack frame.
209  * (addr should always be Sp->header.prof.ccs) 
210  */
211 #define RESTORE_CCCS(addr)   (CCCS = (CostCentreStack *)(addr))
212
213 /* -----------------------------------------------------------------------------
214  * Pushing a new cost centre (i.e. for scc annotations)
215  * -------------------------------------------------------------------------- */
216
217 # define SET_CCC_X(cc,do_subcc_count,do_scc_count)              \
218         do {                                                    \
219         CCCS = PushCostCentre(CCCS,cc);                         \
220         if (do_scc_count)     { CCCS->scc_count++; }            \
221         } while(0)
222
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.
226  */
227
228 # define SET_CCC(cc_ident,do_scc_count) \
229          SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
230
231 # define SET_CCS_TOP(cc_ident) \
232          SET_CCC_X(cc_ident,0,1)
233
234 /* -----------------------------------------------------------------------------
235  * Allocating new cost centres / cost centre stacks.
236  * -------------------------------------------------------------------------- */
237
238 #define ASSIGN_CC_ID(ccID)                \
239         do {                              \
240         ccID = CC_ID;                     \
241         CC_ID++;                          \
242         } while(0)
243
244 #define ASSIGN_CCS_ID(ccsID)              \
245         do {                              \
246         ccsID = CCS_ID;                   \
247         CCS_ID++;                         \
248         } while(0)
249
250 #define ASSIGN_HP_ID(hpID)                \
251         do {                              \
252         hpID = HP_ID;                     \
253         HP_ID++;                          \
254         } while(0)
255
256 #define SET_STATS_TO_ZERO(stack)          \
257         do {                              \
258         (stack)->scc_count = 0;           \
259         (stack)->time_ticks = 0;          \
260         (stack)->mem_alloc = 0;           \
261         } while(0)
262
263 /* -----------------------------------------------------------------------------
264  * Setting the cost centre when we enter a closure
265  * -------------------------------------------------------------------------- */
266
267 #if defined(PROFILING_DETAIL_COUNTS)
268 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
269 #else
270 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
271 #endif
272
273 /* On entry to top level CAFs we count the scc ...*/
274
275 #define ENTER_CCS_CAF_X(ccs)                                \
276         do {                                                \
277         /* set CCCS to ident ccs */                         \
278         CCCS = (CostCentreStack *)(ccs);                    \
279         /* inc scc count of CAF ccs */                      \
280         CCCS->scc_count++;                                  \
281         } while(0)
282  
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))
285
286 /* ----------------------------------------------------------------------------
287  * Entering a Thunk
288  *
289  * On entering a closure we only count the enter to thunks ...
290  * ------------------------------------------------------------------------- */
291
292 #define ENTER_CCS_T(ccs)                                \
293         do {                                            \
294         CCCS = (CostCentreStack *)(ccs);                \
295         CCCS_DETAIL_COUNT(CCCS->thunk_count);           \
296         } while(0)      
297  
298 #define ENTER_CCS_TCL(closure)  ENTER_CCS_T(CCS_HDR(closure))
299  
300 /* -----------------------------------------------------------------------------
301  * Entering a function
302  *
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  * -------------------------------------------------------------------------- */
307
308 #define ENTER_CCS_F(stack)                                              \
309         do {                                                            \
310         CostCentreStack *ccs = (CostCentreStack *) (stack);             \
311         CCCS_DETAIL_COUNT(CCCS->function_count);                        \
312         CCCS = EnterFunCCS(CCCS,ccs);                                   \
313         } while(0)
314  
315 #define ENTER_CCS_FCL(closure)  ENTER_CCS_F(CCS_HDR(closure))
316
317 /* Entering a top-level function: costs are subsumed by the caller 
318  */
319 #define ENTER_CCS_FSUB()                                \
320         do {                                            \
321         CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count);    \
322         CCCS_DETAIL_COUNT(CCCS->function_count);        \
323         entering_PAP = 0;                               \
324         } while(0)
325  
326 #define ENTER_CCS_FCAF(stack)                                   \
327         do {                                                    \
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);                \
332         entering_PAP = 0;                                       \
333         } while(0)
334  
335 #define ENTER_CCS_FLOAD(ccs)                                \
336         do {                                                \
337         CCCS = (CostCentreStack *)(ccs);                    \
338         CCCS_DETAIL_COUNT(CCCS->function_count);            \
339         } while(0)
340  
341 /* These ENTER_CC_PAP things are only used in the RTS */
342  
343 #define ENTER_CCS_PAP(stack)                    \
344         do {                                    \
345         ENTER_CCS_F(stack);                     \
346         entering_PAP = rtsTrue;                 \
347         } while(0)
348
349 #define ENTER_CCS_PAP_CL(closure)  \
350         ENTER_CCS_PAP((closure)->header.prof.ccs)
351
352 /* -----------------------------------------------------------------------------
353    When not profiling, these macros do nothing...
354    -------------------------------------------------------------------------- */
355 #else /* !PROFILING */
356
357 #define CCS_ALLOC(ccs, amount) doNothing()
358 #define ENTER_CC_PAP_CL(r)     doNothing()
359 #define ENTER_CCS_PAP_CL(r)    doNothing()
360  
361 #endif /* PROFILING */
362
363 #endif /* STGPROF_H */