2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
4 %************************************************************************
6 \section[RednCounts.lh]{Interface (and macros) for reduction-count statistics}
8 %************************************************************************
10 Multi-slurp protection:
16 There are macros in here for:
19 ``SPAT-profiling'' (\tr{DO_SPAT_PROFILING}), counting instructions
20 per ``activity,'' using the SPAT instruction-trace analysis tools.
22 ``Ticky-ticky profiling'' (\tr{DO_REDN_COUNTING}), counting the
23 number of various STG-events (updates, enters, etc.)
25 This file goes with \tr{RednCounts.lc}, which initialises the counters
26 and does the printing [ticky-ticky only].
28 %************************************************************************
30 \subsection[SPAT-macros]{Macros for SPAT instruction counting}
32 %************************************************************************
34 These definitions are for instruction tracing, e.g. using SPAT on the
38 #ifdef DO_SPAT_PROFILING
40 #define ACT_BASE 0x000000ab /* random; to fit in 13 bits */
42 #define ACT_UNKNOWN (0+ACT_BASE)
43 #define ACT_GC (1+ACT_BASE)
44 #define ACT_REDN (2+ACT_BASE)
45 #define ACT_ASTK_STUB (3+ACT_BASE)
46 #define ACT_FILL_IN_HEAP (4+ACT_BASE)
47 #define ACT_HEAP_CHK (5+ACT_BASE)
48 #define ACT_RETURN (6+ACT_BASE)
49 #define ACT_UPDATE (7+ACT_BASE)
50 #define ACT_PUSH_UPDF (8+ACT_BASE)
51 #define ACT_ARGS_CHK (9+ACT_BASE)
52 #define ACT_UPDATE_PAP (10+ACT_BASE)
53 #define ACT_INDIRECT (11+ACT_BASE)
54 #define ACT_PRIM (12+ACT_BASE)
56 #define ACT_OVERHEAD (14+ACT_BASE) /* only used in analyser */
57 #define ACT_TAILCALL (15+ACT_BASE)
58 /* Note: quite a lot gets lumped under TAILCALL; the analyser
59 untangles it with other info. WDP 95/01
64 #define ACT_GC_STOP (ACTIVITIES+1)
65 #define ACT_PRIM_STOP (ACTIVITIES+2)
67 /* values that "signal" the start/stop of something,
68 thus suggesting to the analyser that it stop/start something.
70 I do not think they are used (WDP 95/01)
73 #define ACT_SIGNAL_BASE 0xbababa00 /* pretty random; yes */
75 #define ACT_START_GOING (1+ACT_SIGNAL_BASE)
76 #define ACT_STOP_GOING (2+ACT_SIGNAL_BASE)
77 #define ACT_START_GC (3+ACT_SIGNAL_BASE)
78 #define ACT_STOP_GC (4+ACT_SIGNAL_BASE)
80 #define SET_ACTIVITY(act) do { /* ActivityReg = (act) */ \
81 __asm__ volatile ("or %%g0,%1,%0" \
82 : "=r" (ActivityReg) \
86 #define ALLOC_HEAP(n) /* nothing */
87 #define UN_ALLOC_HEAP(n) /* nothing */
88 #define DO_ASTK_HWM() /* nothing */
89 #define DO_BSTK_HWM() /* nothing */
91 #define A_STK_STUB(n) /* nothing */
92 #define A_STK_REUSE(n) /* not used at all */
93 #define B_STK_REUSE(n) /* ditto */
95 #define ALLOC_FUN(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
96 #define ALLOC_THK(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
97 #define ALLOC_CON(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
98 #define ALLOC_TUP(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
99 #define ALLOC_BH(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
100 /*#define ALLOC_PAP(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)*/
101 #define ALLOC_UPD_PAP(a,g,s,t) SET_ACTIVITY(ACT_UPDATE_PAP) /* NB */
102 /*#define ALLOC_UPD_CON(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP) */
103 #define ALLOC_PRIM(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
104 #define ALLOC_PRIM2(w) SET_ACTIVITY(ACT_FILL_IN_HEAP)
105 #define ALLOC_STK(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
106 #define ALLOC_TSO(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
107 #define ALLOC_FMBQ(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
108 #define ALLOC_FME(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
109 #define ALLOC_BF(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
111 /* we only use the ENT_ macros to be sure activity is set to "reduction" */
112 #define ENT_VIA_NODE() /* nothing */
113 #define ENT_THK() SET_ACTIVITY(ACT_REDN)
114 #define ENT_FUN_STD() SET_ACTIVITY(ACT_REDN)
115 #define ENT_FUN_DIRECT(f,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
116 SET_ACTIVITY(ACT_REDN)
117 #define ENT_CON(n) SET_ACTIVITY(ACT_REDN)
118 #define ENT_IND(n) SET_ACTIVITY(ACT_REDN)
119 #define ENT_PAP(n) SET_ACTIVITY(ACT_UPDATE_PAP) /* NB */
121 #define RET_NEW_IN_HEAP() SET_ACTIVITY(ACT_RETURN)
122 #define RET_NEW_IN_REGS() SET_ACTIVITY(ACT_RETURN)
123 #define RET_OLD_IN_HEAP() SET_ACTIVITY(ACT_RETURN)
124 #define RET_OLD_IN_REGS() SET_ACTIVITY(ACT_RETURN)
125 #define RET_SEMI_BY_DEFAULT() SET_ACTIVITY(ACT_RETURN)
126 #define RET_SEMI_IN_HEAP() SET_ACTIVITY(ACT_RETURN)
127 #define RET_SEMI_IN_REGS() SET_ACTIVITY(ACT_RETURN)
128 #define VEC_RETURN() /* nothing */
130 #define UPDF_OMITTED() /* nothing (set directly by PUSH_STD_UPD_FRAME) */
131 #define UPDF_STD_PUSHED() SET_ACTIVITY(ACT_PUSH_UPDF)
132 #define UPDF_CON_PUSHED() /* nothing */
133 #define UPDF_HOLE_PUSHED() /* nothing */
134 #define UPDF_RCC_PUSHED() /* nothing */
135 #define UPDF_RCC_OMITTED() /* nothing */
137 #define UPD_EXISTING() /* nothing -- used in .lc code */
138 #define UPD_CON_W_NODE() SET_ACTIVITY(ACT_UPDATE)
139 #define UPD_CON_IN_PLACE() SET_ACTIVITY(ACT_UPDATE)
140 #define UPD_PAP_IN_PLACE() /* nothing -- UpdatePAP has its own activity */
141 #define UPD_CON_IN_NEW() SET_ACTIVITY(ACT_UPDATE)
142 #define UPD_PAP_IN_NEW() /* nothing -- UpdatePAP has its own activity */
145 For special subsequent enter counting:
147 #define UPDATED_SET_UPDATED(n) /* nothing */
148 #define ENTERED_CHECK_UPDATED(n) /* nothing */
151 For a generational collector:
153 #define UPD_NEW_IND() /* nothing (set elsewhere [?]) */
154 #define UPD_NEW_IN_PLACE_PTRS() /* nothing */
155 #define UPD_NEW_IN_PLACE_NOPTRS() /* nothing */
156 #define UPD_OLD_IND() /* nothing */
157 #define UPD_OLD_IN_PLACE_PTRS() /* nothing */
158 #define UPD_OLD_IN_PLACE_NOPTRS() /* nothing */
160 #endif /* DO_SPAT_PROFILING */
163 %************************************************************************
165 \subsection[ticky-ticky-macros]{Stuff for ``ticky-ticky'' profiling}
167 %************************************************************************
170 #ifdef DO_REDN_COUNTING
172 #define SET_ACTIVITY(act) /* quickly: make this do NOTHING */
175 Measure what proportion of ...:
178 ... Enters are to data values, function values, thunks.
180 ... allocations are for data values, functions values, thunks.
182 ... updates are for data values, function values.
186 ... return-in-heap (dynamic)
188 ... vectored return (dynamic)
190 ... updates are wasted (never re-entered).
192 ... constructor returns get away without hitting an update.
195 %************************************************************************
197 \subsubsection[ticky-stk-heap-use]{Stack and heap usage}
199 %************************************************************************
201 Things we are interested in here:
204 How many times we do a heap check and move @Hp@; comparing this with
205 the allocations gives an indication of how many things we get per trip
208 #define ALLOC_HEAP(n) ALLOC_HEAP_ctr++; ALLOC_HEAP_tot += (n)
211 If we do a ``heap lookahead,'' we haven't really allocated any
212 heap, so we need to undo the effects of an \tr{ALLOC_HEAP}:
214 #define UN_ALLOC_HEAP(n) ALLOC_HEAP_ctr--; ALLOC_HEAP_tot -= (n)
218 The stack high-water marks. This is {\em direction-sensitive}!!
219 (A stack grows downward, B stack upwards)
222 #define DO_ASTK_HWM() if (SpA < max_SpA) { max_SpA = SpA; }
223 #define DO_BSTK_HWM() if (SpB > max_SpB) { max_SpB = SpB; }
226 * This is not direction sensitive, because we threads people are well-behaved.
227 * However, it might be a good idea to cache the constant bits (DEP + BOT and
228 * HWM) from the STKO and TSO in more readily accessible places. -- ToDo!
230 #define DO_ASTK_HWM() { \
231 I_ depth = STKO_ADEP(StkOReg) + AREL((I_) STKO_ASTK_BOT(StkOReg) - (I_) SpA);\
232 if (depth > TSO_AHWM(CurrentTSO)) \
233 TSO_AHWM(CurrentTSO) = depth; \
235 #define DO_BSTK_HWM() { \
236 I_ depth = STKO_BDEP(StkOReg) + BREL((I_) STKO_BSTK_BOT(StkOReg) - (I_) SpB);\
237 if (depth > TSO_BHWM(CurrentTSO)) \
238 TSO_BHWM(CurrentTSO) = depth; \
244 Re-use of stack slots, and stubbing of stack slots:
246 #define A_STK_STUB(n) A_STK_STUB_ctr += (n)
247 #define A_STK_REUSE(n) A_STK_REUSE_ctr += (n) /* not used at all? */
248 #define B_STK_REUSE(n) B_STK_REUSE_ctr += (n) /* not used at all? */
252 %************************************************************************
254 \subsubsection[ticky-allocs]{Allocations}
256 %************************************************************************
258 We count things every time we allocate something in the dynamic heap.
259 For each, we count the number of words of (1)~``admin'' (header),
260 (2)~good stuff (useful pointers and data), and (3)~``slop'' (extra
261 space, in hopes it will allow an in-place update).
263 The first five macros are inserted when the compiler generates code
264 to allocate something; the categories correspond to the @ClosureClass@
265 datatype (manifest functions, thunks, constructors, big tuples, and
266 partial applications).
268 #define ALLOC_FUN(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
269 ALLOC_FUN_ctr++; ALLOC_FUN_adm += (a); \
270 ALLOC_FUN_gds += (g); ALLOC_FUN_slp += (s); \
271 ALLOC_HISTO(FUN,a,g,s)
272 #define ALLOC_THK(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
273 ALLOC_THK_ctr++; ALLOC_THK_adm += (a); \
274 ALLOC_THK_gds += (g); ALLOC_THK_slp += (s); \
275 ALLOC_HISTO(THK,a,g,s)
276 #define ALLOC_CON(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
277 ALLOC_CON_ctr++; ALLOC_CON_adm += (a); \
278 ALLOC_CON_gds += (g); ALLOC_CON_slp += (s); \
279 ALLOC_HISTO(CON,a,g,s)
280 #define ALLOC_TUP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
281 ALLOC_TUP_ctr++; ALLOC_TUP_adm += (a); \
282 ALLOC_TUP_gds += (g); ALLOC_TUP_slp += (s); \
283 ALLOC_HISTO(TUP,a,g,s)
284 #define ALLOC_BH(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
285 ALLOC_BH_ctr++; ALLOC_BH_adm += (a); \
286 ALLOC_BH_gds += (g); ALLOC_BH_slp += (s); \
287 ALLOC_HISTO(BH,a,g,s)
289 #define ALLOC_PAP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
290 ALLOC_PAP_ctr++; ALLOC_PAP_adm += (a); \
291 ALLOC_PAP_gds += (g); ALLOC_PAP_slp += (s); \
292 ALLOC_HISTO(PAP,a,g,s)
296 We may also allocate space when we do an update, and there isn't
297 enough space. These macros suffice (for: updating with a partial
298 application and a constructor):
300 #define ALLOC_UPD_PAP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
301 ALLOC_UPD_PAP_ctr++; ALLOC_UPD_PAP_adm += (a); \
302 ALLOC_UPD_PAP_gds += (g); ALLOC_UPD_PAP_slp += (s); \
303 ALLOC_HISTO(UPD_PAP,a,g,s)
305 #define ALLOC_UPD_CON(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
306 ALLOC_UPD_CON_ctr++; ALLOC_UPD_CON_adm += (a); \
307 ALLOC_UPD_CON_gds += (g); ALLOC_UPD_CON_slp += (s); \
308 ALLOC_HISTO(UPD_CON,a,g,s)
312 In the threaded world, we allocate space for the spark pool, stack objects,
313 and thread state objects.
317 #define ALLOC_STK(a,g,s) ALLOC_STK_ctr++; ALLOC_STK_adm += (a); \
318 ALLOC_STK_gds += (g); ALLOC_STK_slp += (s); \
319 ALLOC_HISTO(STK,a,g,s)
321 #define ALLOC_TSO(a,g,s) ALLOC_TSO_ctr++; ALLOC_TSO_adm += (a); \
322 ALLOC_TSO_gds += (g); ALLOC_TSO_slp += (s); \
323 ALLOC_HISTO(TSO,a,g,s)
325 #define ALLOC_FMBQ(a,g,s) ALLOC_FMBQ_ctr++; ALLOC_FMBQ_adm += (a); \
326 ALLOC_FMBQ_gds += (g); ALLOC_FMBQ_slp += (s); \
327 ALLOC_HISTO(FMBQ,a,g,s)
329 #define ALLOC_FME(a,g,s) ALLOC_FME_ctr++; ALLOC_FME_adm += (a); \
330 ALLOC_FME_gds += (g); ALLOC_FME_slp += (s); \
331 ALLOC_HISTO(FME,a,g,s)
333 #define ALLOC_BF(a,g,s) ALLOC_BF_ctr++; ALLOC_BF_adm += (a); \
334 ALLOC_BF_gds += (g); ALLOC_BF_slp += (s); \
335 ALLOC_HISTO(BF,a,g,s)
339 The histogrammy bit is fairly straightforward; the \tr{-2} is: one for
340 0-origin C arrays; the other one because we do {\em no} one-word
341 allocations, so we would never inc that histogram slot; so we shift
342 everything over by one.
344 #define ALLOC_HISTO(categ,a,g,s) \
346 __idx = (a) + (g) + (s) - 2; \
347 CAT3(ALLOC_,categ,_hst)[((__idx > 4) ? 4 : __idx)] += 1;}
350 Some hard-to-account-for words are allocated by/for primitives,
351 includes Integer support. @ALLOC_PRIM2@ tells us about these. We
352 count everything as ``goods'', which is not strictly correct.
353 (@ALLOC_PRIM@ is the same sort of stuff, but we know the
354 admin/goods/slop breakdown.)
356 #define ALLOC_PRIM(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
357 ALLOC_PRIM_ctr++; ALLOC_PRIM_adm += (a); \
358 ALLOC_PRIM_gds += (g); ALLOC_PRIM_slp += (s); \
359 ALLOC_HISTO(PRIM,a,g,s)
360 #define ALLOC_PRIM2(w) ALLOC_PRIM_ctr++; ALLOC_PRIM_gds +=(w); \
361 ALLOC_HISTO(PRIM,0,w,0)
364 %************************************************************************
366 \subsubsection[ticky-enters]{Enters}
368 %************************************************************************
371 #define ENT_VIA_NODE() ENT_VIA_NODE_ctr++ /* via ENT_ macro */
373 #define ENT_THK() ENT_THK_ctr++
374 #define ENT_FUN_STD() ENT_FUN_STD_ctr++ /* manifest fun; std entry pt */
376 #define ENT_CON(n) ENTERED_CHECK_UPDATED(n); ENT_CON_ctr++ /* enter code for constructor */
377 #define ENT_IND(n) ENTERED_CHECK_UPDATED(n); ENT_IND_ctr++ /* enter indirection */
378 #define ENT_PAP(n) ENTERED_CHECK_UPDATED(n); ENT_PAP_ctr++ /* enter partial application */
381 We do more magical things with @ENT_FUN_DIRECT@. Besides simply knowing
382 how many ``fast-entry-point'' enters there were, we'd like {\em simple}
383 information about where those enters were, and the properties thereof.
386 unsigned registeredp:16, /* 0 == no, 1 == yes */
387 arity:16, /* arity (static info) */
388 Astk_args:16, /* # of args off A stack */
389 Bstk_args:16; /* # of args off B stack */
390 /* (rest of args are in registers) */
391 StgChar *f_str; /* name of the thing */
392 StgChar *f_arg_kinds; /* info about the args types */
393 StgChar *wrap_str; /* name of its wrapper (if any) */
394 StgChar *wrap_arg_kinds;/* info about the orig wrapper's arg types */
395 I_ ctr; /* the actual counter */
396 struct ent_counter *link; /* link to chain them all together */
399 /* OLD: extern void RegisterEntryPt PROTO((struct ent_counter *)); */
400 extern struct ent_counter *ListOfEntryCtrs;
402 #define ENT_FUN_DIRECT(f_ct,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
403 static struct ent_counter f_ct \
405 (f_arity), (Aargs), (Bargs), (f_str), (arg_kinds),\
406 (wrap), (wrap_kinds), \
408 if ( ! f_ct.registeredp ) { \
409 /* hook this one onto the front of the list */ \
410 f_ct.link = ListOfEntryCtrs; \
411 ListOfEntryCtrs = & (f_ct); \
413 /* mark it as "registered" */ \
414 f_ct.registeredp = 1; \
417 ENT_FUN_DIRECT_ctr++ /* the old boring one */
420 %************************************************************************
422 \subsubsection[ticky-returns]{Returns}
424 %************************************************************************
426 Whenever a ``return'' occurs, it is returning the constituent parts of
427 a data constructor. The parts can be returned either in registers, or
428 by allocating some heap to put it in (the @ALLOC_*@ macros account for
429 the allocation). The constructor can either be an existing one
430 (\tr{*OLD*}) or we could have {\em just} figured out this stuff
433 Here's some special magic that Simon wants [edited to match names
436 From: Simon L Peyton Jones <simonpj>
438 Subject: counting updates
439 Date: Wed, 25 Mar 92 08:39:48 +0000
441 I'd like to count how many times we update in place when actually Node
442 points to the thing. Here's how:
444 \tr{RET_OLD_IN_REGS} sets the variable \tr{ReturnInRegsNodeValid} to \tr{True};
445 \tr{RET_NEW_IN_REGS} sets it to \tr{False}.
447 \tr{RET_SEMI_???} sets it to??? ToDo [WDP]
449 \tr{UPD_CON_IN_PLACE} tests the variable, and increments \tr{UPD_IN_PLACE_COPY_ctr}
452 Then we need to report it along with the update-in-place info.
456 #define RET_NEW_IN_HEAP() RET_NEW_IN_HEAP_ctr++
457 #define RET_OLD_IN_HEAP() RET_OLD_IN_HEAP_ctr++
459 #define RET_NEW_IN_REGS() RET_NEW_IN_REGS_ctr++; \
460 ReturnInRegsNodeValid = 0
461 #define RET_OLD_IN_REGS() RET_OLD_IN_REGS_ctr++; \
462 ReturnInRegsNodeValid = 1
464 #define RET_SEMI_BY_DEFAULT() RET_SEMI_BY_DEFAULT_ctr++
465 #define RET_SEMI_IN_HEAP() RET_SEMI_IN_HEAP_ctr++
466 #define RET_SEMI_IN_REGS() RET_SEMI_IN_REGS_ctr++
469 Of all the returns (sum of four categories above), how many were
470 vectored? (The rest were obviously unvectored).
472 #define VEC_RETURN() VEC_RETURN_ctr++
475 %************************************************************************
477 \subsubsection[ticky-update-frames]{Update frames}
479 %************************************************************************
481 These macros count up the following update information.
483 %partain:\begin{center}
484 \begin{tabular}{ll} \hline
485 Macro & Counts \\ \hline
487 \tr{UPDF_STD_PUSHED} & Update frame pushed \\
488 \tr{UPDF_CON_PUSHED} & Constructor update frame pushed \\
489 \tr{UPDF_HOLE_PUSHED} & An update frame to update a black hole \\
490 \tr{UPDF_OMITTED} & A thunk decided not to push an update frame \\
491 & (all subsets of \tr{ENT_THK}) \\
492 \tr{UPDF_RCC_PUSHED} & Cost Centre restore frame pushed \\
493 \tr{UPDF_RCC_OMITTED} & Cost Centres not required -- not pushed \\\hline
495 %partain:\end{center}
498 #define UPDF_OMITTED() UPDF_OMITTED_ctr++
500 #define UPDF_STD_PUSHED() UPDF_STD_PUSHED_ctr++
501 #define UPDF_CON_PUSHED() UPDF_CON_PUSHED_ctr++
502 #define UPDF_HOLE_PUSHED() UPDF_HOLE_PUSHED_ctr++
504 #define UPDF_RCC_PUSHED() UPDF_RCC_PUSHED_ctr++
505 #define UPDF_RCC_OMITTED() UPDF_RCC_OMITTED_ctr++
508 %************************************************************************
510 \subsubsection[ticky-updates]{Updates}
512 %************************************************************************
514 These macros record information when we do an update. We always
515 update either with a data constructor (CON) or a partial application
518 %partain:\begin{center}
519 \begin{tabular}{|l|l|}\hline
520 Macro & Where \\ \hline
522 \tr{UPD_EXISTING} & Updating with an indirection to something \\
523 & already in the heap \\
525 \tr{UPD_CON_W_NODE} & Updating with a CON: by indirecting to Node \\
527 \tr{UPD_CON_IN_PLACE} & Ditto, but in place \\
528 \tr{UPD_CON_IN_NEW} & Ditto, but allocating the object \\
530 \tr{UPD_PAP_IN_PLACE} & Same, but updating w/ a PAP \\
531 \tr{UPD_PAP_IN_NEW} & \\\hline
533 %partain:\end{center}
536 #define UPD_EXISTING() UPD_EXISTING_ctr++
538 #define UPD_CON_W_NODE() UPD_CON_W_NODE_ctr++
540 #define UPD_CON_IN_NEW() UPD_CON_IN_NEW_ctr++
541 #define UPD_PAP_IN_NEW() UPD_PAP_IN_NEW_ctr++
542 /* ToDo: UPD_NEW_COPY_ctr, as below */
544 #define UPD_CON_IN_PLACE() UPD_CON_IN_PLACE_ctr++ ; \
545 UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid
546 /* increments if True; otherwise, no */
547 #define UPD_PAP_IN_PLACE() UPD_PAP_IN_PLACE_ctr++ ; \
548 UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid
549 /* increments if True; otherwise, no */
552 For a generational collector:
554 #define UPD_NEW_IND() UPD_NEW_IND_ctr++;
555 #define UPD_NEW_IN_PLACE_PTRS() UPD_NEW_IN_PLACE_PTRS_ctr++;
556 #define UPD_NEW_IN_PLACE_NOPTRS() UPD_NEW_IN_PLACE_NOPTRS_ctr++;
557 #define UPD_OLD_IND() UPD_OLD_IND_ctr++;
558 #define UPD_OLD_IN_PLACE_PTRS() UPD_OLD_IN_PLACE_PTRS_ctr++;
559 #define UPD_OLD_IN_PLACE_NOPTRS() UPD_OLD_IN_PLACE_NOPTRS_ctr++;
562 %************************************************************************
564 \subsubsection[ticky-updates-entered]{Updates Subsequently Entered}
566 %************************************************************************
568 If @UPDATES_ENTERED_COUNT@ is defined we add the Age word to the
569 closures. This is used to record indicate if a closure has been
570 updated but not yet entered. It is set when the closure is updated and
571 cleared when subsequently entered.
573 The commoning up of @CONST@, @CHARLIKE@ and @INTLIKE@ closures is
574 turned if this is required. This has only been done for 2s collection.
575 It is done using a nasty hack which defines the @_Evacuate@ and
576 @_Scavenge@ code for @CONST@, @CHARLIKE@ and @INTLIKE@ info tables to
577 be @_Evacuate_1@ and @_Scavenge_1_0@.
579 Unfortunately this broke everything so it has not been done ;-(.
580 Instead we have to run with enough heap so no garbage collection is
581 needed for accurate numbers. ToDo: Fix this!
583 As implemented it can not be used in conjunction with heap profiling
584 or lifetime profiling becasue they make conflicting use the Age word!
587 #if defined(UPDATES_ENTERED_COUNT)
589 #define UPDATED_SET_UPDATED(n) AGE_HDR(n) = 1
591 #define ENTERED_CHECK_UPDATED(n) \
593 if (AGE_HDR(n) == 1) { \
597 UPD_ENTERED_AGAIN_ctr++; \
601 #else /* ! UPDATES_ENTERED_COUNT */
603 #define UPDATED_SET_UPDATED(n) /* nothing */
604 #define ENTERED_CHECK_UPDATED(n) /* nothing */
606 #endif /* ! UPDATES_ENTERED_COUNT */
609 %************************************************************************
611 \subsubsection[ticky-counters]{The accumulators (extern decls)}
613 %************************************************************************
616 extern I_ ALLOC_HEAP_ctr;
617 extern I_ ALLOC_HEAP_tot;
622 extern I_ A_STK_STUB_ctr;
624 extern I_ A_STK_REUSE_ctr;
625 extern I_ B_STK_REUSE_ctr;
628 extern I_ ALLOC_FUN_ctr;
629 extern I_ ALLOC_FUN_adm;
630 extern I_ ALLOC_FUN_gds;
631 extern I_ ALLOC_FUN_slp;
632 extern I_ ALLOC_FUN_hst[5];
633 extern I_ ALLOC_THK_ctr;
634 extern I_ ALLOC_THK_adm;
635 extern I_ ALLOC_THK_gds;
636 extern I_ ALLOC_THK_slp;
637 extern I_ ALLOC_THK_hst[5];
638 extern I_ ALLOC_CON_ctr;
639 extern I_ ALLOC_CON_adm;
640 extern I_ ALLOC_CON_gds;
641 extern I_ ALLOC_CON_slp;
642 extern I_ ALLOC_CON_hst[5];
643 extern I_ ALLOC_TUP_ctr;
644 extern I_ ALLOC_TUP_adm;
645 extern I_ ALLOC_TUP_gds;
646 extern I_ ALLOC_TUP_slp;
647 extern I_ ALLOC_TUP_hst[5];
648 extern I_ ALLOC_BH_ctr;
649 extern I_ ALLOC_BH_adm;
650 extern I_ ALLOC_BH_gds;
651 extern I_ ALLOC_BH_slp;
652 extern I_ ALLOC_BH_hst[5];
654 extern I_ ALLOC_PAP_ctr;
655 extern I_ ALLOC_PAP_adm;
656 extern I_ ALLOC_PAP_gds;
657 extern I_ ALLOC_PAP_slp;
658 extern I_ ALLOC_PAP_hst[5];
661 extern I_ ALLOC_UPD_CON_ctr;
662 extern I_ ALLOC_UPD_CON_adm;
663 extern I_ ALLOC_UPD_CON_gds;
664 extern I_ ALLOC_UPD_CON_slp;
665 extern I_ ALLOC_UPD_CON_hst[5];
667 extern I_ ALLOC_UPD_PAP_ctr;
668 extern I_ ALLOC_UPD_PAP_adm;
669 extern I_ ALLOC_UPD_PAP_gds;
670 extern I_ ALLOC_UPD_PAP_slp;
671 extern I_ ALLOC_UPD_PAP_hst[5];
672 extern I_ ALLOC_PRIM_ctr;
673 extern I_ ALLOC_PRIM_adm;
674 extern I_ ALLOC_PRIM_gds;
675 extern I_ ALLOC_PRIM_slp;
676 extern I_ ALLOC_PRIM_hst[5];
679 extern I_ ALLOC_STK_ctr;
680 extern I_ ALLOC_STK_adm;
681 extern I_ ALLOC_STK_gds;
682 extern I_ ALLOC_STK_slp;
683 extern I_ ALLOC_STK_hst[5];
684 extern I_ ALLOC_TSO_ctr;
685 extern I_ ALLOC_TSO_adm;
686 extern I_ ALLOC_TSO_gds;
687 extern I_ ALLOC_TSO_slp;
688 extern I_ ALLOC_TSO_hst[5];
690 extern I_ ALLOC_FMBQ_ctr;
691 extern I_ ALLOC_FMBQ_adm;
692 extern I_ ALLOC_FMBQ_gds;
693 extern I_ ALLOC_FMBQ_slp;
694 extern I_ ALLOC_FMBQ_hst[5];
695 extern I_ ALLOC_FME_ctr;
696 extern I_ ALLOC_FME_adm;
697 extern I_ ALLOC_FME_gds;
698 extern I_ ALLOC_FME_slp;
699 extern I_ ALLOC_FME_hst[5];
700 extern I_ ALLOC_BF_ctr;
701 extern I_ ALLOC_BF_adm;
702 extern I_ ALLOC_BF_gds;
703 extern I_ ALLOC_BF_slp;
704 extern I_ ALLOC_BF_hst[5];
708 extern I_ ENT_VIA_NODE_ctr;
710 extern I_ ENT_CON_ctr;
711 extern I_ ENT_FUN_STD_ctr;
712 extern I_ ENT_FUN_DIRECT_ctr;
713 extern I_ ENT_IND_ctr;
714 extern I_ ENT_PAP_ctr;
715 extern I_ ENT_THK_ctr;
717 extern I_ UPD_ENTERED_ctr;
718 extern I_ UPD_ENTERED_AGAIN_ctr;
720 extern I_ RET_NEW_IN_HEAP_ctr;
721 extern I_ RET_NEW_IN_REGS_ctr;
722 extern I_ RET_OLD_IN_HEAP_ctr;
723 extern I_ RET_OLD_IN_REGS_ctr;
724 extern I_ RET_SEMI_BY_DEFAULT_ctr;
725 extern I_ RET_SEMI_IN_HEAP_ctr;
726 extern I_ RET_SEMI_IN_REGS_ctr;
727 extern I_ VEC_RETURN_ctr;
729 extern I_ ReturnInRegsNodeValid; /* see below */
731 extern I_ UPDF_OMITTED_ctr;
732 extern I_ UPDF_STD_PUSHED_ctr;
733 extern I_ UPDF_CON_PUSHED_ctr;
734 extern I_ UPDF_HOLE_PUSHED_ctr;
736 extern I_ UPDF_RCC_PUSHED_ctr;
737 extern I_ UPDF_RCC_OMITTED_ctr;
739 extern I_ UPD_EXISTING_ctr;
740 extern I_ UPD_CON_W_NODE_ctr;
741 extern I_ UPD_CON_IN_PLACE_ctr;
742 extern I_ UPD_PAP_IN_PLACE_ctr;
743 extern I_ UPD_CON_IN_NEW_ctr;
744 extern I_ UPD_PAP_IN_NEW_ctr;
746 extern I_ UPD_NEW_IND_ctr;
747 extern I_ UPD_NEW_IN_PLACE_PTRS_ctr;
748 extern I_ UPD_NEW_IN_PLACE_NOPTRS_ctr;
749 extern I_ UPD_OLD_IND_ctr;
750 extern I_ UPD_OLD_IN_PLACE_PTRS_ctr;
751 extern I_ UPD_OLD_IN_PLACE_NOPTRS_ctr;
753 extern I_ UPD_IN_PLACE_COPY_ctr; /* see below */
755 #endif /* DO_REDN_COUNTING */
758 %************************************************************************
760 \subsection[RednCounts-nonmacros]{Un-macros for ``none of the above''}
762 %************************************************************************
765 #if ! (defined(DO_SPAT_PROFILING) || defined(DO_REDN_COUNTING))
767 #define SET_ACTIVITY(act) /* nothing */
769 #define ALLOC_HEAP(n) /* nothing */
770 #define UN_ALLOC_HEAP(n) /* nothing */
771 #define DO_ASTK_HWM() /* nothing */
772 #define DO_BSTK_HWM() /* nothing */
774 #define A_STK_STUB(n) /* nothing */
775 #define A_STK_REUSE(n) /* not used at all */
776 #define B_STK_REUSE(n) /* not used at all */
778 #define ALLOC_FUN(a,g,s,t) /* nothing */
779 #define ALLOC_THK(a,g,s,t) /* nothing */
780 #define ALLOC_CON(a,g,s,t) /* nothing */
781 #define ALLOC_TUP(a,g,s,t) /* nothing */
782 #define ALLOC_BH(a,g,s,t) /* nothing */
783 /*#define ALLOC_PAP(a,g,s,t) /? nothing */
784 #define ALLOC_PRIM(a,g,s,t) /* nothing */
785 #define ALLOC_PRIM2(w) /* nothing */
786 #define ALLOC_UPD_PAP(a,g,s,t) /* nothing */
787 /*#define ALLOC_UPD_CON(a,g,s,t) /? nothing */
788 #define ALLOC_STK(a,g,s) /* nothing */
789 #define ALLOC_TSO(a,g,s) /* nothing */
790 #define ALLOC_FMBQ(a,g,s) /* nothing */
791 #define ALLOC_FME(a,g,s) /* nothing */
792 #define ALLOC_BF(a,g,s) /* nothing */
794 #define ENT_VIA_NODE() /* nothing */
795 #define ENT_THK() /* nothing */
796 #define ENT_FUN_STD() /* nothing */
797 #define ENT_FUN_DIRECT(f,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
799 #define ENT_CON(n) /* nothing */
800 #define ENT_IND(n) /* nothing */
801 #define ENT_PAP(n) /* nothing */
803 #define RET_NEW_IN_HEAP() /* nothing */
804 #define RET_NEW_IN_REGS() /* nothing */
805 #define RET_OLD_IN_HEAP() /* nothing */
806 #define RET_OLD_IN_REGS() /* nothing */
807 #define RET_SEMI_BY_DEFAULT() /* nothing */
808 #define RET_SEMI_IN_HEAP() /* nothing */
809 #define RET_SEMI_IN_REGS() /* nothing */
810 #define VEC_RETURN() /* nothing */
812 #define UPDF_OMITTED() /* nothing */
813 #define UPDF_STD_PUSHED() /* nothing */
814 #define UPDF_CON_PUSHED() /* nothing */
815 #define UPDF_HOLE_PUSHED() /* nothing */
817 #define UPDF_RCC_PUSHED() /* nothing */
818 #define UPDF_RCC_OMITTED() /* nothing */
820 #define UPD_EXISTING() /* nothing */
821 #define UPD_CON_W_NODE() /* nothing */
822 #define UPD_CON_IN_PLACE() /* nothing */
823 #define UPD_PAP_IN_PLACE() /* nothing */
824 #define UPD_CON_IN_NEW() /* nothing */
825 #define UPD_PAP_IN_NEW() /* nothing */
828 For special subsequent enter counting:
830 #define UPDATED_SET_UPDATED(n) /* nothing */
831 #define ENTERED_CHECK_UPDATED(n) /* nothing */
834 For a generational collector:
836 #define UPD_NEW_IND() /* nothing */
837 #define UPD_NEW_IN_PLACE_PTRS() /* nothing */
838 #define UPD_NEW_IN_PLACE_NOPTRS() /* nothing */
839 #define UPD_OLD_IND() /* nothing */
840 #define UPD_OLD_IN_PLACE_PTRS() /* nothing */
841 #define UPD_OLD_IN_PLACE_NOPTRS() /* nothing */
843 #endif /* <none-of-the-above> */
846 End of file multi-slurp protection:
848 #endif /* ! REDNCOUNTS_H */