[project @ 2005-04-27 14:37:26 by simonmar]
[ghc-hetmet.git] / ghc / includes / Storage.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2004
4  *
5  * External Storage Manger Interface
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #ifndef STORAGE_H
10 #define STORAGE_H
11
12 #include <stddef.h>
13 #include "OSThreads.h"
14
15 /* -----------------------------------------------------------------------------
16  * Generational GC
17  *
18  * We support an arbitrary number of generations, with an arbitrary number
19  * of steps per generation.  Notes (in no particular order):
20  *
21  *       - all generations except the oldest should have two steps.  This gives
22  *         objects a decent chance to age before being promoted, and in
23  *         particular will ensure that we don't end up with too many
24  *         thunks being updated in older generations.
25  *
26  *       - the oldest generation has one step.  There's no point in aging
27  *         objects in the oldest generation.
28  *
29  *       - generation 0, step 0 (G0S0) is the allocation area.  It is given
30  *         a fixed set of blocks during initialisation, and these blocks
31  *         are never freed.
32  *
33  *       - during garbage collection, each step which is an evacuation
34  *         destination (i.e. all steps except G0S0) is allocated a to-space.
35  *         evacuated objects are allocated into the step's to-space until
36  *         GC is finished, when the original step's contents may be freed
37  *         and replaced by the to-space.
38  *
39  *       - the mutable-list is per-generation (not per-step).  G0 doesn't 
40  *         have one (since every garbage collection collects at least G0).
41  * 
42  *       - block descriptors contain pointers to both the step and the
43  *         generation that the block belongs to, for convenience.
44  *
45  *       - static objects are stored in per-generation lists.  See GC.c for
46  *         details of how we collect CAFs in the generational scheme.
47  *
48  *       - large objects are per-step, and are promoted in the same way
49  *         as small objects, except that we may allocate large objects into
50  *         generation 1 initially.
51  *
52  * ------------------------------------------------------------------------- */
53
54 typedef struct step_ {
55   unsigned int         no;              /* step number */
56   bdescr *             blocks;          /* blocks in this step */
57   unsigned int         n_blocks;        /* number of blocks */
58   struct step_ *       to;              /* destination step for live objects */
59   struct generation_ * gen;             /* generation this step belongs to */
60   unsigned int         gen_no;          /* generation number (cached) */
61   bdescr *             large_objects;   /* large objects (doubly linked) */
62   unsigned int         n_large_blocks;  /* no. of blocks used by large objs */
63   int                  is_compacted;    /* compact this step? (old gen only) */
64
65   /* temporary use during GC: */
66   StgPtr       hp;                      /* next free locn in to-space */
67   StgPtr       hpLim;                   /* end of current to-space block */
68   bdescr *     hp_bd;                   /* bdescr of current to-space block */
69   bdescr *     to_blocks;               /* bdescr of first to-space block */
70   unsigned int n_to_blocks;             /* number of blocks in to-space */
71   bdescr *     scan_bd;                 /* block currently being scanned */
72   StgPtr       scan;                    /* scan pointer in current block */
73   bdescr *     new_large_objects;       /* large objects collected so far */
74   bdescr *     scavenged_large_objects; /* live large objs after GC (d-link) */
75   unsigned int n_scavenged_large_blocks;/* size of above */
76   bdescr *     bitmap;                  /* bitmap for compacting collection */
77 } step;
78
79 typedef struct generation_ {
80   unsigned int   no;                    /* generation number */
81   step *         steps;                 /* steps */
82   unsigned int   n_steps;               /* number of steps */
83   unsigned int   max_blocks;            /* max blocks in step 0 */
84   bdescr        *mut_list;              /* mut objects in this gen (not G0)*/
85
86   /* temporary use during GC: */
87   bdescr        *saved_mut_list;
88
89   /* stats information */
90   unsigned int collections;
91   unsigned int failed_promotions;
92 } generation;
93
94 extern generation * RTS_VAR(generations);
95
96 extern generation * RTS_VAR(g0);
97 extern step * RTS_VAR(g0s0);
98 extern generation * RTS_VAR(oldest_gen);
99
100 /* -----------------------------------------------------------------------------
101    Initialisation / De-initialisation
102    -------------------------------------------------------------------------- */
103
104 extern void initStorage(void);
105 extern void exitStorage(void);
106
107 /* -----------------------------------------------------------------------------
108    Generic allocation
109
110    StgPtr allocate(nat n)       Allocates a chunk of contiguous store
111                                 n words long, returning a pointer to
112                                 the first word.  Always succeeds.
113                                 
114    StgPtr allocatePinned(nat n) Allocates a chunk of contiguous store
115                                 n words long, which is at a fixed
116                                 address (won't be moved by GC).  
117                                 Returns a pointer to the first word.
118                                 Always succeeds.
119                                 
120                                 NOTE: the GC can't in general handle
121                                 pinned objects, so allocatePinned()
122                                 can only be used for ByteArrays at the
123                                 moment.
124
125                                 Don't forget to TICK_ALLOC_XXX(...)
126                                 after calling allocate or
127                                 allocatePinned, for the
128                                 benefit of the ticky-ticky profiler.
129
130    rtsBool doYouWantToGC(void)  Returns True if the storage manager is
131                                 ready to perform a GC, False otherwise.
132
133    lnat  allocated_bytes(void)  Returns the number of bytes allocated
134                                 via allocate() since the last GC.
135                                 Used in the reporting of statistics.
136
137    SMP: allocate and doYouWantToGC can be used from STG code, they are
138    surrounded by a mutex.
139    -------------------------------------------------------------------------- */
140
141 extern StgPtr  allocate        ( nat n );
142 extern StgPtr  allocatePinned  ( nat n );
143 extern lnat    allocated_bytes ( void );
144
145 extern bdescr * RTS_VAR(small_alloc_list);
146 extern bdescr * RTS_VAR(large_alloc_list);
147 extern bdescr * RTS_VAR(pinned_object_block);
148
149 extern StgPtr RTS_VAR(alloc_Hp);
150 extern StgPtr RTS_VAR(alloc_HpLim);
151
152 extern nat RTS_VAR(alloc_blocks);
153 extern nat RTS_VAR(alloc_blocks_lim);
154
155 INLINE_HEADER rtsBool
156 doYouWantToGC( void )
157 {
158   return (alloc_blocks >= alloc_blocks_lim);
159 }
160
161 /* -----------------------------------------------------------------------------
162    Performing Garbage Collection
163
164    GarbageCollect(get_roots)    Performs a garbage collection.  
165                                 'get_roots' is called to find all the 
166                                 roots that the system knows about.
167
168    StgClosure                   Called by get_roots on each root.       
169    MarkRoot(StgClosure *p)      Returns the new location of the root.
170    -------------------------------------------------------------------------- */
171
172 extern void GarbageCollect(void (*get_roots)(evac_fn),rtsBool force_major_gc);
173
174 /* -----------------------------------------------------------------------------
175    Generational garbage collection support
176
177    recordMutable(StgPtr p)       Informs the garbage collector that a
178                                  previously immutable object has
179                                  become (permanently) mutable.  Used
180                                  by thawArray and similar.
181
182    updateWithIndirection(p1,p2)  Updates the object at p1 with an
183                                  indirection pointing to p2.  This is
184                                  normally called for objects in an old
185                                  generation (>0) when they are updated.
186
187    updateWithPermIndirection(p1,p2)  As above but uses a permanent indir.
188
189    -------------------------------------------------------------------------- */
190
191 /*
192  * Storage manager mutex
193  */
194 #if defined(SMP)
195 extern Mutex sm_mutex;
196 #define ACQUIRE_SM_LOCK   ACQUIRE_LOCK(&sm_mutex);
197 #define RELEASE_SM_LOCK   RELEASE_LOCK(&sm_mutex);
198 #else
199 #define ACQUIRE_SM_LOCK
200 #define RELEASE_SM_LOCK
201 #endif
202
203 INLINE_HEADER void
204 recordMutableGen(StgClosure *p, generation *gen)
205 {
206     bdescr *bd;
207
208     bd = gen->mut_list;
209     if (bd->free >= bd->start + BLOCK_SIZE_W) {
210         bdescr *new_bd;
211         new_bd = allocBlock();
212         new_bd->link = bd;
213         bd = new_bd;
214         gen->mut_list = bd;
215     }
216     *bd->free++ = (StgWord)p;
217
218 }
219
220 INLINE_HEADER void
221 recordMutableGenLock(StgClosure *p, generation *gen)
222 {
223     ACQUIRE_SM_LOCK;
224     recordMutableGen(p,gen);
225     RELEASE_SM_LOCK;
226 }
227
228 INLINE_HEADER void
229 recordMutable(StgClosure *p)
230 {
231     bdescr *bd;
232     ASSERT(closure_MUTABLE(p));
233     bd = Bdescr((P_)p);
234     if (bd->gen_no > 0) recordMutableGen(p, &RTS_DEREF(generations)[bd->gen_no]);
235 }
236
237 INLINE_HEADER void
238 recordMutableLock(StgClosure *p)
239 {
240     ACQUIRE_SM_LOCK;
241     recordMutable(p);
242     RELEASE_SM_LOCK;
243 }
244
245 /* -----------------------------------------------------------------------------
246    The CAF table - used to let us revert CAFs in GHCi
247    -------------------------------------------------------------------------- */
248
249 /* set to disable CAF garbage collection in GHCi. */
250 /* (needed when dynamic libraries are used). */
251 extern rtsBool keepCAFs;
252
253 /* -----------------------------------------------------------------------------
254    DEBUGGING predicates for pointers
255
256    LOOKS_LIKE_INFO_PTR(p)    returns False if p is definitely not an info ptr
257    LOOKS_LIKE_CLOSURE_PTR(p) returns False if p is definitely not a closure ptr
258
259    These macros are complete but not sound.  That is, they might
260    return false positives.  Do not rely on them to distinguish info
261    pointers from closure pointers, for example.
262
263    We don't use address-space predicates these days, for portability
264    reasons, and the fact that code/data can be scattered about the
265    address space in a dynamically-linked environment.  Our best option
266    is to look at the alleged info table and see whether it seems to
267    make sense...
268    -------------------------------------------------------------------------- */
269
270 #define LOOKS_LIKE_INFO_PTR(p) \
271    (p && ((StgInfoTable *)(INFO_PTR_TO_STRUCT(p)))->type != INVALID_OBJECT && \
272     ((StgInfoTable *)(INFO_PTR_TO_STRUCT(p)))->type < N_CLOSURE_TYPES)
273
274 #define LOOKS_LIKE_CLOSURE_PTR(p) \
275    (LOOKS_LIKE_INFO_PTR(((StgClosure *)(p))->header.info))
276
277 /* -----------------------------------------------------------------------------
278    Macros for calculating how big a closure will be (used during allocation)
279    -------------------------------------------------------------------------- */
280
281 INLINE_HEADER StgOffset PAP_sizeW   ( nat n_args )
282 { return sizeofW(StgPAP) + n_args; }
283
284 INLINE_HEADER StgOffset AP_sizeW   ( nat n_args )
285 { return sizeofW(StgAP) + n_args; }
286
287 INLINE_HEADER StgOffset AP_STACK_sizeW ( nat size )
288 { return sizeofW(StgAP_STACK) + size; }
289
290 INLINE_HEADER StgOffset CONSTR_sizeW( nat p, nat np )
291 { return sizeofW(StgHeader) + p + np; }
292
293 INLINE_HEADER StgOffset THUNK_SELECTOR_sizeW ( void )
294 { return stg_max(sizeofW(StgHeader)+MIN_UPD_SIZE, sizeofW(StgSelector)); }
295
296 INLINE_HEADER StgOffset BLACKHOLE_sizeW ( void )
297 { return sizeofW(StgHeader)+MIN_UPD_SIZE; }
298
299 /* --------------------------------------------------------------------------
300    Sizes of closures
301    ------------------------------------------------------------------------*/
302
303 INLINE_HEADER StgOffset sizeW_fromITBL( const StgInfoTable* itbl ) 
304 { return sizeofW(StgClosure) 
305        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
306        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
307
308 INLINE_HEADER StgOffset thunk_sizeW_fromITBL( const StgInfoTable* itbl ) 
309 { return sizeofW(StgThunk) 
310        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
311        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
312
313 INLINE_HEADER StgOffset ap_stack_sizeW( StgAP_STACK* x )
314 { return AP_STACK_sizeW(x->size); }
315
316 INLINE_HEADER StgOffset ap_sizeW( StgAP* x )
317 { return AP_sizeW(x->n_args); }
318
319 INLINE_HEADER StgOffset pap_sizeW( StgPAP* x )
320 { return PAP_sizeW(x->n_args); }
321
322 INLINE_HEADER StgOffset arr_words_sizeW( StgArrWords* x )
323 { return sizeofW(StgArrWords) + x->words; }
324
325 INLINE_HEADER StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
326 { return sizeofW(StgMutArrPtrs) + x->ptrs; }
327
328 INLINE_HEADER StgWord tso_sizeW ( StgTSO *tso )
329 { return TSO_STRUCT_SIZEW + tso->stack_size; }
330
331 INLINE_HEADER StgWord bco_sizeW ( StgBCO *bco )
332 { return bco->size; }
333
334 /* -----------------------------------------------------------------------------
335    Sizes of stack frames
336    -------------------------------------------------------------------------- */
337
338 INLINE_HEADER StgWord stack_frame_sizeW( StgClosure *frame )
339 {
340     StgRetInfoTable *info;
341
342     info = get_ret_itbl(frame);
343     switch (info->i.type) {
344
345     case RET_DYN:
346     {
347         StgRetDyn *dyn = (StgRetDyn *)frame;
348         return  sizeofW(StgRetDyn) + RET_DYN_BITMAP_SIZE + 
349             RET_DYN_NONPTR_REGS_SIZE +
350             RET_DYN_PTRS(dyn->liveness) + RET_DYN_NONPTRS(dyn->liveness);
351     }
352             
353     case RET_FUN:
354         return sizeofW(StgRetFun) + ((StgRetFun *)frame)->size;
355
356     case RET_BIG:
357     case RET_VEC_BIG:
358         return 1 + GET_LARGE_BITMAP(&info->i)->size;
359
360     case RET_BCO:
361         return 2 + BCO_BITMAP_SIZE((StgBCO *)((P_)frame)[1]);
362
363     default:
364         return 1 + BITMAP_SIZE(info->i.layout.bitmap);
365     }
366 }
367
368 /* -----------------------------------------------------------------------------
369    Nursery manipulation
370    -------------------------------------------------------------------------- */
371
372 extern void     allocNurseries       ( void );
373 extern void     resetNurseries       ( void );
374 extern void     resizeNurseries      ( nat blocks );
375 extern void     resizeNurseriesFixed ( nat blocks );
376 extern void     tidyAllocateLists    ( void );
377 extern lnat     countNurseryBlocks   ( void );
378
379 /* -----------------------------------------------------------------------------
380    Functions from GC.c 
381    -------------------------------------------------------------------------- */
382
383 extern void         threadPaused ( StgTSO * );
384 extern StgClosure * isAlive      ( StgClosure *p );
385 extern void         markCAFs     ( evac_fn evac );
386
387 /* -----------------------------------------------------------------------------
388    Stats 'n' DEBUG stuff
389    -------------------------------------------------------------------------- */
390
391 extern ullong RTS_VAR(total_allocated);
392
393 extern lnat calcAllocated  ( void );
394 extern lnat calcLive       ( void );
395 extern lnat calcNeeded     ( void );
396
397 #if defined(DEBUG)
398 extern void memInventory(void);
399 extern void checkSanity(void);
400 extern nat  countBlocks(bdescr *);
401 #endif
402
403 #if defined(DEBUG)
404 void printMutOnceList(generation *gen);
405 void printMutableList(generation *gen);
406 #endif
407
408 /* ----------------------------------------------------------------------------
409    Storage manager internal APIs and globals
410    ------------------------------------------------------------------------- */
411
412 #define END_OF_STATIC_LIST stgCast(StgClosure*,1)
413
414 extern void newDynCAF(StgClosure *);
415
416 extern void move_TSO(StgTSO *src, StgTSO *dest);
417 extern StgTSO *relocate_stack(StgTSO *dest, ptrdiff_t diff);
418
419 extern StgClosure * RTS_VAR(static_objects);
420 extern StgClosure * RTS_VAR(scavenged_static_objects);
421 extern StgWeak    * RTS_VAR(old_weak_ptr_list);
422 extern StgWeak    * RTS_VAR(weak_ptr_list);
423 extern StgClosure * RTS_VAR(caf_list);
424 extern StgClosure * RTS_VAR(revertible_caf_list);
425 extern StgTSO     * RTS_VAR(resurrected_threads);
426
427 #endif /* STORAGE_H */