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 */
36 if (heap_space == 0) { /* allocates if it doesn't already exist */
38 /* Allocate the roots space */
39 sm->roots = (P_ *) xmalloc( SM_MAXROOTS * sizeof(W_) );
41 /* Allocate the heap */
42 heap_space = (P_) xmalloc((SM_word_heap_size + EXTRA_HEAP_WORDS) * sizeof(W_));
44 compactingInfo.bit_words = (SM_word_heap_size + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
45 compactingInfo.bits = (BitWord *)(heap_space + SM_word_heap_size) - compactingInfo.bit_words;
47 compactingInfo.heap_words = SM_word_heap_size - compactingInfo.bit_words;
48 compactingInfo.base = HEAP_FRAME_BASE(heap_space, compactingInfo.heap_words);
49 compactingInfo.lim = HEAP_FRAME_LIMIT(heap_space, compactingInfo.heap_words);
51 stat_init("COMPACTING", "", "");
54 sm->hp = hp_start = compactingInfo.base - 1;
57 sm->hplim = sm->hp + SM_alloc_size;
58 SM_alloc_min = 0; /* No min; alloc size specified */
60 if (sm->hplim > compactingInfo.lim) {
61 fprintf(stderr, "Not enough heap for requested alloc size\n");
65 sm->hplim = compactingInfo.lim;
75 fprintf(stderr, "COMPACTING Heap: Base 0x%lx, Lim 0x%lx, Bits 0x%lx, bit words 0x%lx\n",
76 (W_) compactingInfo.base, (W_) compactingInfo.lim,
77 (W_) compactingInfo.bits, (W_) compactingInfo.bit_words);
78 fprintf(stderr, "COMPACTING Initial: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
79 (W_) compactingInfo.base,
80 (W_) compactingInfo.lim,
81 (W_) sm->hp, (W_) sm->hplim, (W_) (sm->hplim - sm->hp) * sizeof(W_));
88 collectHeap(reqsize, sm, do_full_collection)
91 rtsBool do_full_collection; /* ignored */
93 I_ free_space, /* No of words of free space following GC */
94 alloc, /* Number of words allocated since last GC */
95 resident; /* Number of words remaining after GC */
97 SAVE_REGS(&ScanRegDump); /* Save registers */
101 fflush(stdout); /* Flush stdout at start of GC */
102 fprintf(stderr, "COMPACTING Start: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, req %lu\n",
103 (W_) compactingInfo.base, (W_) compactingInfo.lim,
104 (W_) sm->hp, (W_) sm->hplim, (W_) (reqsize * sizeof(W_)));
107 alloc = sm->hp - hp_start;
111 /* bracket use of MARK_REG_MAP with RESTORE/SAVE of SCAN_REG_MAP */
112 RESTORE_REGS(&ScanRegDump);
114 markHeapRoots(sm, sm->CAFlist, 0,
117 compactingInfo.bits);
119 SAVE_REGS(&ScanRegDump);
123 sweepUpDeadMallocPtrs(sm->MallocPtrList,
125 compactingInfo.bits );
128 LinkCAFs(sm->CAFlist);
130 LinkRoots( sm->roots, sm->rootno );
135 LinkLiveGAs(compactingInfo.base, compactingInfo.bits);
137 DEBUG_STRING("Linking Stable Pointer Table:");
138 LINK_LOCATION_TO_CLOSURE(&sm->StablePointerTable);
139 LinkAStack( MAIN_SpA, stackInfo.botA );
140 LinkBStack( MAIN_SuB, stackInfo.botB );
141 #endif /* parallel */
143 /* Do Inplace Compaction */
144 /* Returns start of next closure, -1 gives last allocated word */
146 sm->hp = Inplace_Compaction(compactingInfo.base,
150 compactingInfo.bit_words
152 , &(sm->MallocPtrList)
156 resident = sm->hp - (compactingInfo.base - 1);
157 DO_MAX_RESIDENCY(resident); /* stats only */
160 sm->hplim = sm->hp + SM_alloc_size;
161 if (sm->hplim > compactingInfo.lim) {
164 free_space = SM_alloc_size;
167 sm->hplim = compactingInfo.lim;
168 free_space = sm->hplim - sm->hp;
173 stat_endGC(alloc, compactingInfo.heap_words, resident, "");
176 fprintf(stderr, "COMPACTING Done: base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
177 (W_) compactingInfo.base, (W_) compactingInfo.lim,
178 (W_) sm->hp, (W_) sm->hplim, (W_) (free_space * sizeof(W_)));
181 /* To help flush out bugs, we trash the part of the heap from
182 which we're about to start allocating. */
183 TrashMem(sm->hp+1, sm->hplim);
186 RESTORE_REGS(&ScanRegDump); /* Restore Registers */
188 if ((SM_alloc_min > free_space) || (reqsize > free_space))
189 return GC_HARD_LIMIT_EXCEEDED; /* Heap exhausted */
191 return GC_SUCCESS; /* Heap OK */