use the new "prim %write_barrier()" in .cmm instead of calls to wb()
[ghc-hetmet.git] / 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   /* During GC, if we are collecting this step, blocks and n_blocks
66    * are copied into the following two fields.  After GC, these blocks
67    * are freed. */
68   bdescr *     old_blocks;              /* bdescr of first from-space block */
69   unsigned int n_old_blocks;            /* number of blocks in from-space */
70
71   /* temporary use during GC: */
72   StgPtr       hp;                      /* next free locn in to-space */
73   StgPtr       hpLim;                   /* end of current to-space block */
74   bdescr *     hp_bd;                   /* bdescr of current to-space block */
75   StgPtr       scavd_hp;                /* ... same as above, but already */
76   StgPtr       scavd_hpLim;             /*     scavenged.  */
77   bdescr *     scan_bd;                 /* block currently being scanned */
78   StgPtr       scan;                    /* scan pointer in current block */
79   bdescr *     new_large_objects;       /* large objects collected so far */
80   bdescr *     scavenged_large_objects; /* live large objs after GC (d-link) */
81   unsigned int n_scavenged_large_blocks;/* size of above */
82   bdescr *     bitmap;                  /* bitmap for compacting collection */
83 } step;
84
85 typedef struct generation_ {
86   unsigned int   no;                    /* generation number */
87   step *         steps;                 /* steps */
88   unsigned int   n_steps;               /* number of steps */
89   unsigned int   max_blocks;            /* max blocks in step 0 */
90   bdescr        *mut_list;              /* mut objects in this gen (not G0)*/
91
92   /* temporary use during GC: */
93   bdescr        *saved_mut_list;
94
95   /* stats information */
96   unsigned int collections;
97   unsigned int failed_promotions;
98 } generation;
99
100 extern generation * RTS_VAR(generations);
101
102 extern generation * RTS_VAR(g0);
103 extern step * RTS_VAR(g0s0);
104 extern generation * RTS_VAR(oldest_gen);
105
106 /* -----------------------------------------------------------------------------
107    Initialisation / De-initialisation
108    -------------------------------------------------------------------------- */
109
110 extern void initStorage(void);
111 extern void exitStorage(void);
112 extern void freeStorage(void);
113
114 /* -----------------------------------------------------------------------------
115    Generic allocation
116
117    StgPtr allocate(nat n)       Allocates a chunk of contiguous store
118                                 n words long, returning a pointer to
119                                 the first word.  Always succeeds.
120                                 
121    StgPtr allocatePinned(nat n) Allocates a chunk of contiguous store
122                                 n words long, which is at a fixed
123                                 address (won't be moved by GC).  
124                                 Returns a pointer to the first word.
125                                 Always succeeds.
126                                 
127                                 NOTE: the GC can't in general handle
128                                 pinned objects, so allocatePinned()
129                                 can only be used for ByteArrays at the
130                                 moment.
131
132                                 Don't forget to TICK_ALLOC_XXX(...)
133                                 after calling allocate or
134                                 allocatePinned, for the
135                                 benefit of the ticky-ticky profiler.
136
137    rtsBool doYouWantToGC(void)  Returns True if the storage manager is
138                                 ready to perform a GC, False otherwise.
139
140    lnat  allocated_bytes(void)  Returns the number of bytes allocated
141                                 via allocate() since the last GC.
142                                 Used in the reporting of statistics.
143
144    THREADED_RTS: allocate and doYouWantToGC can be used from STG code, they are
145    surrounded by a mutex.
146    -------------------------------------------------------------------------- */
147
148 extern StgPtr  allocate        ( nat n );
149 extern StgPtr  allocateLocal   ( Capability *cap, nat n );
150 extern StgPtr  allocatePinned  ( nat n );
151 extern lnat    allocated_bytes ( void );
152
153 extern bdescr * RTS_VAR(small_alloc_list);
154 extern bdescr * RTS_VAR(large_alloc_list);
155 extern bdescr * RTS_VAR(pinned_object_block);
156
157 extern StgPtr RTS_VAR(alloc_Hp);
158 extern StgPtr RTS_VAR(alloc_HpLim);
159
160 extern nat RTS_VAR(alloc_blocks);
161 extern nat RTS_VAR(alloc_blocks_lim);
162
163 INLINE_HEADER rtsBool
164 doYouWantToGC( void )
165 {
166   return (alloc_blocks >= alloc_blocks_lim);
167 }
168
169 /* memory allocator for executable memory */
170 extern void *allocateExec (nat bytes);
171 extern void freeExec (void *p);
172
173 /* -----------------------------------------------------------------------------
174    Performing Garbage Collection
175
176    GarbageCollect(get_roots)    Performs a garbage collection.  
177                                 'get_roots' is called to find all the 
178                                 roots that the system knows about.
179
180    StgClosure                   Called by get_roots on each root.       
181    MarkRoot(StgClosure *p)      Returns the new location of the root.
182    -------------------------------------------------------------------------- */
183
184 extern void GarbageCollect(void (*get_roots)(evac_fn),rtsBool force_major_gc);
185
186 /* -----------------------------------------------------------------------------
187    Generational garbage collection support
188
189    recordMutable(StgPtr p)       Informs the garbage collector that a
190                                  previously immutable object has
191                                  become (permanently) mutable.  Used
192                                  by thawArray and similar.
193
194    updateWithIndirection(p1,p2)  Updates the object at p1 with an
195                                  indirection pointing to p2.  This is
196                                  normally called for objects in an old
197                                  generation (>0) when they are updated.
198
199    updateWithPermIndirection(p1,p2)  As above but uses a permanent indir.
200
201    -------------------------------------------------------------------------- */
202
203 /*
204  * Storage manager mutex
205  */
206 #if defined(THREADED_RTS)
207 extern Mutex sm_mutex;
208 extern Mutex atomic_modify_mutvar_mutex;
209 #endif
210
211 #if defined(THREADED_RTS)
212 #define ACQUIRE_SM_LOCK   ACQUIRE_LOCK(&sm_mutex);
213 #define RELEASE_SM_LOCK   RELEASE_LOCK(&sm_mutex);
214 #define ASSERT_SM_LOCK()  ASSERT_LOCK_HELD(&sm_mutex);
215 #else
216 #define ACQUIRE_SM_LOCK
217 #define RELEASE_SM_LOCK
218 #define ASSERT_SM_LOCK()
219 #endif
220
221 INLINE_HEADER void
222 recordMutableGen(StgClosure *p, generation *gen)
223 {
224     bdescr *bd;
225
226     bd = gen->mut_list;
227     if (bd->free >= bd->start + BLOCK_SIZE_W) {
228         bdescr *new_bd;
229         new_bd = allocBlock();
230         new_bd->link = bd;
231         bd = new_bd;
232         gen->mut_list = bd;
233     }
234     *bd->free++ = (StgWord)p;
235
236 }
237
238 INLINE_HEADER void
239 recordMutableGenLock(StgClosure *p, generation *gen)
240 {
241     ACQUIRE_SM_LOCK;
242     recordMutableGen(p,gen);
243     RELEASE_SM_LOCK;
244 }
245
246 INLINE_HEADER void
247 recordMutable(StgClosure *p)
248 {
249     bdescr *bd;
250     ASSERT(closure_MUTABLE(p));
251     bd = Bdescr((P_)p);
252     if (bd->gen_no > 0) recordMutableGen(p, &RTS_DEREF(generations)[bd->gen_no]);
253 }
254
255 INLINE_HEADER void
256 recordMutableLock(StgClosure *p)
257 {
258     ACQUIRE_SM_LOCK;
259     recordMutable(p);
260     RELEASE_SM_LOCK;
261 }
262
263 /* -----------------------------------------------------------------------------
264    The CAF table - used to let us revert CAFs in GHCi
265    -------------------------------------------------------------------------- */
266
267 /* set to disable CAF garbage collection in GHCi. */
268 /* (needed when dynamic libraries are used). */
269 extern rtsBool keepCAFs;
270
271 /* -----------------------------------------------------------------------------
272    This is the write barrier for MUT_VARs, a.k.a. IORefs.  A
273    MUT_VAR_CLEAN object is not on the mutable list; a MUT_VAR_DIRTY
274    is.  When written to, a MUT_VAR_CLEAN turns into a MUT_VAR_DIRTY
275    and is put on the mutable list.
276    -------------------------------------------------------------------------- */
277
278 void dirty_MUT_VAR(StgRegTable *reg, StgClosure *p);
279
280 /* -----------------------------------------------------------------------------
281    DEBUGGING predicates for pointers
282
283    LOOKS_LIKE_INFO_PTR(p)    returns False if p is definitely not an info ptr
284    LOOKS_LIKE_CLOSURE_PTR(p) returns False if p is definitely not a closure ptr
285
286    These macros are complete but not sound.  That is, they might
287    return false positives.  Do not rely on them to distinguish info
288    pointers from closure pointers, for example.
289
290    We don't use address-space predicates these days, for portability
291    reasons, and the fact that code/data can be scattered about the
292    address space in a dynamically-linked environment.  Our best option
293    is to look at the alleged info table and see whether it seems to
294    make sense...
295    -------------------------------------------------------------------------- */
296
297 #define LOOKS_LIKE_INFO_PTR(p) \
298    (p && ((StgInfoTable *)(INFO_PTR_TO_STRUCT(p)))->type != INVALID_OBJECT && \
299     ((StgInfoTable *)(INFO_PTR_TO_STRUCT(p)))->type < N_CLOSURE_TYPES)
300
301 #define LOOKS_LIKE_CLOSURE_PTR(p) \
302    (LOOKS_LIKE_INFO_PTR(((StgClosure *)(p))->header.info))
303
304 /* -----------------------------------------------------------------------------
305    Macros for calculating how big a closure will be (used during allocation)
306    -------------------------------------------------------------------------- */
307
308 INLINE_HEADER StgOffset PAP_sizeW   ( nat n_args )
309 { return sizeofW(StgPAP) + n_args; }
310
311 INLINE_HEADER StgOffset AP_sizeW   ( nat n_args )
312 { return sizeofW(StgAP) + n_args; }
313
314 INLINE_HEADER StgOffset AP_STACK_sizeW ( nat size )
315 { return sizeofW(StgAP_STACK) + size; }
316
317 INLINE_HEADER StgOffset CONSTR_sizeW( nat p, nat np )
318 { return sizeofW(StgHeader) + p + np; }
319
320 INLINE_HEADER StgOffset THUNK_SELECTOR_sizeW ( void )
321 { return sizeofW(StgSelector); }
322
323 INLINE_HEADER StgOffset BLACKHOLE_sizeW ( void )
324 { return sizeofW(StgHeader)+MIN_PAYLOAD_SIZE; }
325
326 /* --------------------------------------------------------------------------
327    Sizes of closures
328    ------------------------------------------------------------------------*/
329
330 INLINE_HEADER StgOffset sizeW_fromITBL( const StgInfoTable* itbl ) 
331 { return sizeofW(StgClosure) 
332        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
333        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
334
335 INLINE_HEADER StgOffset thunk_sizeW_fromITBL( const StgInfoTable* itbl ) 
336 { return sizeofW(StgThunk) 
337        + sizeofW(StgPtr)  * itbl->layout.payload.ptrs 
338        + sizeofW(StgWord) * itbl->layout.payload.nptrs; }
339
340 INLINE_HEADER StgOffset ap_stack_sizeW( StgAP_STACK* x )
341 { return AP_STACK_sizeW(x->size); }
342
343 INLINE_HEADER StgOffset ap_sizeW( StgAP* x )
344 { return AP_sizeW(x->n_args); }
345
346 INLINE_HEADER StgOffset pap_sizeW( StgPAP* x )
347 { return PAP_sizeW(x->n_args); }
348
349 INLINE_HEADER StgOffset arr_words_sizeW( StgArrWords* x )
350 { return sizeofW(StgArrWords) + x->words; }
351
352 INLINE_HEADER StgOffset mut_arr_ptrs_sizeW( StgMutArrPtrs* x )
353 { return sizeofW(StgMutArrPtrs) + x->ptrs; }
354
355 INLINE_HEADER StgWord tso_sizeW ( StgTSO *tso )
356 { return TSO_STRUCT_SIZEW + tso->stack_size; }
357
358 INLINE_HEADER StgWord bco_sizeW ( StgBCO *bco )
359 { return bco->size; }
360
361 STATIC_INLINE nat
362 closure_sizeW_ (StgClosure *p, StgInfoTable *info)
363 {
364     switch (info->type) {
365     case THUNK_0_1:
366     case THUNK_1_0:
367         return sizeofW(StgThunk) + 1;
368     case FUN_0_1:
369     case CONSTR_0_1:
370     case FUN_1_0:
371     case CONSTR_1_0:
372         return sizeofW(StgHeader) + 1;
373     case THUNK_0_2:
374     case THUNK_1_1:
375     case THUNK_2_0:
376         return sizeofW(StgThunk) + 2;
377     case FUN_0_2:
378     case CONSTR_0_2:
379     case FUN_1_1:
380     case CONSTR_1_1:
381     case FUN_2_0:
382     case CONSTR_2_0:
383         return sizeofW(StgHeader) + 2;
384     case THUNK:
385         return thunk_sizeW_fromITBL(info);
386     case THUNK_SELECTOR:
387         return THUNK_SELECTOR_sizeW();
388     case AP_STACK:
389         return ap_stack_sizeW((StgAP_STACK *)p);
390     case AP:
391     case PAP:
392         return pap_sizeW((StgPAP *)p);
393     case IND:
394     case IND_PERM:
395     case IND_OLDGEN:
396     case IND_OLDGEN_PERM:
397         return sizeofW(StgInd);
398     case ARR_WORDS:
399         return arr_words_sizeW((StgArrWords *)p);
400     case MUT_ARR_PTRS_CLEAN:
401     case MUT_ARR_PTRS_DIRTY:
402     case MUT_ARR_PTRS_FROZEN:
403     case MUT_ARR_PTRS_FROZEN0:
404         return mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
405     case TSO:
406         return tso_sizeW((StgTSO *)p);
407     case BCO:
408         return bco_sizeW((StgBCO *)p);
409     case TVAR_WAIT_QUEUE:
410         return sizeofW(StgTVarWaitQueue);
411     case TVAR:
412         return sizeofW(StgTVar);
413     case TREC_CHUNK:
414         return sizeofW(StgTRecChunk);
415     case TREC_HEADER:
416         return sizeofW(StgTRecHeader);
417     default:
418         return sizeW_fromITBL(info);
419     }
420 }
421
422 // The definitive way to find the size, in words, of a heap-allocated closure
423 STATIC_INLINE nat
424 closure_sizeW (StgClosure *p)
425 {
426     return closure_sizeW_(p, get_itbl(p));
427 }
428
429 /* -----------------------------------------------------------------------------
430    Sizes of stack frames
431    -------------------------------------------------------------------------- */
432
433 INLINE_HEADER StgWord stack_frame_sizeW( StgClosure *frame )
434 {
435     StgRetInfoTable *info;
436
437     info = get_ret_itbl(frame);
438     switch (info->i.type) {
439
440     case RET_DYN:
441     {
442         StgRetDyn *dyn = (StgRetDyn *)frame;
443         return  sizeofW(StgRetDyn) + RET_DYN_BITMAP_SIZE + 
444             RET_DYN_NONPTR_REGS_SIZE +
445             RET_DYN_PTRS(dyn->liveness) + RET_DYN_NONPTRS(dyn->liveness);
446     }
447             
448     case RET_FUN:
449         return sizeofW(StgRetFun) + ((StgRetFun *)frame)->size;
450
451     case RET_BIG:
452     case RET_VEC_BIG:
453         return 1 + GET_LARGE_BITMAP(&info->i)->size;
454
455     case RET_BCO:
456         return 2 + BCO_BITMAP_SIZE((StgBCO *)((P_)frame)[1]);
457
458     default:
459         return 1 + BITMAP_SIZE(info->i.layout.bitmap);
460     }
461 }
462
463 /* -----------------------------------------------------------------------------
464    Nursery manipulation
465    -------------------------------------------------------------------------- */
466
467 extern void     allocNurseries       ( void );
468 extern void     resetNurseries       ( void );
469 extern void     resizeNurseries      ( nat blocks );
470 extern void     resizeNurseriesFixed ( nat blocks );
471 extern void     tidyAllocateLists    ( void );
472 extern lnat     countNurseryBlocks   ( void );
473
474 /* -----------------------------------------------------------------------------
475    Functions from GC.c 
476    -------------------------------------------------------------------------- */
477
478 extern void         threadPaused ( Capability *cap, StgTSO * );
479 extern StgClosure * isAlive      ( StgClosure *p );
480 extern void         markCAFs     ( evac_fn evac );
481
482 /* -----------------------------------------------------------------------------
483    Stats 'n' DEBUG stuff
484    -------------------------------------------------------------------------- */
485
486 extern ullong RTS_VAR(total_allocated);
487
488 extern lnat calcAllocated  ( void );
489 extern lnat calcLive       ( void );
490 extern lnat calcNeeded     ( void );
491
492 #if defined(DEBUG)
493 extern void memInventory(void);
494 extern void checkSanity(void);
495 extern nat  countBlocks(bdescr *);
496 extern void checkNurserySanity( step *stp );
497 #endif
498
499 #if defined(DEBUG)
500 void printMutOnceList(generation *gen);
501 void printMutableList(generation *gen);
502 #endif
503
504 /* ----------------------------------------------------------------------------
505    Storage manager internal APIs and globals
506    ------------------------------------------------------------------------- */
507
508 #define END_OF_STATIC_LIST stgCast(StgClosure*,1)
509
510 extern void newDynCAF(StgClosure *);
511
512 extern void move_TSO(StgTSO *src, StgTSO *dest);
513 extern StgTSO *relocate_stack(StgTSO *dest, ptrdiff_t diff);
514
515 extern StgClosure * RTS_VAR(scavenged_static_objects);
516 extern StgWeak    * RTS_VAR(old_weak_ptr_list);
517 extern StgWeak    * RTS_VAR(weak_ptr_list);
518 extern StgClosure * RTS_VAR(caf_list);
519 extern StgClosure * RTS_VAR(revertible_caf_list);
520 extern StgTSO     * RTS_VAR(resurrected_threads);
521
522 #endif /* STORAGE_H */