From: simonm Date: Thu, 21 Jan 1999 10:31:57 +0000 (+0000) Subject: [project @ 1999-01-21 10:31:41 by simonm] X-Git-Tag: Approx_2487_patches~32 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=ec48c5ab896b9334fa8d747c0a542e0679fe3a8f;p=ghc-hetmet.git [project @ 1999-01-21 10:31:41 by simonm] Resurrect ticky-ticky profiling. Not quite polished yet, but it compiles and produces some reasonable-looking stats. --- diff --git a/ghc/compiler/codeGen/CgClosure.lhs b/ghc/compiler/codeGen/CgClosure.lhs index 12bbf02..6721172 100644 --- a/ghc/compiler/codeGen/CgClosure.lhs +++ b/ghc/compiler/codeGen/CgClosure.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgClosure.lhs,v 1.22 1999/01/15 15:57:36 simonm Exp $ +% $Id: CgClosure.lhs,v 1.23 1999/01/21 10:31:55 simonm Exp $ % \section[CgClosure]{Code generation for closures} @@ -371,12 +371,15 @@ closureCodeBody binder_info srt closure_info cc all_args body fast_entry_code = profCtrC SLIT("TICK_ENT_FUN_DIRECT") [ - CLbl (mkRednCountsLabel name) PtrRep, + mkIntCLit stg_arity -- total # of args + + {- CLbl (mkRednCountsLabel name) PtrRep, CString (_PK_ (showSDoc (ppr name))), mkIntCLit stg_arity, -- total # of args mkIntCLit sp_stk_args, -- # passed on stk CString (_PK_ (map (showTypeCategory . idType) all_args)), CString SLIT(""), CString SLIT("") + -} -- Nuked for now; see comment at end of file -- CString (_PK_ (show_wrapper_name wrapper_maybe)), diff --git a/ghc/compiler/codeGen/CgCon.lhs b/ghc/compiler/codeGen/CgCon.lhs index 1d71cd0..0a9a76d 100644 --- a/ghc/compiler/codeGen/CgCon.lhs +++ b/ghc/compiler/codeGen/CgCon.lhs @@ -344,6 +344,7 @@ cgReturnDataCon con amodes all_zero_size_args ASSERT(not (isUnboxedTupleCon con)) buildDynCon binder currentCCS con amodes all_zero_size_args `thenFC` \ idinfo -> + profCtrC SLIT("TICK_RET_NEW") [mkIntCLit (length amodes)] `thenC` idInfoToAmode PtrRep idinfo `thenFC` \ amode -> performReturn (move_to_reg amode node) jump_to_join_point @@ -361,6 +362,9 @@ cgReturnDataCon con amodes all_zero_size_args let (ret_regs, leftovers) = assignRegs [] (map getAmodeRep amodes) in + profCtrC SLIT("TICK_RET_UNBOXED_TUP") + [mkIntCLit (length amodes)] `thenC` + doTailCall amodes ret_regs mkUnboxedTupleReturnCode (length leftovers) {- fast args arity -} @@ -385,7 +389,7 @@ cgReturnDataCon con amodes all_zero_size_args -- RETURN - profCtrC SLIT("TICK_RET_CON") [mkIntCLit (length amodes)] `thenC` + profCtrC SLIT("TICK_RET_NEW") [mkIntCLit (length amodes)] `thenC` -- could use doTailCall here. performReturn (move_to_reg amode node) (mkStaticAlgReturnCode con) diff --git a/ghc/compiler/codeGen/CgHeapery.lhs b/ghc/compiler/codeGen/CgHeapery.lhs index 6209ac6..f1a0ef2 100644 --- a/ghc/compiler/codeGen/CgHeapery.lhs +++ b/ghc/compiler/codeGen/CgHeapery.lhs @@ -1,14 +1,14 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgHeapery.lhs,v 1.11 1998/12/18 17:40:51 simonpj Exp $ +% $Id: CgHeapery.lhs,v 1.12 1999/01/21 10:31:56 simonm Exp $ % \section[CgHeapery]{Heap management functions} \begin{code} module CgHeapery ( fastEntryChecks, altHeapCheck, thunkChecks, - allocHeap, allocDynClosure + allocDynClosure -- new functions, basically inserting macro calls into Code -- HWL ,fetchAndReschedule, yield @@ -436,10 +436,8 @@ allocDynClosure closure_info use_cc blame_cc amodes_with_offsets in -- SAY WHAT WE ARE ABOUT TO DO profCtrC (allocProfilingMsg closure_info) - [mkIntCLit fixedHdrSize, - mkIntCLit (closureGoodStuffSize closure_info), - mkIntCLit slop_size, - mkIntCLit closure_size] `thenC` + [mkIntCLit (closureGoodStuffSize closure_info), + mkIntCLit slop_size] `thenC` -- GENERATE THE CODE absC ( mkAbstractCs ( @@ -468,27 +466,3 @@ cInitHdr closure_info amode cc | otherwise = CInitHdr closure_info amode (panic "absent cc") \end{code} - -%************************************************************************ -%* * -\subsection{Allocate uninitialized heap space} -%* * -%************************************************************************ - -\begin{code} -allocHeap :: HeapOffset -- Size of the space required - -> FCode CAddrMode -- Addr mode for first word of object - -allocHeap space - = getVirtAndRealHp `thenFC` \ (virtHp, realHp) -> - let block_start = virtHp + 1 - in - -- We charge the allocation to "PRIM" (which is probably right) - profCtrC SLIT("ALLOC_PRIM2") [mkIntCLit space] `thenC` - - -- BUMP THE VIRTUAL HEAP POINTER - setVirtHp (virtHp + space) `thenC` - - -- RETURN PTR TO START OF OBJECT - returnFC (CAddr (hpRel realHp block_start)) -\end{code} diff --git a/ghc/compiler/codeGen/CgTailCall.lhs b/ghc/compiler/codeGen/CgTailCall.lhs index 772d2fe..b6953b1 100644 --- a/ghc/compiler/codeGen/CgTailCall.lhs +++ b/ghc/compiler/codeGen/CgTailCall.lhs @@ -1,7 +1,7 @@ % % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 % -% $Id: CgTailCall.lhs,v 1.17 1998/12/18 17:40:53 simonpj Exp $ +% $Id: CgTailCall.lhs,v 1.18 1999/01/21 10:31:57 simonm Exp $ % %******************************************************** %* * @@ -307,6 +307,8 @@ returnUnboxedTuple amodes before_jump let (ret_regs, leftovers) = assignRegs [] (map getAmodeRep amodes) in + profCtrC SLIT("TICK_RET_UNBOXED_TUP") [mkIntCLit (length amodes)] `thenC` + doTailCall amodes ret_regs mkUnboxedTupleReturnCode (length leftovers) {- fast args arity -} diff --git a/ghc/includes/Constants.h b/ghc/includes/Constants.h index c521b76..d970160 100644 --- a/ghc/includes/Constants.h +++ b/ghc/includes/Constants.h @@ -1,5 +1,5 @@ /* ---------------------------------------------------------------------------- - * $Id: Constants.h,v 1.2 1998/12/02 13:21:03 simonm Exp $ + * $Id: Constants.h,v 1.3 1999/01/21 10:31:41 simonm Exp $ * * Constants * @@ -21,7 +21,7 @@ #define STD_HDR_SIZE 1 #define PROF_HDR_SIZE 1 #define GRAN_HDR_SIZE 1 -#define TICKY_HDR_SIZE 1 +#define TICKY_HDR_SIZE 0 #define ARR_HDR_SIZE 1 @@ -33,13 +33,13 @@ NOTE: keep these in line with the real definitions in InfoTables.h - NOTE: the PROF, GRAN and TICKY values are *wrong* (ToDo) + NOTE: the PROF, and GRAN values are *wrong* (ToDo) -------------------------------------------------------------------------- */ #define STD_ITBL_SIZE 3 #define PROF_ITBL_SIZE 1 #define GRAN_ITBL_SIZE 1 -#define TICKY_ITBL_SIZE 1 +#define TICKY_ITBL_SIZE 0 /* ----------------------------------------------------------------------------- Minimum closure sizes diff --git a/ghc/includes/PrimOps.h b/ghc/includes/PrimOps.h index 1664303..58f2df0 100644 --- a/ghc/includes/PrimOps.h +++ b/ghc/includes/PrimOps.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: PrimOps.h,v 1.7 1999/01/19 09:49:55 simonm Exp $ + * $Id: PrimOps.h,v 1.8 1999/01/21 10:31:42 simonm Exp $ * * Macros for primitive operations in STG-ish C code. * @@ -278,7 +278,7 @@ typedef union { arg2._mp_size = (s2); \ arg2._mp_d = (unsigned long int *) (BYTE_ARR_CTS(d2)); \ \ - (r) = RET_PRIM_STGCALL2(I_,mpz_cmp,&arg1,&arg2); \ + (r) = RET_PRIM_STGCALL2(I_,mpz_cmp,&arg1,&arg2); \ } /* A glorious hack: calling mpz_neg would entail allocation and diff --git a/ghc/includes/Rts.h b/ghc/includes/Rts.h index 3f7d868..45f66cf 100644 --- a/ghc/includes/Rts.h +++ b/ghc/includes/Rts.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Rts.h,v 1.3 1999/01/13 17:25:54 simonm Exp $ + * $Id: Rts.h,v 1.4 1999/01/21 10:31:43 simonm Exp $ * * Top-level include file for the RTS itself * @@ -46,20 +46,6 @@ typedef enum { -------------------------------------------------------------------------- */ #ifndef DEBUG -#define ASSERT(predicate) /* nothing */ -#else - -void _stgAssert (char *, unsigned int); - -#define ASSERT(predicate) \ - if (predicate) \ - /*null*/; \ - else \ - _stgAssert(__FILE__, __LINE__) - -#endif /* DEBUG */ - -#ifndef DEBUG #define IF_DEBUG(c,s) doNothing() #else #define IF_DEBUG(c,s) if (RtsFlags.DebugFlags.c) { s; } diff --git a/ghc/includes/Stg.h b/ghc/includes/Stg.h index 12ccdbe..555c7b1 100644 --- a/ghc/includes/Stg.h +++ b/ghc/includes/Stg.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Stg.h,v 1.3 1999/01/18 14:37:43 sof Exp $ + * $Id: Stg.h,v 1.4 1999/01/21 10:31:43 simonm Exp $ * * Top-level include file for everything STG-ish. * @@ -90,7 +90,7 @@ #include "StgProf.h" #include "PrimOps.h" #include "Updates.h" -#include "Ticky.h" +#include "StgTicky.h" #include "CCall.h" /* Built-in entry points */ @@ -106,10 +106,27 @@ extern int prog_argc; extern char **environ; /* Creating and destroying an adjustor thunk. - I cannot make myself creating a separate .h file + I cannot make myself create a separate .h file for these two (sof.) */ extern void* createAdjustor(int cconv, StgStablePtr hptr, StgFunPtr wptr); extern void freeHaskellFunctionPtr(void* ptr); +/* ----------------------------------------------------------------------------- + Assertions and Debuggery + -------------------------------------------------------------------------- */ + +#ifndef DEBUG +#define ASSERT(predicate) /* nothing */ +#else + +void _stgAssert (char *, unsigned int); + +#define ASSERT(predicate) \ + if (predicate) \ + /*null*/; \ + else \ + _stgAssert(__FILE__, __LINE__) +#endif /* DEBUG */ + #endif /* STG_H */ diff --git a/ghc/includes/StgMacros.h b/ghc/includes/StgMacros.h index 07e5e5f..d17d4ad 100644 --- a/ghc/includes/StgMacros.h +++ b/ghc/includes/StgMacros.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: StgMacros.h,v 1.2 1998/12/02 13:21:35 simonm Exp $ + * $Id: StgMacros.h,v 1.3 1999/01/21 10:31:43 simonm Exp $ * * Macros used for writing STG-ish C code. * @@ -156,17 +156,19 @@ static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; } if ((Hp += headroom) > HpLim) { \ EXTFUN(stg_chk_##layout); \ tag_assts \ - (r) = (P_)ret; \ + (r) = (P_)ret; \ JMP_(stg_chk_##layout); \ - } + } \ + TICK_ALLOC_HEAP(headroom); #define HP_STK_CHK(stk_headroom,hp_headroom,ret,r,layout,tag_assts) \ if (Sp - stk_headroom < SpLim || (Hp += hp_headroom) > HpLim) { \ EXTFUN(stg_chk_##layout); \ tag_assts \ - (r) = (P_)ret; \ + (r) = (P_)ret; \ JMP_(stg_chk_##layout); \ - } + } \ + TICK_ALLOC_HEAP(hp_headroom); /* ----------------------------------------------------------------------------- A Heap Check in a case alternative are much simpler: everything is @@ -195,21 +197,24 @@ static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; } EXTFUN(stg_gc_enter_##ptrs); \ tag_assts \ JMP_(stg_gc_enter_##ptrs); \ - } + } \ + TICK_ALLOC_HEAP(headroom); #define HP_CHK_SEQ_NP(headroom,ptrs,tag_assts) \ if ((Hp += (headroom)) > HpLim) { \ EXTFUN(stg_gc_seq_##ptrs); \ tag_assts \ JMP_(stg_gc_seq_##ptrs); \ - } + } \ + TICK_ALLOC_HEAP(headroom); #define HP_STK_CHK_NP(stk_headroom, hp_headroom, ptrs, tag_assts) \ if ((Sp - (stk_headroom)) < SpLim || (Hp += (hp_headroom)) > HpLim) { \ EXTFUN(stg_gc_enter_##ptrs); \ tag_assts \ JMP_(stg_gc_enter_##ptrs); \ - } + } \ + TICK_ALLOC_HEAP(hp_headroom); /* Heap checks for branches of a primitive case / unboxed tuple return */ @@ -218,7 +223,8 @@ static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; } EXTFUN(lbl); \ tag_assts \ JMP_(lbl); \ - } + } \ + TICK_ALLOC_HEAP(headroom); #define HP_CHK_NOREGS(headroom,tag_assts) \ GEN_HP_CHK_ALT(headroom,stg_gc_noregs,tag_assts); @@ -295,30 +301,32 @@ static inline int IS_ARG_TAG( StgWord p ) { return p <= ARGTAG_MAX; } #define R7_PTR 1<<6 #define R8_PTR 1<<7 -#define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \ - if ((Hp += (headroom)) > HpLim ) { \ - EF_(stg_gen_chk); \ - tag_assts \ - R9.w = (W_)LIVENESS_MASK(liveness); \ - R10.w = (W_)reentry; \ - JMP_(stg_gen_chk); \ - } - -#define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \ - if ((Sp - (headroom)) < SpLim) { \ - EF_(stg_gen_chk); \ - tag_assts \ - R9.w = (W_)LIVENESS_MASK(liveness); \ - R10.w = (W_)reentry; \ - JMP_(stg_gen_chk); \ - } - -#define MAYBE_GC(liveness,reentry) \ - if (doYouWantToGC()) { \ - EF_(stg_gen_hp); \ - R9.w = (W_)LIVENESS_MASK(liveness); \ - R10.w = (W_)reentry; \ - JMP_(stg_gen_hp); \ +#define HP_CHK_GEN(headroom,liveness,reentry,tag_assts) \ + if ((Hp += (headroom)) > HpLim ) { \ + EF_(stg_gen_chk); \ + tag_assts \ + R9.w = (W_)LIVENESS_MASK(liveness); \ + R10.w = (W_)reentry; \ + JMP_(stg_gen_chk); \ + } \ + TICK_ALLOC_HEAP(headroom); + +#define STK_CHK_GEN(headroom,liveness,reentry,tag_assts) \ + if ((Sp - (headroom)) < SpLim) { \ + EF_(stg_gen_chk); \ + tag_assts \ + R9.w = (W_)LIVENESS_MASK(liveness); \ + R10.w = (W_)reentry; \ + JMP_(stg_gen_chk); \ + } \ + TICK_ALLOC_HEAP(headroom); + +#define MAYBE_GC(liveness,reentry) \ + if (doYouWantToGC()) { \ + EF_(stg_gen_hp); \ + R9.w = (W_)LIVENESS_MASK(liveness); \ + R10.w = (W_)reentry; \ + JMP_(stg_gen_hp); \ } /* ----------------------------------------------------------------------------- diff --git a/ghc/includes/StgTicky.h b/ghc/includes/StgTicky.h new file mode 100644 index 0000000..fe756a1 --- /dev/null +++ b/ghc/includes/StgTicky.h @@ -0,0 +1,528 @@ +/* ---------------------------------------------------------------------------- + * $Id: StgTicky.h,v 1.1 1999/01/21 10:31:44 simonm Exp $ + * + * Ticky-ticky profiling macros. + * + * -------------------------------------------------------------------------- */ + +#ifndef TICKY_H +#define TICKY_H + +#ifdef TICKY_TICKY + +/* ----------------------------------------------------------------------------- + Allocations + -------------------------------------------------------------------------- */ + +/* 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: + */ +#define TICK_ALLOC_HEAP(n) ALLOC_HEAP_ctr++; ALLOC_HEAP_tot += (n) + +/* 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, to leave room for an old generation indirection for example). + * + * 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). + */ + +#define _HS sizeofW(StgHeader) + +#define TICK_ALLOC_FUN(g,s) \ + ALLOC_FUN_ctr++; ALLOC_FUN_adm += _HS; \ + ALLOC_FUN_gds += (g); ALLOC_FUN_slp += (s); \ + TICK_ALLOC_HISTO(FUN,_HS,g,s) + +#define TICK_ALLOC_THK(g,s) \ + ALLOC_THK_ctr++; ALLOC_THK_adm += _HS; \ + ALLOC_THK_gds += (g); ALLOC_THK_slp += (s); \ + TICK_ALLOC_HISTO(THK,_HS,g,s) + +#define TICK_ALLOC_CON(g,s) \ + ALLOC_CON_ctr++; ALLOC_CON_adm += _HS; \ + ALLOC_CON_gds += (g); ALLOC_CON_slp += (s); \ + TICK_ALLOC_HISTO(CON,_HS,g,s) + +#define TICK_ALLOC_TUP(g,s) \ + ALLOC_TUP_ctr++; ALLOC_TUP_adm += _HS; \ + ALLOC_TUP_gds += (g); ALLOC_TUP_slp += (s); \ + TICK_ALLOC_HISTO(TUP,_HS,g,s) + +#define TICK_ALLOC_BH(g,s) \ + ALLOC_BH_ctr++; ALLOC_BH_adm += _HS; \ + ALLOC_BH_gds += (g); ALLOC_BH_slp += (s); \ + TICK_ALLOC_HISTO(BH,_HS,g,s) + +#define TICK_ALLOC_UPD_PAP(g,s) \ + ALLOC_UPD_PAP_ctr++; ALLOC_UPD_PAP_adm += sizeofW(StgPAP)-1; \ + ALLOC_UPD_PAP_gds += (g); ALLOC_UPD_PAP_slp += (s); \ + TICK_ALLOC_HISTO(UPD_PAP,sizeofW(StgPAP)-1,g,s) + +#define TICK_ALLOC_TSO(g,s) \ + ALLOC_TSO_ctr++; ALLOC_TSO_adm += sizeofW(StgTSO); \ + ALLOC_TSO_gds += (g); ALLOC_TSO_slp += (s); \ + TICK_ALLOC_HISTO(TSO,sizeofW(StgTSO),g,s) + +#ifdef PAR +#define TICK_ALLOC_FMBQ(a,g,s) \ + ALLOC_FMBQ_ctr++; ALLOC_FMBQ_adm += (a); \ + ALLOC_FMBQ_gds += (g); ALLOC_FMBQ_slp += (s); \ + TICK_ALLOC_HISTO(FMBQ,a,g,s) + +#define TICK_ALLOC_FME(a,g,s) \ + ALLOC_FME_ctr++; ALLOC_FME_adm += (a); \ + ALLOC_FME_gds += (g); ALLOC_FME_slp += (s); \ + TICK_ALLOC_HISTO(FME,a,g,s) + +#define TICK_ALLOC_BF(a,g,s) \ + ALLOC_BF_ctr++; ALLOC_BF_adm += (a); \ + ALLOC_BF_gds += (g); ALLOC_BF_slp += (s); \ + TICK_ALLOC_HISTO(BF,a,g,s) +#endif + +/* The histogrammy bit is fairly straightforward; the -2 is: one for + * 0-origin C arrays; the other one because we do no one-word + * allocations, so we would never inc that histogram slot; so we shift + * everything over by one. + */ +#define TICK_ALLOC_HISTO(categ,a,g,s) \ + { I_ __idx; \ + __idx = (a) + (g) + (s) - 2; \ + ALLOC_##categ##_hst[((__idx > 4) ? 4 : __idx)] += 1;} + +/* 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.) + */ +#define TICK_ALLOC_PRIM(a,g,s) \ + ALLOC_PRIM_ctr++; ALLOC_PRIM_adm += (a); \ + ALLOC_PRIM_gds += (g); ALLOC_PRIM_slp += (s); \ + TICK_ALLOC_HISTO(PRIM,a,g,s) + +#define TICK_ALLOC_PRIM2(w) ALLOC_PRIM_ctr++; ALLOC_PRIM_gds +=(w); \ + TICK_ALLOC_HISTO(PRIM,0,w,0) + + +/* ----------------------------------------------------------------------------- + Enters + -------------------------------------------------------------------------- */ + +#define TICK_ENT_VIA_NODE() ENT_VIA_NODE_ctr++ + +#define TICK_ENT_THK() ENT_THK_ctr++ /* thunk */ +#define TICK_ENT_FUN_STD() ENT_FUN_STD_ctr++ /* std entry pt */ +#define TICK_ENT_FUN_DIRECT(n) ENT_FUN_DIRECT_ctr++ /* fast entry pt */ + +#define TICK_ENT_CON(n) ENT_CON_ctr++ /* enter constructor */ +#define TICK_ENT_IND(n) ENT_IND_ctr++ /* enter indirection */ +#define TICK_ENT_PAP(n) ENT_PAP_ctr++ /* enter PAP */ +#define TICK_ENT_AP_UPD(n) ENT_AP_UPD_ctr++ /* enter AP_UPD */ +#define TICK_ENT_BH() ENT_BH_ctr++ /* enter BLACKHOLE */ + +/* ----------------------------------------------------------------------------- + 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 TICK_ALLOC_* macros account for + * the allocation). The constructor can either be an existing one + * *OLD* or we could have {\em just} figured out this stuff + * *NEW*. + */ + +#define TICK_RET_HISTO(categ,n) \ + { I_ __idx; \ + __idx = (n); \ + RET_##categ##_hst[((__idx > 8) ? 8 : __idx)] += 1;} + +#define TICK_RET_NEW(n) RET_NEW_ctr++; \ + TICK_RET_HISTO(NEW,n) + +#define TICK_RET_OLD(n) RET_OLD_ctr++; \ + TICK_RET_HISTO(OLD,n) + +#define TICK_RET_UNBOXED_TUP(n) RET_UNBOXED_TUP_ctr++; \ + TICK_RET_HISTO(UNBOXED_TUP,n) + +#define TICK_RET_SEMI(n) RET_SEMI_IN_HEAP_ctr++; \ + TICK_RET_HISTO(SEMI_IN_HEAP,n) + +#define TICK_RET_SEMI_BY_DEFAULT()/*???*/ RET_SEMI_BY_DEFAULT_ctr++ + +#define TICK_RET_SEMI_FAILED(tag) do { \ + if ((tag) == INFO_IND_TAG) \ + RET_SEMI_FAILED_IND_ctr++; \ + else \ + RET_SEMI_FAILED_UNEVAL_ctr++; \ + } while (0) + +#define TICK_VEC_RETURN(n) VEC_RETURN_ctr++; \ + TICK_RET_HISTO(VEC_RETURN,n) + +/* ----------------------------------------------------------------------------- + Stack Frames + + Macro Counts + ------------------ ------------------------------------------- + TICK_UPDF_PUSHED Update frame pushed + TICK_SEQF_PUSHED Seq frame pushed + TICK_CATCHF_PUSHED Catch frame pushed + TICK_UPDF_OMITTED A thunk decided not to push an update frame + TICK_UPDF_RCC_PUSHED Cost Centre restore frame pushed + TICK_UPDF_RCC_OMITTED Cost Centres not required -- not pushed + + -------------------------------------------------------------------------- */ + +#define TICK_UPDF_OMITTED() UPDF_OMITTED_ctr++ +#define TICK_UPDF_PUSHED() UPDF_PUSHED_ctr++ +#define TICK_SEQF_PUSHED() SEQF_PUSHED_ctr++ +#define TICK_CATCHF_PUSHED() CATCHF_PUSHED_ctr++ +#define TICK_UPDF_RCC_PUSHED() UPDF_RCC_PUSHED_ctr++ +#define TICK_UPDF_RCC_OMITTED() UPDF_RCC_OMITTED_ctr++ + +/* ----------------------------------------------------------------------------- + Updates + + These macros record information when we do an update. We always + update either with a data constructor (CON) or a partial application + (PAP). + + + Macro Where + ----------------------- -------------------------------------------- + TICK_UPD_EXISTING Updating with an indirection to something + already in the heap + TICK_UPD_SQUEEZED Same as UPD_EXISTING but because + of stack-squeezing + TICK_UPD_CON_IN_NEW Allocating a new CON + TICK_UPD_PAP_IN_NEW Allocating a new PAP + TICK_UPD_PAP_IN_PLACE Updating with a PAP in place + + -------------------------------------------------------------------------- */ + +#define TICK_UPD_HISTO(categ,n) \ + { I_ __idx; \ + __idx = (n); \ + UPD_##categ##_hst[((__idx > 8) ? 8 : __idx)] += 1;} + +#define TICK_UPD_EXISTING() UPD_EXISTING_ctr++ +#define TICK_UPD_SQUEEZED() UPD_SQUEEZED_ctr++ + +#define TICK_UPD_CON_IN_NEW(n) UPD_CON_IN_NEW_ctr++ ; \ + TICK_UPD_HISTO(CON_IN_NEW,n) + +#define TICK_UPD_PAP_IN_NEW(n) UPD_PAP_IN_NEW_ctr++ ; \ + TICK_UPD_HISTO(PAP_IN_NEW,n) + +#define TICK_UPD_PAP_IN_PLACE() UPD_PAP_IN_PLACE_ctr++ + +/* For the generational collector: + */ +#define TICK_UPD_NEW_IND() UPD_NEW_IND_ctr++ +#define TICK_UPD_OLD_IND() UPD_OLD_IND_ctr++ + +/* ----------------------------------------------------------------------------- + Garbage collection counters + -------------------------------------------------------------------------- */ + +/* Selectors: + * + * GC_SEL_ABANDONED: we could've done the selection, but we gave up + * (e.g., to avoid overflowing the C stack); GC_SEL_MINOR: did a + * selection in a minor GC; GC_SEL_MAJOR: ditto, but major GC. + */ +#define TICK_GC_SEL_ABANDONED() GC_SEL_ABANDONED_ctr++ +#define TICK_GC_SEL_MINOR() GC_SEL_MINOR_ctr++ +#define TICK_GC_SEL_MAJOR() GC_SEL_MAJOR_ctr++ + +/* Failed promotion: we wanted to promote an object early, but + * it had already been evacuated to (or resided in) a younger + * generation. + */ +#define TICK_GC_FAILED_PROMOTION() GC_FAILED_PROMOTION_ctr++ + +/* ----------------------------------------------------------------------------- + The accumulators (extern decls) + -------------------------------------------------------------------------- */ + +#ifdef TICKY_C +#define INIT(ializer) = ializer +#define EXTERN +#else +#define INIT(ializer) +#define EXTERN extern +#endif + +EXTERN unsigned long ALLOC_HEAP_ctr INIT(0); +EXTERN unsigned long ALLOC_HEAP_tot INIT(0); + +EXTERN unsigned long ALLOC_FUN_ctr INIT(0); +EXTERN unsigned long ALLOC_FUN_adm INIT(0); +EXTERN unsigned long ALLOC_FUN_gds INIT(0); +EXTERN unsigned long ALLOC_FUN_slp INIT(0); +EXTERN unsigned long ALLOC_FUN_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} /* urk, can't use INIT macro 'cause of the commas */ +#endif +; + +EXTERN unsigned long ALLOC_THK_ctr INIT(0); +EXTERN unsigned long ALLOC_THK_adm INIT(0); +EXTERN unsigned long ALLOC_THK_gds INIT(0); +EXTERN unsigned long ALLOC_THK_slp INIT(0); +EXTERN unsigned long ALLOC_THK_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_CON_ctr INIT(0); +EXTERN unsigned long ALLOC_CON_adm INIT(0); +EXTERN unsigned long ALLOC_CON_gds INIT(0); +EXTERN unsigned long ALLOC_CON_slp INIT(0); +EXTERN unsigned long ALLOC_CON_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_TUP_ctr INIT(0); +EXTERN unsigned long ALLOC_TUP_adm INIT(0); +EXTERN unsigned long ALLOC_TUP_gds INIT(0); +EXTERN unsigned long ALLOC_TUP_slp INIT(0); +EXTERN unsigned long ALLOC_TUP_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_BH_ctr INIT(0); +EXTERN unsigned long ALLOC_BH_adm INIT(0); +EXTERN unsigned long ALLOC_BH_gds INIT(0); +EXTERN unsigned long ALLOC_BH_slp INIT(0); +EXTERN unsigned long ALLOC_BH_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_PRIM_ctr INIT(0); +EXTERN unsigned long ALLOC_PRIM_adm INIT(0); +EXTERN unsigned long ALLOC_PRIM_gds INIT(0); +EXTERN unsigned long ALLOC_PRIM_slp INIT(0); +EXTERN unsigned long ALLOC_PRIM_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_UPD_PAP_ctr INIT(0); +EXTERN unsigned long ALLOC_UPD_PAP_adm INIT(0); +EXTERN unsigned long ALLOC_UPD_PAP_gds INIT(0); +EXTERN unsigned long ALLOC_UPD_PAP_slp INIT(0); +EXTERN unsigned long ALLOC_UPD_PAP_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_TSO_ctr INIT(0); +EXTERN unsigned long ALLOC_TSO_adm INIT(0); +EXTERN unsigned long ALLOC_TSO_gds INIT(0); +EXTERN unsigned long ALLOC_TSO_slp INIT(0); +EXTERN unsigned long ALLOC_TSO_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +# ifdef PAR +EXTERN unsigned long ALLOC_FMBQ_ctr INIT(0); +EXTERN unsigned long ALLOC_FMBQ_adm INIT(0); +EXTERN unsigned long ALLOC_FMBQ_gds INIT(0); +EXTERN unsigned long ALLOC_FMBQ_slp INIT(0); +EXTERN unsigned long ALLOC_FMBQ_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_FME_ctr INIT(0); +EXTERN unsigned long ALLOC_FME_adm INIT(0); +EXTERN unsigned long ALLOC_FME_gds INIT(0); +EXTERN unsigned long ALLOC_FME_slp INIT(0); +EXTERN unsigned long ALLOC_FME_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; + +EXTERN unsigned long ALLOC_BF_ctr INIT(0); +EXTERN unsigned long ALLOC_BF_adm INIT(0); +EXTERN unsigned long ALLOC_BF_gds INIT(0); +EXTERN unsigned long ALLOC_BF_slp INIT(0); +EXTERN unsigned long ALLOC_BF_hst[5] +#ifdef TICKY_C + = {0,0,0,0,0} +#endif +; +#endif + +EXTERN unsigned long ENT_VIA_NODE_ctr INIT(0); +EXTERN unsigned long ENT_THK_ctr INIT(0); +EXTERN unsigned long ENT_FUN_STD_ctr INIT(0); +EXTERN unsigned long ENT_FUN_DIRECT_ctr INIT(0); +EXTERN unsigned long ENT_CON_ctr INIT(0); +EXTERN unsigned long ENT_IND_ctr INIT(0); +EXTERN unsigned long ENT_PAP_ctr INIT(0); +EXTERN unsigned long ENT_AP_UPD_ctr INIT(0); +EXTERN unsigned long ENT_BH_ctr INIT(0); + +EXTERN unsigned long RET_NEW_ctr INIT(0); +EXTERN unsigned long RET_OLD_ctr INIT(0); +EXTERN unsigned long RET_UNBOXED_TUP_ctr INIT(0); +EXTERN unsigned long RET_SEMI_BY_DEFAULT_ctr INIT(0); +EXTERN unsigned long RET_SEMI_IN_HEAP_ctr INIT(0); +EXTERN unsigned long RET_SEMI_FAILED_IND_ctr INIT(0); +EXTERN unsigned long RET_SEMI_FAILED_UNEVAL_ctr INIT(0); + +EXTERN unsigned long VEC_RETURN_ctr INIT(0); + +EXTERN unsigned long RET_NEW_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; +EXTERN unsigned long RET_OLD_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; +EXTERN unsigned long RET_UNBOXED_TUP_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; +EXTERN unsigned long RET_SEMI_IN_HEAP_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; +EXTERN unsigned long RET_VEC_RETURN_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; + +EXTERN unsigned long RET_SEMI_loads_avoided INIT(0); + +EXTERN unsigned long UPDF_OMITTED_ctr INIT(0); +EXTERN unsigned long UPDF_PUSHED_ctr INIT(0); +EXTERN unsigned long SEQF_PUSHED_ctr INIT(0); +EXTERN unsigned long CATCHF_PUSHED_ctr INIT(0); +EXTERN unsigned long UPDF_RCC_PUSHED_ctr INIT(0); +EXTERN unsigned long UPDF_RCC_OMITTED_ctr INIT(0); + +EXTERN unsigned long UPD_EXISTING_ctr INIT(0); +EXTERN unsigned long UPD_SQUEEZED_ctr INIT(0); +EXTERN unsigned long UPD_CON_IN_NEW_ctr INIT(0); +EXTERN unsigned long UPD_PAP_IN_NEW_ctr INIT(0); +EXTERN unsigned long UPD_PAP_IN_PLACE_ctr INIT(0); + +EXTERN unsigned long UPD_CON_IN_NEW_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; +EXTERN unsigned long UPD_PAP_IN_NEW_hst[9] +#ifdef TICKY_C + = {0,0,0,0,0,0,0,0,0} +#endif +; + +EXTERN unsigned long UPD_NEW_IND_ctr INIT(0); +EXTERN unsigned long UPD_OLD_IND_ctr INIT(0); + +EXTERN unsigned long GC_SEL_ABANDONED_ctr INIT(0); +EXTERN unsigned long GC_SEL_MINOR_ctr INIT(0); +EXTERN unsigned long GC_SEL_MAJOR_ctr INIT(0); + +EXTERN unsigned long GC_FAILED_PROMOTION_ctr INIT(0); + +#undef INIT +#undef EXTERN + +/* ----------------------------------------------------------------------------- + Just stubs if no ticky-ticky profiling + -------------------------------------------------------------------------- */ + +#else /* !TICKY_TICKY */ + +#define TICK_ALLOC_HEAP(words) + +#define TICK_ALLOC_FUN(g,s) +#define TICK_ALLOC_THK(g,s) +#define TICK_ALLOC_CON(g,s) +#define TICK_ALLOC_TUP(g,s) +#define TICK_ALLOC_BH(g,s) +#define TICK_ALLOC_UPD_PAP(g,s) +#define TICK_ALLOC_TSO(g,s) +#define TICK_ALLOC_FMBQ(a,g,s) +#define TICK_ALLOC_FME(a,g,s) +#define TICK_ALLOC_BF(a,g,s) +#define TICK_ALLOC_PRIM(a,g,s) +#define TICK_ALLOC_PRIM2(w) + +#define TICK_ENT_VIA_NODE() + +#define TICK_ENT_THK() +#define TICK_ENT_FUN_STD() +#define TICK_ENT_FUN_DIRECT(n) + +#define TICK_ENT_CON(n) +#define TICK_ENT_IND(n) +#define TICK_ENT_PAP(n) +#define TICK_ENT_AP_UPD(n) +#define TICK_ENT_BH() + +#define TICK_RET_NEW(n) +#define TICK_RET_OLD(n) +#define TICK_RET_UNBOXED_TUP(n) +#define TICK_RET_SEMI(n) +#define TICK_RET_SEMI_BY_DEFAULT() +#define TICK_RET_SEMI_FAILED(tag) +#define TICK_VEC_RETURN(n) + +#define TICK_UPDF_OMITTED() +#define TICK_UPDF_PUSHED() +#define TICK_SEQF_PUSHED() +#define TICK_CATCHF_PUSHED() +#define TICK_UPDF_RCC_PUSHED() +#define TICK_UPDF_RCC_OMITTED() + +#define TICK_UPD_EXISTING() +#define TICK_UPD_SQUEEZED() +#define TICK_UPD_CON_IN_NEW(n) +#define TICK_UPD_PAP_IN_NEW(n) +#define TICK_UPD_PAP_IN_PLACE() + +#define TICK_UPD_NEW_IND() +#define TICK_UPD_OLD_IND() + +#define TICK_GC_SEL_ABANDONED() +#define TICK_GC_SEL_MINOR() +#define TICK_GC_SEL_MAJOR() + +#define TICK_GC_FAILED_PROMOTION() + +#endif /* !TICKY_TICKY */ + +#endif /* TICKY_H */ diff --git a/ghc/includes/Ticky.h b/ghc/includes/Ticky.h deleted file mode 100644 index a2bd814..0000000 --- a/ghc/includes/Ticky.h +++ /dev/null @@ -1,33 +0,0 @@ -/* ---------------------------------------------------------------------------- - * $Id: Ticky.h,v 1.2 1998/12/02 13:21:45 simonm Exp $ - * - * Closures - * - * -------------------------------------------------------------------------- */ - -#ifndef TICKY_H -#define TICKY_H - - -#ifndef TICKY -/* just stubs if no ticky-ticky profiling*/ -#define TICK_ENT_CAF_ENTERED(Node) /* enter CAF */ -#define TICK_ENT_IND(Node) /* enter indirection */ -#define TICK_ENT_VIA_NODE() /* enter node */ -#define TICK_UPD_EXISTING() /* entering an update frame */ -#define TICK_UPD_SQUEEZED() /* squeezed an update frame */ -#define TICK_UPDATED_SET_UPDATED(updclosure) /* updating a closure w/ ind */ -#define TICK_ALLOC_HEAP(words) /* allocate some words on the heap */ -#define TICK_UNALLOC_HEAP(words) /* unallocate some words on the heap */ -#define TICK_ALLOC_UPD_PAP(DYN_HS,NArgWords,N,PapSize) -#define TICK_ALLOC_PRIM(hdr,args,n,size) -#define TICK_ENT_PAP(pap) /* entering a PAP */ -#define TICK_UPD_PAP_IN_NEW(NArgWords) -#define TICK_UPD_PAP_IN_PLACE() -#define TICK_UPDF_PUSHED() -#define TICK_SEQF_PUSHED() -#else -#error ticky-ticky not implemented! -#endif - -#endif /* TICKY_H */ diff --git a/ghc/includes/Updates.h b/ghc/includes/Updates.h index 5398318..04838e7 100644 --- a/ghc/includes/Updates.h +++ b/ghc/includes/Updates.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Updates.h,v 1.5 1999/01/18 15:21:42 simonm Exp $ + * $Id: Updates.h,v 1.6 1999/01/21 10:31:45 simonm Exp $ * * Definitions related to updates. * @@ -25,7 +25,6 @@ */ #define UPD_IND(updclosure, heapptr) \ - TICK_UPDATED_SET_UPDATED(updclosure); \ AWAKEN_BQ(updclosure); \ updateWithIndirection((StgClosure *)updclosure, \ (StgClosure *)heapptr); diff --git a/ghc/rts/Main.c b/ghc/rts/Main.c index 2b7433a..c363eb2 100644 --- a/ghc/rts/Main.c +++ b/ghc/rts/Main.c @@ -1,5 +1,7 @@ /* ----------------------------------------------------------------------------- - * $Id: Main.c,v 1.2 1998/12/02 13:28:30 simonm Exp $ + * $Id: Main.c,v 1.3 1999/01/21 10:31:47 simonm Exp $ + * + * (c) The GHC Team 1998-1999 * * Main function for a standalone Haskell program. * @@ -7,6 +9,7 @@ #include "Rts.h" #include "RtsAPI.h" +#include "RtsFlags.h" #include "Schedule.h" /* for MainTSO */ #include "RtsUtils.h" @@ -35,14 +38,18 @@ int main(int argc, char *argv[]) startupHaskell(argc,argv); #ifndef PAR - MainTSO = createIOThread(BLOCK_SIZE_W,(StgClosure *)&mainIO_closure); + MainTSO = createIOThread(stg_max(BLOCK_SIZE_W, + RtsFlags.GcFlags.initialStkSize), + (StgClosure *)&mainIO_closure); status = schedule(MainTSO,NULL); #else if (IAmMainThread == rtsTrue) { /*Just to show we're alive */ fprintf(stderr, "Main Thread Started ...\n"); - MainTSO = createIOThread(BLOCK_SIZE_W,(StgClosure *)&mainIO_closure); + MainTSO = createIOThread(stg_max(BLOCK_SIZE_W, + RtsFlags.GcFlags.initialStkSize), + (StgClosure *)&mainIO_closure); status = schedule(MainTSO,NULL); } else { WaitForPEOp(PP_FINISH,SysManTask); diff --git a/ghc/rts/PrimOps.hc b/ghc/rts/PrimOps.hc index 31919dc..10f49d5 100644 --- a/ghc/rts/PrimOps.hc +++ b/ghc/rts/PrimOps.hc @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: PrimOps.hc,v 1.4 1999/01/15 17:32:22 simonm Exp $ + * $Id: PrimOps.hc,v 1.5 1999/01/21 10:31:47 simonm Exp $ * * Primitive functions / data * @@ -196,8 +196,10 @@ const stuff_size = BYTES_TO_STGWORDS(n*scale); \ size = sizeofW(StgArrWords)+ stuff_size; \ p = (StgArrWords *)RET_STGCALL1(P_,allocate,size); \ + TICK_ALLOC_PRIM(sizeofW(StgArrWords),stuff_size,0); \ SET_HDR(p, &MUT_ARR_WORDS_info, CCCS); \ p->words = stuff_size; \ + TICK_RET_UNBOXED_TUP(1) \ RET_P(p); \ FE_ \ } @@ -222,6 +224,7 @@ FN_(newArrayZh_fast) size = sizeofW(StgMutArrPtrs) + n; arr = (StgMutArrPtrs *)RET_STGCALL1(P_, allocate, size); + TICK_ALLOC_PRIM(sizeofW(StgMutArrPtrs), n, 0); SET_HDR(arr,&MUT_ARR_PTRS_info,CCCS); arr->ptrs = n; @@ -232,6 +235,7 @@ FN_(newArrayZh_fast) *p = (W_)init; } + TICK_RET_UNBOXED_TUP(1); RET_P(arr); FE_ } @@ -243,15 +247,15 @@ FN_(newMutVarZh_fast) FB_ HP_CHK_GEN(sizeofW(StgMutVar), R1_PTR, newMutVarZh_fast,); - TICK_ALLOC_PRIM(sizeofW(StgMutVar),wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgHeader)+1,1, 0); /* hack, dependent on rep. */ CCS_ALLOC(CCCS,sizeofW(StgMutVar)); - mv = stgCast(StgMutVar*,Hp-sizeofW(StgMutVar)+1); + mv = (StgMutVar *)(Hp-sizeofW(StgMutVar)+1); SET_HDR(mv,&MUT_VAR_info,CCCS); mv->var = R1.cl; + TICK_RET_UNBOXED_TUP(1); RET_P(mv); - FE_ } @@ -269,7 +273,8 @@ FN_(makeForeignObjZh_fast) FB_ HP_CHK_GEN(sizeofW(StgForeignObj), NO_PTRS, makeForeignObjZh_fast,); - TICK_ALLOC_PRIM(sizeofW(StgForeignObj),wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgHeader), + sizeofW(StgForeignObj)-sizeofW(StgHeader), 0); CCS_ALLOC(CCCS,sizeofW(StgForeignObj)); /* ccs prof */ result = (StgForeignObj *) (Hp + 1 - sizeofW(StgForeignObj)); @@ -277,6 +282,7 @@ FN_(makeForeignObjZh_fast) result->data = R1.p; /* returns (# s#, ForeignObj# #) */ + TICK_RET_UNBOXED_TUP(1); RET_P(result); FE_ } @@ -298,7 +304,8 @@ FN_(mkWeakZh_fast) FB_ HP_CHK_GEN(sizeofW(StgWeak), R1_PTR|R2_PTR|R3_PTR, mkWeakZh_fast,); - TICK_ALLOC_PRIM(sizeofW(StgWeak),wibble,wibble,wibble); + TICK_ALLOC_PRIM(sizeofW(StgHeader)+1, // +1 is for the link field + sizeofW(StgWeak)-sizeofW(StgHeader)-1, 0); CCS_ALLOC(CCCS,sizeofW(StgWeak)); /* ccs prof */ w = (StgWeak *) (Hp + 1 - sizeofW(StgWeak)); @@ -312,6 +319,7 @@ FN_(mkWeakZh_fast) weak_ptr_list = w; IF_DEBUG(weak, fprintf(stderr,"New weak pointer at %p\n",w)); + TICK_RET_UNBOXED_TUP(1); RET_P(w); FE_ } @@ -323,6 +331,7 @@ FN_(deRefWeakZh_fast) StgWeak *w; FB_ + TICK_RET_UNBOXED_TUP(2); w = (StgWeak *)R1.p; if (w->header.info == &WEAK_info) { RET_NP(1, w->value); @@ -347,8 +356,8 @@ FN_(int2IntegerZh_fast) FB_ val = R1.i; - HP_CHK_GEN(sizeofW(StgArrWords)+1, NO_PTRS, int2IntegerZh_fast,) - TICK_ALLOC_PRIM(sizeofW(StgArrWords)+1,wibble,wibble,wibble) + HP_CHK_GEN(sizeofW(StgArrWords)+1, NO_PTRS, int2IntegerZh_fast,); + TICK_ALLOC_PRIM(sizeofW(StgArrWords),1,0); CCS_ALLOC(CCCS,sizeofW(StgArrWords)+1); /* ccs prof */ p = stgCast(StgArrWords*,Hp)-1; @@ -370,6 +379,7 @@ FN_(int2IntegerZh_fast) data :: ByteArray# #) */ + TICK_RET_UNBOXED_TUP(3); RET_NNP(1,s,p); FE_ } @@ -385,7 +395,7 @@ FN_(word2IntegerZh_fast) val = R1.w; HP_CHK_GEN(sizeofW(StgArrWords)+1, NO_PTRS, word2IntegerZh_fast,) - TICK_ALLOC_PRIM(sizeofW(StgArrWords)+1,wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgArrWords),1,0); CCS_ALLOC(CCCS,sizeofW(StgArrWords)+1); /* ccs prof */ p = stgCast(StgArrWords*,Hp)-1; @@ -403,6 +413,7 @@ FN_(word2IntegerZh_fast) data :: ByteArray# #) */ + TICK_RET_UNBOXED_TUP(3); RET_NNP(1,s,p); FE_ } @@ -422,6 +433,7 @@ FN_(addr2IntegerZh_fast) if (RET_STGCALL3(int, mpz_init_set_str,&result,(str),/*base*/10)) abort(); + TICK_RET_UNBOXED_TUP(3); RET_NNP(result._mp_alloc, result._mp_size, result._mp_d - sizeofW(StgArrWords)); FE_ @@ -453,7 +465,7 @@ FN_(int64ToIntegerZh_fast) words_needed = 1; } HP_CHK_GEN(sizeofW(StgArrWords)+words_needed, NO_PTRS, int64ToIntegerZh_fast,) - TICK_ALLOC_PRIM(sizeofW(StgArrWords)+words_needed,wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgArrWords),words_needed,0); CCS_ALLOC(CCCS,sizeofW(StgArrWords)+words_needed); /* ccs prof */ p = stgCast(StgArrWords*,Hp)-1; @@ -484,6 +496,7 @@ FN_(int64ToIntegerZh_fast) data :: ByteArray# #) */ + TICK_RET_UNBOXED_TUP(3); RET_NNP(a,s,p); FE_ } @@ -505,7 +518,7 @@ FN_(word64ToIntegerZh_fast) words_needed = 1; } HP_CHK_GEN(sizeofW(StgArrWords)+words_needed, NO_PTRS, word64ToIntegerZh_fast,) - TICK_ALLOC_PRIM(sizeofW(StgArrWords)+words_needed,wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgArrWords),words_needed,0); CCS_ALLOC(CCCS,sizeofW(StgArrWords)+words_needed); /* ccs prof */ p = stgCast(StgArrWords*,Hp)-1; @@ -531,6 +544,7 @@ FN_(word64ToIntegerZh_fast) data :: ByteArray# #) */ + TICK_RET_UNBOXED_TUP(3); RET_NNP(a,s,p); FE_ } @@ -571,6 +585,7 @@ FN_(name) \ /* Perform the operation */ \ STGCALL3(mp_fun,&result,&arg1,&arg2); \ \ + TICK_RET_UNBOXED_TUP(3); \ RET_NNP(result._mp_alloc, \ result._mp_size, \ result._mp_d-sizeofW(StgArrWords)); \ @@ -609,6 +624,7 @@ FN_(name) \ /* Perform the operation */ \ STGCALL4(mp_fun,&result1,&result2,&arg1,&arg2); \ \ + TICK_RET_UNBOXED_TUP(6); \ RET_NNPNNP(result1._mp_alloc, \ result1._mp_size, \ result1._mp_d-sizeofW(StgArrWords), \ @@ -639,7 +655,7 @@ FN_(decodeFloatZh_fast) arg = F1; HP_CHK_GEN(sizeof(StgArrWords)+1, NO_PTRS, decodeFloatZh_fast,); - TICK_ALLOC_PRIM(sizeofW(StgArrWords)+1,wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgArrWords),1,0); CCS_ALLOC(CCCS,sizeofW(StgArrWords)+1); /* ccs prof */ /* Be prepared to tell Lennart-coded __decodeFloat */ @@ -652,6 +668,7 @@ FN_(decodeFloatZh_fast) STGCALL3(__decodeFloat,&mantissa,&exponent,arg); /* returns: (R1 = Int# (expn), R2 = Int#, R3 = Int#, R4 = ByteArray#) */ + TICK_RET_UNBOXED_TUP(4); RET_NNNP(exponent,mantissa._mp_alloc,mantissa._mp_size,p); FE_ } @@ -671,7 +688,7 @@ FN_(decodeDoubleZh_fast) arg = D1; HP_CHK_GEN(ARR_SIZE, NO_PTRS, decodeDoubleZh_fast,); - TICK_ALLOC_PRIM(ARR_SIZE,wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeof(StgArrWords),DOUBLE_MANTISSA_SIZE,0); CCS_ALLOC(CCCS,ARR_SIZE); /* ccs prof */ /* Be prepared to tell Lennart-coded __decodeDouble */ @@ -684,6 +701,7 @@ FN_(decodeDoubleZh_fast) STGCALL3(__decodeDouble,&mantissa,&exponent,arg); /* returns: (R1 = Int# (expn), R2 = Int#, R3 = Int#, R4 = ByteArray#) */ + TICK_RET_UNBOXED_TUP(4); RET_NNNP(exponent,mantissa._mp_alloc,mantissa._mp_size,p); FE_ } @@ -709,8 +727,7 @@ FN_(forkZh_fast) context_switch = 1; } - JMP_(*Sp); - + JMP_(ENTRY_CODE(Sp[0])); FE_ } @@ -743,7 +760,8 @@ FN_(newMVarZh_fast) /* args: none */ HP_CHK_GEN(sizeofW(StgMVar), NO_PTRS, newMVarZh_fast,); - TICK_ALLOC_PRIM(sizeofW(StgMVar),wibble,wibble,wibble) + TICK_ALLOC_PRIM(sizeofW(StgMutVar)-1, // consider head,tail,link as admin wds + 1, 0); CCS_ALLOC(CCCS,sizeofW(StgMVar)); /* ccs prof */ mvar = (StgMVar *) (Hp - sizeofW(StgMVar) + 1); @@ -751,15 +769,15 @@ FN_(newMVarZh_fast) mvar->head = mvar->tail = (StgTSO *)&END_TSO_QUEUE_closure; mvar->value = (StgClosure *)&END_TSO_QUEUE_closure; - R1.p = (P_)mvar; - - JMP_(ENTRY_CODE(Sp[0])); + TICK_RET_UNBOXED_TUP(1); + RET_P(mvar); FE_ } FN_(takeMVarZh_fast) { StgMVar *mvar; + StgClosure *val; FB_ /* args: R1 = MVar closure */ @@ -782,10 +800,11 @@ FN_(takeMVarZh_fast) } SET_INFO(mvar,&EMPTY_MVAR_info); - R1.cl = mvar->value; + val = mvar->value; mvar->value = (StgClosure *)&END_TSO_QUEUE_closure; - JMP_(ENTRY_CODE(Sp[0])); + TICK_RET_UNBOXED_TUP(1); + RET_P(val); FE_ } @@ -822,7 +841,7 @@ FN_(putMVarZh_fast) } /* ToDo: yield here for better communication performance? */ - JMP_(ENTRY_CODE(*Sp)); + JMP_(ENTRY_CODE(Sp[0])); FE_ } diff --git a/ghc/rts/RtsFlags.c b/ghc/rts/RtsFlags.c index 3d0d866..089efd2 100644 --- a/ghc/rts/RtsFlags.c +++ b/ghc/rts/RtsFlags.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: RtsFlags.c,v 1.5 1999/01/19 17:06:04 simonm Exp $ + * $Id: RtsFlags.c,v 1.6 1999/01/21 10:31:48 simonm Exp $ * * Functions for parsing the argument list. * @@ -190,8 +190,6 @@ void initRtsFlagsDefaults(void) #ifdef TICKY_TICKY RtsFlags.TickyFlags.showTickyStats = rtsFalse; RtsFlags.TickyFlags.tickyFile = NULL; - - AllFlags.doUpdEntryCounts = rtsTrue; /*ToDo:move? */ #endif } diff --git a/ghc/rts/RtsStartup.c b/ghc/rts/RtsStartup.c index e075c9d..b9018aa 100644 --- a/ghc/rts/RtsStartup.c +++ b/ghc/rts/RtsStartup.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: RtsStartup.c,v 1.2 1998/12/02 13:28:41 simonm Exp $ + * $Id: RtsStartup.c,v 1.3 1999/01/21 10:31:49 simonm Exp $ * * Main function for a standalone Haskell program. * @@ -14,6 +14,7 @@ #include "Schedule.h" /* initScheduler */ #include "Stats.h" /* initStats */ #include "Weak.h" +#include "Ticky.h" #if defined(PROFILING) # include "ProfRTS.h" @@ -132,8 +133,7 @@ shutdownHaskell(void) #endif #if defined(TICKY_TICKY) - #error FixMe. - if (RTSflags.TickyFlags.showTickyStats) PrintTickyInfo(); + if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo(); #endif /* diff --git a/ghc/rts/RtsUtils.c b/ghc/rts/RtsUtils.c index e67cd46..2ed09d3 100644 --- a/ghc/rts/RtsUtils.c +++ b/ghc/rts/RtsUtils.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: RtsUtils.c,v 1.2 1998/12/02 13:28:41 simonm Exp $ + * $Id: RtsUtils.c,v 1.3 1999/01/21 10:31:49 simonm Exp $ * * General utility functions used in the RTS. * @@ -11,6 +11,7 @@ #include "Hooks.h" #include "Main.h" #include "RtsUtils.h" +#include "Ticky.h" #ifdef HAVE_TIME_H #include @@ -114,7 +115,7 @@ stackOverflow(nat max_stack_size) StackOverflowHook(max_stack_size * sizeof(W_)); /*msg*/ #if defined(TICKY_TICKY) - if (RTSflags.TickyFlags.showTickyStats) PrintTickyInfo(); + if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo(); #endif stg_exit(EXIT_FAILURE); @@ -128,7 +129,7 @@ heapOverflow(void) RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE); #if defined(TICKY_TICKY) - if (Rtsflags.TickyFlags.showTickyStats) PrintTickyInfo(); + if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo(); #endif stg_exit(EXIT_FAILURE); diff --git a/ghc/rts/Schedule.c b/ghc/rts/Schedule.c index d3af459..4ee0892 100644 --- a/ghc/rts/Schedule.c +++ b/ghc/rts/Schedule.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Schedule.c,v 1.4 1999/01/13 17:25:44 simonm Exp $ + * $Id: Schedule.c,v 1.5 1999/01/21 10:31:50 simonm Exp $ * * Scheduler * @@ -92,6 +92,7 @@ createThread(nat stack_size) } tso = (StgTSO *)allocate(stack_size); + TICK_ALLOC_TSO(stack_size-sizeofW(StgTSO),0); initThread(tso, stack_size - TSO_STRUCT_SIZEW); return tso; @@ -192,6 +193,7 @@ void deleteThread(StgTSO *tso) int words = (stgCast(StgPtr,su) - stgCast(StgPtr,sp)) - 1; nat i; StgAP_UPD* ap = stgCast(StgAP_UPD*,allocate(AP_sizeW(words))); + TICK_ALLOC_THK(words+1,0); /* First build an AP_UPD consisting of the stack chunk above the * current update frame, with the top word on the stack as the @@ -245,6 +247,7 @@ void deleteThread(StgTSO *tso) /* now build o = FUN(catch,ap,handler) */ o = stgCast(StgClosure*, allocate(sizeofW(StgClosure)+2)); + TICK_ALLOC_THK(2,0); SET_HDR(o,&catch_info,su->header.prof.ccs /* ToDo */); payloadCPtr(o,0) = stgCast(StgClosure*,ap); payloadCPtr(o,1) = cf->handler; @@ -270,6 +273,7 @@ void deleteThread(StgTSO *tso) /* now build o = FUN(seq,ap) */ o = stgCast(StgClosure*, allocate(sizeofW(StgClosure)+1)); + TICK_ALLOC_THK(1,0); SET_HDR(o,&seq_info,su->header.prof.ccs /* ToDo */); payloadCPtr(o,0) = stgCast(StgClosure*,ap); @@ -678,6 +682,7 @@ threadStackOverflow(StgTSO *tso) IF_DEBUG(scheduler, fprintf(stderr,"increasing stack size from %d words to %d.\n", tso->stack_size, new_stack_size)); dest = (StgTSO *)allocate(new_tso_size); + TICK_ALLOC_TSO(new_tso_size-sizeofW(StgTSO),0); /* copy the TSO block and the old stack into the new area */ memcpy(dest,tso,TSO_STRUCT_SIZE); diff --git a/ghc/rts/StgMiscClosures.hc b/ghc/rts/StgMiscClosures.hc index 195fcb6..94dc96c 100644 --- a/ghc/rts/StgMiscClosures.hc +++ b/ghc/rts/StgMiscClosures.hc @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: StgMiscClosures.hc,v 1.6 1999/01/18 15:21:39 simonm Exp $ + * $Id: StgMiscClosures.hc,v 1.7 1999/01/21 10:31:51 simonm Exp $ * * Entry code for various built-in closure types. * @@ -111,8 +111,6 @@ INFO_TABLE(CAF_ENTERED_info,CAF_ENTERED_entry,2,1,CAF_ENTERED,const,EF_,0,0); STGFUN(CAF_ENTERED_entry) { FB_ - TICK_ENT_CAF_ENTERED(Node); /* tick */ - R1.p = (P_) ((StgCAF*)R1.p)->value; /* just a fancy indirection */ TICK_ENT_VIA_NODE(); JMP_(GET_ENTRY(R1.cl)); @@ -138,6 +136,8 @@ INFO_TABLE(BLACKHOLE_info, BLACKHOLE_entry,0,2,BLACKHOLE,const,EF_,0,0); STGFUN(BLACKHOLE_entry) { FB_ + TICK_ENT_BH(); + /* Change the BLACKHOLE into a BLACKHOLE_BQ */ ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info; /* Put ourselves on the blocking queue for this black hole */ @@ -155,6 +155,8 @@ INFO_TABLE(BLACKHOLE_BQ_info, BLACKHOLE_BQ_entry,1,1,BLACKHOLE_BQ,const,EF_,0,0) STGFUN(BLACKHOLE_BQ_entry) { FB_ + TICK_ENT_BH(); + /* Put ourselves on the blocking queue for this black hole */ CurrentTSO->link = ((StgBlockingQueue *)R1.p)->blocking_queue; ((StgBlockingQueue *)R1.p)->blocking_queue = CurrentTSO; @@ -169,6 +171,8 @@ INFO_TABLE(CAF_BLACKHOLE_info, CAF_BLACKHOLE_entry,0,2,CAF_BLACKHOLE,const,EF_,0 STGFUN(CAF_BLACKHOLE_entry) { FB_ + TICK_ENT_BH(); + /* Change the BLACKHOLE into a BLACKHOLE_BQ */ ((StgBlockingQueue *)R1.p)->header.info = &BLACKHOLE_BQ_info; /* Put ourselves on the blocking queue for this black hole */ diff --git a/ghc/rts/Storage.c b/ghc/rts/Storage.c index e093888..6b44104 100644 --- a/ghc/rts/Storage.c +++ b/ghc/rts/Storage.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Storage.c,v 1.5 1999/01/19 17:06:05 simonm Exp $ + * $Id: Storage.c,v 1.6 1999/01/21 10:31:51 simonm Exp $ * * Storage manager front end * @@ -248,7 +248,7 @@ allocate(nat n) bdescr *bd; StgPtr p; - TICK_ALLOC_PRIM(n,wibble,wibble,wibble) + TICK_ALLOC_HEAP(n); CCS_ALLOC(CCCS,n); /* big allocation (>LARGE_OBJECT_THRESHOLD) */ diff --git a/ghc/rts/Storage.h b/ghc/rts/Storage.h index 60df8b9..35c46b3 100644 --- a/ghc/rts/Storage.h +++ b/ghc/rts/Storage.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Storage.h,v 1.4 1999/01/18 15:21:40 simonm Exp $ + * $Id: Storage.h,v 1.5 1999/01/21 10:31:52 simonm Exp $ * * External Storage Manger Interface * @@ -25,6 +25,10 @@ extern void exitStorage(void); StgPtr allocate(int n) Allocates a chunk of contiguous store n words long, returning a pointer to the first word. Always succeeds. + + Don't forget to TICK_ALLOC_XXX(...) + after calling allocate, for the + benefit of the ticky-ticky profiler. rtsBool doYouWantToGC(void) Returns True if the storage manager is ready to perform a GC, False otherwise. @@ -89,12 +93,6 @@ extern StgClosure *MarkRoot(StgClosure *p); extern void recordMutable(StgMutClosure *p); -#ifdef TICKY_TICKY -#error updateWithIndirection: maybe permanent indirection? -# define Ind_info_TO_USE ((AllFlags.doUpdEntryCounts) ? &IND_PERM_info : &IND_info -) -#endif - static inline void updateWithIndirection(StgClosure *p1, StgClosure *p2) { @@ -104,11 +102,13 @@ updateWithIndirection(StgClosure *p1, StgClosure *p2) if (bd->gen->no == 0) { SET_INFO(p1,&IND_info); ((StgInd *)p1)->indirectee = p2; + TICK_UPD_NEW_IND(); } else { SET_INFO(p1,&IND_OLDGEN_info); ((StgIndOldGen *)p1)->indirectee = p2; ((StgIndOldGen *)p1)->mut_link = bd->gen->mut_list; bd->gen->mut_list = (StgMutClosure *)p1; + TICK_UPD_OLD_IND(); } } diff --git a/ghc/rts/Ticky.c b/ghc/rts/Ticky.c new file mode 100644 index 0000000..1cfe5c7 --- /dev/null +++ b/ghc/rts/Ticky.c @@ -0,0 +1,521 @@ +/* ----------------------------------------------------------------------------- + * $Id: Ticky.c,v 1.1 1999/01/21 10:31:52 simonm Exp $ + * + * (c) The GHC Team, Glasgow University, 1992-1998 + * + * Ticky-ticky profiling + *-------------------------------------------------------------------------- */ + +#if defined(TICKY_TICKY) + +#define TICKY_C /* define those variables */ +#include "Rts.h" +#include "RtsFlags.h" +#include "Ticky.h" + +/* ----------------------------------------------------------------------------- + Print out all the counters + -------------------------------------------------------------------------- */ + +static void printRegisteredCounterInfo (FILE *); /* fwd decl */ + +#define INTAVG(a,b) ((b == 0) ? 0.0 : ((double) (a) / (double) (b))) +#define PC(a) (100.0 * a) + +#define AVG(thing) \ + StgDouble avg##thing = INTAVG(tot##thing,ctr##thing) + +void +PrintTickyInfo(void) +{ + unsigned long i; + unsigned long tot_allocs = /* total number of things allocated */ + ALLOC_FUN_ctr + ALLOC_THK_ctr + ALLOC_CON_ctr + ALLOC_TUP_ctr + + ALLOC_TSO_ctr + +#ifdef PAR + ALLOC_FMBQ_ctr + ALLOC_FME_ctr + ALLOC_BF_ctr + +#endif + ALLOC_BH_ctr + ALLOC_UPD_PAP_ctr + ALLOC_PRIM_ctr; + + unsigned long tot_adm_wds = /* total number of admin words allocated */ + ALLOC_FUN_adm + ALLOC_THK_adm + ALLOC_CON_adm + ALLOC_TUP_adm + + ALLOC_TSO_adm + +#ifdef PAR + ALLOC_FMBQ_adm + ALLOC_FME_adm + ALLOC_BF_adm + +#endif + ALLOC_BH_adm + ALLOC_UPD_PAP_adm + ALLOC_PRIM_adm; + + unsigned long tot_gds_wds = /* total number of words of ``good stuff'' allocated */ + ALLOC_FUN_gds + ALLOC_THK_gds + ALLOC_CON_gds + ALLOC_TUP_gds + + ALLOC_TSO_gds + +#ifdef PAR + ALLOC_FMBQ_gds + ALLOC_FME_gds + ALLOC_BF_gds + +#endif + + ALLOC_BH_gds + ALLOC_UPD_PAP_gds + ALLOC_PRIM_gds; + + unsigned long tot_slp_wds = /* total number of ``slop'' words allocated */ + ALLOC_FUN_slp + ALLOC_THK_slp + ALLOC_CON_slp + ALLOC_TUP_slp + + ALLOC_TSO_slp + +#ifdef PAR + ALLOC_FMBQ_slp + ALLOC_FME_slp + ALLOC_BF_slp + +#endif + ALLOC_BH_slp + ALLOC_UPD_PAP_slp + ALLOC_PRIM_slp; + + unsigned long tot_wds = /* total words */ + tot_adm_wds + tot_gds_wds + tot_slp_wds; + + unsigned long tot_enters = + ENT_CON_ctr + ENT_FUN_DIRECT_ctr + + ENT_IND_ctr + ENT_PAP_ctr + ENT_THK_ctr; + unsigned long jump_direct_enters = + tot_enters - ENT_VIA_NODE_ctr; + unsigned long bypass_enters = + ENT_FUN_DIRECT_ctr - + (ENT_FUN_STD_ctr - UPD_PAP_IN_NEW_ctr); + + unsigned long tot_returns = + RET_NEW_ctr + RET_OLD_ctr + RET_UNBOXED_TUP_ctr + + RET_SEMI_IN_HEAP_ctr + RET_SEMI_BY_DEFAULT_ctr/*?*/; + + unsigned long tot_returns_of_new = RET_NEW_ctr; + + unsigned long pap_updates = UPD_PAP_IN_NEW_ctr + UPD_PAP_IN_PLACE_ctr; + + unsigned long tot_updates = UPD_EXISTING_ctr + UPD_SQUEEZED_ctr + pap_updates; + + unsigned long tot_new_updates = UPD_NEW_IND_ctr; + unsigned long tot_old_updates = UPD_OLD_IND_ctr; + unsigned long tot_gengc_updates = tot_new_updates + tot_old_updates; + + FILE *tf = RtsFlags.TickyFlags.tickyFile; + + fprintf(tf,"\n\nALLOCATIONS: %ld (%ld words total: %ld admin, %ld goods, %ld slop)\n", + tot_allocs, tot_wds, tot_adm_wds, tot_gds_wds, tot_slp_wds); + fprintf(tf,"\t\t\t\ttotal words:\t 2 3 4 5 6+\n"); + +#define ALLOC_HISTO_MAGIC(categ) \ + (PC(INTAVG(ALLOC_##categ##_hst[0], ALLOC_##categ##_ctr))), \ + (PC(INTAVG(ALLOC_##categ##_hst[1], ALLOC_##categ##_ctr))), \ + (PC(INTAVG(ALLOC_##categ##_hst[2], ALLOC_##categ##_ctr))), \ + (PC(INTAVG(ALLOC_##categ##_hst[3], ALLOC_##categ##_ctr))), \ + (PC(INTAVG(ALLOC_##categ##_hst[4], ALLOC_##categ##_ctr))) + + fprintf(tf,"%7ld (%5.1f%%) function values", + ALLOC_FUN_ctr, + PC(INTAVG(ALLOC_FUN_ctr, tot_allocs))); + if (ALLOC_FUN_ctr != 0) + fprintf(tf,"\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(FUN)); + + fprintf(tf,"\n%7ld (%5.1f%%) thunks", + ALLOC_THK_ctr, + PC(INTAVG(ALLOC_THK_ctr, tot_allocs))); + if (ALLOC_THK_ctr != 0) + fprintf(tf,"\t\t\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(THK)); + + fprintf(tf,"\n%7ld (%5.1f%%) data values", + ALLOC_CON_ctr, + PC(INTAVG(ALLOC_CON_ctr, tot_allocs))); + if (ALLOC_CON_ctr != 0) + fprintf(tf,"\t\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(CON)); + + fprintf(tf,"\n%7ld (%5.1f%%) big tuples", + ALLOC_TUP_ctr, + PC(INTAVG(ALLOC_TUP_ctr, tot_allocs))); + if (ALLOC_TUP_ctr != 0) + fprintf(tf,"\t\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(TUP)); + + fprintf(tf,"\n%7ld (%5.1f%%) black holes", + ALLOC_BH_ctr, + PC(INTAVG(ALLOC_BH_ctr, tot_allocs))); + if (ALLOC_BH_ctr != 0) + fprintf(tf,"\t\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(BH)); + + fprintf(tf,"\n%7ld (%5.1f%%) prim things", + ALLOC_PRIM_ctr, + PC(INTAVG(ALLOC_PRIM_ctr, tot_allocs))); + if (ALLOC_PRIM_ctr != 0) + fprintf(tf,"\t\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(PRIM)); + + fprintf(tf,"\n%7ld (%5.1f%%) partial applications", + ALLOC_UPD_PAP_ctr, + PC(INTAVG(ALLOC_UPD_PAP_ctr, tot_allocs))); + if (ALLOC_UPD_PAP_ctr != 0) + fprintf(tf,"\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(UPD_PAP)); + + fprintf(tf,"\n%7ld (%5.1f%%) thread state objects", + ALLOC_TSO_ctr, + PC(INTAVG(ALLOC_TSO_ctr, tot_allocs))); + if (ALLOC_TSO_ctr != 0) + fprintf(tf,"\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(TSO)); +#ifdef PAR + fprintf(tf,"\n%7ld (%5.1f%%) thread state objects", + ALLOC_FMBQ_ctr, + PC(INTAVG(ALLOC_FMBQ_ctr, tot_allocs))); + if (ALLOC_FMBQ_ctr != 0) + fprintf(tf,"\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(FMBQ)); + fprintf(tf,"\n%7ld (%5.1f%%) thread state objects", + ALLOC_FME_ctr, + PC(INTAVG(ALLOC_FME_ctr, tot_allocs))); + if (ALLOC_FME_ctr != 0) + fprintf(tf,"\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(FME)); + fprintf(tf,"\n%7ld (%5.1f%%) thread state objects", + ALLOC_BF_ctr, + PC(INTAVG(ALLOC_BF_ctr, tot_allocs))); + if (ALLOC_BF_ctr != 0) + fprintf(tf,"\t\t%5.1f %5.1f %5.1f %5.1f %5.1f", ALLOC_HISTO_MAGIC(BF)); +#endif + fprintf(tf,"\n"); + + fprintf(tf,"\nTotal storage-manager allocations: %ld (%ld words)\n\t[%ld words lost to speculative heap-checks]\n", ALLOC_HEAP_ctr, ALLOC_HEAP_tot, ALLOC_HEAP_tot - tot_wds); + + fprintf(tf,"\nSTACK USAGE:\n"); /* NB: some bits are direction sensitive */ + + fprintf(tf,"\nENTERS: %ld of which %ld (%.1f%%) direct to the entry code\n\t\t [the rest indirected via Node's info ptr]\n", + tot_enters, + jump_direct_enters, + PC(INTAVG(jump_direct_enters,tot_enters))); + fprintf(tf,"%7ld (%5.1f%%) thunks\n", + ENT_THK_ctr, + PC(INTAVG(ENT_THK_ctr,tot_enters))); + fprintf(tf,"%7ld (%5.1f%%) data values\n", + ENT_CON_ctr, + PC(INTAVG(ENT_CON_ctr,tot_enters))); + fprintf(tf,"%7ld (%5.1f%%) function values\n\t\t [of which %ld (%.1f%%) bypassed arg-satisfaction chk]\n", + ENT_FUN_DIRECT_ctr, + PC(INTAVG(ENT_FUN_DIRECT_ctr,tot_enters)), + bypass_enters, + PC(INTAVG(bypass_enters,ENT_FUN_DIRECT_ctr))); + fprintf(tf,"%7ld (%5.1f%%) partial applications\n", + ENT_PAP_ctr, + PC(INTAVG(ENT_PAP_ctr,tot_enters))); + fprintf(tf,"%7ld (%5.1f%%) indirections\n", + ENT_IND_ctr, + PC(INTAVG(ENT_IND_ctr,tot_enters))); + + fprintf(tf,"\nRETURNS: %ld\n", tot_returns); + fprintf(tf,"%7ld (%5.1f%%) from entering a new constructor\n\t\t [the rest from entering an existing constructor]\n", + tot_returns_of_new, + PC(INTAVG(tot_returns_of_new,tot_returns))); + fprintf(tf,"%7ld (%5.1f%%) vectored [the rest unvectored]\n", + VEC_RETURN_ctr, + PC(INTAVG(VEC_RETURN_ctr,tot_returns))); + + fprintf(tf, "\nRET_NEW: %7ld: ", RET_NEW_ctr); + for (i = 0; i < 9; i++) { fprintf(tf, "%5.1f%%", + PC(INTAVG(RET_NEW_hst[i],RET_NEW_ctr))); } + fprintf(tf, "\n"); + fprintf(tf, "RET_OLD: %7ld: ", RET_OLD_ctr); + for (i = 0; i < 9; i++) { fprintf(tf, "%5.1f%%", + PC(INTAVG(RET_OLD_hst[i],RET_OLD_ctr))); } + fprintf(tf, "\n"); + fprintf(tf, "RET_UNBOXED_TUP: %7ld: ", RET_UNBOXED_TUP_ctr); + for (i = 0; i < 9; i++) { fprintf(tf, "%5.1f%%", + PC(INTAVG(RET_UNBOXED_TUP_hst[i], + RET_UNBOXED_TUP_ctr))); } + fprintf(tf, "\n"); + fprintf(tf, "\nRET_VEC_RETURN : %7ld: ", VEC_RETURN_ctr); + for (i = 0; i < 9; i++) { fprintf(tf, "%5.1f%%", + PC(INTAVG(RET_VEC_RETURN_hst[i],VEC_RETURN_ctr))); } + fprintf(tf, "\n"); + + fprintf(tf,"\nUPDATE FRAMES: %ld (%ld omitted from thunks)", + UPDF_PUSHED_ctr, + UPDF_OMITTED_ctr); + + fprintf(tf,"\nSEQ FRAMES: %ld", SEQF_PUSHED_ctr); + + fprintf(tf,"\nCATCH FRAMES: %ld", CATCHF_PUSHED_ctr); + + if (UPDF_RCC_PUSHED_ctr != 0) + fprintf(tf,"%7ld restore cost centre frames (%ld omitted)\n", + UPDF_RCC_PUSHED_ctr, + UPDF_RCC_OMITTED_ctr); + + fprintf(tf,"\nUPDATES: %ld\n", tot_updates); + fprintf(tf,"%7ld (%5.1f%%) data values\n", + UPD_CON_IN_NEW_ctr, + PC(INTAVG(UPD_CON_IN_NEW_ctr,tot_updates))); + fprintf(tf,"%7ld (%5.1f%%) partial applications\n\t\t [%ld in place, %ld allocated new space]\n", + pap_updates, + PC(INTAVG(pap_updates,tot_updates)), + UPD_PAP_IN_PLACE_ctr, UPD_PAP_IN_NEW_ctr); + fprintf(tf,"%7ld (%5.1f%%) updates to existing heap objects (%ld by squeezing)\n", + UPD_EXISTING_ctr + UPD_SQUEEZED_ctr, + PC(INTAVG(UPD_EXISTING_ctr + UPD_SQUEEZED_ctr, tot_updates)), + UPD_SQUEEZED_ctr); + + fprintf(tf, "UPD_CON_IN_NEW: %7ld: ", UPD_CON_IN_NEW_ctr); + for (i = 0; i < 9; i++) { fprintf(tf, "%7ld", UPD_CON_IN_NEW_hst[i]); } + fprintf(tf, "\n"); + fprintf(tf, "UPD_PAP_IN_NEW: %7ld: ", UPD_PAP_IN_NEW_ctr); + for (i = 0; i < 9; i++) { fprintf(tf, "%7ld", UPD_PAP_IN_NEW_hst[i]); } + fprintf(tf, "\n"); + + if (tot_gengc_updates != 0) { + fprintf(tf,"\nNEW GEN UPDATES: %ld (%5.1f%%)\n", + tot_new_updates, + PC(INTAVG(tot_new_updates,tot_gengc_updates))); + fprintf(tf,"\nOLD GEN UPDATES: %ld (%5.1f%%)\n", + tot_old_updates, + PC(INTAVG(tot_old_updates,tot_gengc_updates))); + } + +#if 0 + printRegisteredCounterInfo(tf); +#endif + + fprintf(tf,"\n**************************************************\n"); + + /* here, we print out all the raw numbers; these are really + more useful when we want to snag them for subsequent + rdb-etc processing. WDP 95/11 + */ + +#define PR_CTR(ctr) \ + do { fprintf(tf,"%7ld " #ctr "\n", ctr); } while(0) +#define PR_HST(hst,i) \ + do { fprintf(tf,"%7ld " #hst "_" #i "\n", hst[i]); } while(0) + + PR_CTR(ALLOC_HEAP_ctr); + PR_CTR(ALLOC_HEAP_tot); + + PR_CTR(ALLOC_FUN_ctr); + PR_CTR(ALLOC_FUN_adm); + PR_CTR(ALLOC_FUN_gds); + PR_CTR(ALLOC_FUN_slp); + PR_HST(ALLOC_FUN_hst,0); + PR_HST(ALLOC_FUN_hst,1); + PR_HST(ALLOC_FUN_hst,2); + PR_HST(ALLOC_FUN_hst,3); + PR_HST(ALLOC_FUN_hst,4); + PR_CTR(ALLOC_THK_ctr); + PR_CTR(ALLOC_THK_adm); + PR_CTR(ALLOC_THK_gds); + PR_CTR(ALLOC_THK_slp); + PR_HST(ALLOC_THK_hst,0); + PR_HST(ALLOC_THK_hst,1); + PR_HST(ALLOC_THK_hst,2); + PR_HST(ALLOC_THK_hst,3); + PR_HST(ALLOC_THK_hst,4); + PR_CTR(ALLOC_CON_ctr); + PR_CTR(ALLOC_CON_adm); + PR_CTR(ALLOC_CON_gds); + PR_CTR(ALLOC_CON_slp); + PR_HST(ALLOC_CON_hst,0); + PR_HST(ALLOC_CON_hst,1); + PR_HST(ALLOC_CON_hst,2); + PR_HST(ALLOC_CON_hst,3); + PR_HST(ALLOC_CON_hst,4); + PR_CTR(ALLOC_TUP_ctr); + PR_CTR(ALLOC_TUP_adm); + PR_CTR(ALLOC_TUP_gds); + PR_CTR(ALLOC_TUP_slp); + PR_HST(ALLOC_TUP_hst,0); + PR_HST(ALLOC_TUP_hst,1); + PR_HST(ALLOC_TUP_hst,2); + PR_HST(ALLOC_TUP_hst,3); + PR_HST(ALLOC_TUP_hst,4); + PR_CTR(ALLOC_BH_ctr); + PR_CTR(ALLOC_BH_adm); + PR_CTR(ALLOC_BH_gds); + PR_CTR(ALLOC_BH_slp); + PR_HST(ALLOC_BH_hst,0); + PR_HST(ALLOC_BH_hst,1); + PR_HST(ALLOC_BH_hst,2); + PR_HST(ALLOC_BH_hst,3); + PR_HST(ALLOC_BH_hst,4); + PR_CTR(ALLOC_PRIM_ctr); + PR_CTR(ALLOC_PRIM_adm); + PR_CTR(ALLOC_PRIM_gds); + PR_CTR(ALLOC_PRIM_slp); + PR_HST(ALLOC_PRIM_hst,0); + PR_HST(ALLOC_PRIM_hst,1); + PR_HST(ALLOC_PRIM_hst,2); + PR_HST(ALLOC_PRIM_hst,3); + PR_HST(ALLOC_PRIM_hst,4); + PR_CTR(ALLOC_UPD_PAP_ctr); + PR_CTR(ALLOC_UPD_PAP_adm); + PR_CTR(ALLOC_UPD_PAP_gds); + PR_CTR(ALLOC_UPD_PAP_slp); + PR_HST(ALLOC_UPD_PAP_hst,0); + PR_HST(ALLOC_UPD_PAP_hst,1); + PR_HST(ALLOC_UPD_PAP_hst,2); + PR_HST(ALLOC_UPD_PAP_hst,3); + PR_HST(ALLOC_UPD_PAP_hst,4); + + PR_CTR(ALLOC_TSO_ctr); + PR_CTR(ALLOC_TSO_adm); + PR_CTR(ALLOC_TSO_gds); + PR_CTR(ALLOC_TSO_slp); + PR_HST(ALLOC_TSO_hst,0); + PR_HST(ALLOC_TSO_hst,1); + PR_HST(ALLOC_TSO_hst,2); + PR_HST(ALLOC_TSO_hst,3); + PR_HST(ALLOC_TSO_hst,4); + +#ifdef PAR + PR_CTR(ALLOC_FMBQ_ctr); + PR_CTR(ALLOC_FMBQ_adm); + PR_CTR(ALLOC_FMBQ_gds); + PR_CTR(ALLOC_FMBQ_slp); + PR_HST(ALLOC_FMBQ_hst,0); + PR_HST(ALLOC_FMBQ_hst,1); + PR_HST(ALLOC_FMBQ_hst,2); + PR_HST(ALLOC_FMBQ_hst,3); + PR_HST(ALLOC_FMBQ_hst,4); + PR_CTR(ALLOC_FME_ctr); + PR_CTR(ALLOC_FME_adm); + PR_CTR(ALLOC_FME_gds); + PR_CTR(ALLOC_FME_slp); + PR_HST(ALLOC_FME_hst,0); + PR_HST(ALLOC_FME_hst,1); + PR_HST(ALLOC_FME_hst,2); + PR_HST(ALLOC_FME_hst,3); + PR_HST(ALLOC_FME_hst,4); + PR_CTR(ALLOC_BF_ctr); + PR_CTR(ALLOC_BF_adm); + PR_CTR(ALLOC_BF_gds); + PR_CTR(ALLOC_BF_slp); + PR_HST(ALLOC_BF_hst,0); + PR_HST(ALLOC_BF_hst,1); + PR_HST(ALLOC_BF_hst,2); + PR_HST(ALLOC_BF_hst,3); + PR_HST(ALLOC_BF_hst,4); +#endif + + PR_CTR(ENT_VIA_NODE_ctr); + PR_CTR(ENT_CON_ctr); + PR_CTR(ENT_FUN_STD_ctr); + PR_CTR(ENT_FUN_DIRECT_ctr); + PR_CTR(ENT_IND_ctr); + PR_CTR(ENT_PAP_ctr); + PR_CTR(ENT_THK_ctr); + + PR_CTR(RET_NEW_ctr); + PR_CTR(RET_OLD_ctr); + PR_CTR(RET_SEMI_BY_DEFAULT_ctr); + PR_CTR(RET_SEMI_IN_HEAP_ctr); + PR_CTR(RET_SEMI_FAILED_IND_ctr); + PR_CTR(RET_SEMI_FAILED_UNEVAL_ctr); + PR_CTR(VEC_RETURN_ctr); + + PR_HST(RET_NEW_hst,0); + PR_HST(RET_NEW_hst,1); + PR_HST(RET_NEW_hst,2); + PR_HST(RET_NEW_hst,3); + PR_HST(RET_NEW_hst,4); + PR_HST(RET_NEW_hst,5); + PR_HST(RET_NEW_hst,6); + PR_HST(RET_NEW_hst,7); + PR_HST(RET_NEW_hst,8); + PR_HST(RET_OLD_hst,0); + PR_HST(RET_OLD_hst,1); + PR_HST(RET_OLD_hst,2); + PR_HST(RET_OLD_hst,3); + PR_HST(RET_OLD_hst,4); + PR_HST(RET_OLD_hst,5); + PR_HST(RET_OLD_hst,6); + PR_HST(RET_OLD_hst,7); + PR_HST(RET_OLD_hst,8); + PR_HST(RET_SEMI_IN_HEAP_hst,0); + PR_HST(RET_SEMI_IN_HEAP_hst,1); + PR_HST(RET_SEMI_IN_HEAP_hst,2); + PR_HST(RET_SEMI_IN_HEAP_hst,3); + PR_HST(RET_SEMI_IN_HEAP_hst,4); + PR_HST(RET_SEMI_IN_HEAP_hst,5); + PR_HST(RET_SEMI_IN_HEAP_hst,6); + PR_HST(RET_SEMI_IN_HEAP_hst,7); + PR_HST(RET_SEMI_IN_HEAP_hst,8); + PR_HST(RET_VEC_RETURN_hst,0); + PR_HST(RET_VEC_RETURN_hst,1); + PR_HST(RET_VEC_RETURN_hst,2); + PR_HST(RET_VEC_RETURN_hst,3); + PR_HST(RET_VEC_RETURN_hst,4); + PR_HST(RET_VEC_RETURN_hst,5); + PR_HST(RET_VEC_RETURN_hst,6); + PR_HST(RET_VEC_RETURN_hst,7); + PR_HST(RET_VEC_RETURN_hst,8); + + PR_CTR(RET_SEMI_loads_avoided); + + PR_CTR(UPDF_OMITTED_ctr); + PR_CTR(UPDF_PUSHED_ctr); + PR_CTR(SEQF_PUSHED_ctr); + PR_CTR(CATCHF_PUSHED_ctr); + + PR_CTR(UPDF_RCC_PUSHED_ctr); + PR_CTR(UPDF_RCC_OMITTED_ctr); + + PR_CTR(UPD_EXISTING_ctr); + PR_CTR(UPD_SQUEEZED_ctr); + PR_CTR(UPD_CON_IN_NEW_ctr); + PR_CTR(UPD_PAP_IN_NEW_ctr); + + PR_HST(UPD_CON_IN_NEW_hst,0); + PR_HST(UPD_CON_IN_NEW_hst,1); + PR_HST(UPD_CON_IN_NEW_hst,2); + PR_HST(UPD_CON_IN_NEW_hst,3); + PR_HST(UPD_CON_IN_NEW_hst,4); + PR_HST(UPD_CON_IN_NEW_hst,5); + PR_HST(UPD_CON_IN_NEW_hst,6); + PR_HST(UPD_CON_IN_NEW_hst,7); + PR_HST(UPD_CON_IN_NEW_hst,8); + PR_HST(UPD_PAP_IN_NEW_hst,0); + PR_HST(UPD_PAP_IN_NEW_hst,1); + PR_HST(UPD_PAP_IN_NEW_hst,2); + PR_HST(UPD_PAP_IN_NEW_hst,3); + PR_HST(UPD_PAP_IN_NEW_hst,4); + PR_HST(UPD_PAP_IN_NEW_hst,5); + PR_HST(UPD_PAP_IN_NEW_hst,6); + PR_HST(UPD_PAP_IN_NEW_hst,7); + PR_HST(UPD_PAP_IN_NEW_hst,8); + + PR_CTR(UPD_NEW_IND_ctr); + PR_CTR(UPD_OLD_IND_ctr); + + PR_CTR(GC_SEL_ABANDONED_ctr); + PR_CTR(GC_SEL_MINOR_ctr); + PR_CTR(GC_SEL_MAJOR_ctr); + PR_CTR(GC_FAILED_PROMOTION_ctr); +} + +#if 0 +/* Data structure used in ``registering'' one of these counters. */ + +struct ent_counter *ListOfEntryCtrs = NULL; /* root of list of them */ + +/* To print out all the registered-counter info: */ + +static void +printRegisteredCounterInfo (FILE *tf) +{ + struct ent_counter *p; + + if ( ListOfEntryCtrs != NULL ) { + fprintf(tf,"\n**************************************************\n"); + } + + for (p = ListOfEntryCtrs; p != NULL; p = p->link) { + /* common stuff first; then the wrapper info if avail */ + fprintf(tf, "%-40s%u\t%u\t%u\t%-16s%ld", + p->f_str, + p->arity, + p->Astk_args, + p->Bstk_args, + p->f_arg_kinds, + p->ctr); + + if ( p->wrap_str == NULL ) { + fprintf(tf, "\n"); + + } else { + fprintf(tf, "\t%s\t%s\n", + p->wrap_str, + p->wrap_arg_kinds); + } + } +} +#endif + +#endif /* TICKY_TICKY */ diff --git a/ghc/rts/Ticky.h b/ghc/rts/Ticky.h new file mode 100644 index 0000000..9f93e29 --- /dev/null +++ b/ghc/rts/Ticky.h @@ -0,0 +1,10 @@ +/* ----------------------------------------------------------------------------- + * $Id: Ticky.h,v 1.1 1999/01/21 10:31:53 simonm Exp $ + * + * (c) The GHC Team 1999 + * + * Header for Ticky.c + * + * ---------------------------------------------------------------------------*/ + +extern void PrintTickyInfo(void); diff --git a/ghc/rts/Updates.hc b/ghc/rts/Updates.hc index c98dfa1..cbebe92 100644 --- a/ghc/rts/Updates.hc +++ b/ghc/rts/Updates.hc @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Updates.hc,v 1.6 1999/01/15 17:57:11 simonm Exp $ + * $Id: Updates.hc,v 1.7 1999/01/21 10:31:53 simonm Exp $ * * Code to perform updates. * @@ -273,11 +273,11 @@ EXTFUN(stg_update_PAP) JMP_(stg_gc_entertop); } - TICK_ALLOC_UPD_PAP(DYN_HS, NArgWords, 0, PapSize); + TICK_ALLOC_UPD_PAP(1/*fun*/ + Words, 0); #ifdef PROFILING CCS_ALLOC(CCS_pap, PapSize); #endif - + PapClosure = (StgPAP *)(Hp + 1 - PapSize); /* The new PapClosure */ SET_HDR(PapClosure,&PAP_info,CCS_pap); @@ -335,7 +335,7 @@ EXTFUN(stg_update_PAP) UPD_IND(Updatee,PapClosure); if (Words != 0) { - TICK_UPD_PAP_IN_NEW(NArgWords); + TICK_UPD_PAP_IN_NEW(Words+1); } else { TICK_UPD_PAP_IN_PLACE(); @@ -418,7 +418,7 @@ STGFUN(AP_UPD_entry) PUSH_UPD_FRAME(R1.p, 0); Sp -= sizeofW(StgUpdateFrame) + Words; - TICK_ENT_PAP(ap); /* ToDo: TICK_ENT_AP_UPD */ + TICK_ENT_AP_UPD(ap); /* Enter PAP cost centre -- lexical scoping only */ ENTER_CCS_PAP_CL(ap); /* ToDo: ENTER_CC_AP_UPD_CL */ @@ -571,6 +571,7 @@ FN_(catchZh_fast) fp -> handler = R2.cl; fp -> link = Su; Su = (StgUpdateFrame *)fp; + TICK_CATCHF_PUSHED(); TICK_ENT_VIA_NODE(); JMP_(ENTRY_CODE(*R1.p));