GC.h 10.4 KB
Newer Older
Simon Marlow's avatar
Simon Marlow committed
1 2 3 4 5 6 7 8
/* -----------------------------------------------------------------------------
 *
 * (c) The GHC Team, 1998-2004
 *
 * External Storage Manger Interface
 *
 * ---------------------------------------------------------------------------*/

9
#pragma once
Simon Marlow's avatar
Simon Marlow committed
10 11 12 13 14 15 16

#include <stddef.h>
#include "rts/OSThreads.h"

/* -----------------------------------------------------------------------------
 * Generational GC
 *
Simon Marlow's avatar
Simon Marlow committed
17 18
 * We support an arbitrary number of generations.  Notes (in no particular
 * order):
Simon Marlow's avatar
Simon Marlow committed
19
 *
Simon Marlow's avatar
Simon Marlow committed
20 21
 *       - Objects "age" in the nursery for one GC cycle before being promoted
 *         to the next generation.  There is no aging in other generations.
Simon Marlow's avatar
Simon Marlow committed
22
 *
Simon Marlow's avatar
Simon Marlow committed
23
 *       - generation 0 is the allocation area.  It is given
Simon Marlow's avatar
Simon Marlow committed
24 25 26 27
 *         a fixed set of blocks during initialisation, and these blocks
 *         normally stay in G0S0.  In parallel execution, each
 *         Capability has its own nursery.
 *
Simon Marlow's avatar
Simon Marlow committed
28 29 30 31 32 33
 *       - during garbage collection, each generation which is an
 *         evacuation destination (i.e. all generations except G0) is
 *         allocated a to-space.  evacuated objects are allocated into
 *         the generation's to-space until GC is finished, when the
 *         original generations's contents may be freed and replaced
 *         by the to-space.
Simon Marlow's avatar
Simon Marlow committed
34
 *
Simon Marlow's avatar
Simon Marlow committed
35 36
 *       - the mutable-list is per-generation.  G0 doesn't have one
 *         (since every garbage collection collects at least G0).
37
 *
Simon Marlow's avatar
Simon Marlow committed
38 39
 *       - block descriptors contain a pointer to the generation that
 *         the block belongs to, for convenience.
Simon Marlow's avatar
Simon Marlow committed
40 41 42 43
 *
 *       - static objects are stored in per-generation lists.  See GC.c for
 *         details of how we collect CAFs in the generational scheme.
 *
Simon Marlow's avatar
Simon Marlow committed
44 45
 *       - large objects are per-generation, and are promoted in the
 *         same way as small objects.
Simon Marlow's avatar
Simon Marlow committed
46 47 48
 *
 * ------------------------------------------------------------------------- */

49 50 51 52 53 54 55 56
// A count of blocks needs to store anything up to the size of memory
// divided by the block size.  The safest thing is therefore to use a
// type that can store the full range of memory addresses,
// ie. StgWord.  Note that we have had some tricky int overflows in a
// couple of cases caused by using ints rather than longs (e.g. #5086)

typedef StgWord memcount;

57 58
typedef struct nursery_ {
    bdescr *       blocks;
59
    memcount       n_blocks;
60
} nursery;
Simon Marlow's avatar
Simon Marlow committed
61

Simon Marlow's avatar
Simon Marlow committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
// Nursery invariants:
//
//  - cap->r.rNursery points to the nursery for this capability
//
//  - cap->r.rCurrentNursery points to the block in the nursery that we are
//    currently allocating into.  While in Haskell the current heap pointer is
//    in Hp, outside Haskell it is stored in cap->r.rCurrentNursery->free.
//
//  - the blocks *after* cap->rCurrentNursery in the chain are empty
//    (although their bd->free pointers have not been updated to
//    reflect that)
//
//  - the blocks *before* cap->rCurrentNursery have been used.  Except
//    for rCurrentAlloc.
//
//  - cap->r.rCurrentAlloc is either NULL, or it points to a block in
//    the nursery *before* cap->r.rCurrentNursery.
//
// See also Note [allocation accounting] to understand how total
// memory allocation is tracked.

83
typedef struct generation_ {
84
    uint32_t       no;                  // generation number
Simon Marlow's avatar
Simon Marlow committed
85

86
    bdescr *       blocks;              // blocks in this gen
87 88
    memcount       n_blocks;            // number of blocks
    memcount       n_words;             // number of used words
Simon Marlow's avatar
Simon Marlow committed
89

90
    bdescr *       large_objects;       // large objects (doubly linked)
91
    memcount       n_large_blocks;      // no. of blocks used by large objs
92
    memcount       n_large_words;       // no. of words used by large objs
93
    memcount       n_new_large_words;   // words of new large objects
94
                                        // (for doYouWantToGC())
Simon Marlow's avatar
Simon Marlow committed
95

gcampax's avatar
gcampax committed
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
    bdescr *       compact_objects;     // compact objects chain
                                        // the second block in each compact is
                                        // linked from the closure object, while
                                        // the second compact object in the
                                        // chain is linked from bd->link (like
                                        // large objects)
    memcount       n_compact_blocks;    // no. of blocks used by all compacts
    bdescr *       compact_blocks_in_import; // compact objects being imported
                                             // (not known to the GC because
                                             // potentially invalid, but we
                                             // need to keep track of them
                                             // to avoid assertions in Sanity)
                                             // this is a list shaped like compact_objects
    memcount       n_compact_blocks_in_import; // no. of blocks used by compacts
                                               // being imported

112 113 114 115 116 117
    // Max blocks to allocate in this generation before collecting it. Collect
    // this generation when
    //
    //     n_blocks + n_large_blocks + n_compact_blocks > max_blocks
    //
    memcount       max_blocks;
118

119
    StgTSO *       threads;             // threads in this gen
Simon Marlow's avatar
Simon Marlow committed
120
                                        // linked via global_link
121 122
    StgWeak *      weak_ptr_list;       // weak pointers in this gen

123
    struct generation_ *to;             // destination gen for live objects
124 125

    // stats information
126 127
    uint32_t collections;
    uint32_t par_collections;
128
    uint32_t failed_promotions;         // Currently unused
Simon Marlow's avatar
Simon Marlow committed
129 130 131 132 133 134 135

    // ------------------------------------
    // Fields below are used during GC only

#if defined(THREADED_RTS)
    char pad[128];                      // make sure the following is
                                        // on a separate cache line.
Simon Marlow's avatar
Simon Marlow committed
136
    SpinLock     sync;                  // lock for large_objects
Simon Marlow's avatar
Simon Marlow committed
137 138 139
                                        //    and scavenged_large_objects
#endif

140 141
    int          mark;                  // mark (not copy)? (old gen only)
    int          compact;               // compact (not sweep)? (old gen only)
Simon Marlow's avatar
Simon Marlow committed
142

143
    // During GC, if we are collecting this gen, blocks and n_blocks
144 145
    // are copied into the following two fields.  After GC, these blocks
    // are freed.
146
    bdescr *     old_blocks;            // bdescr of first from-space block
147 148
    memcount     n_old_blocks;         // number of blocks in from-space
    memcount     live_estimate;         // for sweeping: estimate of live data
149

Simon Marlow's avatar
Simon Marlow committed
150
    bdescr *     scavenged_large_objects;  // live large objs after GC (d-link)
151
    memcount     n_scavenged_large_blocks; // size (not count) of above
Simon Marlow's avatar
Simon Marlow committed
152

gcampax's avatar
gcampax committed
153 154 155
    bdescr *     live_compact_objects;  // live compact objs after GC (d-link)
    memcount     n_live_compact_blocks; // size (not count) of above

156
    bdescr *     bitmap;                // bitmap for compacting collection
Simon Marlow's avatar
Simon Marlow committed
157 158

    StgTSO *     old_threads;
159
    StgWeak *    old_weak_ptr_list;
Simon Marlow's avatar
Simon Marlow committed
160 161 162 163 164 165 166 167 168
} generation;

extern generation * generations;
extern generation * g0;
extern generation * oldest_gen;

/* -----------------------------------------------------------------------------
   Generic allocation

169
   StgPtr allocate(Capability *cap, W_ n)
Simon Marlow's avatar
Simon Marlow committed
170
                                Allocates memory from the nursery in
Simon Marlow's avatar
Simon Marlow committed
171
                                the current Capability.
Simon Marlow's avatar
Simon Marlow committed
172

173
   StgPtr allocatePinned(Capability *cap, W_ n)
174
                                Allocates a chunk of contiguous store
175 176 177 178 179 180 181 182 183 184 185 186 187 188
                                n words long, which is at a fixed
                                address (won't be moved by GC).
                                Returns a pointer to the first word.
                                Always succeeds.

                                NOTE: the GC can't in general handle
                                pinned objects, so allocatePinned()
                                can only be used for ByteArrays at the
                                moment.

                                Don't forget to TICK_ALLOC_XXX(...)
                                after calling allocate or
                                allocatePinned, for the
                                benefit of the ticky-ticky profiler.
Simon Marlow's avatar
Simon Marlow committed
189 190 191

   -------------------------------------------------------------------------- */

192 193 194
StgPtr  allocate          ( Capability *cap, W_ n );
StgPtr  allocateMightFail ( Capability *cap, W_ n );
StgPtr  allocatePinned    ( Capability *cap, W_ n );
Simon Marlow's avatar
Simon Marlow committed
195 196

/* memory allocator for executable memory */
197 198 199 200
typedef void* AdjustorWritable;
typedef void* AdjustorExecutable;

AdjustorWritable allocateExec(W_ len, AdjustorExecutable *exec_addr);
201
void flushExec(W_ len, AdjustorExecutable exec_addr);
202 203 204
#if defined(ios_HOST_OS)
AdjustorWritable execToWritable(AdjustorExecutable exec);
#endif
205
void             freeExec (AdjustorExecutable p);
Simon Marlow's avatar
Simon Marlow committed
206

207
// Used by GC checks in external .cmm code:
208
extern W_ large_alloc_lim;
209

Simon Marlow's avatar
Simon Marlow committed
210 211 212 213 214 215 216 217 218 219 220
/* -----------------------------------------------------------------------------
   Performing Garbage Collection
   -------------------------------------------------------------------------- */

void performGC(void);
void performMajorGC(void);

/* -----------------------------------------------------------------------------
   The CAF table - used to let us revert CAFs in GHCi
   -------------------------------------------------------------------------- */

221 222 223
StgInd *newCAF         (StgRegTable *reg, StgIndStatic *caf);
StgInd *newRetainedCAF (StgRegTable *reg, StgIndStatic *caf);
StgInd *newGCdCAF      (StgRegTable *reg, StgIndStatic *caf);
Simon Marlow's avatar
Simon Marlow committed
224 225
void revertCAFs (void);

226
// Request that all CAFs are retained indefinitely.
227
// (preferably use RtsConfig.keep_cafs instead)
228 229
void setKeepCAFs (void);

230 231 232 233 234 235 236
/* -----------------------------------------------------------------------------
   This is the write barrier for MUT_VARs, a.k.a. IORefs.  A
   MUT_VAR_CLEAN object is not on the mutable list; a MUT_VAR_DIRTY
   is.  When written to, a MUT_VAR_CLEAN turns into a MUT_VAR_DIRTY
   and is put on the mutable list.
   -------------------------------------------------------------------------- */

237
void dirty_MUT_VAR(StgRegTable *reg, StgMutVar *mv, StgClosure *old);
238

Simon Marlow's avatar
Simon Marlow committed
239 240
/* set to disable CAF garbage collection in GHCi. */
/* (needed when dynamic libraries are used). */
Ben Gamari's avatar
Ben Gamari committed
241
extern bool keepCAFs;
Simon Marlow's avatar
Simon Marlow committed
242

243 244
#include "rts/Flags.h"

245
INLINE_HEADER void initBdescr(bdescr *bd, generation *gen, generation *dest)
246
{
Simon Marlow's avatar
Simon Marlow committed
247 248 249
    bd->gen     = gen;
    bd->gen_no  = gen->no;
    bd->dest_no = dest->no;
250 251 252 253 254 255

#if !IN_STG_CODE
    /* See Note [RtsFlags is a pointer in STG code] */
    ASSERT(gen->no < RtsFlags.GcFlags.generations);
    ASSERT(dest->no < RtsFlags.GcFlags.generations);
#endif
256
}