[project @ 1996-01-11 14:06:51 by partain]
[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         static struct ent_counter f_ct                          \
345           = { 0,                                                \
346               (f_arity), (Aargs), (Bargs), (f_str), (arg_kinds),\
347               (wrap), (wrap_kinds),                             \
348               0, NULL };                                        \
349         if ( ! f_ct.registeredp ) {                             \
350             /* hook this one onto the front of the list */      \
351             f_ct.link = ListOfEntryCtrs;                        \
352             ListOfEntryCtrs = & (f_ct);                         \
353                                                                 \
354             /* mark it as "registered" */                       \
355             f_ct.registeredp = 1;                               \
356         }                                                       \
357         f_ct.ctr += 1;                                          \
358         ENT_FUN_DIRECT_ctr++ /* the old boring one */
359 \end{code}
360
361 %************************************************************************
362 %*                                                                      *
363 \subsubsection[ticky-returns]{Returns}
364 %*                                                                      *
365 %************************************************************************
366
367 Whenever a ``return'' occurs, it is returning the constituent parts of
368 a data constructor.  The parts can be returned either in registers, or
369 by allocating some heap to put it in (the @ALLOC_*@ macros account for
370 the allocation).  The constructor can either be an existing one
371 (\tr{*OLD*}) or we could have {\em just} figured out this stuff
372 (\tr{*NEW*}).
373
374 Here's some special magic that Simon wants [edited to match names
375 actually used]:
376 \begin{display}
377 From: Simon L Peyton Jones <simonpj>
378 To: partain, simonpj
379 Subject: counting updates
380 Date: Wed, 25 Mar 92 08:39:48 +0000
381
382 I'd like to count how many times we update in place when actually Node
383 points to the thing.  Here's how:
384
385 \tr{RET_OLD_IN_REGS} sets the variable \tr{ReturnInRegsNodeValid} to \tr{True};
386 \tr{RET_NEW_IN_REGS} sets it to \tr{False}.
387
388 \tr{RET_SEMI_???} sets it to??? ToDo [WDP]
389
390 \tr{UPD_CON_IN_PLACE} tests the variable, and increments \tr{UPD_IN_PLACE_COPY_ctr}
391 if it is true.
392
393 Then we need to report it along with the update-in-place info.
394 \end{display}
395
396 \begin{code}
397 #define RET_HISTO(categ,n,offset) \
398         { I_ __idx;                                              \
399           __idx = (n) - (offset);                                \
400          CAT3(RET_,categ,_hst)[((__idx > 8) ? 8 : __idx)] += 1;} 
401
402 /* "slide" histogramming by (__STG_REGS_AVAIL__ - 1) -- usually 7 --
403    so we do not collect lots and lots of useless zeros for _IN_HEAP.
404    WDP 95/11
405 */
406 #define RET_NEW_IN_HEAP(n)      RET_NEW_IN_HEAP_ctr++;      \
407                                 RET_HISTO(NEW_IN_HEAP,n,__STG_REGS_AVAIL__ - 1)
408 #define RET_OLD_IN_HEAP(n)      RET_OLD_IN_HEAP_ctr++;      \
409                                 RET_HISTO(OLD_IN_HEAP,n,__STG_REGS_AVAIL__ - 1)
410 #define RET_SEMI_IN_HEAP(n)     RET_SEMI_IN_HEAP_ctr++;     \
411                                 RET_HISTO(SEMI_IN_HEAP,n,__STG_REGS_AVAIL__ - 1)
412
413 #define RET_NEW_IN_REGS(n)      RET_NEW_IN_REGS_ctr++;      \
414                                 ReturnInRegsNodeValid = 0;  \
415                                 RET_HISTO(NEW_IN_REGS,n,0)
416 #define RET_OLD_IN_REGS(n)      RET_OLD_IN_REGS_ctr++;      \
417                                 ReturnInRegsNodeValid = 1;  \
418                                 RET_HISTO(OLD_IN_REGS,n,0)
419 #define RET_SEMI_IN_REGS(n,u)   RET_SEMI_IN_REGS_ctr++;     \
420                                 RET_SEMI_loads_avoided += ((n) - (u)); \
421                                 RET_HISTO(SEMI_IN_REGS,u,0)
422
423 #define RET_SEMI_BY_DEFAULT()/*???*/    RET_SEMI_BY_DEFAULT_ctr++
424
425 #define RET_SEMI_FAILED(tag)    do {                                    \
426                                 if ((tag) == INFO_IND_TAG)              \
427                                     RET_SEMI_FAILED_IND_ctr++;          \
428                                 else                                    \
429                                     RET_SEMI_FAILED_UNEVAL_ctr++;       \
430                                 } while (0)
431
432 \end{code}
433
434 Of all the returns (sum of four categories above), how many were
435 vectored?  (The rest were obviously unvectored).
436 \begin{code}
437 #define VEC_RETURN(n)           VEC_RETURN_ctr++;           \
438                                 RET_HISTO(VEC_RETURN,n,0)
439 \end{code}
440
441 %************************************************************************
442 %*                                                                      *
443 \subsubsection[ticky-update-frames]{Update frames}
444 %*                                                                      *
445 %************************************************************************
446
447 These macros count up the following update information.
448
449 %partain:\begin{center}
450 \begin{tabular}{ll} \hline
451 Macro                   &       Counts                                  \\ \hline
452                         &                                               \\
453 \tr{UPDF_STD_PUSHED}    &       Update frame pushed                     \\
454 \tr{UPDF_CON_PUSHED}    &       Constructor update frame pushed         \\
455 \tr{UPDF_HOLE_PUSHED}   &       An update frame to update a black hole  \\
456 \tr{UPDF_OMITTED}       &       A thunk decided not to push an update frame \\
457                         &       (all subsets of \tr{ENT_THK})           \\
458 \tr{UPDF_RCC_PUSHED}    &       Cost Centre restore frame pushed        \\
459 \tr{UPDF_RCC_OMITTED}   &       Cost Centres not required -- not pushed \\\hline
460 \end{tabular}
461 %partain:\end{center}
462
463 \begin{code}
464 #define UPDF_OMITTED()          UPDF_OMITTED_ctr++
465
466 #define UPDF_STD_PUSHED()       UPDF_STD_PUSHED_ctr++
467 #define UPDF_CON_PUSHED()       UPDF_CON_PUSHED_ctr++
468 #define UPDF_HOLE_PUSHED()      UPDF_HOLE_PUSHED_ctr++
469
470 #define UPDF_RCC_PUSHED()       UPDF_RCC_PUSHED_ctr++
471 #define UPDF_RCC_OMITTED()      UPDF_RCC_OMITTED_ctr++
472 \end{code}
473
474 %************************************************************************
475 %*                                                                      *
476 \subsubsection[ticky-updates]{Updates}
477 %*                                                                      *
478 %************************************************************************
479
480 These macros record information when we do an update.  We always
481 update either with a data constructor (CON) or a partial application
482 (PAP).
483
484 %partain:\begin{center}
485 \begin{tabular}{|l|l|}\hline
486 Macro                   &       Where                                           \\ \hline
487                         &                                                       \\
488 \tr{UPD_EXISTING}       &       Updating with an indirection to something       \\
489                         &       already in the heap                             \\
490 \tr{UPD_SQUEEZED}       &       Same as \tr{UPD_EXISTING} but because           \\
491                         &       of stack-squeezing                              \\
492 \tr{UPD_CON_W_NODE}     &       Updating with a CON: by indirecting to Node     \\
493 \tr{UPD_CON_IN_PLACE}   &       Ditto, but in place                             \\
494 \tr{UPD_CON_IN_NEW}     &       Ditto, but allocating the object                \\
495 \tr{UPD_PAP_IN_PLACE}   &       Same, but updating w/ a PAP                     \\
496 \tr{UPD_PAP_IN_NEW}     &                                                       \\\hline
497 \end{tabular}
498 %partain:\end{center}
499
500 \begin{code}
501 #define UPD_HISTO(categ,n) \
502         { I_ __idx;                                              \
503           __idx = (n);                                           \
504          CAT3(UPD_,categ,_hst)[((__idx > 8) ? 8 : __idx)] += 1;} 
505
506 #define UPD_EXISTING()          UPD_EXISTING_ctr++
507 #define UPD_SQUEEZED()          UPD_SQUEEZED_ctr++
508
509 #define UPD_CON_W_NODE()        UPD_CON_W_NODE_ctr++
510
511 #define UPD_CON_IN_NEW(n)       UPD_CON_IN_NEW_ctr++ ; \
512                                 UPD_HISTO(CON_IN_NEW,n)
513 #define UPD_PAP_IN_NEW(n)       UPD_PAP_IN_NEW_ctr++ ; \
514                                 UPD_HISTO(PAP_IN_NEW,n)
515 /* ToDo: UPD_NEW_COPY_ctr, as below */
516
517 #define UPD_CON_IN_PLACE(n)     UPD_CON_IN_PLACE_ctr++ ; \
518                                 UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid ; \
519                                 /* increments if True; otherwise, no */ \
520                                 UPD_HISTO(CON_IN_PLACE,n)
521 #define UPD_PAP_IN_PLACE()      UPD_PAP_IN_PLACE_ctr++ ; \
522                                 UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid
523                                 /* increments if True; otherwise, no */
524 \end{code}
525
526 For a generational collector:
527 \begin{code}
528 #define UPD_NEW_IND()                   UPD_NEW_IND_ctr++;
529 #define UPD_NEW_IN_PLACE_PTRS()         UPD_NEW_IN_PLACE_PTRS_ctr++;
530 #define UPD_NEW_IN_PLACE_NOPTRS()       UPD_NEW_IN_PLACE_NOPTRS_ctr++;
531 #define UPD_OLD_IND()                   UPD_OLD_IND_ctr++;                      
532 #define UPD_OLD_IN_PLACE_PTRS()         UPD_OLD_IN_PLACE_PTRS_ctr++;
533 #define UPD_OLD_IN_PLACE_NOPTRS()       UPD_OLD_IN_PLACE_NOPTRS_ctr++;
534 \end{code}
535
536 %************************************************************************
537 %*                                                                      *
538 \subsubsection[ticky-selectors]{Doing selectors at GC time}
539 %*                                                                      *
540 %************************************************************************
541
542 @GC_SEL_ABANDONED@: we could've done the selection, but we gave up
543 (e.g., to avoid overflowing the C stack); @GC_SEL_MINOR@: did a
544 selection in a minor GC; @GC_SEL_MAJOR@: ditto, but major GC.
545
546 \begin{code}
547 #define GC_SEL_ABANDONED()              GC_SEL_ABANDONED_ctr++;
548 #define GC_SEL_MINOR()                  GC_SEL_MINOR_ctr++;
549 #define GC_SEL_MAJOR()                  GC_SEL_MAJOR_ctr++;
550
551 #define GC_SHORT_IND()                  GC_SHORT_IND_ctr++;
552 #define GC_SHORT_CAF()                  GC_SHORT_CAF_ctr++;
553 #define GC_COMMON_CHARLIKE()            GC_COMMON_CHARLIKE_ctr++;
554 #define GC_COMMON_INTLIKE()             GC_COMMON_INTLIKE_ctr++;
555 #define GC_COMMON_INTLIKE_FAIL()        GC_COMMON_INTLIKE_FAIL_ctr++;
556 #define GC_COMMON_CONST()               GC_COMMON_CONST_ctr++;
557 \end{code}
558
559 %************************************************************************
560 %*                                                                      *
561 \subsubsection[ticky-counters]{The accumulators (extern decls)}
562 %*                                                                      *
563 %************************************************************************
564
565 \begin{code}
566 extern I_ ALLOC_HEAP_ctr;
567 extern I_ ALLOC_HEAP_tot;
568
569 extern PP_ max_SpA;
570 extern P_  max_SpB;
571
572 extern I_ A_STK_STUB_ctr;
573 /* not used at all?
574 extern I_ A_STK_REUSE_ctr;
575 extern I_ B_STK_REUSE_ctr;
576 */
577
578 extern I_ ALLOC_FUN_ctr;
579 extern I_ ALLOC_FUN_adm;
580 extern I_ ALLOC_FUN_gds;
581 extern I_ ALLOC_FUN_slp;
582 extern I_ ALLOC_FUN_hst[5];
583 extern I_ ALLOC_THK_ctr;
584 extern I_ ALLOC_THK_adm;
585 extern I_ ALLOC_THK_gds;
586 extern I_ ALLOC_THK_slp;
587 extern I_ ALLOC_THK_hst[5];
588 extern I_ ALLOC_CON_ctr;
589 extern I_ ALLOC_CON_adm;
590 extern I_ ALLOC_CON_gds;
591 extern I_ ALLOC_CON_slp;
592 extern I_ ALLOC_CON_hst[5];
593 extern I_ ALLOC_TUP_ctr;
594 extern I_ ALLOC_TUP_adm;
595 extern I_ ALLOC_TUP_gds;
596 extern I_ ALLOC_TUP_slp;
597 extern I_ ALLOC_TUP_hst[5];
598 extern I_ ALLOC_BH_ctr;
599 extern I_ ALLOC_BH_adm;
600 extern I_ ALLOC_BH_gds;
601 extern I_ ALLOC_BH_slp;
602 extern I_ ALLOC_BH_hst[5];
603 /*
604 extern I_ ALLOC_PAP_ctr;
605 extern I_ ALLOC_PAP_adm;
606 extern I_ ALLOC_PAP_gds;
607 extern I_ ALLOC_PAP_slp;
608 extern I_ ALLOC_PAP_hst[5];
609 */
610 /*
611 extern I_ ALLOC_UPD_CON_ctr;
612 extern I_ ALLOC_UPD_CON_adm;
613 extern I_ ALLOC_UPD_CON_gds;
614 extern I_ ALLOC_UPD_CON_slp;
615 extern I_ ALLOC_UPD_CON_hst[5];
616 */
617 extern I_ ALLOC_UPD_PAP_ctr;
618 extern I_ ALLOC_UPD_PAP_adm;
619 extern I_ ALLOC_UPD_PAP_gds;
620 extern I_ ALLOC_UPD_PAP_slp;
621 extern I_ ALLOC_UPD_PAP_hst[5];
622 extern I_ ALLOC_PRIM_ctr;
623 extern I_ ALLOC_PRIM_adm;
624 extern I_ ALLOC_PRIM_gds;
625 extern I_ ALLOC_PRIM_slp;
626 extern I_ ALLOC_PRIM_hst[5];
627
628 #ifdef CONCURRENT
629 extern I_ ALLOC_STK_ctr;
630 extern I_ ALLOC_STK_adm;
631 extern I_ ALLOC_STK_gds;
632 extern I_ ALLOC_STK_slp;
633 extern I_ ALLOC_STK_hst[5];
634 extern I_ ALLOC_TSO_ctr;
635 extern I_ ALLOC_TSO_adm;
636 extern I_ ALLOC_TSO_gds;
637 extern I_ ALLOC_TSO_slp;
638 extern I_ ALLOC_TSO_hst[5];
639 #ifdef PAR
640 extern I_ ALLOC_FMBQ_ctr;
641 extern I_ ALLOC_FMBQ_adm;
642 extern I_ ALLOC_FMBQ_gds;
643 extern I_ ALLOC_FMBQ_slp;
644 extern I_ ALLOC_FMBQ_hst[5];
645 extern I_ ALLOC_FME_ctr;
646 extern I_ ALLOC_FME_adm;
647 extern I_ ALLOC_FME_gds;
648 extern I_ ALLOC_FME_slp;
649 extern I_ ALLOC_FME_hst[5];
650 extern I_ ALLOC_BF_ctr;
651 extern I_ ALLOC_BF_adm;
652 extern I_ ALLOC_BF_gds;
653 extern I_ ALLOC_BF_slp;
654 extern I_ ALLOC_BF_hst[5];
655 #endif
656 #endif
657
658 extern I_ ENT_VIA_NODE_ctr;
659
660 extern I_ ENT_CON_ctr;
661 extern I_ ENT_FUN_STD_ctr;
662 extern I_ ENT_FUN_DIRECT_ctr;
663 extern I_ ENT_IND_ctr;
664 extern I_ ENT_PAP_ctr;
665 extern I_ ENT_THK_ctr;
666
667 extern I_ UPD_ENTERED_hst[9];
668
669 extern I_ RET_NEW_IN_HEAP_ctr;
670 extern I_ RET_NEW_IN_REGS_ctr;
671 extern I_ RET_OLD_IN_HEAP_ctr;
672 extern I_ RET_OLD_IN_REGS_ctr;
673 extern I_ RET_SEMI_BY_DEFAULT_ctr;
674 extern I_ RET_SEMI_IN_HEAP_ctr;
675 extern I_ RET_SEMI_IN_REGS_ctr;
676 extern I_ VEC_RETURN_ctr;
677
678 extern I_ RET_SEMI_FAILED_IND_ctr;
679 extern I_ RET_SEMI_FAILED_UNEVAL_ctr;
680
681 extern I_ RET_SEMI_loads_avoided;
682
683 extern I_ RET_NEW_IN_HEAP_hst[9];
684 extern I_ RET_NEW_IN_REGS_hst[9];
685 extern I_ RET_OLD_IN_HEAP_hst[9];
686 extern I_ RET_OLD_IN_REGS_hst[9];
687 /*no such thing: extern I_ RET_SEMI_BY_DEFAULT_hst[9]; */
688 extern I_ RET_SEMI_IN_HEAP_hst[9];
689 extern I_ RET_SEMI_IN_REGS_hst[9];
690 extern I_ RET_VEC_RETURN_hst[9];
691
692 extern I_ ReturnInRegsNodeValid; /* see below */
693
694 extern I_ UPDF_OMITTED_ctr;
695 extern I_ UPDF_STD_PUSHED_ctr;
696 extern I_ UPDF_CON_PUSHED_ctr;
697 extern I_ UPDF_HOLE_PUSHED_ctr;
698
699 extern I_ UPDF_RCC_PUSHED_ctr;
700 extern I_ UPDF_RCC_OMITTED_ctr;
701
702 extern I_ UPD_EXISTING_ctr;
703 extern I_ UPD_SQUEEZED_ctr;
704 extern I_ UPD_CON_W_NODE_ctr;
705 extern I_ UPD_CON_IN_PLACE_ctr;
706 extern I_ UPD_PAP_IN_PLACE_ctr;
707 extern I_ UPD_CON_IN_NEW_ctr;
708 extern I_ UPD_PAP_IN_NEW_ctr;
709
710 extern I_ UPD_CON_IN_PLACE_hst[9];
711 extern I_ UPD_CON_IN_NEW_hst[9];
712 extern I_ UPD_PAP_IN_NEW_hst[9];
713
714 extern I_ UPD_NEW_IND_ctr;
715 extern I_ UPD_NEW_IN_PLACE_PTRS_ctr;
716 extern I_ UPD_NEW_IN_PLACE_NOPTRS_ctr;
717 extern I_ UPD_OLD_IND_ctr;
718 extern I_ UPD_OLD_IN_PLACE_PTRS_ctr;
719 extern I_ UPD_OLD_IN_PLACE_NOPTRS_ctr;
720
721 extern I_ UPD_IN_PLACE_COPY_ctr; /* see below */
722
723 extern I_ GC_SEL_ABANDONED_ctr;
724 extern I_ GC_SEL_MINOR_ctr;
725 extern I_ GC_SEL_MAJOR_ctr;
726 extern I_ GC_SHORT_IND_ctr;
727 extern I_ GC_SHORT_CAF_ctr;
728 extern I_ GC_COMMON_CHARLIKE_ctr;
729 extern I_ GC_COMMON_INTLIKE_ctr;
730 extern I_ GC_COMMON_INTLIKE_FAIL_ctr;
731 extern I_ GC_COMMON_CONST_ctr;
732
733 #endif /* TICKY_TICKY */
734 \end{code}
735
736 %************************************************************************
737 %*                                                                      *
738 \subsection[Ticky-nonmacros]{Un-macros for ``none of the above''}
739 %*                                                                      *
740 %************************************************************************
741
742 \begin{code}
743 #ifndef TICKY_TICKY
744
745 #define ALLOC_HEAP(n)    /* nothing */
746 #define UN_ALLOC_HEAP(n) /* nothing */
747 #define DO_ASTK_HWM()    /* nothing */
748 #define DO_BSTK_HWM()    /* nothing */
749
750 #define A_STK_STUB(n)   /* nothing */
751 #define A_STK_REUSE(n)  /* not used at all */
752 #define B_STK_REUSE(n)  /* not used at all */
753
754 #define ALLOC_FUN(a,g,s,t) /* nothing */
755 #define ALLOC_THK(a,g,s,t) /* nothing */
756 #define ALLOC_CON(a,g,s,t) /* nothing */
757 #define ALLOC_TUP(a,g,s,t) /* nothing */
758 #define ALLOC_BH(a,g,s,t)  /* nothing */
759 /*#define ALLOC_PAP(a,g,s,t) /? nothing */
760 #define ALLOC_PRIM(a,g,s,t) /* nothing */
761 #define ALLOC_PRIM2(w)   /* nothing */
762 #define ALLOC_UPD_PAP(a,g,s,t) /* nothing */
763 /*#define ALLOC_UPD_CON(a,g,s,t) /? nothing */
764 #define ALLOC_STK(a,g,s) /* nothing */
765 #define ALLOC_TSO(a,g,s) /* nothing */
766 #define ALLOC_FMBQ(a,g,s) /* nothing */
767 #define ALLOC_FME(a,g,s) /* nothing */
768 #define ALLOC_BF(a,g,s) /* nothing */
769
770 #define ENT_VIA_NODE()  /* nothing */
771 #define ENT_THK()       /* nothing */
772 #define ENT_FUN_STD()   /* nothing */
773 #define ENT_FUN_DIRECT(f,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
774                         /* nothing */ 
775 #define ENT_CON(n)      /* nothing */
776 #define ENT_IND(n)      /* nothing */
777 #define ENT_PAP(n)      /* nothing */
778
779 #define RET_NEW_IN_HEAP(n)      /* nothing */
780 #define RET_NEW_IN_REGS(n)      /* nothing */
781 #define RET_OLD_IN_HEAP(n)      /* nothing */
782 #define RET_OLD_IN_REGS(n)      /* nothing */
783 #define RET_SEMI_BY_DEFAULT()   /* nothing */
784 #define RET_SEMI_IN_HEAP(n)     /* nothing */
785 #define RET_SEMI_IN_REGS(n,u)   /* nothing */
786 #define RET_SEMI_FAILED(t)      /* nothing */
787 #define VEC_RETURN(n)           /* nothing */
788
789 #define UPDF_OMITTED()          /* nothing */
790 #define UPDF_STD_PUSHED()       /* nothing */
791 #define UPDF_CON_PUSHED()       /* nothing */
792 #define UPDF_HOLE_PUSHED()      /* nothing */
793
794 #define UPDF_RCC_PUSHED()       /* nothing */
795 #define UPDF_RCC_OMITTED()      /* nothing */
796
797 #define UPD_EXISTING()          /* nothing */
798 #define UPD_SQUEEZED()          /* nothing */
799 #define UPD_CON_W_NODE()        /* nothing */
800 #define UPD_CON_IN_PLACE(n)     /* nothing */
801 #define UPD_PAP_IN_PLACE()      /* nothing */
802 #define UPD_CON_IN_NEW(n)       /* nothing */
803 #define UPD_PAP_IN_NEW(n)       /* nothing */
804
805 #define GC_SEL_ABANDONED()      /* nothing */
806 #define GC_SEL_MINOR()          /* nothing */
807 #define GC_SEL_MAJOR()          /* nothing */
808
809 #define GC_SHORT_IND()          /* nothing */
810 #define GC_SHORT_CAF()          /* nothing */
811 #define GC_COMMON_CHARLIKE()    /* nothing */
812 #define GC_COMMON_INTLIKE()     /* nothing */
813 #define GC_COMMON_INTLIKE_FAIL()/* nothing */
814 #define GC_COMMON_CONST()       /* nothing */
815 \end{code}
816
817 For a generational collector:
818 \begin{code}
819 #define UPD_NEW_IND()                   /* nothing */
820 #define UPD_NEW_IN_PLACE_PTRS()         /* nothing */
821 #define UPD_NEW_IN_PLACE_NOPTRS()       /* nothing */
822 #define UPD_OLD_IND()                   /* nothing */
823 #define UPD_OLD_IN_PLACE_PTRS()         /* nothing */
824 #define UPD_OLD_IN_PLACE_NOPTRS()       /* nothing */
825
826 #endif /* <none-of-the-above> */
827 \end{code}
828
829 End of file multi-slurp protection:
830 \begin{code}
831 #endif /* ! TICKY_H */
832 \end{code}