[project @ 2000-03-08 15:58:30 by simonmar]
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgProf.h,v 1.7 1999/09/15 13:45:14 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 /* -----------------------------------------------------------------------------
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              0,                                                         \
94              0,                                                         \
95              subsumed,                                                  \
96              0 }};
97
98 # define CCS_DECLARE(ccs_ident,cc_ident,subsumed,is_local)      \
99      is_local CostCentreStack ccs_ident[1]                      \
100        = {{ ccsID               : 0,                            \
101             cc                  : cc_ident,                     \
102             prevStack           : NULL,                         \
103             indexTable          : NULL,                         \
104             scc_count           : 0,                            \
105             sub_scc_count       : 0,                            \
106             sub_cafcc_count     : 0,                            \
107             time_ticks          : 0,                            \
108             mem_alloc           : 0,                            \
109             mem_resid           : 0,                            \
110             root                : 0,                            \
111        }};
112
113 # define CC_EXTERN(cc_ident) \
114     extern CostCentre cc_ident[];
115
116 /* -----------------------------------------------------------------------------
117  * Time / Allocation Macros
118  * ---------------------------------------------------------------------------*/
119
120 #define CCS_TICK(ccs)  (ccs)->time_ticks++
121
122 /* eliminate profiling overhead from allocation costs */
123 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
124
125 /* For grabbing the cost centre from a closure */
126 #define CCS_HDR(closure)   ((StgClosure *)(closure))->header.prof.ccs
127
128 /* Restore the CCCS from a stack frame.
129  * (addr should always be Sp->header.prof.ccs) 
130  */
131 #define RESTORE_CCCS(addr)   (CCCS = (CostCentreStack *)(addr))
132
133 /* -----------------------------------------------------------------------------
134  * Pushing a new cost centre (i.e. for scc annotations)
135  * -------------------------------------------------------------------------- */
136
137 # define SET_CCC_X(cc,do_subcc_count,do_scc_count)              \
138         do {                                                    \
139         if (do_subcc_count)   { CCCS->sub_scc_count++; }        \
140         CCCS = PushCostCentre(CCCS,cc);                         \
141         if (do_scc_count)     { CCCS->scc_count++; }            \
142         } while(0)
143
144 /* We sometimes don't increment the scc_count field, for example when
145  * this scc has been placed by the compiler on an expression it
146  * floated outside the main scc annotation.
147  */
148
149 # define SET_CCC(cc_ident,do_scc_count) \
150          SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
151
152 # define SET_CCS_TOP(cc_ident) \
153          SET_CCC_X(cc_ident,0,1)
154
155 /* -----------------------------------------------------------------------------
156  * Allocating new cost centres / cost centre stacks.
157  * -------------------------------------------------------------------------- */
158
159 #define ASSIGN_CC_ID(ccID)                \
160         do {                              \
161         ccID = CC_ID;                     \
162         CC_ID++;                          \
163         } while(0)
164
165 #define ASSIGN_CCS_ID(ccsID)              \
166         do {                              \
167         ccsID = CCS_ID;                   \
168         CCS_ID++;                         \
169         } while(0)
170
171 #define ASSIGN_HP_ID(hpID)                \
172         do {                              \
173         hpID = HP_ID;                     \
174         HP_ID++;                          \
175         } while(0)
176
177 #define SET_STATS_TO_ZERO(stack)          \
178         do {                              \
179         (stack)->scc_count = 0;           \
180         (stack)->time_ticks = 0;          \
181         (stack)->sub_cafcc_count = 0;     \
182         (stack)->mem_alloc = 0;           \
183         } while(0)
184
185 /* -----------------------------------------------------------------------------
186  * Setting the cost centre when we enter a closure
187  * -------------------------------------------------------------------------- */
188
189 #if defined(PROFILING_DETAIL_COUNTS)
190 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
191 #else
192 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
193 #endif
194
195 #define IS_CAF_OR_SUB_CCS(ccs)                  \
196         /* tests for lower case character */    \
197         ((ccs)->is_subsumed & ' ')
198         
199
200 /* On entry to top level CAFs we count the scc ...*/
201
202 #define ENTER_CCS_CAF_X(ccs)                                \
203         do {                                                \
204         /* inc subcaf count of CCCS */                      \
205         CCCS->sub_cafcc_count++;                            \
206         /* set CCCS to ident ccs */                         \
207         CCCS = (CostCentreStack *)(ccs);                    \
208         /* inc scc count of CAF ccs */                      \
209         CCCS->scc_count++;                                  \
210         } while(0)
211  
212 #define ENTER_CCS_CAF(ccs_ident)   ENTER_CCS_CAF_X(ccs_ident)
213 #define ENTER_CCS_CAF_CL(closure)  ENTER_CCS_CAF_X(CCS_HDR(closure))
214
215 /* ----------------------------------------------------------------------------
216  * Entering a Thunk
217  *
218  * On entering a closure we only count the enter to thunks ...
219  * ------------------------------------------------------------------------- */
220
221 #define ENTER_CCS_T(ccs)                                \
222         do {                                            \
223         CCCS = (CostCentreStack *)(ccs);                \
224         CCCS_DETAIL_COUNT(CCCS->thunk_count);           \
225         } while(0)      
226  
227 #define ENTER_CCS_TCL(closure)  ENTER_CCS_T(CCS_HDR(closure))
228  
229 /* -----------------------------------------------------------------------------
230  * Entering a function
231  *
232  * Here is our special "hybrid" case when we do *not* set the CCCS.
233  *  (a) The closure is a function, not a thunk;
234  *  (b) The CCS is CAF-ish.
235  * -------------------------------------------------------------------------- */
236
237 #define ENTER_CCS_F(stack)                                              \
238         do {                                                            \
239         CostCentreStack *ccs = (CostCentreStack *) (stack);             \
240         CCCS_DETAIL_COUNT(CCCS->function_count);                        \
241         CCCS = EnterFunCCS(CCCS,ccs);                                   \
242         } while(0)
243  
244 #define ENTER_CCS_FCL(closure)  ENTER_CCS_F(CCS_HDR(closure))
245
246 /* Entering a top-level function: costs are subsumed by the caller 
247  */
248 #define ENTER_CCS_FSUB()                                \
249         do {                                            \
250         CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count);    \
251         CCCS_DETAIL_COUNT(CCCS->function_count);        \
252         entering_PAP = 0;                               \
253         } while(0)
254  
255 #define ENTER_CCS_FCAF(stack)                                   \
256         do {                                                    \
257         CostCentreStack *ccs = (CostCentreStack *) (stack);     \
258         CCCS_DETAIL_COUNT(ccs->caffun_subsumed);                \
259         CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count);            \
260         CCCS_DETAIL_COUNT(CCCS->function_count);                \
261         entering_PAP = 0;                                       \
262         } while(0)
263  
264 #define ENTER_CCS_FLOAD(ccs)                                \
265         do {                                                \
266         CCCS = (CostCentreStack *)(ccs);                    \
267         CCCS_DETAIL_COUNT(CCCS->function_count);            \
268         } while(0)
269  
270 /* These ENTER_CC_PAP things are only used in the RTS */
271  
272 #define ENTER_CCS_PAP(stack)                    \
273         do {                                    \
274         ENTER_CCS_F(stack);                     \
275         entering_PAP = rtsTrue;                 \
276         } while(0)
277
278 #define ENTER_CCS_PAP_CL(closure)  \
279         ENTER_CCS_PAP((closure)->header.prof.ccs)
280
281  /* temp EW */
282 #define STATIC_CCS_REF(ccs) (ccs)
283
284 #endif /* PROFILING */
285
286 #endif /* STGPROF_H */