[project @ 2000-03-08 17:48:24 by simonmar]
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgProf.h,v 1.8 2000/03/08 17:48:26 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 CostCentre *CC_LIST;               /* registered CC list */
38 extern CostCentreStack *CCS_LIST;         /* registered CCS list */
39
40 #define REGISTER_CC(cc)                                 \
41         do {                                            \
42         extern CostCentre cc[];                         \
43         if ((cc)->link == (CostCentre *)0) {            \
44             (cc)->link = CC_LIST;                       \
45             CC_LIST = (cc);                             \
46             (cc)->ccID = CC_ID++;                       \
47         }} while(0)
48
49 #define REGISTER_CCS(ccs)                               \
50         do {                                            \
51         extern CostCentreStack ccs[];                   \
52         if ((ccs)->prevStack == (CostCentreStack *)0) { \
53           (ccs)->prevStack = CCS_LIST;                  \
54           CCS_LIST = (ccs);                             \
55           (ccs)->ccsID = CCS_ID++;                      \
56         }} while(0)
57
58 /* -----------------------------------------------------------------------------
59  * Declaring Cost Centres & Cost Centre Stacks.
60  * -------------------------------------------------------------------------- */
61
62 # define CC_DECLARE(cc_ident,name,module,subsumed,is_local)     \
63      is_local CostCentre cc_ident[1]                            \
64         = {{ 0,                                                 \
65              name,                                              \
66              module,                                            \
67              0,                                                 \
68              0,                                                 \
69              subsumed,                                          \
70              0 }};
71
72 # define CCS_DECLARE(ccs_ident,cc_ident,subsumed,is_local)      \
73      is_local CostCentreStack ccs_ident[1]                      \
74        = {{ ccsID               : 0,                            \
75             cc                  : cc_ident,                     \
76             prevStack           : NULL,                         \
77             indexTable          : NULL,                         \
78             scc_count           : 0,                            \
79             sub_scc_count       : 0,                            \
80             sub_cafcc_count     : 0,                            \
81             time_ticks          : 0,                            \
82             mem_alloc           : 0,                            \
83             mem_resid           : 0,                            \
84             root                : 0,                            \
85        }};
86
87 # define CC_EXTERN(cc_ident) \
88     extern CostCentre cc_ident[];
89
90 /* -----------------------------------------------------------------------------
91  * Time / Allocation Macros
92  * ---------------------------------------------------------------------------*/
93
94 #define CCS_TICK(ccs)  (ccs)->time_ticks++
95
96 /* eliminate profiling overhead from allocation costs */
97 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
98
99 /* For grabbing the cost centre from a closure */
100 #define CCS_HDR(closure)   ((StgClosure *)(closure))->header.prof.ccs
101
102 /* Restore the CCCS from a stack frame.
103  * (addr should always be Sp->header.prof.ccs) 
104  */
105 #define RESTORE_CCCS(addr)   (CCCS = (CostCentreStack *)(addr))
106
107 /* -----------------------------------------------------------------------------
108  * Pushing a new cost centre (i.e. for scc annotations)
109  * -------------------------------------------------------------------------- */
110
111 # define SET_CCC_X(cc,do_subcc_count,do_scc_count)              \
112         do {                                                    \
113         if (do_subcc_count)   { CCCS->sub_scc_count++; }        \
114         CCCS = PushCostCentre(CCCS,cc);                         \
115         if (do_scc_count)     { CCCS->scc_count++; }            \
116         } while(0)
117
118 /* We sometimes don't increment the scc_count field, for example when
119  * this scc has been placed by the compiler on an expression it
120  * floated outside the main scc annotation.
121  */
122
123 # define SET_CCC(cc_ident,do_scc_count) \
124          SET_CCC_X(cc_ident,do_scc_count,do_scc_count)
125
126 # define SET_CCS_TOP(cc_ident) \
127          SET_CCC_X(cc_ident,0,1)
128
129 /* -----------------------------------------------------------------------------
130  * Allocating new cost centres / cost centre stacks.
131  * -------------------------------------------------------------------------- */
132
133 #define ASSIGN_CC_ID(ccID)                \
134         do {                              \
135         ccID = CC_ID;                     \
136         CC_ID++;                          \
137         } while(0)
138
139 #define ASSIGN_CCS_ID(ccsID)              \
140         do {                              \
141         ccsID = CCS_ID;                   \
142         CCS_ID++;                         \
143         } while(0)
144
145 #define ASSIGN_HP_ID(hpID)                \
146         do {                              \
147         hpID = HP_ID;                     \
148         HP_ID++;                          \
149         } while(0)
150
151 #define SET_STATS_TO_ZERO(stack)          \
152         do {                              \
153         (stack)->scc_count = 0;           \
154         (stack)->time_ticks = 0;          \
155         (stack)->sub_cafcc_count = 0;     \
156         (stack)->mem_alloc = 0;           \
157         } while(0)
158
159 /* -----------------------------------------------------------------------------
160  * Setting the cost centre when we enter a closure
161  * -------------------------------------------------------------------------- */
162
163 #if defined(PROFILING_DETAIL_COUNTS)
164 #define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
165 #else
166 #define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
167 #endif
168
169 #define IS_CAF_OR_SUB_CCS(ccs)                  \
170         /* tests for lower case character */    \
171         ((ccs)->is_subsumed & ' ')
172         
173
174 /* On entry to top level CAFs we count the scc ...*/
175
176 #define ENTER_CCS_CAF_X(ccs)                                \
177         do {                                                \
178         /* inc subcaf count of CCCS */                      \
179         CCCS->sub_cafcc_count++;                            \
180         /* set CCCS to ident ccs */                         \
181         CCCS = (CostCentreStack *)(ccs);                    \
182         /* inc scc count of CAF ccs */                      \
183         CCCS->scc_count++;                                  \
184         } while(0)
185  
186 #define ENTER_CCS_CAF(ccs_ident)   ENTER_CCS_CAF_X(ccs_ident)
187 #define ENTER_CCS_CAF_CL(closure)  ENTER_CCS_CAF_X(CCS_HDR(closure))
188
189 /* ----------------------------------------------------------------------------
190  * Entering a Thunk
191  *
192  * On entering a closure we only count the enter to thunks ...
193  * ------------------------------------------------------------------------- */
194
195 #define ENTER_CCS_T(ccs)                                \
196         do {                                            \
197         CCCS = (CostCentreStack *)(ccs);                \
198         CCCS_DETAIL_COUNT(CCCS->thunk_count);           \
199         } while(0)      
200  
201 #define ENTER_CCS_TCL(closure)  ENTER_CCS_T(CCS_HDR(closure))
202  
203 /* -----------------------------------------------------------------------------
204  * Entering a function
205  *
206  * Here is our special "hybrid" case when we do *not* set the CCCS.
207  *  (a) The closure is a function, not a thunk;
208  *  (b) The CCS is CAF-ish.
209  * -------------------------------------------------------------------------- */
210
211 #define ENTER_CCS_F(stack)                                              \
212         do {                                                            \
213         CostCentreStack *ccs = (CostCentreStack *) (stack);             \
214         CCCS_DETAIL_COUNT(CCCS->function_count);                        \
215         CCCS = EnterFunCCS(CCCS,ccs);                                   \
216         } while(0)
217  
218 #define ENTER_CCS_FCL(closure)  ENTER_CCS_F(CCS_HDR(closure))
219
220 /* Entering a top-level function: costs are subsumed by the caller 
221  */
222 #define ENTER_CCS_FSUB()                                \
223         do {                                            \
224         CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count);    \
225         CCCS_DETAIL_COUNT(CCCS->function_count);        \
226         entering_PAP = 0;                               \
227         } while(0)
228  
229 #define ENTER_CCS_FCAF(stack)                                   \
230         do {                                                    \
231         CostCentreStack *ccs = (CostCentreStack *) (stack);     \
232         CCCS_DETAIL_COUNT(ccs->caffun_subsumed);                \
233         CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count);            \
234         CCCS_DETAIL_COUNT(CCCS->function_count);                \
235         entering_PAP = 0;                                       \
236         } while(0)
237  
238 #define ENTER_CCS_FLOAD(ccs)                                \
239         do {                                                \
240         CCCS = (CostCentreStack *)(ccs);                    \
241         CCCS_DETAIL_COUNT(CCCS->function_count);            \
242         } while(0)
243  
244 /* These ENTER_CC_PAP things are only used in the RTS */
245  
246 #define ENTER_CCS_PAP(stack)                    \
247         do {                                    \
248         ENTER_CCS_F(stack);                     \
249         entering_PAP = rtsTrue;                 \
250         } while(0)
251
252 #define ENTER_CCS_PAP_CL(closure)  \
253         ENTER_CCS_PAP((closure)->header.prof.ccs)
254
255  /* temp EW */
256 #define STATIC_CCS_REF(ccs) (ccs)
257
258 #endif /* PROFILING */
259
260 #endif /* STGPROF_H */