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