b94066e20a38046c8d86489f8f53bf0035d58b59
[ghc-hetmet.git] / ghc / includes / StgProf.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 2004
4  *
5  * Macros for profiling operations in STG code
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #ifndef STGPROF_H
10 #define STGPROF_H
11
12 /* -----------------------------------------------------------------------------
13  * Data Structures 
14  * ---------------------------------------------------------------------------*/  
15 // NB. be careful to avoid unwanted padding between fields, by
16 // putting the 8-byte fields on an 8-byte boundary.  Padding can
17 // vary between C compilers, and we don't take into account any
18 // possible padding when generating CCS and CC decls in the code
19 // generator (compiler/codeGen/CgProf.hs).
20
21 typedef struct _CostCentre {
22   StgInt ccID;
23
24   char * label;
25   char * module;
26  
27   /* used for accumulating costs at the end of the run... */
28   StgWord   time_ticks;
29   StgWord64 mem_alloc;      // align 8 (see above)
30
31   StgInt    is_caf;
32
33   struct _CostCentre *link;
34 } CostCentre;
35
36 typedef struct _CostCentreStack {
37   StgInt ccsID;
38
39   CostCentre *cc;
40   struct _CostCentreStack *prevStack;
41   struct _IndexTable *indexTable;
42
43   StgWord64  scc_count;       // align 8 (see above)
44   StgWord    selected;
45   StgWord    time_ticks;
46   StgWord64  mem_alloc;       // align 8 (see above)
47   StgWord64  inherited_alloc; // align 8 (see above)
48   StgWord    inherited_ticks;
49
50   CostCentre *root;
51 } CostCentreStack;
52
53
54 /* -----------------------------------------------------------------------------
55  * The rest is PROFILING only...
56  * ---------------------------------------------------------------------------*/
57
58 #if defined(PROFILING)
59   
60 /* -----------------------------------------------------------------------------
61  * Constants
62  * ---------------------------------------------------------------------------*/
63
64 #define EMPTY_STACK NULL
65 #define EMPTY_TABLE NULL
66
67 /* Constants used to set sumbsumed flag on CostCentres */
68
69 #define CC_IS_CAF      'c'            /* 'c'  => *is* a CAF cc           */
70 #define CC_IS_BORING   'B'            /* 'B'  => *not* a CAF/sub cc      */
71
72
73 /* -----------------------------------------------------------------------------
74  * Data Structures
75  * ---------------------------------------------------------------------------*/
76
77 typedef struct _IndexTable {
78   CostCentre *cc;
79   CostCentreStack *ccs;
80   struct _IndexTable *next;
81   unsigned int back_edge;
82 } IndexTable;
83
84      
85 /* -----------------------------------------------------------------------------
86    Pre-defined cost centres and cost centre stacks
87    -------------------------------------------------------------------------- */
88
89 extern CostCentreStack * RTS_VAR(CCCS);         /* current CCS */
90  
91 #if IN_STG_CODE
92
93 extern StgWord CC_MAIN[];       
94 extern StgWord CCS_MAIN[];      /* Top CCS */
95
96 extern StgWord CC_SYSTEM[];     
97 extern StgWord CCS_SYSTEM[];    /* RTS costs */
98
99 extern StgWord CC_GC[];
100 extern StgWord CCS_GC[];         /* Garbage collector costs */
101
102 extern StgWord CC_SUBSUMED[];   
103 extern StgWord CCS_SUBSUMED[];   /* Costs are subsumed by caller */
104
105 extern StgWord CC_OVERHEAD[];
106 extern StgWord CCS_OVERHEAD[];   /* Profiling overhead */
107
108 extern StgWord CC_DONT_CARE[];
109 extern StgWord CCS_DONT_CARE[];  /* shouldn't ever get set */
110
111 #else
112
113 extern CostCentre      CC_MAIN[];       
114 extern CostCentreStack CCS_MAIN[];      /* Top CCS */
115
116 extern CostCentre      CC_SYSTEM[];     
117 extern CostCentreStack CCS_SYSTEM[];    /* RTS costs */
118
119 extern CostCentre      CC_GC[];
120 extern CostCentreStack CCS_GC[];         /* Garbage collector costs */
121
122 extern CostCentre      CC_SUBSUMED[];   
123 extern CostCentreStack CCS_SUBSUMED[];   /* Costs are subsumed by caller */
124
125 extern CostCentre      CC_OVERHEAD[];
126 extern CostCentreStack CCS_OVERHEAD[];   /* Profiling overhead */
127
128 extern CostCentre      CC_DONT_CARE[];
129 extern CostCentreStack CCS_DONT_CARE[];  /* shouldn't ever get set */
130
131 #endif // IN_STG_CODE
132
133 extern unsigned int RTS_VAR(CC_ID);     /* global ids */
134 extern unsigned int RTS_VAR(CCS_ID);
135 extern unsigned int RTS_VAR(HP_ID);
136
137 extern unsigned int RTS_VAR(era);
138
139 /* -----------------------------------------------------------------------------
140  * Functions 
141  * ---------------------------------------------------------------------------*/
142
143 void EnterFunCCS ( CostCentreStack *ccsfn );
144 CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
145 CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
146
147 extern unsigned int RTS_VAR(entering_PAP);
148
149 /* -----------------------------------------------------------------------------
150  * Registering CCs
151  
152  Cost centres are registered at startup by calling a registering
153  routine in each module. Each module registers its cost centres and
154  calls the registering routine for all imported modules. The RTS calls
155  the registering routine for the module Main. This registering must be
156  done before initialisation since the evaluation required for
157  initialisation may use the cost centres.
158  
159  As the code for each module uses tail calls we use an auxiliary stack
160  (in the heap) to record imported modules still to be registered. At
161  the bottom of the stack is NULL which indicates that
162  @miniInterpretEnd@ should be resumed.
163  
164  @START_REGISTER@ and @END_REGISTER@ are special macros used to
165  delimit the function. @END_REGISTER@ pops the next registering
166  routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
167  centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
168  the register stack.
169
170  -------------------------------------------------------------------------- */
171
172 extern CostCentre * RTS_VAR(CC_LIST);               /* registered CC list */
173 extern CostCentreStack * RTS_VAR(CCS_LIST);         /* registered CCS list */
174
175 #define REGISTER_CC(cc)                                 \
176         do {                                            \
177         extern CostCentre cc[];                         \
178         if ((cc)->link == (CostCentre *)0) {            \
179             (cc)->link = CC_LIST;                       \
180             CC_LIST = (cc);                             \
181             (cc)->ccID = CC_ID++;                       \
182         }} while(0)
183
184 #define REGISTER_CCS(ccs)                               \
185         do {                                            \
186         extern CostCentreStack ccs[];                   \
187         if ((ccs)->prevStack == (CostCentreStack *)0) { \
188           (ccs)->prevStack = CCS_LIST;                  \
189           CCS_LIST = (ccs);                             \
190           (ccs)->ccsID = CCS_ID++;                      \
191         }} while(0)
192
193 /* -----------------------------------------------------------------------------
194  * Declaring Cost Centres & Cost Centre Stacks.
195  * -------------------------------------------------------------------------- */
196
197 # define CC_DECLARE(cc_ident,name,module,caf,is_local)          \
198      is_local CostCentre cc_ident[1]                            \
199         = {{ 0,                                                 \
200              name,                                              \
201              module,                                            \
202              0,                                                 \
203              0,                                                 \
204              caf,                                               \
205              0 }};
206
207 # define CCS_DECLARE(ccs_ident,cc_ident,is_local)               \
208      is_local CostCentreStack ccs_ident[1]                      \
209        = {{ ccsID               : 0,                            \
210             cc                  : cc_ident,                     \
211             prevStack           : NULL,                         \
212             indexTable          : NULL,                         \
213             selected            : 0,                            \
214             scc_count           : 0,                            \
215             time_ticks          : 0,                            \
216             mem_alloc           : 0,                            \
217             inherited_ticks     : 0,                            \
218             inherited_alloc     : 0,                            \
219             root                : 0,                            \
220        }};
221
222 /* -----------------------------------------------------------------------------
223  * Time / Allocation Macros
224  * ---------------------------------------------------------------------------*/
225
226 /* eliminate profiling overhead from allocation costs */
227 #define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
228
229 #else /* !PROFILING */
230
231 #define CCS_ALLOC(ccs, amount) doNothing()
232  
233 #endif /* PROFILING */
234
235 #endif /* STGPROF_H */
236