1 ***************************************************************************
3 COMPACTING GARBAGE COLLECTION
5 Additional Global Data Requirements:
6 ++ All the root locations are in malloced space (and info tables in
7 static data space). This is to simplify the location list end test.
9 ***************************************************************************
11 [Someone needs to document this too. KH]
16 ToDo: Soft heap limits
19 #include "SMinternal.h"
20 #include "SMcompacting.h"
25 compactingData compactingInfo = {0, 0, 0, 0, 0};
27 P_ heap_space = 0; /* Address of first word of slab
28 of memory allocated for heap */
30 P_ hp_start; /* Value of Hp when reduction was resumed */
33 initHeap( smInfo *sm )
35 if (heap_space == 0) { /* allocates if it doesn't already exist */
37 /* Allocate the roots space */
38 sm->roots = (P_ *) stgMallocWords(SM_MAXROOTS, "initHeap (roots)");
40 /* Allocate the heap */
41 heap_space = (P_) stgMallocWords(RTSflags.GcFlags.heapSize + EXTRA_HEAP_WORDS,
44 compactingInfo.bit_words
45 = (RTSflags.GcFlags.heapSize + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
47 = (BitWord *)(heap_space + RTSflags.GcFlags.heapSize) - compactingInfo.bit_words;
49 compactingInfo.heap_words = RTSflags.GcFlags.heapSize - compactingInfo.bit_words;
50 compactingInfo.base = HEAP_FRAME_BASE(heap_space, compactingInfo.heap_words);
51 compactingInfo.lim = HEAP_FRAME_LIMIT(heap_space, compactingInfo.heap_words);
53 stat_init("COMPACTING", "", "");
56 sm->hp = hp_start = compactingInfo.base - 1;
58 if (! RTSflags.GcFlags.allocAreaSizeGiven) {
59 sm->hplim = compactingInfo.lim;
61 sm->hplim = sm->hp + RTSflags.GcFlags.allocAreaSize;
63 RTSflags.GcFlags.minAllocAreaSize = 0; /* specified size takes precedence */
65 if (sm->hplim > compactingInfo.lim) {
66 fprintf(stderr, "Not enough heap for requested alloc size\n");
77 if (RTSflags.GcFlags.trace) {
78 fprintf(stderr, "COMPACTING Heap: Base 0x%lx, Lim 0x%lx, Bits 0x%lx, bit words 0x%lx\n",
79 (W_) compactingInfo.base, (W_) compactingInfo.lim,
80 (W_) compactingInfo.bits, (W_) compactingInfo.bit_words);
81 fprintf(stderr, "COMPACTING Initial: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
82 (W_) compactingInfo.base,
83 (W_) compactingInfo.lim,
84 (W_) sm->hp, (W_) sm->hplim, (W_) (sm->hplim - sm->hp) * sizeof(W_));
87 return rtsTrue; /* OK */
91 collectHeap(reqsize, sm, do_full_collection)
94 rtsBool do_full_collection; /* ignored */
96 I_ free_space, /* No of words of free space following GC */
97 alloc, /* Number of words allocated since last GC */
98 resident; /* Number of words remaining after GC */
100 SAVE_REGS(&ScanRegDump); /* Save registers */
102 if (RTSflags.GcFlags.trace) {
103 fflush(stdout); /* Flush stdout at start of GC */
104 fprintf(stderr, "COMPACTING Start: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, req %lu\n",
105 (W_) compactingInfo.base, (W_) compactingInfo.lim,
106 (W_) sm->hp, (W_) sm->hplim, (W_) (reqsize * sizeof(W_)));
109 alloc = sm->hp - hp_start;
113 /* bracket use of MARK_REG_MAP with RESTORE/SAVE of SCAN_REG_MAP */
114 RESTORE_REGS(&ScanRegDump);
116 markHeapRoots(sm, sm->CAFlist, 0,
119 compactingInfo.bits);
121 SAVE_REGS(&ScanRegDump);
125 sweepUpDeadForeignObjs(sm->ForeignObjList,
127 compactingInfo.bits );
130 LinkCAFs(sm->CAFlist);
132 LinkRoots( sm->roots, sm->rootno );
136 #if defined(CONCURRENT)
140 LinkLiveGAs(compactingInfo.base, compactingInfo.bits);
143 The stable pointer table is reachable via sm->roots,
144 (Reason: in markHeapRoots all roots have to be considered,
145 including the StablePointerTable)
147 DEBUG_STRING("Linking Stable Pointer Table:");
148 LINK_LOCATION_TO_CLOSURE(&sm->StablePointerTable);
151 LinkAStack( MAIN_SpA, stackInfo.botA );
152 LinkBStack( MAIN_SuB, stackInfo.botB );
153 #endif /* parallel */
155 /* Do Inplace Compaction */
156 /* Returns start of next closure, -1 gives last allocated word */
158 sm->hp = Inplace_Compaction(compactingInfo.base,
162 compactingInfo.bit_words
164 , &(sm->ForeignObjList)
168 resident = sm->hp - (compactingInfo.base - 1);
169 DO_MAX_RESIDENCY(resident); /* stats only */
171 if (! RTSflags.GcFlags.allocAreaSizeGiven) {
172 sm->hplim = compactingInfo.lim;
173 free_space = sm->hplim - sm->hp;
175 sm->hplim = sm->hp + RTSflags.GcFlags.allocAreaSize;
176 if (sm->hplim > compactingInfo.lim) {
179 free_space = RTSflags.GcFlags.allocAreaSize;
185 stat_endGC(alloc, compactingInfo.heap_words, resident, "");
187 if (RTSflags.GcFlags.trace)
188 fprintf(stderr, "COMPACTING Done: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
189 (W_) compactingInfo.base, (W_) compactingInfo.lim,
190 (W_) sm->hp, (W_) sm->hplim, (W_) (free_space * sizeof(W_)));
193 /* To help flush out bugs, we trash the part of the heap from
194 which we're about to start allocating. */
195 TrashMem(sm->hp+1, sm->hplim);
198 RESTORE_REGS(&ScanRegDump); /* Restore Registers */
200 if (free_space < RTSflags.GcFlags.minAllocAreaSize || free_space < reqsize)
201 return GC_HARD_LIMIT_EXCEEDED; /* Heap exhausted */
203 return GC_SUCCESS; /* Heap OK */