[project @ 2001-11-26 16:54:21 by simonmar]
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgProf.h,v 1.15 2001/11/26 16:54:22 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 /* -----------------------------------------------------------------------------
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   unsigned long long 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 long long scc_count;
39
40   unsigned long time_ticks;
41   unsigned long long mem_alloc;
42
43   unsigned long inherited_ticks;
44   unsigned long long inherited_alloc;
45
46   CostCentre *root;
47 } CostCentreStack;
48
49
50 /* -----------------------------------------------------------------------------
51  * The rest is PROFILING only...
52  * ---------------------------------------------------------------------------*/
53
54 #if defined(PROFILING)
55   
56 /* -----------------------------------------------------------------------------
57  * Constants
58  * ---------------------------------------------------------------------------*/
59
60 #define EMPTY_STACK NULL
61 #define EMPTY_TABLE NULL
62
63 /* Constants used to set sumbsumed flag on CostCentres */
64
65 #define CC_IS_CAF      'c'            /* 'c'  => *is* a CAF cc           */
66 #define CC_IS_BORING   'B'            /* 'B'  => *not* a CAF/sub cc      */
67
68
69 /* -----------------------------------------------------------------------------
70  * Data Structures
71  * ---------------------------------------------------------------------------*/
72
73 typedef struct _IndexTable {
74   CostCentre *cc;
75   CostCentreStack *ccs;
76   struct _IndexTable *next;
77   unsigned int back_edge;
78 } IndexTable;
79
80      
81 /* -----------------------------------------------------------------------------
82    Pre-defined cost centres and cost centre stacks
83    -------------------------------------------------------------------------- */
84
85 extern CostCentreStack *CCCS;           /* current CCS */
86  
87 extern CostCentre      CC_MAIN[];       
88 extern CostCentreStack CCS_MAIN[];      /* Top CCS */
89
90 extern CostCentre      CC_SYSTEM[];     
91 extern CostCentreStack CCS_SYSTEM[];    /* RTS costs */
92
93 extern CostCentre      CC_GC[];
94 extern CostCentreStack CCS_GC[];         /* Garbage collector costs */
95
96 extern CostCentre      CC_SUBSUMED[];   
97 extern CostCentreStack CCS_SUBSUMED[];   /* Costs are subsumed by caller */
98
99 extern CostCentre      CC_OVERHEAD[];
100 extern CostCentreStack CCS_OVERHEAD[];   /* Profiling overhead */
101
102 extern CostCentre      CC_DONT_CARE[];
103 extern CostCentreStack CCS_DONT_CARE[];  /* shouldn't ever get set */
104
105 extern unsigned int CC_ID;      /* global ids */
106 extern unsigned int CCS_ID;
107 extern unsigned int HP_ID;
108
109 /* -----------------------------------------------------------------------------
110  * Functions 
111  * ---------------------------------------------------------------------------*/
112
113 CostCentreStack *EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn );
114 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
115 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
116
117 extern unsigned int entering_PAP;
118
119 /* -----------------------------------------------------------------------------
120  * Registering CCs
121  
122  Cost centres are registered at startup by calling a registering
123  routine in each module. Each module registers its cost centres and
124  calls the registering routine for all imported modules. The RTS calls
125  the registering routine for the module Main. This registering must be
126  done before initialisation since the evaluation required for
127  initialisation may use the cost centres.
128  
129  As the code for each module uses tail calls we use an auxiliary stack
130  (in the heap) to record imported modules still to be registered. At
131  the bottom of the stack is NULL which indicates that
132  @miniInterpretEnd@ should be resumed.
133  
134  @START_REGISTER@ and @END_REGISTER@ are special macros used to
135  delimit the function. @END_REGISTER@ pops the next registering
136  routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
137  centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
138  the register stack.
139
140  -------------------------------------------------------------------------- */
141
142 extern CostCentre *CC_LIST;               /* registered CC list */
143 extern CostCentreStack *CCS_LIST;         /* registered CCS list */
144
145 #define REGISTER_CC(cc)                                 \
146         do {                                            \
147         extern CostCentre cc[];                         \
148         if ((cc)->link == (CostCentre *)0) {            \
149             (cc)->link = CC_LIST;                       \
150             CC_LIST = (cc);                             \
151             (cc)->ccID = CC_ID++;                       \
152         }} while(0)
153
154 #define REGISTER_CCS(ccs)                               \
155         do {                                            \
156         extern CostCentreStack ccs[];                   \
157         if ((ccs)->prevStack == (CostCentreStack *)0) { \
158           (ccs)->prevStack = CCS_LIST;                  \
159           CCS_LIST = (ccs);                             \
160           (ccs)->ccsID = CCS_ID++;                      \
161         }} while(0)
162
163 /* -----------------------------------------------------------------------------
164  * Declaring Cost Centres & Cost Centre Stacks.
165  * -------------------------------------------------------------------------- */
166
167 # define CC_DECLARE(cc_ident,name,module,caf,is_local)          \
168      is_local CostCentre cc_ident[1]                            \
169         = {{ 0,                                                 \
170              name,                                              \
171              module,                                            \
172              0,                                                 \
173              0,                                                 \
174              caf,                                               \
175              0 }};
176
177 # define CCS_DECLARE(ccs_ident,cc_ident,is_local)               \
178      is_local CostCentreStack ccs_ident[1]                      \
179        = {{ ccsID               : 0,                            \
180             cc                  : cc_ident,                     \
181             prevStack           : NULL,                         \
182             indexTable          : NULL,                         \
183             scc_count           : 0,                            \
184             time_ticks          : 0,                            \
185             mem_alloc           : 0,                            \
186             inherited_ticks     : 0,                            \
187             inherited_alloc     : 0,                            \
188             root                : 0,                            \
189        }};
190
191 # define CC_EXTERN(cc_ident) \
192     extern CostCentre cc_ident[];
193
194 /* -----------------------------------------------------------------------------
195  * Time / Allocation Macros
196  * ---------------------------------------------------------------------------*/
197
198 #define CCS_TICK(ccs)  (ccs)->time_ticks++
199
200 /* eliminate profiling overhead from allocation costs */
201 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
202
203 /* For grabbing the cost centre from a closure */
204 #define CCS_HDR(closure)   ((StgClosure *)(closure))->header.prof.ccs
205
206 /* Restore the CCCS from a stack frame.
207  * (addr should always be Sp->header.prof.ccs) 
208  */
209 #define RESTORE_CCCS(addr)   (CCCS = (CostCentreStack *)(addr))
210
211 /* -----------------------------------------------------------------------------
212  * Pushing a new cost centre (i.e. for scc annotations)
213  * -------------------------------------------------------------------------- */
214
215 # define SET_CCC_X(cc,do_subcc_count,do_scc_count)              \
216         do {                                                    \
217         CCCS = PushCostCentre(CCCS,cc);                         \
218         if (do_scc_count)     { CCCS->scc_count++; }            \
219         } while(0)
220
221 /* We sometimes don't increment the scc_count field, for example when
222  * this scc has been placed by the compiler on an expression it
223  * floated outside the main scc annotation.
224  */
225
226 # define SET_CCC(cc_ident,do_scc_count) \
227          SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
228
229 # define SET_CCS_TOP(cc_ident) \
230          SET_CCC_X(cc_ident,0,1)
231
232 /* -----------------------------------------------------------------------------
233  * Allocating new cost centres / cost centre stacks.
234  * -------------------------------------------------------------------------- */
235
236 #define ASSIGN_CC_ID(ccID)                \
237         do {                              \
238         ccID = CC_ID;                     \
239         CC_ID++;                          \
240         } while(0)
241
242 #define ASSIGN_CCS_ID(ccsID)              \
243         do {                              \
244         ccsID = CCS_ID;                   \
245         CCS_ID++;                         \
246         } while(0)
247
248 #define ASSIGN_HP_ID(hpID)                \
249         do {                              \
250         hpID = HP_ID;                     \
251         HP_ID++;                          \
252         } while(0)
253
254 #define SET_STATS_TO_ZERO(stack)          \
255         do {                              \
256         (stack)->scc_count = 0;           \
257         (stack)->time_ticks = 0;          \
258         (stack)->mem_alloc = 0;           \
259         } while(0)
260
261 /* -----------------------------------------------------------------------------
262  * Setting the cost centre when we enter a closure
263  * -------------------------------------------------------------------------- */
264
265 #if defined(PROFILING_DETAIL_COUNTS)
266 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
267 #else
268 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
269 #endif
270
271 /* On entry to top level CAFs we count the scc ...*/
272
273 #define ENTER_CCS_CAF_X(ccs)                                \
274         do {                                                \
275         /* set CCCS to ident ccs */                         \
276         CCCS = (CostCentreStack *)(ccs);                    \
277         /* inc scc count of CAF ccs */                      \
278         CCCS->scc_count++;                                  \
279         } while(0)
280  
281 #define ENTER_CCS_CAF(ccs_ident)   ENTER_CCS_CAF_X(ccs_ident)
282 #define ENTER_CCS_CAF_CL(closure)  ENTER_CCS_CAF_X(CCS_HDR(closure))
283
284 /* ----------------------------------------------------------------------------
285  * Entering a Thunk
286  *
287  * On entering a closure we only count the enter to thunks ...
288  * ------------------------------------------------------------------------- */
289
290 #define ENTER_CCS_T(ccs)                                \
291         do {                                            \
292         CCCS = (CostCentreStack *)(ccs);                \
293         CCCS_DETAIL_COUNT(CCCS->thunk_count);           \
294         } while(0)      
295  
296 #define ENTER_CCS_TCL(closure)  ENTER_CCS_T(CCS_HDR(closure))
297  
298 /* -----------------------------------------------------------------------------
299  * Entering a function
300  *
301  * Here is our special "hybrid" case when we do *not* set the CCCS.
302  *  (a) The closure is a function, not a thunk;
303  *  (b) The CCS is CAF-ish.
304  * -------------------------------------------------------------------------- */
305
306 #define ENTER_CCS_F(stack)                                              \
307         do {                                                            \
308         CostCentreStack *ccs = (CostCentreStack *) (stack);             \
309         CCCS_DETAIL_COUNT(CCCS->function_count);                        \
310         CCCS = EnterFunCCS(CCCS,ccs);                                   \
311         } while(0)
312  
313 #define ENTER_CCS_FCL(closure)  ENTER_CCS_F(CCS_HDR(closure))
314
315 /* Entering a top-level function: costs are subsumed by the caller 
316  */
317 #define ENTER_CCS_FSUB()                                \
318         do {                                            \
319         CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count);    \
320         CCCS_DETAIL_COUNT(CCCS->function_count);        \
321         entering_PAP = 0;                               \
322         } while(0)
323  
324 #define ENTER_CCS_FCAF(stack)                                   \
325         do {                                                    \
326         CostCentreStack *ccs = (CostCentreStack *) (stack);     \
327         CCCS_DETAIL_COUNT(ccs->caffun_subsumed);                \
328         CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count);            \
329         CCCS_DETAIL_COUNT(CCCS->function_count);                \
330         entering_PAP = 0;                                       \
331         } while(0)
332  
333 #define ENTER_CCS_FLOAD(ccs)                                \
334         do {                                                \
335         CCCS = (CostCentreStack *)(ccs);                    \
336         CCCS_DETAIL_COUNT(CCCS->function_count);            \
337         } while(0)
338  
339 /* These ENTER_CC_PAP things are only used in the RTS */
340  
341 #define ENTER_CCS_PAP(stack)                    \
342         do {                                    \
343         ENTER_CCS_F(stack);                     \
344         entering_PAP = rtsTrue;                 \
345         } while(0)
346
347 #define ENTER_CCS_PAP_CL(closure)  \
348         ENTER_CCS_PAP((closure)->header.prof.ccs)
349
350 /* -----------------------------------------------------------------------------
351    When not profiling, these macros do nothing...
352    -------------------------------------------------------------------------- */
353 #else /* !PROFILING */
354
355 #define CCS_ALLOC(ccs, amount) doNothing()
356 #define ENTER_CC_PAP_CL(r)     doNothing()
357 #define ENTER_CCS_PAP_CL(r)    doNothing()
358  
359 #endif /* PROFILING */
360
361 #endif /* STGPROF_H */