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