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