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