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