summaryrefslogtreecommitdiff
path: root/includes/StgProf.h
blob: 9b3ce69a9f7d365b8b4e5f7d1e347b33695bf57a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
/* -----------------------------------------------------------------------------
 *
 * (c) The GHC Team, 2004
 *
 * Macros for profiling operations in STG code
 *
 * ---------------------------------------------------------------------------*/

#ifndef STGPROF_H
#define STGPROF_H

/* -----------------------------------------------------------------------------
 * Data Structures 
 * ---------------------------------------------------------------------------*/  
/*
 * NB. be careful to avoid unwanted padding between fields, by
 * putting the 8-byte fields on an 8-byte boundary.  Padding can
 * vary between C compilers, and we don't take into account any
 * possible padding when generating CCS and CC decls in the code
 * generator (compiler/codeGen/CgProf.hs).
 */

typedef struct _CostCentre {
  StgInt ccID;

  char * label;
  char * module;
 
  /* used for accumulating costs at the end of the run... */
  StgWord   time_ticks;
  StgWord64 mem_alloc;      /* align 8 (see above) */

  StgInt    is_caf;

  struct _CostCentre *link;
} CostCentre;

typedef struct _CostCentreStack {
  StgInt ccsID;

  CostCentre *cc;
  struct _CostCentreStack *prevStack;
  struct _IndexTable *indexTable;

  StgWord64  scc_count;       /* align 8 (see above) */
  StgWord    selected;
  StgWord    time_ticks;
  StgWord64  mem_alloc;       /* align 8 (see above) */
  StgWord64  inherited_alloc; /* align 8 (see above) */
  StgWord    inherited_ticks;

  CostCentre *root;
} CostCentreStack;


/* -----------------------------------------------------------------------------
 * The rest is PROFILING only...
 * ---------------------------------------------------------------------------*/

#if defined(PROFILING)
  
/* -----------------------------------------------------------------------------
 * Constants
 * ---------------------------------------------------------------------------*/

#define EMPTY_STACK NULL
#define EMPTY_TABLE NULL

/* Constants used to set sumbsumed flag on CostCentres */

#define CC_IS_CAF      'c'            /* 'c'  => *is* a CAF cc           */
#define CC_IS_BORING   'B'            /* 'B'  => *not* a CAF/sub cc      */


/* -----------------------------------------------------------------------------
 * Data Structures
 * ---------------------------------------------------------------------------*/

typedef struct _IndexTable {
  CostCentre *cc;
  CostCentreStack *ccs;
  struct _IndexTable *next;
  unsigned int back_edge;
} IndexTable;

     
/* -----------------------------------------------------------------------------
   Pre-defined cost centres and cost centre stacks
   -------------------------------------------------------------------------- */

extern CostCentreStack * RTS_VAR(CCCS);	        /* current CCS */
 
#if IN_STG_CODE

extern StgWord CC_MAIN[];	
extern StgWord CCS_MAIN[];      /* Top CCS */

extern StgWord CC_SYSTEM[];	
extern StgWord CCS_SYSTEM[];    /* RTS costs */

extern StgWord CC_GC[];
extern StgWord CCS_GC[];	 /* Garbage collector costs */

extern StgWord CC_SUBSUMED[];	
extern StgWord CCS_SUBSUMED[];   /* Costs are subsumed by caller */

extern StgWord CC_OVERHEAD[];
extern StgWord CCS_OVERHEAD[];   /* Profiling overhead */

extern StgWord CC_DONT_CARE[];
extern StgWord CCS_DONT_CARE[];  /* shouldn't ever get set */

#else

extern CostCentre      CC_MAIN[];	
extern CostCentreStack CCS_MAIN[];      /* Top CCS */

extern CostCentre      CC_SYSTEM[];	
extern CostCentreStack CCS_SYSTEM[];    /* RTS costs */

extern CostCentre      CC_GC[];
extern CostCentreStack CCS_GC[];	 /* Garbage collector costs */

extern CostCentre      CC_SUBSUMED[];	
extern CostCentreStack CCS_SUBSUMED[];   /* Costs are subsumed by caller */

extern CostCentre      CC_OVERHEAD[];
extern CostCentreStack CCS_OVERHEAD[];   /* Profiling overhead */

extern CostCentre      CC_DONT_CARE[];
extern CostCentreStack CCS_DONT_CARE[];  /* shouldn't ever get set */

#endif /* IN_STG_CODE */

extern unsigned int RTS_VAR(CC_ID);	/* global ids */
extern unsigned int RTS_VAR(CCS_ID);
extern unsigned int RTS_VAR(HP_ID);

extern unsigned int RTS_VAR(era);

/* -----------------------------------------------------------------------------
 * Functions 
 * ---------------------------------------------------------------------------*/

void EnterFunCCS ( CostCentreStack *ccsfn );
CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );

extern unsigned int RTS_VAR(entering_PAP);

/* -----------------------------------------------------------------------------
 * Registering CCs
 
 Cost centres are registered at startup by calling a registering
 routine in each module. Each module registers its cost centres and
 calls the registering routine for all imported modules. The RTS calls
 the registering routine for the module Main. This registering must be
 done before initialisation since the evaluation required for
 initialisation may use the cost centres.
 
 As the code for each module uses tail calls we use an auxiliary stack
 (in the heap) to record imported modules still to be registered. At
 the bottom of the stack is NULL which indicates that
 @miniInterpretEnd@ should be resumed.
 
 @START_REGISTER@ and @END_REGISTER@ are special macros used to
 delimit the function. @END_REGISTER@ pops the next registering
 routine off the stack and jumps to it. @REGISTER_CC@ registers a cost
 centre. @REGISTER_IMPORT@ pushes a modules registering routine onto
 the register stack.

 -------------------------------------------------------------------------- */

extern CostCentre * RTS_VAR(CC_LIST);               /* registered CC list */
extern CostCentreStack * RTS_VAR(CCS_LIST);         /* registered CCS list */

#define REGISTER_CC(cc)					\
	do {						\
	extern CostCentre cc[];				\
	if ((cc)->link == (CostCentre *)0) {		\
	    (cc)->link = CC_LIST;			\
	    CC_LIST = (cc);				\
	    (cc)->ccID = CC_ID++; 			\
	}} while(0)

#define REGISTER_CCS(ccs)				\
	do {						\
	extern CostCentreStack ccs[];			\
        if ((ccs)->prevStack == (CostCentreStack *)0) {	\
	  (ccs)->prevStack = CCS_LIST;			\
	  CCS_LIST = (ccs);				\
	  (ccs)->ccsID = CCS_ID++;			\
	}} while(0)

/* -----------------------------------------------------------------------------
 * Declaring Cost Centres & Cost Centre Stacks.
 * -------------------------------------------------------------------------- */

# define CC_DECLARE(cc_ident,name,module,caf,is_local)		\
     is_local CostCentre cc_ident[1]				\
	= {{ 0,							\
	     name,						\
	     module,						\
             0,							\
	     0,							\
	     caf,						\
	     0 }};

# define CCS_DECLARE(ccs_ident,cc_ident,is_local)		\
     is_local CostCentreStack ccs_ident[1]			\
       = {{ ccsID 		: 0,				\
	    cc 			: cc_ident,			\
	    prevStack 		: NULL,				\
	    indexTable 		: NULL,				\
            selected            : 0,				\
	    scc_count 		: 0,				\
	    time_ticks 		: 0,				\
	    mem_alloc 		: 0,				\
	    inherited_ticks 	: 0,				\
	    inherited_alloc	: 0,				\
	    root 		: 0,				\
       }};

/* -----------------------------------------------------------------------------
 * Time / Allocation Macros
 * ---------------------------------------------------------------------------*/

/* eliminate profiling overhead from allocation costs */
#define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))

#else /* !PROFILING */

#define CCS_ALLOC(ccs, amount) doNothing()
 
#endif /* PROFILING */

#endif /* STGPROF_H */