1 \section[SM-copying]{Copying Collector Subroutines}
3 This is a collection of C functions used in implementing the copying
6 The motivation for making this a separate file/section is twofold:
8 1) It lets us focus on one thing.
10 2) If we don't do this, there will be a huge amount of repetition
11 between the various GC schemes --- a maintenance nightmare.
13 The second is the major motivation.
17 #if defined(GC2s) || defined(GCdu) || defined(GCap) || defined(GCgn)
21 #include "SMinternal.h"
24 #include "SMcopying.h"
27 Comment stolen from SMscav.lc: When doing a new generation copy
28 collection for Appel's collector only evacuate references that point
29 to the new generation. OldGen must be set to point to the end of old
35 #define MAYBE_EVACUATE_CLOSURE( closure ) \
37 P_ evac = (P_) (closure); \
38 if (evac > OldGen) { \
39 (closure) = EVACUATE_CLOSURE(evac); \
45 #define MAYBE_EVACUATE_CLOSURE( closure ) \
47 P_ evac = (P_) (closure); \
48 (closure) = EVACUATE_CLOSURE(evac); \
56 SetCAFInfoTables(P_ CAFlist)
60 /* Set CAF info tables for evacuation */
61 DEBUG_STRING("Setting Evac & Upd CAFs:");
62 for (CAFptr = CAFlist;
64 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr) ) {
65 INFO_PTR(CAFptr) = (W_) Caf_Evac_Upd_info;
72 EvacuateRoots(P_ roots[], I_ rootno)
76 DEBUG_STRING("Evacuate (Reg) Roots:");
77 for (root = 0; root < rootno; root++) {
78 MAYBE_EVACUATE_CLOSURE( roots[root] );
86 EvacuateSparks(STG_NO_ARGS)
92 DEBUG_STRING("Evacuate Sparks:");
93 for (pool = 0; pool < SPARK_POOLS; pool++) {
94 for (sparkptr = PendingSparksHd[pool];
95 sparkptr < PendingSparksTl[pool]; sparkptr++) {
96 MAYBE_EVACUATE_CLOSURE(*((PP_) sparkptr));
103 Note: no \tr{evacuate[AB]Stack} for ``parallel'' systems, because they
104 don't have a single main stack.
109 EvacuateAStack(PP_ stackA, PP_ botA /* botA points to bottom-most word */)
113 DEBUG_STRING("Evacuate A Stack:");
114 for (stackptr = stackA;
115 SUBTRACT_A_STK(stackptr, botA) >= 0;
116 stackptr = stackptr + AREL(1)) {
117 MAYBE_EVACUATE_CLOSURE( *((PP_) stackptr) );
123 ToDo: Optimisation which squeezes out update frames which point to
126 Perform collection first
128 Then process B stack removing update frames (bot to top via pointer
129 reversal) that reference garbage closues (test infoptr !=
132 Otherwise closure is live update reference to to-space address
137 EvacuateBStack( stackB, botB, roots )
139 P_ botB; /* botB points to bottom-most word */
146 DEBUG_STRING("Evacuate B Stack:");
148 for (updateFramePtr = stackB; /* stackB points to topmost update frame */
149 SUBTRACT_B_STK(updateFramePtr, botB) > 0;
150 updateFramePtr = GRAB_SuB(updateFramePtr)) {
152 /* Evacuate the thing to be updated */
153 updatee = GRAB_UPDATEE(updateFramePtr);
154 MAYBE_EVACUATE_CLOSURE(updatee);
155 PUSH_UPDATEE(updateFramePtr, updatee);
163 When we do a copying collection, we want to evacuate all of the local
164 entries in the GALA table for which there are outstanding remote
165 pointers (i.e. for which the weight is not MAX_GA_WEIGHT.)
171 EvacuateLocalGAs(rtsBool full)
177 for (gala = liveIndirections; gala != NULL; gala = next) {
179 ASSERT(gala->ga.loc.gc.gtid == mytid);
180 if (gala->ga.weight != MAX_GA_WEIGHT) {
181 /* Remote references exist, so we must evacuate the local closure */
183 MAYBE_EVACUATE_CLOSURE(gala->la);
184 if (!full && gala->preferred && gala->la != old) {
185 (void) removeHashTable(LAtoGALAtable, (W_) old, (void *) gala);
186 insertHashTable(LAtoGALAtable, (W_) gala->la, (void *) gala);
191 /* Since we have all of the weight, this GA is no longer needed */
192 W_ pga = PackGA(thisPE, gala->ga.loc.gc.slot);
195 fprintf(stderr, "Freeing slot %d\n", gala->ga.loc.gc.slot);
197 gala->next = freeIndirections;
198 freeIndirections = gala;
199 (void) removeHashTable(pGAtoGALAtable, pga, (void *) gala);
200 if (!full && gala->preferred)
201 (void) removeHashTable(LAtoGALAtable, (W_) gala->la, (void *) gala);
203 gala->ga.weight = 0x0d0d0d0d;
204 gala->la = (P_) 0xbadbad;
208 liveIndirections = prev;
215 EXTDATA_RO(Forward_Ref_info);
218 RebuildGAtables(rtsBool full)
225 prepareFreeMsgBuffers();
227 for (gala = liveRemoteGAs, prev = NULL; gala != NULL; gala = next) {
229 ASSERT(gala->ga.loc.gc.gtid != mytid);
234 * If the old closure has not been forwarded, we let go. Note that this
235 * approach also drops global aliases for PLCs.
238 #if defined(GCgn) || defined(GCap)
239 if (closure > OldGen) {
241 if (!full && gala->preferred)
242 (void) removeHashTable(LAtoGALAtable, (W_) gala->la, (void *) gala);
244 /* Follow indirection chains to the end, just in case */
245 while (IS_INDIRECTION(INFO_PTR(closure)))
246 closure = (P_) IND_CLOSURE_PTR(closure);
248 /* Change later to incorporate a _FO bit in the INFO_TYPE for GCgn */
250 fall over, until _FO bits are added
252 if (INFO_PTR(closure) != (W_) Forward_Ref_info) {
253 int pe = taskIDtoPE(gala->ga.loc.gc.gtid);
254 W_ pga = PackGA(pe, gala->ga.loc.gc.slot);
256 (void) removeHashTable(pGAtoGALAtable, pga, (void *) gala);
257 freeRemoteGA(pe, &(gala->ga));
258 gala->next = freeGALAList;
261 /* Find the new space object */
262 closure = (P_) FORWARD_ADDRESS(closure);
265 if (!full && gala->preferred)
266 insertHashTable(LAtoGALAtable, (W_) gala->la, (void *) gala);
270 #if defined(GCgn) || defined(GCap)
272 /* Old generation, minor collection; just keep it */
278 liveRemoteGAs = prev;
280 /* If we have any remaining FREE messages to send off, do so now */
295 DEBUG_SCAN("Scavenging Start", Scav, "ToHp", ToHp);
296 while (Scav <= ToHp) (SCAV_CODE(INFO_PTR(Scav)))();
297 DEBUG_SCAN("Scavenging End", Scav, "ToHp", ToHp);
305 EvacuateCAFs( CAFlist )
310 DEBUG_STRING("Evacuate CAFs:");
311 for (CAFptr = CAFlist;
313 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
314 EVACUATE_CLOSURE(CAFptr); /* evac & upd OR return */
318 /* ToDo: put GCap EvacuateCAFs code here */
323 EvacAndScavengeCAFs( CAFlist, extra_words, roots )
332 DEBUG_STRING("Evacuate & Scavenge CAFs:");
333 for (CAFptr = CAFlist;
335 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
337 EVACUATE_CLOSURE(CAFptr); /* evac & upd OR return */
340 DEBUG_SCAN("Scavenging CAF", Scav, "ToHp", ToHp);
341 while (Scav <= ToHp) (SCAV_CODE(INFO_PTR(Scav)))();
342 DEBUG_SCAN("Scavenging End", Scav, "ToHp", ToHp);
344 *extra_words = ToHp - caf_start;
350 #endif /* defined(_INFO_COPYING) */