+++ /dev/null
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1995
-%
-%************************************************************************
-%* *
-\section[RednCounts.lh]{Interface (and macros) for reduction-count statistics}
-%* *
-%************************************************************************
-
-Multi-slurp protection:
-\begin{code}
-#ifndef REDNCOUNTS_H
-#define REDNCOUNTS_H
-\end{code}
-
-There are macros in here for:
-\begin{enumerate}
-\item
-``SPAT-profiling'' (\tr{DO_SPAT_PROFILING}), counting instructions
-per ``activity,'' using the SPAT instruction-trace analysis tools.
-\item
-``Ticky-ticky profiling'' (\tr{DO_REDN_COUNTING}), counting the
-number of various STG-events (updates, enters, etc.)
-
-This file goes with \tr{RednCounts.lc}, which initialises the counters
-and does the printing [ticky-ticky only].
-
-%************************************************************************
-%* *
-\subsection[SPAT-macros]{Macros for SPAT instruction counting}
-%* *
-%************************************************************************
-
-These definitions are for instruction tracing, e.g. using SPAT on the
-SPARC.
-
-\begin{code}
-#ifdef DO_SPAT_PROFILING
-
-#define ACT_BASE 0x000000ab /* random; to fit in 13 bits */
-
-#define ACT_UNKNOWN (0+ACT_BASE)
-#define ACT_GC (1+ACT_BASE)
-#define ACT_REDN (2+ACT_BASE)
-#define ACT_ASTK_STUB (3+ACT_BASE)
-#define ACT_FILL_IN_HEAP (4+ACT_BASE)
-#define ACT_HEAP_CHK (5+ACT_BASE)
-#define ACT_RETURN (6+ACT_BASE)
-#define ACT_UPDATE (7+ACT_BASE)
-#define ACT_PUSH_UPDF (8+ACT_BASE)
-#define ACT_ARGS_CHK (9+ACT_BASE)
-#define ACT_UPDATE_PAP (10+ACT_BASE)
-#define ACT_INDIRECT (11+ACT_BASE)
-#define ACT_PRIM (12+ACT_BASE)
-
-#define ACT_OVERHEAD (14+ACT_BASE) /* only used in analyser */
-#define ACT_TAILCALL (15+ACT_BASE)
- /* Note: quite a lot gets lumped under TAILCALL; the analyser
- untangles it with other info. WDP 95/01
- */
-
-#define ACTIVITIES 16
-
-#define ACT_GC_STOP (ACTIVITIES+1)
-#define ACT_PRIM_STOP (ACTIVITIES+2)
-
-/* values that "signal" the start/stop of something,
- thus suggesting to the analyser that it stop/start something.
-
- I do not think they are used (WDP 95/01)
-*/
-
-#define ACT_SIGNAL_BASE 0xbababa00 /* pretty random; yes */
-
-#define ACT_START_GOING (1+ACT_SIGNAL_BASE)
-#define ACT_STOP_GOING (2+ACT_SIGNAL_BASE)
-#define ACT_START_GC (3+ACT_SIGNAL_BASE)
-#define ACT_STOP_GC (4+ACT_SIGNAL_BASE)
-
-#define SET_ACTIVITY(act) do { /* ActivityReg = (act) */ \
- __asm__ volatile ("or %%g0,%1,%0" \
- : "=r" (ActivityReg) \
- : "I" (act)); \
- } while(0)
-
-#define ALLOC_HEAP(n) /* nothing */
-#define UN_ALLOC_HEAP(n) /* nothing */
-#define DO_ASTK_HWM() /* nothing */
-#define DO_BSTK_HWM() /* nothing */
-
-#define A_STK_STUB(n) /* nothing */
-#define A_STK_REUSE(n) /* not used at all */
-#define B_STK_REUSE(n) /* ditto */
-
-#define ALLOC_FUN(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_THK(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_CON(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_TUP(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_BH(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-/*#define ALLOC_PAP(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)*/
-#define ALLOC_UPD_PAP(a,g,s,t) SET_ACTIVITY(ACT_UPDATE_PAP) /* NB */
-/*#define ALLOC_UPD_CON(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP) */
-#define ALLOC_PRIM(a,g,s,t) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_PRIM2(w) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_STK(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_TSO(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_FMBQ(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_FME(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-#define ALLOC_BF(a,g,s) SET_ACTIVITY(ACT_FILL_IN_HEAP)
-
-/* we only use the ENT_ macros to be sure activity is set to "reduction" */
-#define ENT_VIA_NODE() /* nothing */
-#define ENT_THK() SET_ACTIVITY(ACT_REDN)
-#define ENT_FUN_STD() SET_ACTIVITY(ACT_REDN)
-#define ENT_FUN_DIRECT(f,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
- SET_ACTIVITY(ACT_REDN)
-#define ENT_CON(n) SET_ACTIVITY(ACT_REDN)
-#define ENT_IND(n) SET_ACTIVITY(ACT_REDN)
-#define ENT_PAP(n) SET_ACTIVITY(ACT_UPDATE_PAP) /* NB */
-
-#define RET_NEW_IN_HEAP() SET_ACTIVITY(ACT_RETURN)
-#define RET_NEW_IN_REGS() SET_ACTIVITY(ACT_RETURN)
-#define RET_OLD_IN_HEAP() SET_ACTIVITY(ACT_RETURN)
-#define RET_OLD_IN_REGS() SET_ACTIVITY(ACT_RETURN)
-#define RET_SEMI_BY_DEFAULT() SET_ACTIVITY(ACT_RETURN)
-#define RET_SEMI_IN_HEAP() SET_ACTIVITY(ACT_RETURN)
-#define RET_SEMI_IN_REGS() SET_ACTIVITY(ACT_RETURN)
-#define VEC_RETURN() /* nothing */
-
-#define UPDF_OMITTED() /* nothing (set directly by PUSH_STD_UPD_FRAME) */
-#define UPDF_STD_PUSHED() SET_ACTIVITY(ACT_PUSH_UPDF)
-#define UPDF_CON_PUSHED() /* nothing */
-#define UPDF_HOLE_PUSHED() /* nothing */
-#define UPDF_RCC_PUSHED() /* nothing */
-#define UPDF_RCC_OMITTED() /* nothing */
-
-#define UPD_EXISTING() /* nothing -- used in .lc code */
-#define UPD_CON_W_NODE() SET_ACTIVITY(ACT_UPDATE)
-#define UPD_CON_IN_PLACE() SET_ACTIVITY(ACT_UPDATE)
-#define UPD_PAP_IN_PLACE() /* nothing -- UpdatePAP has its own activity */
-#define UPD_CON_IN_NEW() SET_ACTIVITY(ACT_UPDATE)
-#define UPD_PAP_IN_NEW() /* nothing -- UpdatePAP has its own activity */
-\end{code}
-
-For special subsequent enter counting:
-\begin{code}
-#define UPDATED_SET_UPDATED(n) /* nothing */
-#define ENTERED_CHECK_UPDATED(n) /* nothing */
-\end{code}
-
-For a generational collector:
-\begin{code}
-#define UPD_NEW_IND() /* nothing (set elsewhere [?]) */
-#define UPD_NEW_IN_PLACE_PTRS() /* nothing */
-#define UPD_NEW_IN_PLACE_NOPTRS() /* nothing */
-#define UPD_OLD_IND() /* nothing */
-#define UPD_OLD_IN_PLACE_PTRS() /* nothing */
-#define UPD_OLD_IN_PLACE_NOPTRS() /* nothing */
-
-#endif /* DO_SPAT_PROFILING */
-\end{code}
-
-%************************************************************************
-%* *
-\subsection[ticky-ticky-macros]{Stuff for ``ticky-ticky'' profiling}
-%* *
-%************************************************************************
-
-\begin{code}
-#ifdef DO_REDN_COUNTING
-
-#define SET_ACTIVITY(act) /* quickly: make this do NOTHING */
-\end{code}
-
-Measure what proportion of ...:
-\begin{itemize}
-\item
-... Enters are to data values, function values, thunks.
-\item
-... allocations are for data values, functions values, thunks.
-\item
-... updates are for data values, function values.
-\item
-... updates ``fit''
-\item
-... return-in-heap (dynamic)
-\item
-... vectored return (dynamic)
-\item
-... updates are wasted (never re-entered).
-\item
-... constructor returns get away without hitting an update.
-\end{enumerate}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-stk-heap-use]{Stack and heap usage}
-%* *
-%************************************************************************
-
-Things we are interested in here:
-\begin{itemize}
-\item
-How many times we do a heap check and move @Hp@; comparing this with
-the allocations gives an indication of how many things we get per trip
-to the well:
-\begin{code}
-#define ALLOC_HEAP(n) ALLOC_HEAP_ctr++; ALLOC_HEAP_tot += (n)
-\end{code}
-
-If we do a ``heap lookahead,'' we haven't really allocated any
-heap, so we need to undo the effects of an \tr{ALLOC_HEAP}:
-\begin{code}
-#define UN_ALLOC_HEAP(n) ALLOC_HEAP_ctr--; ALLOC_HEAP_tot -= (n)
-\end{code}
-
-\item
-The stack high-water marks. This is {\em direction-sensitive}!!
-(A stack grows downward, B stack upwards)
-\begin{code}
-#ifndef CONCURRENT
-#define DO_ASTK_HWM() if (SpA < max_SpA) { max_SpA = SpA; }
-#define DO_BSTK_HWM() if (SpB > max_SpB) { max_SpB = SpB; }
-#else
-/*
- * This is not direction sensitive, because we threads people are well-behaved.
- * However, it might be a good idea to cache the constant bits (DEP + BOT and
- * HWM) from the STKO and TSO in more readily accessible places. -- ToDo!
- */
-#define DO_ASTK_HWM() { \
- I_ depth = STKO_ADEP(StkOReg) + AREL((I_) STKO_ASTK_BOT(StkOReg) - (I_) SpA);\
- if (depth > TSO_AHWM(CurrentTSO)) \
- TSO_AHWM(CurrentTSO) = depth; \
-}
-#define DO_BSTK_HWM() { \
- I_ depth = STKO_BDEP(StkOReg) + BREL((I_) STKO_BSTK_BOT(StkOReg) - (I_) SpB);\
- if (depth > TSO_BHWM(CurrentTSO)) \
- TSO_BHWM(CurrentTSO) = depth; \
-}
-#endif
-\end{code}
-
-\item
-Re-use of stack slots, and stubbing of stack slots:
-\begin{code}
-#define A_STK_STUB(n) A_STK_STUB_ctr += (n)
-#define A_STK_REUSE(n) A_STK_REUSE_ctr += (n) /* not used at all? */
-#define B_STK_REUSE(n) B_STK_REUSE_ctr += (n) /* not used at all? */
-\end{code}
-\end{itemize}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-allocs]{Allocations}
-%* *
-%************************************************************************
-
-We count things every time we allocate something in the dynamic heap.
-For each, we count the number of words of (1)~``admin'' (header),
-(2)~good stuff (useful pointers and data), and (3)~``slop'' (extra
-space, in hopes it will allow an in-place update).
-
-The first five macros are inserted when the compiler generates code
-to allocate something; the categories correspond to the @ClosureClass@
-datatype (manifest functions, thunks, constructors, big tuples, and
-partial applications).
-\begin{code}
-#define ALLOC_FUN(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_FUN_ctr++; ALLOC_FUN_adm += (a); \
- ALLOC_FUN_gds += (g); ALLOC_FUN_slp += (s); \
- ALLOC_HISTO(FUN,a,g,s)
-#define ALLOC_THK(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_THK_ctr++; ALLOC_THK_adm += (a); \
- ALLOC_THK_gds += (g); ALLOC_THK_slp += (s); \
- ALLOC_HISTO(THK,a,g,s)
-#define ALLOC_CON(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_CON_ctr++; ALLOC_CON_adm += (a); \
- ALLOC_CON_gds += (g); ALLOC_CON_slp += (s); \
- ALLOC_HISTO(CON,a,g,s)
-#define ALLOC_TUP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_TUP_ctr++; ALLOC_TUP_adm += (a); \
- ALLOC_TUP_gds += (g); ALLOC_TUP_slp += (s); \
- ALLOC_HISTO(TUP,a,g,s)
-#define ALLOC_BH(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_BH_ctr++; ALLOC_BH_adm += (a); \
- ALLOC_BH_gds += (g); ALLOC_BH_slp += (s); \
- ALLOC_HISTO(BH,a,g,s)
-#if 0
-#define ALLOC_PAP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_PAP_ctr++; ALLOC_PAP_adm += (a); \
- ALLOC_PAP_gds += (g); ALLOC_PAP_slp += (s); \
- ALLOC_HISTO(PAP,a,g,s)
-#endif
-\end{code}
-
-We may also allocate space when we do an update, and there isn't
-enough space. These macros suffice (for: updating with a partial
-application and a constructor):
-\begin{code}
-#define ALLOC_UPD_PAP(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_UPD_PAP_ctr++; ALLOC_UPD_PAP_adm += (a); \
- ALLOC_UPD_PAP_gds += (g); ALLOC_UPD_PAP_slp += (s); \
- ALLOC_HISTO(UPD_PAP,a,g,s)
-#if 0
-#define ALLOC_UPD_CON(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_UPD_CON_ctr++; ALLOC_UPD_CON_adm += (a); \
- ALLOC_UPD_CON_gds += (g); ALLOC_UPD_CON_slp += (s); \
- ALLOC_HISTO(UPD_CON,a,g,s)
-#endif /* 0 */
-\end{code}
-
-In the threaded world, we allocate space for the spark pool, stack objects,
-and thread state objects.
-
-\begin{code}
-
-#define ALLOC_STK(a,g,s) ALLOC_STK_ctr++; ALLOC_STK_adm += (a); \
- ALLOC_STK_gds += (g); ALLOC_STK_slp += (s); \
- ALLOC_HISTO(STK,a,g,s)
-
-#define ALLOC_TSO(a,g,s) ALLOC_TSO_ctr++; ALLOC_TSO_adm += (a); \
- ALLOC_TSO_gds += (g); ALLOC_TSO_slp += (s); \
- ALLOC_HISTO(TSO,a,g,s)
-
-#define ALLOC_FMBQ(a,g,s) ALLOC_FMBQ_ctr++; ALLOC_FMBQ_adm += (a); \
- ALLOC_FMBQ_gds += (g); ALLOC_FMBQ_slp += (s); \
- ALLOC_HISTO(FMBQ,a,g,s)
-
-#define ALLOC_FME(a,g,s) ALLOC_FME_ctr++; ALLOC_FME_adm += (a); \
- ALLOC_FME_gds += (g); ALLOC_FME_slp += (s); \
- ALLOC_HISTO(FME,a,g,s)
-
-#define ALLOC_BF(a,g,s) ALLOC_BF_ctr++; ALLOC_BF_adm += (a); \
- ALLOC_BF_gds += (g); ALLOC_BF_slp += (s); \
- ALLOC_HISTO(BF,a,g,s)
-
-\end{code}
-
-The histogrammy bit is fairly straightforward; the \tr{-2} is: one for
-0-origin C arrays; the other one because we do {\em no} one-word
-allocations, so we would never inc that histogram slot; so we shift
-everything over by one.
-\begin{code}
-#define ALLOC_HISTO(categ,a,g,s) \
- { I_ __idx; \
- __idx = (a) + (g) + (s) - 2; \
- CAT3(ALLOC_,categ,_hst)[((__idx > 4) ? 4 : __idx)] += 1;}
-\end{code}
-
-Some hard-to-account-for words are allocated by/for primitives,
-includes Integer support. @ALLOC_PRIM2@ tells us about these. We
-count everything as ``goods'', which is not strictly correct.
-(@ALLOC_PRIM@ is the same sort of stuff, but we know the
-admin/goods/slop breakdown.)
-\begin{code}
-#define ALLOC_PRIM(a,g,s,t) ASSERT((t) == (a)+(g)+(s)); \
- ALLOC_PRIM_ctr++; ALLOC_PRIM_adm += (a); \
- ALLOC_PRIM_gds += (g); ALLOC_PRIM_slp += (s); \
- ALLOC_HISTO(PRIM,a,g,s)
-#define ALLOC_PRIM2(w) ALLOC_PRIM_ctr++; ALLOC_PRIM_gds +=(w); \
- ALLOC_HISTO(PRIM,0,w,0)
-\end{code}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-enters]{Enters}
-%* *
-%************************************************************************
-
-\begin{code}
-#define ENT_VIA_NODE() ENT_VIA_NODE_ctr++ /* via ENT_ macro */
-
-#define ENT_THK() ENT_THK_ctr++
-#define ENT_FUN_STD() ENT_FUN_STD_ctr++ /* manifest fun; std entry pt */
-
-#define ENT_CON(n) ENTERED_CHECK_UPDATED(n); ENT_CON_ctr++ /* enter code for constructor */
-#define ENT_IND(n) ENTERED_CHECK_UPDATED(n); ENT_IND_ctr++ /* enter indirection */
-#define ENT_PAP(n) ENTERED_CHECK_UPDATED(n); ENT_PAP_ctr++ /* enter partial application */
-\end{code}
-
-We do more magical things with @ENT_FUN_DIRECT@. Besides simply knowing
-how many ``fast-entry-point'' enters there were, we'd like {\em simple}
-information about where those enters were, and the properties thereof.
-\begin{code}
-struct ent_counter {
- unsigned registeredp:16, /* 0 == no, 1 == yes */
- arity:16, /* arity (static info) */
- Astk_args:16, /* # of args off A stack */
- Bstk_args:16; /* # of args off B stack */
- /* (rest of args are in registers) */
- StgChar *f_str; /* name of the thing */
- StgChar *f_arg_kinds; /* info about the args types */
- StgChar *wrap_str; /* name of its wrapper (if any) */
- StgChar *wrap_arg_kinds;/* info about the orig wrapper's arg types */
- I_ ctr; /* the actual counter */
- struct ent_counter *link; /* link to chain them all together */
-};
-
-/* OLD: extern void RegisterEntryPt PROTO((struct ent_counter *)); */
-extern struct ent_counter *ListOfEntryCtrs;
-
-#define ENT_FUN_DIRECT(f_ct,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
- static struct ent_counter f_ct \
- = { 0, \
- (f_arity), (Aargs), (Bargs), (f_str), (arg_kinds),\
- (wrap), (wrap_kinds), \
- 0, NULL }; \
- if ( ! f_ct.registeredp ) { \
- /* hook this one onto the front of the list */ \
- f_ct.link = ListOfEntryCtrs; \
- ListOfEntryCtrs = & (f_ct); \
- \
- /* mark it as "registered" */ \
- f_ct.registeredp = 1; \
- } \
- f_ct.ctr += 1; \
- ENT_FUN_DIRECT_ctr++ /* the old boring one */
-\end{code}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-returns]{Returns}
-%* *
-%************************************************************************
-
-Whenever a ``return'' occurs, it is returning the constituent parts of
-a data constructor. The parts can be returned either in registers, or
-by allocating some heap to put it in (the @ALLOC_*@ macros account for
-the allocation). The constructor can either be an existing one
-(\tr{*OLD*}) or we could have {\em just} figured out this stuff
-(\tr{*NEW*}).
-
-Here's some special magic that Simon wants [edited to match names
-actually used]:
-\begin{display}
-From: Simon L Peyton Jones <simonpj>
-To: partain, simonpj
-Subject: counting updates
-Date: Wed, 25 Mar 92 08:39:48 +0000
-
-I'd like to count how many times we update in place when actually Node
-points to the thing. Here's how:
-
-\tr{RET_OLD_IN_REGS} sets the variable \tr{ReturnInRegsNodeValid} to \tr{True};
-\tr{RET_NEW_IN_REGS} sets it to \tr{False}.
-
-\tr{RET_SEMI_???} sets it to??? ToDo [WDP]
-
-\tr{UPD_CON_IN_PLACE} tests the variable, and increments \tr{UPD_IN_PLACE_COPY_ctr}
-if it is true.
-
-Then we need to report it along with the update-in-place info.
-\end{display}
-
-\begin{code}
-#define RET_NEW_IN_HEAP() RET_NEW_IN_HEAP_ctr++
-#define RET_OLD_IN_HEAP() RET_OLD_IN_HEAP_ctr++
-
-#define RET_NEW_IN_REGS() RET_NEW_IN_REGS_ctr++; \
- ReturnInRegsNodeValid = 0
-#define RET_OLD_IN_REGS() RET_OLD_IN_REGS_ctr++; \
- ReturnInRegsNodeValid = 1
-
-#define RET_SEMI_BY_DEFAULT() RET_SEMI_BY_DEFAULT_ctr++
-#define RET_SEMI_IN_HEAP() RET_SEMI_IN_HEAP_ctr++
-#define RET_SEMI_IN_REGS() RET_SEMI_IN_REGS_ctr++
-\end{code}
-
-Of all the returns (sum of four categories above), how many were
-vectored? (The rest were obviously unvectored).
-\begin{code}
-#define VEC_RETURN() VEC_RETURN_ctr++
-\end{code}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-update-frames]{Update frames}
-%* *
-%************************************************************************
-
-These macros count up the following update information.
-
-%partain:\begin{center}
-\begin{tabular}{ll} \hline
-Macro & Counts \\ \hline
- & \\
-\tr{UPDF_STD_PUSHED} & Update frame pushed \\
-\tr{UPDF_CON_PUSHED} & Constructor update frame pushed \\
-\tr{UPDF_HOLE_PUSHED} & An update frame to update a black hole \\
-\tr{UPDF_OMITTED} & A thunk decided not to push an update frame \\
- & (all subsets of \tr{ENT_THK}) \\
-\tr{UPDF_RCC_PUSHED} & Cost Centre restore frame pushed \\
-\tr{UPDF_RCC_OMITTED} & Cost Centres not required -- not pushed \\\hline
-\end{tabular}
-%partain:\end{center}
-
-\begin{code}
-#define UPDF_OMITTED() UPDF_OMITTED_ctr++
-
-#define UPDF_STD_PUSHED() UPDF_STD_PUSHED_ctr++
-#define UPDF_CON_PUSHED() UPDF_CON_PUSHED_ctr++
-#define UPDF_HOLE_PUSHED() UPDF_HOLE_PUSHED_ctr++
-
-#define UPDF_RCC_PUSHED() UPDF_RCC_PUSHED_ctr++
-#define UPDF_RCC_OMITTED() UPDF_RCC_OMITTED_ctr++
-\end{code}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-updates]{Updates}
-%* *
-%************************************************************************
-
-These macros record information when we do an update. We always
-update either with a data constructor (CON) or a partial application
-(PAP).
-
-%partain:\begin{center}
-\begin{tabular}{|l|l|}\hline
-Macro & Where \\ \hline
- & \\
-\tr{UPD_EXISTING} & Updating with an indirection to something \\
- & already in the heap \\
-
-\tr{UPD_CON_W_NODE} & Updating with a CON: by indirecting to Node \\
-
-\tr{UPD_CON_IN_PLACE} & Ditto, but in place \\
-\tr{UPD_CON_IN_NEW} & Ditto, but allocating the object \\
-
-\tr{UPD_PAP_IN_PLACE} & Same, but updating w/ a PAP \\
-\tr{UPD_PAP_IN_NEW} & \\\hline
-\end{tabular}
-%partain:\end{center}
-
-\begin{code}
-#define UPD_EXISTING() UPD_EXISTING_ctr++
-
-#define UPD_CON_W_NODE() UPD_CON_W_NODE_ctr++
-
-#define UPD_CON_IN_NEW() UPD_CON_IN_NEW_ctr++
-#define UPD_PAP_IN_NEW() UPD_PAP_IN_NEW_ctr++
-/* ToDo: UPD_NEW_COPY_ctr, as below */
-
-#define UPD_CON_IN_PLACE() UPD_CON_IN_PLACE_ctr++ ; \
- UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid
- /* increments if True; otherwise, no */
-#define UPD_PAP_IN_PLACE() UPD_PAP_IN_PLACE_ctr++ ; \
- UPD_IN_PLACE_COPY_ctr += ReturnInRegsNodeValid
- /* increments if True; otherwise, no */
-\end{code}
-
-For a generational collector:
-\begin{code}
-#define UPD_NEW_IND() UPD_NEW_IND_ctr++;
-#define UPD_NEW_IN_PLACE_PTRS() UPD_NEW_IN_PLACE_PTRS_ctr++;
-#define UPD_NEW_IN_PLACE_NOPTRS() UPD_NEW_IN_PLACE_NOPTRS_ctr++;
-#define UPD_OLD_IND() UPD_OLD_IND_ctr++;
-#define UPD_OLD_IN_PLACE_PTRS() UPD_OLD_IN_PLACE_PTRS_ctr++;
-#define UPD_OLD_IN_PLACE_NOPTRS() UPD_OLD_IN_PLACE_NOPTRS_ctr++;
-\end{code}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-updates-entered]{Updates Subsequently Entered}
-%* *
-%************************************************************************
-
-If @UPDATES_ENTERED_COUNT@ is defined we add the Age word to the
-closures. This is used to record indicate if a closure has been
-updated but not yet entered. It is set when the closure is updated and
-cleared when subsequently entered.
-
-The commoning up of @CONST@, @CHARLIKE@ and @INTLIKE@ closures is
-turned if this is required. This has only been done for 2s collection.
-It is done using a nasty hack which defines the @_Evacuate@ and
-@_Scavenge@ code for @CONST@, @CHARLIKE@ and @INTLIKE@ info tables to
-be @_Evacuate_1@ and @_Scavenge_1_0@.
-
-Unfortunately this broke everything so it has not been done ;-(.
-Instead we have to run with enough heap so no garbage collection is
-needed for accurate numbers. ToDo: Fix this!
-
-As implemented it can not be used in conjunction with heap profiling
-or lifetime profiling becasue they make conflicting use the Age word!
-
-\begin{code}
-#if defined(UPDATES_ENTERED_COUNT)
-
-#define UPDATED_SET_UPDATED(n) AGE_HDR(n) = 1
-
-#define ENTERED_CHECK_UPDATED(n) \
- if (AGE_HDR(n)) { \
- if (AGE_HDR(n) == 1) { \
- UPD_ENTERED_ctr++; \
- AGE_HDR(n) += 1; \
- } else { \
- UPD_ENTERED_AGAIN_ctr++; \
- AGE_HDR(n) = 0; \
- }}
-
-#else /* ! UPDATES_ENTERED_COUNT */
-
-#define UPDATED_SET_UPDATED(n) /* nothing */
-#define ENTERED_CHECK_UPDATED(n) /* nothing */
-
-#endif /* ! UPDATES_ENTERED_COUNT */
-\end{code}
-
-%************************************************************************
-%* *
-\subsubsection[ticky-counters]{The accumulators (extern decls)}
-%* *
-%************************************************************************
-
-\begin{code}
-extern I_ ALLOC_HEAP_ctr;
-extern I_ ALLOC_HEAP_tot;
-
-extern PP_ max_SpA;
-extern P_ max_SpB;
-
-extern I_ A_STK_STUB_ctr;
-/* not used at all?
-extern I_ A_STK_REUSE_ctr;
-extern I_ B_STK_REUSE_ctr;
-*/
-
-extern I_ ALLOC_FUN_ctr;
-extern I_ ALLOC_FUN_adm;
-extern I_ ALLOC_FUN_gds;
-extern I_ ALLOC_FUN_slp;
-extern I_ ALLOC_FUN_hst[5];
-extern I_ ALLOC_THK_ctr;
-extern I_ ALLOC_THK_adm;
-extern I_ ALLOC_THK_gds;
-extern I_ ALLOC_THK_slp;
-extern I_ ALLOC_THK_hst[5];
-extern I_ ALLOC_CON_ctr;
-extern I_ ALLOC_CON_adm;
-extern I_ ALLOC_CON_gds;
-extern I_ ALLOC_CON_slp;
-extern I_ ALLOC_CON_hst[5];
-extern I_ ALLOC_TUP_ctr;
-extern I_ ALLOC_TUP_adm;
-extern I_ ALLOC_TUP_gds;
-extern I_ ALLOC_TUP_slp;
-extern I_ ALLOC_TUP_hst[5];
-extern I_ ALLOC_BH_ctr;
-extern I_ ALLOC_BH_adm;
-extern I_ ALLOC_BH_gds;
-extern I_ ALLOC_BH_slp;
-extern I_ ALLOC_BH_hst[5];
-/*
-extern I_ ALLOC_PAP_ctr;
-extern I_ ALLOC_PAP_adm;
-extern I_ ALLOC_PAP_gds;
-extern I_ ALLOC_PAP_slp;
-extern I_ ALLOC_PAP_hst[5];
-*/
-/*
-extern I_ ALLOC_UPD_CON_ctr;
-extern I_ ALLOC_UPD_CON_adm;
-extern I_ ALLOC_UPD_CON_gds;
-extern I_ ALLOC_UPD_CON_slp;
-extern I_ ALLOC_UPD_CON_hst[5];
-*/
-extern I_ ALLOC_UPD_PAP_ctr;
-extern I_ ALLOC_UPD_PAP_adm;
-extern I_ ALLOC_UPD_PAP_gds;
-extern I_ ALLOC_UPD_PAP_slp;
-extern I_ ALLOC_UPD_PAP_hst[5];
-extern I_ ALLOC_PRIM_ctr;
-extern I_ ALLOC_PRIM_adm;
-extern I_ ALLOC_PRIM_gds;
-extern I_ ALLOC_PRIM_slp;
-extern I_ ALLOC_PRIM_hst[5];
-
-#ifdef CONCURRENT
-extern I_ ALLOC_STK_ctr;
-extern I_ ALLOC_STK_adm;
-extern I_ ALLOC_STK_gds;
-extern I_ ALLOC_STK_slp;
-extern I_ ALLOC_STK_hst[5];
-extern I_ ALLOC_TSO_ctr;
-extern I_ ALLOC_TSO_adm;
-extern I_ ALLOC_TSO_gds;
-extern I_ ALLOC_TSO_slp;
-extern I_ ALLOC_TSO_hst[5];
-#ifdef PAR
-extern I_ ALLOC_FMBQ_ctr;
-extern I_ ALLOC_FMBQ_adm;
-extern I_ ALLOC_FMBQ_gds;
-extern I_ ALLOC_FMBQ_slp;
-extern I_ ALLOC_FMBQ_hst[5];
-extern I_ ALLOC_FME_ctr;
-extern I_ ALLOC_FME_adm;
-extern I_ ALLOC_FME_gds;
-extern I_ ALLOC_FME_slp;
-extern I_ ALLOC_FME_hst[5];
-extern I_ ALLOC_BF_ctr;
-extern I_ ALLOC_BF_adm;
-extern I_ ALLOC_BF_gds;
-extern I_ ALLOC_BF_slp;
-extern I_ ALLOC_BF_hst[5];
-#endif
-#endif
-
-extern I_ ENT_VIA_NODE_ctr;
-
-extern I_ ENT_CON_ctr;
-extern I_ ENT_FUN_STD_ctr;
-extern I_ ENT_FUN_DIRECT_ctr;
-extern I_ ENT_IND_ctr;
-extern I_ ENT_PAP_ctr;
-extern I_ ENT_THK_ctr;
-
-extern I_ UPD_ENTERED_ctr;
-extern I_ UPD_ENTERED_AGAIN_ctr;
-
-extern I_ RET_NEW_IN_HEAP_ctr;
-extern I_ RET_NEW_IN_REGS_ctr;
-extern I_ RET_OLD_IN_HEAP_ctr;
-extern I_ RET_OLD_IN_REGS_ctr;
-extern I_ RET_SEMI_BY_DEFAULT_ctr;
-extern I_ RET_SEMI_IN_HEAP_ctr;
-extern I_ RET_SEMI_IN_REGS_ctr;
-extern I_ VEC_RETURN_ctr;
-
-extern I_ ReturnInRegsNodeValid; /* see below */
-
-extern I_ UPDF_OMITTED_ctr;
-extern I_ UPDF_STD_PUSHED_ctr;
-extern I_ UPDF_CON_PUSHED_ctr;
-extern I_ UPDF_HOLE_PUSHED_ctr;
-
-extern I_ UPDF_RCC_PUSHED_ctr;
-extern I_ UPDF_RCC_OMITTED_ctr;
-
-extern I_ UPD_EXISTING_ctr;
-extern I_ UPD_CON_W_NODE_ctr;
-extern I_ UPD_CON_IN_PLACE_ctr;
-extern I_ UPD_PAP_IN_PLACE_ctr;
-extern I_ UPD_CON_IN_NEW_ctr;
-extern I_ UPD_PAP_IN_NEW_ctr;
-
-extern I_ UPD_NEW_IND_ctr;
-extern I_ UPD_NEW_IN_PLACE_PTRS_ctr;
-extern I_ UPD_NEW_IN_PLACE_NOPTRS_ctr;
-extern I_ UPD_OLD_IND_ctr;
-extern I_ UPD_OLD_IN_PLACE_PTRS_ctr;
-extern I_ UPD_OLD_IN_PLACE_NOPTRS_ctr;
-
-extern I_ UPD_IN_PLACE_COPY_ctr; /* see below */
-
-#endif /* DO_REDN_COUNTING */
-\end{code}
-
-%************************************************************************
-%* *
-\subsection[RednCounts-nonmacros]{Un-macros for ``none of the above''}
-%* *
-%************************************************************************
-
-\begin{code}
-#if ! (defined(DO_SPAT_PROFILING) || defined(DO_REDN_COUNTING))
-
-#define SET_ACTIVITY(act) /* nothing */
-
-#define ALLOC_HEAP(n) /* nothing */
-#define UN_ALLOC_HEAP(n) /* nothing */
-#define DO_ASTK_HWM() /* nothing */
-#define DO_BSTK_HWM() /* nothing */
-
-#define A_STK_STUB(n) /* nothing */
-#define A_STK_REUSE(n) /* not used at all */
-#define B_STK_REUSE(n) /* not used at all */
-
-#define ALLOC_FUN(a,g,s,t) /* nothing */
-#define ALLOC_THK(a,g,s,t) /* nothing */
-#define ALLOC_CON(a,g,s,t) /* nothing */
-#define ALLOC_TUP(a,g,s,t) /* nothing */
-#define ALLOC_BH(a,g,s,t) /* nothing */
-/*#define ALLOC_PAP(a,g,s,t) /? nothing */
-#define ALLOC_PRIM(a,g,s,t) /* nothing */
-#define ALLOC_PRIM2(w) /* nothing */
-#define ALLOC_UPD_PAP(a,g,s,t) /* nothing */
-/*#define ALLOC_UPD_CON(a,g,s,t) /? nothing */
-#define ALLOC_STK(a,g,s) /* nothing */
-#define ALLOC_TSO(a,g,s) /* nothing */
-#define ALLOC_FMBQ(a,g,s) /* nothing */
-#define ALLOC_FME(a,g,s) /* nothing */
-#define ALLOC_BF(a,g,s) /* nothing */
-
-#define ENT_VIA_NODE() /* nothing */
-#define ENT_THK() /* nothing */
-#define ENT_FUN_STD() /* nothing */
-#define ENT_FUN_DIRECT(f,f_str,f_arity,Aargs,Bargs,arg_kinds,wrap,wrap_kinds) \
- /* nothing */
-#define ENT_CON(n) /* nothing */
-#define ENT_IND(n) /* nothing */
-#define ENT_PAP(n) /* nothing */
-
-#define RET_NEW_IN_HEAP() /* nothing */
-#define RET_NEW_IN_REGS() /* nothing */
-#define RET_OLD_IN_HEAP() /* nothing */
-#define RET_OLD_IN_REGS() /* nothing */
-#define RET_SEMI_BY_DEFAULT() /* nothing */
-#define RET_SEMI_IN_HEAP() /* nothing */
-#define RET_SEMI_IN_REGS() /* nothing */
-#define VEC_RETURN() /* nothing */
-
-#define UPDF_OMITTED() /* nothing */
-#define UPDF_STD_PUSHED() /* nothing */
-#define UPDF_CON_PUSHED() /* nothing */
-#define UPDF_HOLE_PUSHED() /* nothing */
-
-#define UPDF_RCC_PUSHED() /* nothing */
-#define UPDF_RCC_OMITTED() /* nothing */
-
-#define UPD_EXISTING() /* nothing */
-#define UPD_CON_W_NODE() /* nothing */
-#define UPD_CON_IN_PLACE() /* nothing */
-#define UPD_PAP_IN_PLACE() /* nothing */
-#define UPD_CON_IN_NEW() /* nothing */
-#define UPD_PAP_IN_NEW() /* nothing */
-\end{code}
-
-For special subsequent enter counting:
-\begin{code}
-#define UPDATED_SET_UPDATED(n) /* nothing */
-#define ENTERED_CHECK_UPDATED(n) /* nothing */
-\end{code}
-
-For a generational collector:
-\begin{code}
-#define UPD_NEW_IND() /* nothing */
-#define UPD_NEW_IN_PLACE_PTRS() /* nothing */
-#define UPD_NEW_IN_PLACE_NOPTRS() /* nothing */
-#define UPD_OLD_IND() /* nothing */
-#define UPD_OLD_IN_PLACE_PTRS() /* nothing */
-#define UPD_OLD_IN_PLACE_NOPTRS() /* nothing */
-
-#endif /* <none-of-the-above> */
-\end{code}
-
-End of file multi-slurp protection:
-\begin{code}
-#endif /* ! REDNCOUNTS_H */
-\end{code}