[project @ 2001-10-18 13:46:47 by simonmar]
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgProf.h,v 1.13 2001/10/18 13:46:47 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   unsigned long mem_resid;
43
44   unsigned long inherited_ticks;
45   unsigned long long inherited_alloc;
46
47   CostCentre *root;
48 } CostCentreStack;
49
50
51 /* -----------------------------------------------------------------------------
52  * The rest is PROFILING only...
53  * ---------------------------------------------------------------------------*/
54
55 #if defined(PROFILING)
56   
57 /* -----------------------------------------------------------------------------
58  * Constants
59  * ---------------------------------------------------------------------------*/
60
61 #define EMPTY_STACK NULL
62 #define EMPTY_TABLE NULL
63
64 /* Constants used to set sumbsumed flag on CostCentres */
65
66 #define CC_IS_CAF      'c'            /* 'c'  => *is* a CAF cc           */
67 #define CC_IS_BORING   'B'            /* 'B'  => *not* a CAF/sub cc      */
68
69
70 /* -----------------------------------------------------------------------------
71  * Data Structures
72  * ---------------------------------------------------------------------------*/
73
74 typedef struct _IndexTable {
75   CostCentre *cc;
76   CostCentreStack *ccs;
77   struct _IndexTable *next;
78   unsigned int back_edge;
79 } IndexTable;
80
81      
82 /* -----------------------------------------------------------------------------
83    Pre-defined cost centres and cost centre stacks
84    -------------------------------------------------------------------------- */
85
86 extern CostCentreStack *CCCS;           /* current CCS */
87  
88 extern CostCentre      CC_MAIN[];       
89 extern CostCentreStack CCS_MAIN[];      /* Top CCS */
90
91 extern CostCentre      CC_SYSTEM[];     
92 extern CostCentreStack CCS_SYSTEM[];    /* RTS costs */
93
94 extern CostCentre      CC_GC[];
95 extern CostCentreStack CCS_GC[];         /* Garbage collector costs */
96
97 extern CostCentre      CC_SUBSUMED[];   
98 extern CostCentreStack CCS_SUBSUMED[];   /* Costs are subsumed by caller */
99
100 extern CostCentre      CC_OVERHEAD[];
101 extern CostCentreStack CCS_OVERHEAD[];   /* Profiling overhead */
102
103 extern CostCentre      CC_DONT_CARE[];
104 extern CostCentreStack CCS_DONT_CARE[];  /* shouldn't ever get set */
105
106 extern unsigned int CC_ID;      /* global ids */
107 extern unsigned int CCS_ID;
108 extern unsigned int HP_ID;
109
110 /* -----------------------------------------------------------------------------
111  * Functions 
112  * ---------------------------------------------------------------------------*/
113
114 CostCentreStack *EnterFunCCS ( CostCentreStack *cccs, CostCentreStack *ccsfn );
115 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
116 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
117
118 extern unsigned int entering_PAP;
119
120 /* -----------------------------------------------------------------------------
121  * Registering CCs
122  
123  Cost centres are registered at startup by calling a registering
124  routine in each module. Each module registers its cost centres and
125  calls the registering routine for all imported modules. The RTS calls
126  the registering routine for the module Main. This registering must be
127  done before initialisation since the evaluation required for
128  initialisation may use the cost centres.
129  
130  As the code for each module uses tail calls we use an auxiliary stack
131  (in the heap) to record imported modules still to be registered. At
132  the bottom of the stack is NULL which indicates that
133  @miniInterpretEnd@ should be resumed.
134  
135  @START_REGISTER@ and @END_REGISTER@ are special macros used to
136  delimit the function. @END_REGISTER@ pops the next registering
137  routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
138  centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
139  the register stack.
140
141  -------------------------------------------------------------------------- */
142
143 extern CostCentre *CC_LIST;               /* registered CC list */
144 extern CostCentreStack *CCS_LIST;         /* registered CCS list */
145
146 #define REGISTER_CC(cc)                                 \
147         do {                                            \
148         extern CostCentre cc[];                         \
149         if ((cc)->link == (CostCentre *)0) {            \
150             (cc)->link = CC_LIST;                       \
151             CC_LIST = (cc);                             \
152             (cc)->ccID = CC_ID++;                       \
153         }} while(0)
154
155 #define REGISTER_CCS(ccs)                               \
156         do {                                            \
157         extern CostCentreStack ccs[];                   \
158         if ((ccs)->prevStack == (CostCentreStack *)0) { \
159           (ccs)->prevStack = CCS_LIST;                  \
160           CCS_LIST = (ccs);                             \
161           (ccs)->ccsID = CCS_ID++;                      \
162         }} while(0)
163
164 /* -----------------------------------------------------------------------------
165  * Declaring Cost Centres & Cost Centre Stacks.
166  * -------------------------------------------------------------------------- */
167
168 # define CC_DECLARE(cc_ident,name,module,caf,is_local)          \
169      is_local CostCentre cc_ident[1]                            \
170         = {{ 0,                                                 \
171              name,                                              \
172              module,                                            \
173              0,                                                 \
174              0,                                                 \
175              caf,                                               \
176              0 }};
177
178 # define CCS_DECLARE(ccs_ident,cc_ident,is_local)               \
179      is_local CostCentreStack ccs_ident[1]                      \
180        = {{ ccsID               : 0,                            \
181             cc                  : cc_ident,                     \
182             prevStack           : NULL,                         \
183             indexTable          : NULL,                         \
184             scc_count           : 0,                            \
185             time_ticks          : 0,                            \
186             mem_alloc           : 0,                            \
187             mem_resid           : 0,                            \
188             inherited_ticks     : 0,                            \
189             inherited_alloc     : 0,                            \
190             root                : 0,                            \
191        }};
192
193 # define CC_EXTERN(cc_ident) \
194     extern CostCentre cc_ident[];
195
196 /* -----------------------------------------------------------------------------
197  * Time / Allocation Macros
198  * ---------------------------------------------------------------------------*/
199
200 #define CCS_TICK(ccs)  (ccs)->time_ticks++
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  /* temp EW */
353 #define STATIC_CCS_REF(ccs) (ccs)
354
355 /* -----------------------------------------------------------------------------
356    When not profiling, these macros do nothing...
357    -------------------------------------------------------------------------- */
358 #else /* !PROFILING */
359
360 #define CCS_ALLOC(ccs, amount) doNothing()
361 #define ENTER_CC_PAP_CL(r)     doNothing()
362 #define ENTER_CCS_PAP_CL(r)    doNothing()
363  
364 #endif /* PROFILING */
365
366 #endif /* STGPROF_H */