[project @ 1999-03-25 13:13:51 by simonm]
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgProf.h,v 1.4 1999/03/25 13:14:04 simonm 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 /* -----------------------------------------------------------------------------
15  * Registering CCs
16  
17  Cost centres are registered at startup by calling a registering
18  routine in each module. Each module registers its cost centres and
19  calls the registering routine for all imported modules. The RTS calls
20  the registering routine for the module Main. This registering must be
21  done before initialisation since the evaluation required for
22  initialisation may use the cost centres.
23  
24  As the code for each module uses tail calls we use an auxiliary stack
25  (in the heap) to record imported modules still to be registered. At
26  the bottom of the stack is NULL which indicates that
27  @miniInterpretEnd@ should be resumed.
28  
29  @START_REGISTER@ and @END_REGISTER@ are special macros used to
30  delimit the function. @END_REGISTER@ pops the next registering
31  routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
32  centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
33  the register stack.
34
35  -------------------------------------------------------------------------- */
36
37 extern F_ *register_stack;
38
39 extern CostCentre *CC_LIST;               /* registered CC list */
40 extern CostCentreStack *CCS_LIST;         /* registered CCS list */
41
42 # define PUSH_REGISTER_STACK(reg_function)                              \
43         *(register_stack++) = (F_)reg_function
44
45 # define POP_REGISTER_STACK()                                           \
46         *(--register_stack)
47
48 # define START_REGISTER_CCS(reg_mod_name)                               \
49         static int _module_registered = 0;                              \
50         FN_(reg_mod_name) {                                             \
51             FB_;                                                        \
52             if (! _module_registered) {                                 \
53                 _module_registered = 1
54
55 # define REGISTER_IMPORT(reg_mod_name)                                  \
56         do { EF_(reg_mod_name);                                         \
57           PUSH_REGISTER_STACK(reg_mod_name) ;                           \
58         } while (0)
59         
60 # define END_REGISTER_CCS()                                             \
61         };                                                              \
62         JMP_(POP_REGISTER_STACK());                                     \
63         FE_ }
64
65 #define REGISTER_CC(cc)                                 \
66         do {                                            \
67         extern CostCentre cc[];                         \
68         if ((cc)->link == (CostCentre *)0) {            \
69             (cc)->link = CC_LIST;                       \
70             CC_LIST = (cc);                             \
71             (cc)->ccID = CC_ID++;                       \
72         }} while(0)
73
74 #define REGISTER_CCS(ccs)                               \
75         do {                                            \
76         extern CostCentreStack ccs[];                   \
77         if ((ccs)->prevStack == (CostCentreStack *)0) { \
78           (ccs)->prevStack = CCS_LIST;                  \
79           CCS_LIST = (ccs);                             \
80           (ccs)->ccsID = CCS_ID++;                      \
81         }} while(0)
82
83 /* -----------------------------------------------------------------------------
84  * Declaring Cost Centres & Cost Centre Stacks.
85  * -------------------------------------------------------------------------- */
86
87 # define CC_DECLARE(cc_ident,name,module,group,subsumed,is_local)       \
88      is_local CostCentre cc_ident[1]                                    \
89         = {{ 0,                                                         \
90              name,                                                      \
91              module,                                                    \
92              group,                                                     \
93              subsumed,                                                  \
94              0 }};
95
96 # define CCS_DECLARE(ccs_ident,cc_ident,subsumed,is_local)      \
97      is_local CostCentreStack ccs_ident[1]                      \
98        = {{ ccsID               : 0,                            \
99             cc                  : cc_ident,                     \
100             prevStack           : NULL,                         \
101             indexTable          : NULL,                         \
102             scc_count           : 0,                            \
103             sub_scc_count       : 0,                            \
104             sub_cafcc_count     : 0,                            \
105             time_ticks          : 0,                            \
106             mem_alloc           : 0,                            \
107             is_subsumed         : subsumed,                     \
108        }};
109
110 # define CC_EXTERN(cc_ident) \
111     extern CostCentre cc_ident[];
112
113 /* -----------------------------------------------------------------------------
114  * Time / Allocation Macros
115  * ---------------------------------------------------------------------------*/
116
117 #define CCS_TICK(ccs)  (ccs)->time_ticks++
118
119 /* eliminate profiling overhead from allocation costs */
120 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
121
122 /* For grabbing the cost centre from a closure */
123 #define CCS_HDR(closure)   ((StgClosure *)(closure))->header.prof.ccs
124
125 /* Restore the CCCS from a stack frame.
126  * (addr should always be Sp->header.prof.ccs) 
127  */
128 #define RESTORE_CCCS(addr)   (CCCS = (CostCentreStack *)(addr))
129
130 /* -----------------------------------------------------------------------------
131  * Pushing a new cost centre (i.e. for scc annotations)
132  * -------------------------------------------------------------------------- */
133
134 # define SET_CCC_X(cc,do_subcc_count,do_scc_count)              \
135         do {                                                    \
136         if (do_subcc_count)   { CCCS->sub_scc_count++; }        \
137         CCCS = PushCostCentre(CCCS,cc);                         \
138         if (do_scc_count)     { CCCS->scc_count++; }            \
139         } while(0)
140
141 /* We sometimes don't increment the scc_count field, for example when
142  * this scc has been placed by the compiler on an expression it
143  * floated outside the main scc annotation.
144  */
145
146 # define SET_CCC(cc_ident,do_scc_count) \
147          SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
148
149 # define SET_CCS_TOP(cc_ident) \
150          SET_CCC_X(cc_ident,0,1)
151
152 /* -----------------------------------------------------------------------------
153  * Allocating new cost centres / cost centre stacks.
154  * -------------------------------------------------------------------------- */
155
156 #define ASSIGN_CC_ID(ccID)                \
157         do {                              \
158         ccID = CC_ID;                     \
159         CC_ID++;                          \
160         } while(0)
161
162 #define ASSIGN_CCS_ID(ccsID)              \
163         do {                              \
164         ccsID = CCS_ID;                   \
165         CCS_ID++;                         \
166         } while(0)
167
168 #define ASSIGN_HP_ID(hpID)                \
169         do {                              \
170         hpID = HP_ID;                     \
171         HP_ID++;                          \
172         } while(0)
173
174 #define SET_STATS_TO_ZERO(stack)          \
175         do {                              \
176         (stack)->scc_count = 0;           \
177         (stack)->time_ticks = 0;          \
178         (stack)->sub_cafcc_count = 0;     \
179         (stack)->mem_alloc = 0;           \
180         } while(0)
181
182 /* -----------------------------------------------------------------------------
183  * Setting the cost centre when we enter a closure
184  * -------------------------------------------------------------------------- */
185
186 #if defined(PROFILING_DETAIL_COUNTS)
187 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
188 #else
189 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
190 #endif
191
192 #define IS_CAF_OR_SUB_CCS(ccs)                  \
193         /* tests for lower case character */    \
194         ((ccs)->is_subsumed & ' ')
195         
196
197 /* On entry to top level CAFs we count the scc ...*/
198
199 #define ENTER_CCS_CAF_X(ccs)                                \
200         do {                                                \
201         /* inc subcaf count of CCCS */                      \
202         CCCS->sub_cafcc_count++;                            \
203         /* set CCCS to ident ccs */                         \
204         CCCS = (CostCentreStack *)(ccs);                    \
205         /* inc scc count of CAF ccs */                      \
206         CCCS->scc_count++;                                  \
207         } while(0)
208  
209 #define ENTER_CCS_CAF(ccs_ident)   ENTER_CCS_CAF_X(ccs_ident)
210 #define ENTER_CCS_CAF_CL(closure)  ENTER_CCS_CAF_X(CCS_HDR(closure))
211
212 /* ----------------------------------------------------------------------------
213  * Entering a Thunk
214  *
215  * On entering a closure we only count the enter to thunks ...
216  * ------------------------------------------------------------------------- */
217
218 #define ENTER_CCS_T(ccs)                                    \
219         do {                                                \
220         CCCS = (CostCentreStack *)(ccs);                    \
221         CCCS_DETAIL_COUNT(CCCS->thunk_count);               \
222         } while(0)      
223  
224 #define ENTER_CCS_TCL(closure)  ENTER_CCS_T(CCS_HDR(closure))
225  
226 /* -----------------------------------------------------------------------------
227  * Entering a function
228  *
229  * Here is our special "hybrid" case when we do *not* set the CCCS.
230  *  (a) The closure is a function, not a thunk;
231  *  (b) The CCS is CAF-ish.
232  * -------------------------------------------------------------------------- */
233
234 #define ENTER_CCS_F(stack)                                      \
235         do {                                                    \
236         CostCentreStack *ccs = (CostCentreStack *) (stack);     \
237         if ( ! IS_CAF_OR_SUB_CCS(ccs) ) {                       \
238            CCCS = ccs;                                          \
239         } else {                                                \
240           CCCS = AppendCCS(CCCS,ccs);                           \
241           CCCS_DETAIL_COUNT(ccs->caffun_subsumed);              \
242           CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count);          \
243         }                                                       \
244         CCCS_DETAIL_COUNT(CCCS->function_count);                \
245         } while(0)
246  
247 #define ENTER_CCS_FCL(closure)  ENTER_CCS_F(CCS_HDR(closure))
248
249 /* Entering a top-level function: costs are subsumed by the caller 
250  */
251 #define ENTER_CCS_FSUB()                                    \
252         do {                                                \
253         CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count);        \
254         CCCS_DETAIL_COUNT(CCCS->function_count);            \
255         } while(0)
256  
257 #define ENTER_CCS_FCAF(stack)                               \
258         do {                                                \
259         CostCentreStack *ccs = (CostCentreStack *) (stack); \
260         CCCS_DETAIL_COUNT(ccs->caffun_subsumed);            \
261         CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count);        \
262         CCCS_DETAIL_COUNT(CCCS->function_count);            \
263         } while(0)
264  
265 #define ENTER_CCS_FLOAD(ccs)                                \
266         do {                                                \
267         CCCS = (CostCentreStack *)(ccs);                    \
268         CCCS_DETAIL_COUNT(CCCS->function_count);            \
269         } while(0)
270  
271 /* These ENTER_CC_PAP things are only used in the RTS */
272  
273 #define ENTER_CCS_PAP(stack)                                    \
274         do {                                                    \
275         CostCentreStack *ccs = (CostCentreStack *) (stack);     \
276         if ( ! IS_CAF_OR_SUB_CCS(ccs) ) {                       \
277             CCCS = ccs;                                         \
278         } else {                                                \
279           CCCS = AppendCCS(CCCS,ccs);                           \
280           CCCS_DETAIL_COUNT(ccs->caffun_subsumed);              \
281           CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count);          \
282         }                                                       \
283         CCCS_DETAIL_COUNT(CCCS->pap_count);                     \
284         } while(0)                      
285
286 #define ENTER_CCS_PAP_CL(closure)  \
287         ENTER_CCS_PAP((closure)->header.prof.ccs)
288
289  /* temp EW */
290 #define STATIC_CCS_REF(ccs) (ccs)
291
292 #endif /* PROFILING */
293
294 #endif /* STGPROF_H */