add wiki commentary links
[ghc-hetmet.git] / rts / sm / MBlock.h
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2008
4  *
5  * MegaBlock Allocator interface.
6  *
7  * See wiki commentary at
8  *  http://hackage.haskell.org/trac/ghc/wiki/Commentary/HeapAlloced
9  *
10  * ---------------------------------------------------------------------------*/
11
12 #ifndef MBLOCK_H
13 #define MBLOCK_H
14
15 extern lnat RTS_VAR(mblocks_allocated);
16
17 extern void initMBlocks(void);
18 extern void * getMBlock(void);
19 extern void * getMBlocks(nat n);
20 extern void freeAllMBlocks(void);
21
22 #ifdef DEBUG
23 extern void *getFirstMBlock(void);
24 extern void *getNextMBlock(void *mblock);
25 #endif
26
27 /* -----------------------------------------------------------------------------
28    The HEAP_ALLOCED() test.
29
30    HEAP_ALLOCED is called FOR EVERY SINGLE CLOSURE during GC.
31    It needs to be FAST.
32
33    See wiki commentary at
34      http://hackage.haskell.org/trac/ghc/wiki/Commentary/HeapAlloced
35
36    Implementation of HEAP_ALLOCED
37    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
38
39    Since heap is allocated in chunks of megablocks (MBLOCK_SIZE), we
40    can just use a table to record which megablocks in the address
41    space belong to the heap.  On a 32-bit machine, with 1Mb
42    megablocks, using 8 bits for each entry in the table, the table
43    requires 4k.  Lookups during GC will be fast, because the table
44    will be quickly cached (indeed, performance measurements showed no
45    measurable difference between doing the table lookup and using a
46    constant comparison).
47
48    On 64-bit machines, we cache one 12-bit block map that describes
49    4096 megablocks or 4GB of memory. If HEAP_ALLOCED is called for
50    an address that is not in the cache, it calls slowIsHeapAlloced
51    (see MBlock.c) which will find the block map for the 4GB block in
52    question.
53    -------------------------------------------------------------------------- */
54
55 #if SIZEOF_VOID_P == 4
56 extern StgWord8 mblock_map[];
57
58 /* On a 32-bit machine a 4KB table is always sufficient */
59 # define MBLOCK_MAP_SIZE        4096
60 # define MBLOCK_MAP_ENTRY(p)    ((StgWord)(p) >> MBLOCK_SHIFT)
61 # define HEAP_ALLOCED(p)        mblock_map[MBLOCK_MAP_ENTRY(p)]
62
63 #elif SIZEOF_VOID_P == 8
64
65 # define MBLOCK_MAP_SIZE        4096
66 # define MBLOCK_MAP_ENTRY(p)    (((StgWord)(p) & 0xffffffff) >> MBLOCK_SHIFT)
67
68 typedef struct {
69     StgWord32   addrHigh32;
70     StgWord8    mblocks[MBLOCK_MAP_SIZE];
71 } MBlockMap;
72
73 extern MBlockMap *mblock_cache;
74
75 StgBool slowIsHeapAlloced(void *p);
76
77 # define HEAP_ALLOCED(p)                                        \
78         ( ((((StgWord)(p)) >> 32) == mblock_cache->addrHigh32)  \
79         ? mblock_cache->mblocks[MBLOCK_MAP_ENTRY(p)]            \
80         : slowIsHeapAlloced(p) )
81
82 #else
83 # error HEAP_ALLOCED not defined
84 #endif
85
86 #endif /* MBLOCK_H */