[project @ 2001-11-22 14:25:11 by simonmar]
[ghc-hetmet.git] / ghc / includes / StgLdvProf.h
1 /* -----------------------------------------------------------------------------
2  * $Id: StgLdvProf.h,v 1.1 2001/11/22 14:25:11 simonmar Exp $
3  *
4  * (c) The GHC Team, 2001
5  * Author: Sungwoo Park
6  *
7  * Lag/Drag/Void profiling.
8  *
9  * ---------------------------------------------------------------------------*/
10
11 #ifndef STGLDVPROF_H
12 #define STGLDVPROF_H
13
14 #ifdef PROFILING
15
16 // Engine
17
18 // declared in LdvProfile.c
19 extern nat ldvTime;
20
21 // LdvGenInfo stores the statistics for one specific census. 
22 typedef struct {
23   double time;    // the time in MUT time at the corresponding census is made
24
25   // We employ int instead of nat, for some values may be negative temporarily,
26   // e.g., dragNew.
27
28   // computed at each census
29   int inherentlyUsed;   // total size of 'inherently used' closures
30   int notUsed;          // total size of 'never used' closures
31   int used;             // total size of 'used at least once' closures
32
33   /*
34     voidNew and dragNew are updated when a closure is destroyed.
35     For instance, when a 'never used' closure of size s and creation time 
36     t is destroyed at time u, voidNew of eras t through u - 1 is increased
37     by s. 
38     Likewise, when a 'used at least once' closure of size s and last use time
39     t is destroyed at time u, dragNew of eras t + 1 through u - 1 is increase
40     by s.
41     In our implementation, voidNew and dragNew are computed indirectly: instead
42     of updating voidNew or dragNew of all intervening eras, we update that
43     of the end two eras (one is increased and the other is decreased). 
44    */
45   int voidNew;  // current total size of 'destroyed without being used' closures
46   int dragNew;  // current total size of 'used at least once and waiting to die'
47                 // closures
48
49   // computed post-mortem
50   int voidTotal;  // total size of closures in 'void' state
51   // lagTotal == notUsed - voidTotal    // in 'lag' state
52   int dragTotal;  // total size of closures in 'drag' state 
53   // useTotal == used - dragTotal       // in 'use' state
54 } LdvGenInfo;
55
56 extern LdvGenInfo *gi;
57
58 // retrieves the LDV word from closure c
59 #define LDVW(c)                 (((StgClosure *)(c))->header.prof.hp.ldvw)
60
61 /*
62   An LDV word is divided into 3 parts: state bits (LDV_STATE_MASK), creation 
63   time bits (LDV_CREATE_MASK), and last use time bits (LDV_LAST_MASK). 
64  */
65 #if SIZEOF_VOID_P == 8
66 #define LDV_SHIFT               30
67 #define LDV_STATE_MASK          0x1000000000000000
68 #define LDV_CREATE_MASK         0x0FFFFFFFC0000000
69 #define LDV_LAST_MASK           0x000000003FFFFFFF
70 #define LDV_STATE_CREATE        0x0000000000000000
71 #define LDV_STATE_USE           0x1000000000000000
72 #else
73 #define LDV_SHIFT               15
74 #define LDV_STATE_MASK          0x40000000 
75 #define LDV_CREATE_MASK         0x3FFF8000
76 #define LDV_LAST_MASK           0x00007FFF
77 #define LDV_STATE_CREATE        0x00000000
78 #define LDV_STATE_USE           0x40000000
79 #endif  // SIZEOF_VOID_P
80
81 // Stores the creation time for closure c. 
82 // This macro is called at the very moment of closure creation.
83 //
84 // NOTE: this initializes LDVW(c) to zero, which ensures that there
85 // is no conflict between retainer profiling and LDV profiling,
86 // because retainer profiling also expects LDVW(c) to be initialised
87 // to zero.
88 #define LDV_recordCreate(c)   \
89   LDVW((c)) = (ldvTime << LDV_SHIFT) | LDV_STATE_CREATE
90
91 // Stores the last use time for closure c.
92 // This macro *must* be called whenever a closure is used, that is, it is 
93 // entered.
94 #define LDV_recordUse(c)                                \
95   {                                                     \
96     if (ldvTime > 0)                                    \
97       LDVW((c)) = (LDVW((c)) & LDV_CREATE_MASK) |       \
98                   ldvTime |                             \
99                   LDV_STATE_USE;                        \
100   }
101
102 // Creates a 0-filled slop of size 'howManyBackwards' backwards from the
103 // address 'from'. 
104 //
105 // Invoked when: 
106 //   1) Hp is incremented and exceeds HpLim (in Updates.hc).
107 //   2) copypart() is called (in GC.c).
108 #define FILL_SLOP(from, howManyBackwards)    \
109   if (ldvTime > 0) {                                    \
110     int i;                                              \
111     for (i = 0;i < (howManyBackwards); i++)             \
112       ((StgWord *)(from))[-i] = 0;                      \
113   }
114
115 // Informs the LDV profiler that closure c has just been evacuated.
116 // Evacuated objects are no longer needed, so we just store its original size in
117 // the LDV field.
118 #define SET_EVACUAEE_FOR_LDV(c, size)   \
119     LDVW((c)) = (size)
120
121 // Macros called when a closure is entered. 
122 // The closure is not an 'inherently used' one.
123 // The closure is not IND or IND_OLDGEN because neither is considered for LDV
124 // profiling.
125 #define LDV_ENTER(c)            LDV_recordUse((c))
126
127 #else  // !PROFILING
128
129 #define LDV_ENTER(c)            
130
131 #endif // PROFILING
132 #endif // STGLDVPROF_H