/* -----------------------------------------------------------------------------
- * $Id: StgProf.h,v 1.2 1998/12/02 13:21:39 simonm Exp $
*
- * (c) The GHC Team, 1998
+ * (c) The GHC Team, 2004
*
* Macros for profiling operations in STG code
+ *
* ---------------------------------------------------------------------------*/
#ifndef STGPROF_H
#define STGPROF_H
+/* -----------------------------------------------------------------------------
+ * Data Structures
+ * ---------------------------------------------------------------------------*/
+/*
+ * NB. be careful to avoid unwanted padding between fields, by
+ * putting the 8-byte fields on an 8-byte boundary. Padding can
+ * vary between C compilers, and we don't take into account any
+ * possible padding when generating CCS and CC decls in the code
+ * generator (compiler/codeGen/CgProf.hs).
+ */
+
+typedef struct _CostCentre {
+ StgInt ccID;
+
+ char * label;
+ char * module;
+
+ /* used for accumulating costs at the end of the run... */
+ StgWord time_ticks;
+ StgWord64 mem_alloc; /* align 8 (see above) */
+
+ StgInt is_caf;
+
+ struct _CostCentre *link;
+} CostCentre;
+
+typedef struct _CostCentreStack {
+ StgInt ccsID;
+
+ CostCentre *cc;
+ struct _CostCentreStack *prevStack;
+ struct _IndexTable *indexTable;
+
+ StgWord64 scc_count; /* align 8 (see above) */
+ StgWord selected;
+ StgWord time_ticks;
+ StgWord64 mem_alloc; /* align 8 (see above) */
+ StgWord64 inherited_alloc; /* align 8 (see above) */
+ StgWord inherited_ticks;
+
+ CostCentre *root;
+} CostCentreStack;
+
+
+/* -----------------------------------------------------------------------------
+ * The rest is PROFILING only...
+ * ---------------------------------------------------------------------------*/
+
#if defined(PROFILING)
/* -----------------------------------------------------------------------------
+ * Constants
+ * ---------------------------------------------------------------------------*/
+
+#define EMPTY_STACK NULL
+#define EMPTY_TABLE NULL
+
+/* Constants used to set sumbsumed flag on CostCentres */
+
+#define CC_IS_CAF 'c' /* 'c' => *is* a CAF cc */
+#define CC_IS_BORING 'B' /* 'B' => *not* a CAF/sub cc */
+
+
+/* -----------------------------------------------------------------------------
+ * Data Structures
+ * ---------------------------------------------------------------------------*/
+
+typedef struct _IndexTable {
+ CostCentre *cc;
+ CostCentreStack *ccs;
+ struct _IndexTable *next;
+ unsigned int back_edge;
+} IndexTable;
+
+
+/* -----------------------------------------------------------------------------
+ Pre-defined cost centres and cost centre stacks
+ -------------------------------------------------------------------------- */
+
+extern CostCentreStack * RTS_VAR(CCCS); /* current CCS */
+
+#if IN_STG_CODE
+
+extern StgWord CC_MAIN[];
+extern StgWord CCS_MAIN[]; /* Top CCS */
+
+extern StgWord CC_SYSTEM[];
+extern StgWord CCS_SYSTEM[]; /* RTS costs */
+
+extern StgWord CC_GC[];
+extern StgWord CCS_GC[]; /* Garbage collector costs */
+
+extern StgWord CC_SUBSUMED[];
+extern StgWord CCS_SUBSUMED[]; /* Costs are subsumed by caller */
+
+extern StgWord CC_OVERHEAD[];
+extern StgWord CCS_OVERHEAD[]; /* Profiling overhead */
+
+extern StgWord CC_DONT_CARE[];
+extern StgWord CCS_DONT_CARE[]; /* shouldn't ever get set */
+
+#else
+
+extern CostCentre CC_MAIN[];
+extern CostCentreStack CCS_MAIN[]; /* Top CCS */
+
+extern CostCentre CC_SYSTEM[];
+extern CostCentreStack CCS_SYSTEM[]; /* RTS costs */
+
+extern CostCentre CC_GC[];
+extern CostCentreStack CCS_GC[]; /* Garbage collector costs */
+
+extern CostCentre CC_SUBSUMED[];
+extern CostCentreStack CCS_SUBSUMED[]; /* Costs are subsumed by caller */
+
+extern CostCentre CC_OVERHEAD[];
+extern CostCentreStack CCS_OVERHEAD[]; /* Profiling overhead */
+
+extern CostCentre CC_DONT_CARE[];
+extern CostCentreStack CCS_DONT_CARE[]; /* shouldn't ever get set */
+
+#endif /* IN_STG_CODE */
+
+extern unsigned int RTS_VAR(CC_ID); /* global ids */
+extern unsigned int RTS_VAR(CCS_ID);
+extern unsigned int RTS_VAR(HP_ID);
+
+extern unsigned int RTS_VAR(era);
+
+/* -----------------------------------------------------------------------------
+ * Functions
+ * ---------------------------------------------------------------------------*/
+
+void EnterFunCCS ( CostCentreStack *ccsfn );
+CostCentreStack *PushCostCentre ( CostCentreStack *, CostCentre * );
+CostCentreStack *AppendCCS ( CostCentreStack *ccs1, CostCentreStack *ccs2 );
+
+extern unsigned int RTS_VAR(entering_PAP);
+
+/* -----------------------------------------------------------------------------
* Registering CCs
Cost centres are registered at startup by calling a registering
-------------------------------------------------------------------------- */
-extern F_ *register_stack;
-
-extern CostCentre *CC_LIST; /* registered CC list */
-extern CostCentreStack *CCS_LIST; /* registered CCS list */
-
-# define PUSH_REGISTER_STACK(reg_function) \
- *(register_stack++) = (F_)reg_function
-
-# define POP_REGISTER_STACK() \
- *(--register_stack)
-
-# define START_REGISTER_CCS(reg_mod_name) \
- static int _module_registered = 0; \
- FN_(reg_mod_name) { \
- FB_; \
- if (! _module_registered) { \
- _module_registered = 1
-
-# define REGISTER_IMPORT(reg_mod_name) \
- do { EF_(reg_mod_name); \
- PUSH_REGISTER_STACK(reg_mod_name) ; \
- } while (0)
-
-# define END_REGISTER_CCS() \
- }; \
- JMP_(POP_REGISTER_STACK()); \
- FE_ }
+extern CostCentre * RTS_VAR(CC_LIST); /* registered CC list */
+extern CostCentreStack * RTS_VAR(CCS_LIST); /* registered CCS list */
#define REGISTER_CC(cc) \
do { \
* Declaring Cost Centres & Cost Centre Stacks.
* -------------------------------------------------------------------------- */
-# define CC_DECLARE(cc_ident,name,module,group,subsumed,is_local) \
- is_local CostCentre cc_ident[1] \
- = {{ 0, \
- name, \
- module, \
- group, \
- subsumed, \
+# define CC_DECLARE(cc_ident,name,module,caf,is_local) \
+ is_local CostCentre cc_ident[1] \
+ = {{ 0, \
+ name, \
+ module, \
+ 0, \
+ 0, \
+ caf, \
0 }};
-# define CCS_DECLARE(ccs_ident,cc_ident,subsumed,is_local) \
+# define CCS_DECLARE(ccs_ident,cc_ident,is_local) \
is_local CostCentreStack ccs_ident[1] \
= {{ ccsID : 0, \
cc : cc_ident, \
prevStack : NULL, \
indexTable : NULL, \
+ selected : 0, \
scc_count : 0, \
- sub_scc_count : 0, \
- sub_cafcc_count : 0, \
- sub_dictcc_count : 0, \
time_ticks : 0, \
mem_alloc : 0, \
- is_subsumed : subsumed, \
+ inherited_ticks : 0, \
+ inherited_alloc : 0, \
+ root : 0, \
}};
-# define CC_EXTERN(cc_ident) \
- extern CostCentre cc_ident[];
-
/* -----------------------------------------------------------------------------
* Time / Allocation Macros
* ---------------------------------------------------------------------------*/
-#define CCS_TICK(ccs) (ccs)->time_ticks++
-
/* eliminate profiling overhead from allocation costs */
#define CCS_ALLOC(ccs, size) (ccs)->mem_alloc += ((size)-sizeofW(StgProfHeader))
-/* For grabbing the cost centre from a closure */
-#define CCS_HDR(closure) ((StgClosure *)(closure))->header.prof.ccs
-
-/* Restore the CCCS from a stack fram.
- * (addr should always be Sp->header.prof.ccs)
- */
-#define RESTORE_CCCS(addr) (CCCS = (CostCentreStack *)(addr))
-
-/* -----------------------------------------------------------------------------
- * Pushing a new cost centre (i.e. for scc annotations)
- * -------------------------------------------------------------------------- */
-
-# define SET_CCC_X(cc,do_subcc_count,do_subdict_count,do_scc_count) \
- do { \
- if (do_subcc_count) { CCCS->sub_scc_count++; } \
- if (do_subdict_count) { CCCS->sub_dictcc_count++; } \
- CCCS = PushCostCentre(CCCS,cc); \
- if (do_scc_count) { CCCS->scc_count++; } \
- } while(0)
-
-/* We sometimes don't increment the scc_count field, for example when
- * this scc has been placed by the compiler on an expression it
- * floated outside the main scc annotation.
- */
-
-# define SET_CCC(cc_ident,do_scc_count) \
- SET_CCC_X(cc_ident,do_scc_count,0,do_scc_count)
-
-# define SET_DICT_CCC(cc_ident,do_scc_count) \
- SET_CCC_X(cc_ident,0,do_scc_count,do_scc_count)
-
-# define SET_CCS_TOP(cc_ident) \
- SET_CCC_X(cc_ident,0,0,1)
-
-/* -----------------------------------------------------------------------------
- * Allocating new cost centres / cost centre stacks.
- * -------------------------------------------------------------------------- */
-
-#define ASSIGN_CC_ID(ccID) \
- do { \
- ccID = CC_ID; \
- CC_ID++; \
- } while(0)
-
-#define ASSIGN_CCS_ID(ccsID) \
- do { \
- ccsID = CCS_ID; \
- CCS_ID++; \
- } while(0)
-
-#define ASSIGN_HP_ID(hpID) \
- do { \
- hpID = HP_ID; \
- HP_ID++; \
- } while(0)
-
-#define SET_STATS_TO_ZERO(stack) \
- do { \
- (stack)->scc_count = 0; \
- (stack)->time_ticks = 0; \
- (stack)->sub_cafcc_count = 0; \
- (stack)->sub_dictcc_count = 0; \
- (stack)->mem_alloc = 0; \
- } while(0)
-
-/* -----------------------------------------------------------------------------
- * Setting the cost centre when we enter a closure
- * -------------------------------------------------------------------------- */
-
-#if defined(PROFILING_DETAIL_COUNTS)
-#define CCCS_DETAIL_COUNT(inc_this) ((inc_this)++)
-#else
-#define CCCS_DETAIL_COUNT(inc_this) /*nothing*/
-#endif
-
-#define IS_CAF_OR_DICT_OR_SUB_CCS(ccs) \
- /* tests for lower case character */ \
- ((ccs)->is_subsumed & ' ')
-
-
-/* On entry to top level CAFs we count the scc ...*/
-
-#define ENTER_CCS_CAF_X(ccs) \
- do { \
- /* inc subcaf count of CCCS */ \
- CCCS->sub_cafcc_count++; \
- /* set CCCS to ident ccs */ \
- CCCS = (CostCentreStack *)(ccs); \
- /* inc scc count of CAF ccs */ \
- CCCS->scc_count++; \
- } while(0)
-
-#define ENTER_CCS_CAF(ccs_ident) ENTER_CCS_CAF_X(ccs_ident)
-#define ENTER_CCS_CAF_CL(closure) ENTER_CCS_CAF_X(CCS_HDR(closure))
-
-/* ----------------------------------------------------------------------------
- * Entering a Thunk
- *
- * On entering a closure we only count the enter to thunks ...
- * ------------------------------------------------------------------------- */
-
-#define ENTER_CCS_T(ccs) \
- do { \
- CCCS = (CostCentreStack *)(ccs); \
- CCCS_DETAIL_COUNT(CCCS->thunk_count); \
- } while(0)
-
-#define ENTER_CCS_TCL(closure) ENTER_CCS_T(CCS_HDR(closure))
-
-/* -----------------------------------------------------------------------------
- * Entering a function
- *
- * Here is our special "hybrid" case when we do *not* set the CCCS.
- * (a) The closure is a function, not a thunk;
- * (b) The CCS is CAF/DICT-ish.
- * -------------------------------------------------------------------------- */
-
-#define ENTER_CCS_F(stack) \
- do { \
- CostCentreStack *ccs = (CostCentreStack *) (stack); \
- if ( ! IS_CAF_OR_DICT_OR_SUB_CCS(ccs) ) { \
- CCCS = ccs; \
- } else { \
- CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
- CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
- } \
- CCCS_DETAIL_COUNT(CCCS->function_count); \
- } while(0)
-
-#define ENTER_CCS_FCL(closure) ENTER_CCS_F(CCS_HDR(closure))
+#else /* !PROFILING */
-/* Entering a top-level function: costs are subsumed by the caller
- */
-#define ENTER_CCS_FSUB() \
- do { \
- CCCS_DETAIL_COUNT(CCCS->subsumed_fun_count); \
- CCCS_DETAIL_COUNT(CCCS->function_count); \
- } while(0)
-
-#define ENTER_CCS_FCAF(stack) \
- do { \
- CostCentreStack *ccs = (CostCentreStack *) (stack); \
- CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
- CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
- CCCS_DETAIL_COUNT(CCCS->function_count); \
- } while(0)
-
-#define ENTER_CCS_FLOAD(ccs) \
- do { \
- CCCS = (CostCentreStack *)(ccs); \
- CCCS_DETAIL_COUNT(CCCS->function_count); \
- } while(0)
+#define CCS_ALLOC(ccs, amount) doNothing()
-/* These ENTER_CC_PAP things are only used in the RTS */
-
-#define ENTER_CCS_PAP(stack) \
- do { \
- CostCentreStack *ccs = (CostCentreStack *) (stack); \
- if ( ! IS_CAF_OR_DICT_OR_SUB_CCS(ccs) ) { \
- CCCS = ccs; \
- } else { \
- CCCS_DETAIL_COUNT(ccs->caffun_subsumed); \
- CCCS_DETAIL_COUNT(CCCS->subsumed_caf_count); \
- } \
- CCCS_DETAIL_COUNT(CCCS->pap_count); \
- } while(0)
-
-#define ENTER_CCS_PAP_CL(closure) \
- ENTER_CCS_PAP((closure)->header.prof.ccs)
-
- /* temp EW */
-#define STATIC_CCS_REF(ccs) (ccs)
-
#endif /* PROFILING */
#endif /* STGPROF_H */
+