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 sweepUpDeadMallocPtrs(sm->MallocPtrList,
127 compactingInfo.bits );
130 LinkCAFs(sm->CAFlist);
132 LinkRoots( sm->roots, sm->rootno );
137 LinkLiveGAs(compactingInfo.base, compactingInfo.bits);
139 DEBUG_STRING("Linking Stable Pointer Table:");
140 LINK_LOCATION_TO_CLOSURE(&sm->StablePointerTable);
141 LinkAStack( MAIN_SpA, stackInfo.botA );
142 LinkBStack( MAIN_SuB, stackInfo.botB );
143 #endif /* parallel */
145 /* Do Inplace Compaction */
146 /* Returns start of next closure, -1 gives last allocated word */
148 sm->hp = Inplace_Compaction(compactingInfo.base,
152 compactingInfo.bit_words
154 , &(sm->MallocPtrList)
158 resident = sm->hp - (compactingInfo.base - 1);
159 DO_MAX_RESIDENCY(resident); /* stats only */
161 if (! RTSflags.GcFlags.allocAreaSizeGiven) {
162 sm->hplim = compactingInfo.lim;
163 free_space = sm->hplim - sm->hp;
165 sm->hplim = sm->hp + RTSflags.GcFlags.allocAreaSize;
166 if (sm->hplim > compactingInfo.lim) {
169 free_space = RTSflags.GcFlags.allocAreaSize;
175 stat_endGC(alloc, compactingInfo.heap_words, resident, "");
177 if (RTSflags.GcFlags.trace)
178 fprintf(stderr, "COMPACTING Done: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
179 (W_) compactingInfo.base, (W_) compactingInfo.lim,
180 (W_) sm->hp, (W_) sm->hplim, (W_) (free_space * sizeof(W_)));
183 /* To help flush out bugs, we trash the part of the heap from
184 which we're about to start allocating. */
185 TrashMem(sm->hp+1, sm->hplim);
188 RESTORE_REGS(&ScanRegDump); /* Restore Registers */
190 if (free_space < RTSflags.GcFlags.minAllocAreaSize || free_space < reqsize)
191 return GC_HARD_LIMIT_EXCEEDED; /* Heap exhausted */
193 return GC_SUCCESS; /* Heap OK */