[project @ 1998-11-26 09:17:22 by sof]
[ghc-hetmet.git] / ghc / includes / Ticky.lh
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
3 %
4 %************************************************************************
5 %*                                                                      *
6 \section[Ticky.lh]{Interface (and macros) for reduction-count statistics}
7 %*                                                                      *
8 %************************************************************************
9
10 Multi-slurp protection:
11 \begin{code}
12 #ifndef TICKY_H
13 #define TICKY_H
14 \end{code}
15
16 There are macros in here for:
17 \begin{enumerate}
18 \item
19 ``Ticky-ticky profiling'' (\tr{TICKY_TICKY}), counting the
20 number of various STG-events (updates, enters, etc.)
21
22 This file goes with \tr{Ticky.lc}, which initialises the counters
23 and does the printing [ticky-ticky only].
24
25 %************************************************************************
26 %*                                                                      *
27 \subsection{Macros for using the `ticky' field in the fixed header}
28 %*                                                                      *
29 %************************************************************************
30
31 \begin{code}
32 #define TICKY_FIXED_HDR                 (TICKY_HDR_SIZE)
33 #define TICKY_HDR_POSN                  AFTER_PROF_HDR
34 #define AFTER_TICKY_HDR                 (TICKY_FIXED_HDR+TICKY_HDR_POSN)
35 \end{code}
36
37 \begin{code}
38 #ifndef TICKY_TICKY
39
40 #define TICKY_HDR_SIZE          0
41 #define TICKY_HDR(closure)
42 #define SET_TICKY_HDR(closure,to)
43 #define SET_STATIC_TICKY_HDR()
44
45 #else
46
47 #define TICKY_HDR_SIZE          1
48 #define TICKY_HDR(closure)      (((P_)(closure))[TICKY_HDR_POSN])
49 #define SET_TICKY_HDR(closure,to) TICKY_HDR(closure) = (to)
50 #define SET_STATIC_TICKY_HDR()  ,0
51
52 #endif /* TICKY_TICKY */
53 \end{code}
54
55 Here, we add the Ticky word to the fixed-header part of closures.
56 This is used to record indicate if a closure has been updated but not
57 yet entered. It is set when the closure is updated and cleared when
58 subsequently entered.
59
60 NB: It is {\em not} an ``entry count'', it is an
61 ``entries-after-update count.''
62
63 The commoning up of @CONST@, @CHARLIKE@ and @INTLIKE@ closures is
64 turned off(?) if this is required. This has only been done for 2s
65 collection.  It is done using a nasty hack which defines the
66 @_Evacuate@ and @_Scavenge@ code for @CONST@, @CHARLIKE@ and @INTLIKE@
67 info tables to be @_Evacuate_1@ and @_Scavenge_1_0@.
68
69 \begin{code}
70 #ifndef TICKY_TICKY
71
72 #define UPDATED_SET_UPDATED(n)   /* nothing */
73 #define ENTERED_CHECK_UPDATED(n) /* nothing */
74
75 #else
76
77 #define UPDATED_SET_UPDATED(n)  do { TICKY_HDR(n) = 1; } while(0)
78
79 #define ENT_UPD_HISTO(n)                                        \
80         do { I_ __idx;                                          \
81           __idx = (n) - 1;                                      \
82                                                                 \
83           /* once 9th enter is recorded, we do not tick anymore;*/\
84           /* we want "TotUpdates - <all 9 cols>" to equal */    \
85           /* "updates that were never entered" */               \
86           if ( __idx <= 8 )                                     \
87              UPD_ENTERED_hst[__idx] += 1;                       \
88                                                                 \
89           /* now undo tick in previous histo slot ... */        \
90           if ( __idx >= 1 && __idx <= 8 )                       \
91              UPD_ENTERED_hst[(__idx - 1)] -= 1;                 \
92         } while(0)
93
94 #define ENTERED_CHECK_UPDATED(n)                                \
95         do {                                                    \
96         I_ t_hdr = TICKY_HDR(n);                                \
97                                                                 \
98         if (t_hdr != 0 && AllFlags.doUpdEntryCounts) {          \
99             ENT_UPD_HISTO(t_hdr);                               \
100             TICKY_HDR(n) += 1;                                  \
101         }} while(0)
102
103 #endif /* TICKY_TICKY */
104 \end{code}
105
106 %************************************************************************
107 %*                                                                      *
108 \subsection[ticky-ticky-macros]{Stuff for ``ticky-ticky'' profiling}
109 %*                                                                      *
110 %************************************************************************
111
112 \begin{code}
113 #ifdef TICKY_TICKY
114 \end{code}
115
116 Measure what proportion of ...:
117 \begin{itemize}
118 \item
119 ... Enters are to data values, function values, thunks.
120 \item
121 ... allocations are for data values, functions values, thunks.
122 \item
123 ... updates are for data values, function values.
124 \item
125 ... updates ``fit''
126 \item
127 ... return-in-heap (dynamic)
128 \item
129 ... vectored return (dynamic)
130 \item
131 ... updates are wasted (never re-entered).
132 \item
133 ... constructor returns get away without hitting an update.
134 \end{enumerate}
135
136 %************************************************************************
137 %*                                                                      *
138 \subsubsection[ticky-stk-heap-use]{Stack and heap usage}
139 %*                                                                      *
140 %************************************************************************
141
142 Things we are interested in here:
143 \begin{itemize}
144 \item
145 How many times we do a heap check and move @Hp@; comparing this with
146 the allocations gives an indication of how many things we get per trip
147 to the well:
148 \begin{code}
149 #define ALLOC_HEAP(n)   ALLOC_HEAP_ctr++; ALLOC_HEAP_tot += (n)
150 \end{code}
151
152 If we do a ``heap lookahead,'' we haven't really allocated any
153 heap, so we need to undo the effects of an \tr{ALLOC_HEAP}:
154 \begin{code}
155 #define UN_ALLOC_HEAP(n) ALLOC_HEAP_ctr--; ALLOC_HEAP_tot -= (n)
156 \end{code}
157
158 \item
159 The stack high-water marks.  This is {\em direction-sensitive}!!
160 (A stack grows downward, B stack upwards)
161 \begin{code}
162 #ifndef CONCURRENT
163 #define DO_ASTK_HWM()   if (SpA < max_SpA) { max_SpA = SpA; }
164 #define DO_BSTK_HWM()   if (SpB > max_SpB) { max_SpB = SpB; }
165 #else
166 /* 
167  * This is not direction sensitive, because we threads people are well-behaved.
168  * However, it might be a good idea to cache the constant bits (DEP + BOT and
169  * HWM) from the STKO and TSO in more readily accessible places. -- ToDo!
170  */
171 #define DO_ASTK_HWM() {             \
172   I_ depth = STKO_ADEP(StkOReg) + AREL((I_) STKO_ASTK_BOT(StkOReg) - (I_) SpA);\
173   if (depth > TSO_AHWM(CurrentTSO)) \
174     TSO_AHWM(CurrentTSO) = depth;   \
175 }
176 #define DO_BSTK_HWM() {             \
177   I_ depth = STKO_BDEP(StkOReg) + BREL((I_) STKO_BSTK_BOT(StkOReg) - (I_) SpB);\
178   if (depth > TSO_BHWM(CurrentTSO)) \
179     TSO_BHWM(CurrentTSO) = depth;   \
180 }
181 #endif
182 \end{code}
183
184 \item
185 Re-use of stack slots, and stubbing of stack slots:
186 \begin{code}
187 #define A_STK_STUB(n)   A_STK_STUB_ctr += (n)
188 #define A_STK_REUSE(n)  A_STK_REUSE_ctr += (n) /* not used at all? */
189 #define B_STK_REUSE(n)  B_STK_REUSE_ctr += (n) /* not used at all? */
190 \end{code}
191 \end{itemize}
192
193 %************************************************************************
194 %*                                                                      *
195 \subsubsection[ticky-allocs]{Allocations}
196 %*                                                                      *
197 %************************************************************************
198
199 We count things every time we allocate something in the dynamic heap.
200 For each, we count the number of words of (1)~``admin'' (header),
201 (2)~good stuff (useful pointers and data), and (3)~``slop'' (extra
202 space, in hopes it will allow an in-place update).
203
204 The first five macros are inserted when the compiler generates code
205 to allocate something; the categories correspond to the @ClosureClass@
206 datatype (manifest functions, thunks, constructors, big tuples, and
207 partial applications).
208 \begin{code}
209 #define ALLOC_FUN(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
210                          ALLOC_FUN_ctr++;       ALLOC_FUN_adm += (a); \
211                          ALLOC_FUN_gds += (g);  ALLOC_FUN_slp += (s); \
212                          ALLOC_HISTO(FUN,a,g,s)
213 #define ALLOC_THK(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
214                          ALLOC_THK_ctr++;       ALLOC_THK_adm += (a); \
215                          ALLOC_THK_gds += (g);  ALLOC_THK_slp += (s); \
216                          ALLOC_HISTO(THK,a,g,s)
217 #define ALLOC_CON(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
218                          ALLOC_CON_ctr++;       ALLOC_CON_adm += (a); \
219                          ALLOC_CON_gds += (g);  ALLOC_CON_slp += (s); \
220                          ALLOC_HISTO(CON,a,g,s)
221 #define ALLOC_TUP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
222                          ALLOC_TUP_ctr++;       ALLOC_TUP_adm += (a); \
223                          ALLOC_TUP_gds += (g);  ALLOC_TUP_slp += (s); \
224                          ALLOC_HISTO(TUP,a,g,s)
225 #define ALLOC_BH(a,g,s,t)  ASSERT((t) == (a)+(g)+(s)); \
226                          ALLOC_BH_ctr++;        ALLOC_BH_adm += (a); \
227                          ALLOC_BH_gds += (g);   ALLOC_BH_slp += (s); \
228                          ALLOC_HISTO(BH,a,g,s)
229 #if 0
230 #define ALLOC_PAP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
231                          ALLOC_PAP_ctr++;       ALLOC_PAP_adm += (a); \
232                          ALLOC_PAP_gds += (g);  ALLOC_PAP_slp += (s); \
233                          ALLOC_HISTO(PAP,a,g,s)
234 #endif
235 \end{code}
236
237 We may also allocate space when we do an update, and there isn't
238 enough space.  These macros suffice (for: updating with a partial
239 application and a constructor):
240 \begin{code}
241 #define ALLOC_UPD_PAP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
242                          ALLOC_UPD_PAP_ctr++;  ALLOC_UPD_PAP_adm += (a); \
243                          ALLOC_UPD_PAP_gds += (g); ALLOC_UPD_PAP_slp += (s); \
244                          ALLOC_HISTO(UPD_PAP,a,g,s)
245 #if 0
246 #define ALLOC_UPD_CON(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
247                          ALLOC_UPD_CON_ctr++;  ALLOC_UPD_CON_adm += (a); \
248                          ALLOC_UPD_CON_gds += (g); ALLOC_UPD_CON_slp += (s); \
249                          ALLOC_HISTO(UPD_CON,a,g,s)
250 #endif /* 0 */
251 \end{code}
252
253 In the threaded world, we allocate space for the spark pool, stack objects,
254 and thread state objects.
255
256 \begin{code}
257
258 #define ALLOC_STK(a,g,s) ALLOC_STK_ctr++;       ALLOC_STK_adm += (a); \
259                          ALLOC_STK_gds += (g);  ALLOC_STK_slp += (s); \
260                          ALLOC_HISTO(STK,a,g,s)
261
262 #define ALLOC_TSO(a,g,s) ALLOC_TSO_ctr++;       ALLOC_TSO_adm += (a); \
263                          ALLOC_TSO_gds += (g);  ALLOC_TSO_slp += (s); \
264                          ALLOC_HISTO(TSO,a,g,s)
265
266 #define ALLOC_FMBQ(a,g,s) ALLOC_FMBQ_ctr++;     ALLOC_FMBQ_adm += (a); \
267                          ALLOC_FMBQ_gds += (g); ALLOC_FMBQ_slp += (s); \
268                          ALLOC_HISTO(FMBQ,a,g,s)
269
270 #define ALLOC_FME(a,g,s) ALLOC_FME_ctr++;       ALLOC_FME_adm += (a); \
271                          ALLOC_FME_gds += (g);  ALLOC_FME_slp += (s); \
272                          ALLOC_HISTO(FME,a,g,s)
273
274 #define ALLOC_BF(a,g,s)  ALLOC_BF_ctr++;        ALLOC_BF_adm += (a); \
275                          ALLOC_BF_gds += (g);   ALLOC_BF_slp += (s); \
276                          ALLOC_HISTO(BF,a,g,s)
277
278 \end{code}
279
280 The histogrammy bit is fairly straightforward; the \tr{-2} is: one for
281 0-origin C arrays; the other one because we do {\em no} one-word
282 allocations, so we would never inc that histogram slot; so we shift
283 everything over by one.
284 \begin{code}
285 #define ALLOC_HISTO(categ,a,g,s) \
286         { I_ __idx;                                              \
287           __idx = (a) + (g) + (s) - 2;                           \
288          CAT3(ALLOC_,categ,_hst)[((__idx > 4) ? 4 : __idx)] += 1;} 
289 \end{code}
290
291 Some hard-to-account-for words are allocated by/for primitives,
292 includes Integer support.  @ALLOC_PRIM2@ tells us about these.  We
293 count everything as ``goods'', which is not strictly correct.
294 (@ALLOC_PRIM@ is the same sort of stuff, but we know the
295 admin/goods/slop breakdown.)
296 \begin{code}
297 #define ALLOC_PRIM(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
298                           ALLOC_PRIM_ctr++;      ALLOC_PRIM_adm += (a); \
299                           ALLOC_PRIM_gds += (g); ALLOC_PRIM_slp += (s); \
300                           ALLOC_HISTO(PRIM,a,g,s)
301 #define ALLOC_PRIM2(w) ALLOC_PRIM_ctr++; ALLOC_PRIM_gds +=(w); \
302                        ALLOC_HISTO(PRIM,0,w,0)
303 \end{code}
304
305 %************************************************************************
306 %*                                                                      *
307 \subsubsection[ticky-enters]{Enters}
308 %*                                                                      *
309 %************************************************************************
310
311 \begin{code}
312 #define ENT_VIA_NODE()  ENT_VIA_NODE_ctr++      /* via ENT_ macro */
313
314 #define ENT_THK()       ENT_THK_ctr++
315 #define ENT_FUN_STD()   ENT_FUN_STD_ctr++       /* manifest fun; std entry pt */
316
317 #define ENT_CON(n)      ENTERED_CHECK_UPDATED(n); ENT_CON_ctr++  /* enter code for constructor */
318 #define ENT_IND(n)      ENTERED_CHECK_UPDATED(n); ENT_IND_ctr++  /* enter indirection */
319 #define ENT_PAP(n)      ENTERED_CHECK_UPDATED(n); ENT_PAP_ctr++  /* enter partial application */
320 \end{code}
321
322 We do more magical things with @ENT_FUN_DIRECT@.  Besides simply knowing
323 how many ``fast-entry-point'' enters there were, we'd like {\em simple}
324 information about where those enters were, and the properties thereof.
325 \begin{code}
326 struct ent_counter {
327     unsigned    registeredp:16, /* 0 == no, 1 == yes */
328                 arity:16,       /* arity (static info) */
329                 Astk_args:16,   /* # of args off A stack */
330                 Bstk_args:16;   /* # of args off B stack */
331                                 /* (rest of args are in registers) */
332     StgChar     *f_str;         /* name of the thing */
333     StgChar     *f_arg_kinds;   /* info about the args types */
334     StgChar     *wrap_str;      /* name of its wrapper (if any) */
335     StgChar     *wrap_arg_kinds;/* info about the orig wrapper's arg types */
336     I_          ctr;            /* the actual counter */
337     struct ent_counter *link;   /* link to chain them all together */
338 };
339
340 /* OLD: extern void RegisterEntryPt PROTO((struct ent_counter *)); */
341 extern struct ent_counter *ListOfEntryCtrs;
342
343 #define ENT_FUN_DIRECT(f_ct,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
344         {                                                       \
345         static struct ent_counter f_ct                          \
346           = { 0,                                                \
347               (f_arity), (Aargs), (Bargs), (f_str), (arg_kinds),\
348               (wrap), (wrap_kinds),                             \
349               0, NULL };                                        \
350         if ( ! f_ct.registeredp ) {                             \
351             /* hook this one onto the front of the list */      \
352             f_ct.link = ListOfEntryCtrs;                        \
353             ListOfEntryCtrs = & (f_ct);                         \
354                                                                 \
355             /* mark it as "registered" */                       \
356             f_ct.registeredp = 1;                               \
357         }                                                       \
358         f_ct.ctr += 1;                                          \
359         }                                                       \
360         ENT_FUN_DIRECT_ctr++ /* the old boring one */
361 \end{code}
362
363 %************************************************************************
364 %*                                                                      *
365 \subsubsection[ticky-returns]{Returns}
366 %*                                                                      *
367 %************************************************************************
368
369 Whenever a ``return'' occurs, it is returning the constituent parts of
370 a data constructor.  The parts can be returned either in registers, or
371 by allocating some heap to put it in (the @ALLOC_*@ macros account for
372 the allocation).  The constructor can either be an existing one
373 (\tr{*OLD*}) or we could have {\em just} figured out this stuff
374 (\tr{*NEW*}).
375
376 Here's some special magic that Simon wants [edited to match names
377 actually used]:
378 \begin{display}
379 From: Simon L Peyton Jones <simonpj>
380 To: partain, simonpj
381 Subject: counting updates
382 Date: Wed, 25 Mar 92 08:39:48 +0000
383
384 I'd like to count how many times we update in place when actually Node
385 points to the thing.  Here's how:
386
387 \tr{RET_OLD_IN_REGS} sets the variable \tr{ReturnInRegsNodeValid} to \tr{True};
388 \tr{RET_NEW_IN_REGS} sets it to \tr{False}.
389
390 \tr{RET_SEMI_???} sets it to??? ToDo [WDP]
391
392 \tr{UPD_CON_IN_PLACE} tests the variable, and increments \tr{UPD_IN_PLACE_COPY_ctr}
393 if it is true.
394
395 Then we need to report it along with the update-in-place info.
396 \end{display}
397
398 \begin{code}
399 #define RET_HISTO(categ,n,offset) \
400         { I_ __idx;                                              \
401           __idx = (n) - (offset);                                \
402          CAT3(RET_,categ,_hst)[((__idx > 8) ? 8 : __idx)] += 1;} 
403
404 /* "slide" histogramming by (__STG_REGS_AVAIL__ - 1) -- usually 7 --
405    so we do not collect lots and lots of useless zeros for _IN_HEAP.
406    WDP 95/11
407 */
408 #define RET_NEW_IN_HEAP(n)      RET_NEW_IN_HEAP_ctr++;      \
409                                 RET_HISTO(NEW_IN_HEAP,n,__STG_REGS_AVAIL__ - 1)
410 #define RET_OLD_IN_HEAP(n)      RET_OLD_IN_HEAP_ctr++;      \
411                                 RET_HISTO(OLD_IN_HEAP,n,__STG_REGS_AVAIL__ - 1)
412 #define RET_SEMI_IN_HEAP(n)     RET_SEMI_IN_HEAP_ctr++;     \
413                                 RET_HISTO(SEMI_IN_HEAP,n,__STG_REGS_AVAIL__ - 1)
414
415 #define RET_NEW_IN_REGS(n)      RET_NEW_IN_REGS_ctr++;      \
416                                 ReturnInRegsNodeValid = 0;  \
417                                 RET_HISTO(NEW_IN_REGS,n,0)
418 #define RET_OLD_IN_REGS(n)      RET_OLD_IN_REGS_ctr++;      \
419                                 ReturnInRegsNodeValid = 1;  \
420                                 RET_HISTO(OLD_IN_REGS,n,0)
421 #define RET_SEMI_IN_REGS(n,u)   RET_SEMI_IN_REGS_ctr++;     \
422                                 RET_SEMI_loads_avoided += ((n) - (u)); \
423                                 RET_HISTO(SEMI_IN_REGS,u,0)
424
425 #define RET_SEMI_BY_DEFAULT()/*???*/    RET_SEMI_BY_DEFAULT_ctr++
426
427 #define RET_SEMI_FAILED(tag)    do {                                    \
428                                 if ((tag) == INFO_IND_TAG)              \
429                                     RET_SEMI_FAILED_IND_ctr++;          \
430                                 else                                    \
431                                     RET_SEMI_FAILED_UNEVAL_ctr++;       \
432                                 } while (0)
433
434 \end{code}
435
436 Of all the returns (sum of four categories above), how many were
437 vectored?  (The rest were obviously unvectored).
438 \begin{code}
439 #define VEC_RETURN(n)           VEC_RETURN_ctr++;           \
440                                 RET_HISTO(VEC_RETURN,n,0)
441 \end{code}
442
443 %************************************************************************
444 %*                                                                      *
445 \subsubsection[ticky-update-frames]{Update frames}
446 %*                                                                      *
447 %************************************************************************
448
449 These macros count up the following update information.
450
451 %partain:\begin{center}
452 \begin{tabular}{ll} \hline
453 Macro                   &       Counts                                  \\ \hline
454                         &                                               \\
455 \tr{UPDF_STD_PUSHED}    &       Update frame pushed                     \\
456 \tr{UPDF_CON_PUSHED}    &       Constructor update frame pushed         \\
457 \tr{UPDF_HOLE_PUSHED}   &       An update frame to update a black hole  \\
458 \tr{UPDF_OMITTED}       &       A thunk decided not to push an update frame \\
459                         &       (all subsets of \tr{ENT_THK})           \\
460 \tr{UPDF_RCC_PUSHED}    &       Cost Centre restore frame pushed        \\
461 \tr{UPDF_RCC_OMITTED}   &       Cost Centres not required -- not pushed \\\hline
462 \end{tabular}
463 %partain:\end{center}
464
465 \begin{code}
466 #define UPDF_OMITTED()          UPDF_OMITTED_ctr++
467
468 #define UPDF_STD_PUSHED()       UPDF_STD_PUSHED_ctr++
469 #define UPDF_CON_PUSHED()       UPDF_CON_PUSHED_ctr++
470 #define UPDF_HOLE_PUSHED()      UPDF_HOLE_PUSHED_ctr++
471
472 #define UPDF_RCC_PUSHED()       UPDF_RCC_PUSHED_ctr++
473 #define UPDF_RCC_OMITTED()      UPDF_RCC_OMITTED_ctr++
474 \end{code}
475
476 %************************************************************************
477 %*                                                                      *
478 \subsubsection[ticky-updates]{Updates}
479 %*                                                                      *
480 %************************************************************************
481
482 These macros record information when we do an update.  We always
483 update either with a data constructor (CON) or a partial application
484 (PAP).
485
486 %partain:\begin{center}
487 \begin{tabular}{|l|l|}\hline
488 Macro                   &       Where                                           \\ \hline
489                         &                                                       \\
490 \tr{UPD_EXISTING}       &       Updating with an indirection to something       \\
491                         &       already in the heap                             \\
492 \tr{UPD_SQUEEZED}       &       Same as \tr{UPD_EXISTING} but because           \\
493                         &       of stack-squeezing                              \\
494 \tr{UPD_CON_W_NODE}     &       Updating with a CON: by indirecting to Node     \\
495 \tr{UPD_CON_IN_PLACE}   &       Ditto, but in place                             \\
496 \tr{UPD_CON_IN_NEW}     &       Ditto, but allocating the object                \\
497 \tr{UPD_PAP_IN_PLACE}   &       Same, but updating w/ a PAP                     \\
498 \tr{UPD_PAP_IN_NEW}     &                                                       \\\hline
499 \end{tabular}
500 %partain:\end{center}
501
502 \begin{code}
503 #define UPD_HISTO(categ,n) \
504         { I_ __idx;                                              \
505           __idx = (n);                                           \
506          CAT3(UPD_,categ,_hst)[((__idx > 8) ? 8 : __idx)] += 1;} 
507
508 #define UPD_EXISTING()          UPD_EXISTING_ctr++
509 #define UPD_SQUEEZED()          UPD_SQUEEZED_ctr++
510
511 #define UPD_CON_W_NODE()        UPD_CON_W_NODE_ctr++
512
513 #define UPD_CON_IN_NEW(n)       UPD_CON_IN_NEW_ctr++ ; \
514                                 UPD_HISTO(CON_IN_NEW,n)
515 #define UPD_PAP_IN_NEW(n)       UPD_PAP_IN_NEW_ctr++ ; \
516                                 UPD_HISTO(PAP_IN_NEW,n)
517 /* ToDo: UPD_NEW_COPY_ctr, as below */
518
519 #define UPD_CON_IN_PLACE(n)     UPD_CON_IN_PLACE_ctr++ ; \
520                                 UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid ; \
521                                 /* increments if True; otherwise, no */ \
522                                 UPD_HISTO(CON_IN_PLACE,n)
523 #define UPD_PAP_IN_PLACE()      UPD_PAP_IN_PLACE_ctr++ ; \
524                                 UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid
525                                 /* increments if True; otherwise, no */
526 \end{code}
527
528 For a generational collector:
529 \begin{code}
530 #define UPD_NEW_IND()                   UPD_NEW_IND_ctr++;
531 #define UPD_NEW_IN_PLACE_PTRS()         UPD_NEW_IN_PLACE_PTRS_ctr++;
532 #define UPD_NEW_IN_PLACE_NOPTRS()       UPD_NEW_IN_PLACE_NOPTRS_ctr++;
533 #define UPD_OLD_IND()                   UPD_OLD_IND_ctr++;                      
534 #define UPD_OLD_IN_PLACE_PTRS()         UPD_OLD_IN_PLACE_PTRS_ctr++;
535 #define UPD_OLD_IN_PLACE_NOPTRS()       UPD_OLD_IN_PLACE_NOPTRS_ctr++;
536 \end{code}
537
538 %************************************************************************
539 %*                                                                      *
540 \subsubsection[ticky-selectors]{Doing selectors at GC time}
541 %*                                                                      *
542 %************************************************************************
543
544 @GC_SEL_ABANDONED@: we could've done the selection, but we gave up
545 (e.g., to avoid overflowing the C stack); @GC_SEL_MINOR@: did a
546 selection in a minor GC; @GC_SEL_MAJOR@: ditto, but major GC.
547
548 \begin{code}
549 #define GC_SEL_ABANDONED()              GC_SEL_ABANDONED_ctr++;
550 #define GC_SEL_MINOR()                  GC_SEL_MINOR_ctr++;
551 #define GC_SEL_MAJOR()                  GC_SEL_MAJOR_ctr++;
552
553 #define GC_SHORT_IND()                  GC_SHORT_IND_ctr++;
554 #define GC_SHORT_CAF()                  GC_SHORT_CAF_ctr++;
555 #define GC_COMMON_CHARLIKE()            GC_COMMON_CHARLIKE_ctr++;
556 #define GC_COMMON_INTLIKE()             GC_COMMON_INTLIKE_ctr++;
557 #define GC_COMMON_INTLIKE_FAIL()        GC_COMMON_INTLIKE_FAIL_ctr++;
558 #define GC_COMMON_CONST()               GC_COMMON_CONST_ctr++;
559 \end{code}
560
561 %************************************************************************
562 %*                                                                      *
563 \subsubsection[ticky-counters]{The accumulators (extern decls)}
564 %*                                                                      *
565 %************************************************************************
566
567 \begin{code}
568 extern I_ ALLOC_HEAP_ctr;
569 extern I_ ALLOC_HEAP_tot;
570
571 extern PP_ max_SpA;
572 extern P_  max_SpB;
573
574 extern I_ A_STK_STUB_ctr;
575 /* not used at all?
576 extern I_ A_STK_REUSE_ctr;
577 extern I_ B_STK_REUSE_ctr;
578 */
579
580 extern I_ ALLOC_FUN_ctr;
581 extern I_ ALLOC_FUN_adm;
582 extern I_ ALLOC_FUN_gds;
583 extern I_ ALLOC_FUN_slp;
584 extern I_ ALLOC_FUN_hst[5];
585 extern I_ ALLOC_THK_ctr;
586 extern I_ ALLOC_THK_adm;
587 extern I_ ALLOC_THK_gds;
588 extern I_ ALLOC_THK_slp;
589 extern I_ ALLOC_THK_hst[5];
590 extern I_ ALLOC_CON_ctr;
591 extern I_ ALLOC_CON_adm;
592 extern I_ ALLOC_CON_gds;
593 extern I_ ALLOC_CON_slp;
594 extern I_ ALLOC_CON_hst[5];
595 extern I_ ALLOC_TUP_ctr;
596 extern I_ ALLOC_TUP_adm;
597 extern I_ ALLOC_TUP_gds;
598 extern I_ ALLOC_TUP_slp;
599 extern I_ ALLOC_TUP_hst[5];
600 extern I_ ALLOC_BH_ctr;
601 extern I_ ALLOC_BH_adm;
602 extern I_ ALLOC_BH_gds;
603 extern I_ ALLOC_BH_slp;
604 extern I_ ALLOC_BH_hst[5];
605 /*
606 extern I_ ALLOC_PAP_ctr;
607 extern I_ ALLOC_PAP_adm;
608 extern I_ ALLOC_PAP_gds;
609 extern I_ ALLOC_PAP_slp;
610 extern I_ ALLOC_PAP_hst[5];
611 */
612 /*
613 extern I_ ALLOC_UPD_CON_ctr;
614 extern I_ ALLOC_UPD_CON_adm;
615 extern I_ ALLOC_UPD_CON_gds;
616 extern I_ ALLOC_UPD_CON_slp;
617 extern I_ ALLOC_UPD_CON_hst[5];
618 */
619 extern I_ ALLOC_UPD_PAP_ctr;
620 extern I_ ALLOC_UPD_PAP_adm;
621 extern I_ ALLOC_UPD_PAP_gds;
622 extern I_ ALLOC_UPD_PAP_slp;
623 extern I_ ALLOC_UPD_PAP_hst[5];
624 extern I_ ALLOC_PRIM_ctr;
625 extern I_ ALLOC_PRIM_adm;
626 extern I_ ALLOC_PRIM_gds;
627 extern I_ ALLOC_PRIM_slp;
628 extern I_ ALLOC_PRIM_hst[5];
629
630 #ifdef CONCURRENT
631 extern I_ ALLOC_STK_ctr;
632 extern I_ ALLOC_STK_adm;
633 extern I_ ALLOC_STK_gds;
634 extern I_ ALLOC_STK_slp;
635 extern I_ ALLOC_STK_hst[5];
636 extern I_ ALLOC_TSO_ctr;
637 extern I_ ALLOC_TSO_adm;
638 extern I_ ALLOC_TSO_gds;
639 extern I_ ALLOC_TSO_slp;
640 extern I_ ALLOC_TSO_hst[5];
641 #ifdef PAR
642 extern I_ ALLOC_FMBQ_ctr;
643 extern I_ ALLOC_FMBQ_adm;
644 extern I_ ALLOC_FMBQ_gds;
645 extern I_ ALLOC_FMBQ_slp;
646 extern I_ ALLOC_FMBQ_hst[5];
647 extern I_ ALLOC_FME_ctr;
648 extern I_ ALLOC_FME_adm;
649 extern I_ ALLOC_FME_gds;
650 extern I_ ALLOC_FME_slp;
651 extern I_ ALLOC_FME_hst[5];
652 extern I_ ALLOC_BF_ctr;
653 extern I_ ALLOC_BF_adm;
654 extern I_ ALLOC_BF_gds;
655 extern I_ ALLOC_BF_slp;
656 extern I_ ALLOC_BF_hst[5];
657 #endif
658 #endif
659
660 extern I_ ENT_VIA_NODE_ctr;
661
662 extern I_ ENT_CON_ctr;
663 extern I_ ENT_FUN_STD_ctr;
664 extern I_ ENT_FUN_DIRECT_ctr;
665 extern I_ ENT_IND_ctr;
666 extern I_ ENT_PAP_ctr;
667 extern I_ ENT_THK_ctr;
668
669 extern I_ UPD_ENTERED_hst[9];
670
671 extern I_ RET_NEW_IN_HEAP_ctr;
672 extern I_ RET_NEW_IN_REGS_ctr;
673 extern I_ RET_OLD_IN_HEAP_ctr;
674 extern I_ RET_OLD_IN_REGS_ctr;
675 extern I_ RET_SEMI_BY_DEFAULT_ctr;
676 extern I_ RET_SEMI_IN_HEAP_ctr;
677 extern I_ RET_SEMI_IN_REGS_ctr;
678 extern I_ VEC_RETURN_ctr;
679
680 extern I_ RET_SEMI_FAILED_IND_ctr;
681 extern I_ RET_SEMI_FAILED_UNEVAL_ctr;
682
683 extern I_ RET_SEMI_loads_avoided;
684
685 extern I_ RET_NEW_IN_HEAP_hst[9];
686 extern I_ RET_NEW_IN_REGS_hst[9];
687 extern I_ RET_OLD_IN_HEAP_hst[9];
688 extern I_ RET_OLD_IN_REGS_hst[9];
689 /*no such thing: extern I_ RET_SEMI_BY_DEFAULT_hst[9]; */
690 extern I_ RET_SEMI_IN_HEAP_hst[9];
691 extern I_ RET_SEMI_IN_REGS_hst[9];
692 extern I_ RET_VEC_RETURN_hst[9];
693
694 extern I_ ReturnInRegsNodeValid; /* see below */
695
696 extern I_ UPDF_OMITTED_ctr;
697 extern I_ UPDF_STD_PUSHED_ctr;
698 extern I_ UPDF_CON_PUSHED_ctr;
699 extern I_ UPDF_HOLE_PUSHED_ctr;
700
701 extern I_ UPDF_RCC_PUSHED_ctr;
702 extern I_ UPDF_RCC_OMITTED_ctr;
703
704 extern I_ UPD_EXISTING_ctr;
705 extern I_ UPD_SQUEEZED_ctr;
706 extern I_ UPD_CON_W_NODE_ctr;
707 extern I_ UPD_CON_IN_PLACE_ctr;
708 extern I_ UPD_PAP_IN_PLACE_ctr;
709 extern I_ UPD_CON_IN_NEW_ctr;
710 extern I_ UPD_PAP_IN_NEW_ctr;
711
712 extern I_ UPD_CON_IN_PLACE_hst[9];
713 extern I_ UPD_CON_IN_NEW_hst[9];
714 extern I_ UPD_PAP_IN_NEW_hst[9];
715
716 extern I_ UPD_NEW_IND_ctr;
717 extern I_ UPD_NEW_IN_PLACE_PTRS_ctr;
718 extern I_ UPD_NEW_IN_PLACE_NOPTRS_ctr;
719 extern I_ UPD_OLD_IND_ctr;
720 extern I_ UPD_OLD_IN_PLACE_PTRS_ctr;
721 extern I_ UPD_OLD_IN_PLACE_NOPTRS_ctr;
722
723 extern I_ UPD_IN_PLACE_COPY_ctr; /* see below */
724
725 extern I_ GC_SEL_ABANDONED_ctr;
726 extern I_ GC_SEL_MINOR_ctr;
727 extern I_ GC_SEL_MAJOR_ctr;
728 extern I_ GC_SHORT_IND_ctr;
729 extern I_ GC_SHORT_CAF_ctr;
730 extern I_ GC_COMMON_CHARLIKE_ctr;
731 extern I_ GC_COMMON_INTLIKE_ctr;
732 extern I_ GC_COMMON_INTLIKE_FAIL_ctr;
733 extern I_ GC_COMMON_CONST_ctr;
734
735 #endif /* TICKY_TICKY */
736 \end{code}
737
738 %************************************************************************
739 %*                                                                      *
740 \subsection[Ticky-nonmacros]{Un-macros for ``none of the above''}
741 %*                                                                      *
742 %************************************************************************
743
744 \begin{code}
745 #ifndef TICKY_TICKY
746
747 #define ALLOC_HEAP(n)    /* nothing */
748 #define UN_ALLOC_HEAP(n) /* nothing */
749 #define DO_ASTK_HWM()    /* nothing */
750 #define DO_BSTK_HWM()    /* nothing */
751
752 #define A_STK_STUB(n)   /* nothing */
753 #define A_STK_REUSE(n)  /* not used at all */
754 #define B_STK_REUSE(n)  /* not used at all */
755
756 #define ALLOC_FUN(a,g,s,t) /* nothing */
757 #define ALLOC_THK(a,g,s,t) /* nothing */
758 #define ALLOC_CON(a,g,s,t) /* nothing */
759 #define ALLOC_TUP(a,g,s,t) /* nothing */
760 #define ALLOC_BH(a,g,s,t)  /* nothing */
761 /*#define ALLOC_PAP(a,g,s,t) /? nothing */
762 #define ALLOC_PRIM(a,g,s,t) /* nothing */
763 #define ALLOC_PRIM2(w)   /* nothing */
764 #define ALLOC_UPD_PAP(a,g,s,t) /* nothing */
765 /*#define ALLOC_UPD_CON(a,g,s,t) /? nothing */
766 #define ALLOC_STK(a,g,s) /* nothing */
767 #define ALLOC_TSO(a,g,s) /* nothing */
768 #define ALLOC_FMBQ(a,g,s) /* nothing */
769 #define ALLOC_FME(a,g,s) /* nothing */
770 #define ALLOC_BF(a,g,s) /* nothing */
771
772 #define ENT_VIA_NODE()  /* nothing */
773 #define ENT_THK()       /* nothing */
774 #define ENT_FUN_STD()   /* nothing */
775 #define ENT_FUN_DIRECT(f,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
776                         /* nothing */ 
777 #define ENT_CON(n)      /* nothing */
778 #define ENT_IND(n)      /* nothing */
779 #define ENT_PAP(n)      /* nothing */
780
781 #define RET_NEW_IN_HEAP(n)      /* nothing */
782 #define RET_NEW_IN_REGS(n)      /* nothing */
783 #define RET_OLD_IN_HEAP(n)      /* nothing */
784 #define RET_OLD_IN_REGS(n)      /* nothing */
785 #define RET_SEMI_BY_DEFAULT()   /* nothing */
786 #define RET_SEMI_IN_HEAP(n)     /* nothing */
787 #define RET_SEMI_IN_REGS(n,u)   /* nothing */
788 #define RET_SEMI_FAILED(t)      /* nothing */
789 #define VEC_RETURN(n)           /* nothing */
790
791 #define UPDF_OMITTED()          /* nothing */
792 #define UPDF_STD_PUSHED()       /* nothing */
793 #define UPDF_CON_PUSHED()       /* nothing */
794 #define UPDF_HOLE_PUSHED()      /* nothing */
795
796 #define UPDF_RCC_PUSHED()       /* nothing */
797 #define UPDF_RCC_OMITTED()      /* nothing */
798
799 #define UPD_EXISTING()          /* nothing */
800 #define UPD_SQUEEZED()          /* nothing */
801 #define UPD_CON_W_NODE()        /* nothing */
802 #define UPD_CON_IN_PLACE(n)     /* nothing */
803 #define UPD_PAP_IN_PLACE()      /* nothing */
804 #define UPD_CON_IN_NEW(n)       /* nothing */
805 #define UPD_PAP_IN_NEW(n)       /* nothing */
806
807 #define GC_SEL_ABANDONED()      /* nothing */
808 #define GC_SEL_MINOR()          /* nothing */
809 #define GC_SEL_MAJOR()          /* nothing */
810
811 #define GC_SHORT_IND()          /* nothing */
812 #define GC_SHORT_CAF()          /* nothing */
813 #define GC_COMMON_CHARLIKE()    /* nothing */
814 #define GC_COMMON_INTLIKE()     /* nothing */
815 #define GC_COMMON_INTLIKE_FAIL()/* nothing */
816 #define GC_COMMON_CONST()       /* nothing */
817 \end{code}
818
819 For a generational collector:
820 \begin{code}
821 #define UPD_NEW_IND()                   /* nothing */
822 #define UPD_NEW_IN_PLACE_PTRS()         /* nothing */
823 #define UPD_NEW_IN_PLACE_NOPTRS()       /* nothing */
824 #define UPD_OLD_IND()                   /* nothing */
825 #define UPD_OLD_IN_PLACE_PTRS()         /* nothing */
826 #define UPD_OLD_IN_PLACE_NOPTRS()       /* nothing */
827
828 #endif /* <none-of-the-above> */
829 \end{code}
830
831 End of file multi-slurp protection:
832 \begin{code}
833 #endif /* ! TICKY_H */
834 \end{code}