1 ***************************************************************************
3 GENERATIONAL GARBAGE COLLECTION
5 Global heap requirements as for 1s and 2s collectors.
6 ++ All closures in the old generation that are updated must be
7 updated with indirections and placed on the linked list of
8 updated old generation closures.
14 Collects allocation area into 2nd semi-space and promotes new semi-space
15 by collecting into old generation.
17 evac < AllocGen ==> Collect to old generation (see _EvacuateP)
19 Roots: Roots, Astk, Bstk, OldRoots, OldInNew, CAFlist, NewCAFlist
21 OldRoots: Newly promoted closures may reference new semi-space.
23 Discard OldInNew roots (promoted).
24 This keeps recent new gen roots in new gen.
25 Remember OldRoots in alloc (not promoted).
27 When evacuating to new check if Scav in OldGen, if so
28 allocate oldgen root ind and add to OldInNew.
29 N.B. This includes evacuating a forward reference.
30 Set special forward ref to this OldGen root closure.
31 if oldgen evacs return oldgen root else return new gen.
33 CAFlist: Remember NewCAFlist in OldCAFlist (promoted).
34 Remember CAFlist in NewCAFlist (not promoted).
36 ***************************************************************************
42 #include "SMinternal.h"
46 genData genInfo = {0, 0, 0, 0,
48 0, {{0, 0}, {0, 0}}, /* New Gen */
49 0, 0, 0, 0, 0, 0, /* Old Gen */
50 0, 0, 0, 0, 0, 0, 0, /* OldRoots & CAfs */
51 0, {{0, 0}, {0, 0}} /* 2s */
54 P_ heap_space = 0; /* Address of first word of slab
55 of memory allocated for heap */
57 P_ hp_start; /* Value of Hp when reduction was resumed */
58 /* Always allocbase - 1 */
67 /* should cause link error */
68 ADRpanic("Completely untested on SP and MP stuff... also doesn't benefit from commoning up in SMcopying and SMcompacting");
70 if (heap_space == 0) { /* allocates if it doesn't already exist */
72 /* Allocate the roots space */
73 sm->roots = (P_ *) xmalloc( SM_MAXROOTS * sizeof(W_) );
75 /* Allocate the heap */
76 heap_space = (P_) xmalloc((SM_word_heap_size + EXTRA_HEAP_WORDS) * sizeof(W_));
78 if (SM_force_gc == USE_2s) {
79 stat_init("TWOSPACE(GEN)",
80 " No of Roots Caf Caf Astk Bstk",
81 "Astk Bstk Reg No bytes bytes bytes");
84 "Promote Old No of Roots Caf Mut- Old Old OldGen Collec Resid",
85 " bytes roots Astk Bstk Reg No able Alc New bytes tion %heap");
89 if (SM_force_gc == USE_2s) {
90 genInfo.semi_space = SM_word_heap_size / 2;
91 genInfo.space[0].base = HEAP_FRAME_BASE(heap_space, genInfo.semi_space);
92 genInfo.space[1].base = HEAP_FRAME_BASE(heap_space + genInfo.semi_space, genInfo.semi_space);
93 genInfo.space[0].lim = HEAP_FRAME_LIMIT(heap_space, genInfo.semi_space);
94 genInfo.space[1].lim = HEAP_FRAME_LIMIT(heap_space + genInfo.semi_space, genInfo.semi_space);
95 genInfo.semi_space = 0;
96 genInfo.oldlim = heap_space - 1; /* Never in old generation */
98 sm->hp = hp_start = genInfo.space[genInfo.semi_space].base - 1;
101 sm->hplim = sm->hp + SM_alloc_size;
102 SM_alloc_min = 0; /* No min; alloc size specified */
104 if (sm->hplim > genInfo.space[genInfo.semi_space].lim) {
105 fprintf(stderr, "Not enough heap for requested alloc size\n");
109 sm->hplim = genInfo.space[genInfo.semi_space].lim;
112 sm->OldLim = genInfo.oldlim;
116 initExtensions( sm );
120 fprintf(stderr, "GEN(2s) Heap: 0x%lx .. 0x%lx\n",
121 (W_) heap_space, (W_) (heap_space - 1 + SM_word_heap_size));
122 fprintf(stderr, "Initial: space %ld, base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %ld\n",
124 (W_) genInfo.space[genInfo.semi_space].base,
125 (W_) genInfo.space[genInfo.semi_space].lim,
126 (W_) sm->hp, (W_) sm->hplim, (I_) (sm->hplim - sm->hp));
131 if (SM_alloc_size == 0) SM_alloc_size = DEFAULT_ALLOC_SIZE;
133 genInfo.alloc_words = SM_alloc_size;
134 genInfo.new_words = SM_alloc_size;
136 genInfo.allocbase = heap_space + SM_word_heap_size - genInfo.alloc_words;
137 genInfo.alloclim = heap_space + SM_word_heap_size - 1;
139 genInfo.newgen[0].newbase = genInfo.allocbase - genInfo.new_words;
140 genInfo.newgen[0].newlim = genInfo.newgen[0].newbase - 1;
142 genInfo.newgen[1].newbase = genInfo.allocbase - 2 * genInfo.new_words;
143 genInfo.newgen[1].newlim = genInfo.newgen[1].newbase - 1;
145 genInfo.oldbase = heap_space;
147 if (SM_major_gen_size) {
148 genInfo.old_words = SM_major_gen_size;
149 genInfo.oldend = heap_space + genInfo.old_words - 1;
150 genInfo.oldthresh = genInfo.oldend - genInfo.new_words;
151 /* ToDo: extra old ind words not accounted for ! */
153 bit_words = (genInfo.old_words + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
154 if (genInfo.alloc_words > bit_words * (sizeof(BitWord)/sizeof(W_))) {
155 /* bit vector in allocation area */
156 genInfo.bit_vect = (BitWord *) genInfo.allocbase;
157 if (genInfo.oldend >= genInfo.newgen[1].newbase) heap_error = 1;
159 /* bit area in free area */
160 genInfo.bit_vect = (BitWord *) genInfo.oldend + 1;
161 if (genInfo.bit_vect + bit_words >= (BitWord *) genInfo.newgen[1].newbase) heap_error = 1;
164 genInfo.old_words = SM_word_heap_size - genInfo.alloc_words - 2 * genInfo.new_words;
165 genInfo.oldend = heap_space + genInfo.old_words - 1;
166 genInfo.oldthresh = genInfo.oldend - genInfo.new_words;
167 /* ToDo: extra old ind words not accounted for ! */
169 bit_words = (genInfo.old_words + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
170 if (genInfo.alloc_words > bit_words * (sizeof(BitWord)/sizeof(W_))) {
171 /* bit vector in allocation area */
172 genInfo.bit_vect = (BitWord *) genInfo.allocbase;
174 /* bit vector in reserved space in old generation */
175 bit_words = (genInfo.old_words + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
177 genInfo.bit_vect = (BitWord *) heap_space;
178 genInfo.oldbase += bit_words;
179 genInfo.old_words -= bit_words;
181 if (genInfo.oldbase > genInfo.oldthresh) heap_error = 1;
185 fprintf(stderr, "initHeap: Requested heap size: %ld\n", SM_word_heap_size);
186 fprintf(stderr, " Alloc area %ld Delay area %ld Old area %ld Bit area %ld\n",
187 genInfo.alloc_words, genInfo.new_words * 2, genInfo.old_words,
188 genInfo.bit_vect == (BitWord *) genInfo.allocbase ? 0 : bit_words);
189 fprintf(stderr, " Heap not large enough for generational gc with these specs\n");
190 fprintf(stderr, " +RTS -H<size> option will increase heap size and/or\n");
191 fprintf(stderr, " -A<size> option will decrease allocation area\n");
196 genInfo.oldlim = genInfo.oldbase - 1;
197 genInfo.oldwas = genInfo.oldbase - 1;
200 genInfo.OldInNew = 0;
201 genInfo.OldInNewno = 0;
202 genInfo.NewCAFlist = NULL;
203 genInfo.NewCAFno = 0;
204 genInfo.OldCAFlist = NULL;
205 genInfo.OldCAFno = 0;
207 genInfo.PromMutables = 0;
209 sm->hp = hp_start = genInfo.allocbase - 1;
210 sm->hplim = genInfo.alloclim;
212 sm->OldLim = genInfo.oldlim;
216 initExtensions( sm );
220 fprintf(stderr, "GEN Heap: 0x%lx .. 0x%lx\n",
221 (W_) heap_space, (W_) (heap_space + SM_word_heap_size - 1));
222 fprintf(stderr, " alloc %ld, new %ld, old %ld, bit %ld\n",
223 genInfo.alloc_words, genInfo.new_words, genInfo.old_words, bit_words);
224 fprintf(stderr, " allocbase 0x%lx, alloclim 0x%lx\n",
225 (W_) genInfo.allocbase, (W_) genInfo.alloclim);
226 fprintf(stderr, " newbases 0x%lx 0x%lx\n",
227 (W_) genInfo.newgen[0].newbase, (W_) genInfo.newgen[1].newbase);
228 fprintf(stderr, " oldbase 0x%lx oldthresh 0x%lx bits 0x%lx\n",
229 (W_) genInfo.oldbase, (W_) genInfo.oldthresh, (W_) genInfo.bit_vect);
230 fprintf(stderr, " hp 0x%lx, hplim 0x%lx\n",
231 (W_) sm->hp, (W_) sm->hplim);
238 collect2s(reqsize, sm)
242 I_ root, bstk_roots, caf_roots, extra_caf_words;
244 P_ CAFptr, updateFramePtr, caf_start;
246 I_ free_space, /* No of words of free space following GC */
247 alloc, /* Number of words allocated since last GC */
248 resident; /* Number of words remaining after GC */
250 SAVE_REGS(&ScavRegDump); /* Save registers */
253 fprintf(stderr, "Start: space %ld, base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, req %lu\n",
255 (W_) genInfo.space[genInfo.semi_space].base,
256 (W_) genInfo.space[genInfo.semi_space].lim,
257 (W_) sm->hp, (W_) sm->hplim, (W_) (reqsize * sizeof(W_)));
259 alloc = sm->hp - hp_start;
262 genInfo.semi_space = NEXT_SEMI_SPACE(genInfo.semi_space);
263 ToHp = genInfo.space[genInfo.semi_space].base - 1;
264 Scav = genInfo.space[genInfo.semi_space].base;
265 OldGen = sm->OldLim; /* always evac ! */
267 DEBUG_STRING("Setting Evac & Upd CAFs:");
268 for (CAFptr = sm->CAFlist; CAFptr;
269 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
270 INFO_PTR(CAFptr) = (W_) Caf_Evac_Upd_info;
274 EvacuateLocalGAs(rtsTrue);
279 DEBUG_STRING("Evacuate Roots:");
280 for (root = 0; root < sm->rootno; root++) {
281 P_ evac = sm->roots[root];
282 sm->roots[root] = EVACUATE_CLOSURE(evac);
287 DEBUG_STRING("Evacuate A Stack:");
288 for (stackptr = MAIN_SpA;
289 SUBTRACT_A_STK(stackptr, stackInfo.botA) >= 0;
290 /* botA points to bottom-most word */
291 stackptr = stackptr + AREL(1)) {
293 *stackptr = EVACUATE_CLOSURE(evac);
295 DEBUG_STRING("Evacuate B Stack:");
297 for (updateFramePtr = MAIN_SuB; /* SuB points to topmost update frame */
298 SUBTRACT_B_STK(updateFramePtr, stackInfo.botB) > 0;
299 /* botB points to bottom-most word */
300 /* re-initialiser given explicitly */) {
302 P_ evac = GRAB_UPDATEE(updateFramePtr);
303 PUSH_UPDATEE(updateFramePtr, EVACUATE_CLOSURE(evac));
306 updateFramePtr = GRAB_SuB(updateFramePtr);
310 DEBUG_SCAN("Scavenging Start", Scav, "ToHp", ToHp);
311 while (Scav <= ToHp) (SCAV_CODE(INFO_PTR(Scav)))();
312 DEBUG_SCAN("Scavenging End", Scav, "ToHp", ToHp);
314 DEBUG_STRING("Evacuate & Scavenge CAFs:");
317 for (CAFptr = sm->CAFlist; CAFptr;
318 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
320 EVACUATE_CLOSURE(CAFptr); /* evac & upd OR return */
323 DEBUG_SCAN("Scavenging CAF", Scav, "ToHp", ToHp);
324 while (Scav <= ToHp) (SCAV_CODE(INFO_PTR(Scav)))();
325 DEBUG_SCAN("Scavenging End", Scav, "ToHp", ToHp);
327 /* this_extra_caf_words = ToHp - this_caf_start; */
328 /* ToDo: Report individual CAF space */
330 extra_caf_words = ToHp - caf_start;
333 RebuildGAtables(rtsTrue);
335 reportDeadMallocPtrs( sm->MallocPtrList, NULL, &(sm->MallocPtrList) );
338 /* TIDY UP AND RETURN */
340 sm->hp = hp_start = ToHp; /* Last allocated word */
341 sm->hplim = genInfo.space[genInfo.semi_space].lim;
343 resident = sm->hp - (genInfo.space[genInfo.semi_space].base - 1);
344 /* DONT_DO_MAX_RESIDENCY -- because this collector is utterly hosed */
345 free_space = sm->hplim - sm->hp;
347 if (SM_stats_verbose) {
348 char comment_str[BIG_STRING_LEN];
350 sprintf(comment_str, "%4u %4ld %3ld %3ld %6lu %6lu %6lu 2s",
351 (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
352 bstk_roots, sm->rootno,
353 caf_roots, extra_caf_words*sizeof(W_),
354 (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1)*sizeof(W_),
355 (SUBTRACT_B_STK(MAIN_SpB, stackInfo.botB) + 1)*sizeof(W_));
357 /* ToDo: come up with some interesting statistics for the parallel world */
358 sprintf(comment_str, "%4u %4ld %3ld %3ld %6lu %6lu %6lu 2s",
359 0, 0, sm->rootno, caf_roots, extra_caf_words*sizeof(W_), 0, 0);
361 stat_endGC(alloc, SM_word_heap_size, resident, comment_str);
363 stat_endGC(alloc, SM_word_heap_size, resident, "");
367 fprintf(stderr, "Done: space %ld, base 0x%lx, lim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
369 (W_) genInfo.space[genInfo.semi_space].base,
370 (W_) genInfo.space[genInfo.semi_space].lim,
371 (W_) sm->hp, (W_) sm->hplim, (W_) (free_space * sizeof(W_)));
374 /* To help flush out bugs, we trash the part of the heap from
375 which we're about to start allocating. */
376 TrashMem(sm->hp+1, sm->hplim);
379 RESTORE_REGS(&ScavRegDump); /* Restore Registers */
381 if ((SM_alloc_size > free_space) || (reqsize > free_space))
382 return(-1); /* Heap exhausted */
384 return(0); /* Heap OK */
389 collectHeap(reqsize, sm)
394 P_ mutptr, prevmut, updateFramePtr, botB,
395 CAFptr, prevCAF, oldroot, oldstartToHp, oldstartOldHp,
397 I_ root, rootno, bstk_roots, mutable, alloc_cafs, new_cafs,
398 alloc_oldroots, new_oldroots, old_words;
404 I_ alloc, /* number of words allocated since last GC */
405 collect, /* number of words collected */
406 promote, /* number of words promoted */
407 resident, /* number of words remaining */
408 total_resident; /* total number of words remaining after major collection */
410 fflush(stdout); /* Flush stdout at start of GC */
412 if (SM_force_gc == USE_2s) {
413 return collect2s(reqsize, sm);
417 if (reqsize > genInfo.alloc_words) {
418 fprintf(stderr, "collectHeap: Required size %ld greater then allocation area %ld!\n",
419 reqsize, genInfo.alloc_words);
420 fprintf(stderr, " Rerun using +RTS -A<size> to increase allocation area\n");
424 SAVE_REGS(&ScavRegDump); /* Save registers */
426 if (SM_trace) fprintf(stderr, "GEN Start: hp 0x%lx, hplim 0x%lx, req %ld Minor\n",
427 (W_) sm->hp, (W_) sm->hplim, (I_) (reqsize * sizeof(W_)));
429 alloc = sm->hp - hp_start;
432 /* MINOR COLLECTION WITH PROMOTION */
434 collect = alloc + (genInfo.newgen[genInfo.curnew].newlim - genInfo.newgen[genInfo.curnew].newbase + 1);
435 genInfo.curnew = (genInfo.curnew + 1) % 2;
437 ToHp = genInfo.newgen[genInfo.curnew].newbase - 1;
438 OldGen = genInfo.oldend; /* <= OldGen indicates in the old generation */
440 AllocGen = genInfo.allocbase; /* < AllocGen indicates in delay bucket -> promote */
441 OldHp = genInfo.oldlim;
443 newscav = genInfo.newgen[genInfo.curnew].newbase; /* Point to (info field of) first closure */
444 oldscav = genInfo.oldlim + 1; /* Point to (info field of) first closure */
447 DEBUG_STRING("Setting Evac & Upd CAFs:");
448 for (CAFptr = sm->CAFlist; CAFptr;
449 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
450 INFO_PTR(CAFptr) = (W_) Caf_Evac_Upd_info;
452 for (CAFptr = genInfo.NewCAFlist; CAFptr;
453 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
454 INFO_PTR(CAFptr) = (W_) Caf_Evac_Upd_info;
458 /* FIRST: Evacuate and scavenge OldMutable, Roots, AStk & BStk */
459 /* Ensure these roots don't use old generation root indirection when evacuated */
462 DEBUG_STRING("Evacuate Roots:");
463 for (root = 0, rootno = sm->rootno; root < rootno; root++) {
464 P_ evac = sm->roots[root];
466 sm->roots[root] = EVACUATE_CLOSURE(evac);
471 DEBUG_STRING("Evacuate A Stack:");
472 for (stackptr = MAIN_SpA, botA = stackInfo.botA;
473 SUBTRACT_A_STK(stackptr, botA) >= 0;
474 stackptr = stackptr + AREL(1)) {
477 *stackptr = EVACUATE_CLOSURE(evac);
480 DEBUG_STRING("Evacuate B Stack:");
482 for (updateFramePtr = MAIN_SuB, botB = stackInfo.botB;
483 SUBTRACT_B_STK(updateFramePtr, botB) > 0;
484 /* re-initialiser given explicitly */) {
486 /* Evacuate the thing to be updated */
487 P_ evac = GRAB_UPDATEE(updateFramePtr);
489 PUSH_UPDATEE(updateFramePtr, EVACUATE_CLOSURE(evac));
493 updateFramePtr = GRAB_SuB(updateFramePtr);
497 DEBUG_STRING("Evacuate Mutable Roots:");
499 mutptr = sm->OldMutables;
500 prevmut = ((P_)&sm->OldMutables) - FIXED_HS;
504 /* Scavenge the OldMutable closure */
505 P_ info = (P_) INFO_PTR(mutptr);
506 StgScavPtr scav_code = SCAV_CODE(info);
510 /* Remove from OldMutables if no longer mutable */
511 /* HACK ALERT: See comment in SMap.lc
512 about why we do this terrible pointer comparison.
514 if (info == ImMutArrayOfPtrs_info) { /* ToDo: use different test? (WDP 94/11) */
516 MUT_LINK(prevmut) = MUT_LINK(mutptr);
517 mutptr = (P_) MUT_LINK(mutptr);
518 MUT_LINK(tmp) = MUT_NOT_LINKED;
521 mutptr = (P_) MUT_LINK(mutptr);
527 EvacuateLocalGAs(rtsFalse);
532 while ((newscav <= ToHp) || (oldscav <= OldHp)) {
534 DEBUG_SCAN("Scav: NewScav", Scav, "ToHp", ToHp);
535 while (Scav <= ToHp) (SCAV_CODE(INFO_PTR(Scav)))();
539 DEBUG_SCAN("Scav: OldScav", Scav, "OldHp", OldHp);
540 while (Scav <= OldHp) (SCAV_CODE(INFO_PTR(Scav)))();
545 /* SECOND: Evacuate & Scavenge CAFs and OldGen roots */
546 /* Ensure these roots don't use old generation root indirection when evacuated */
550 oldstartOldHp = OldHp;
553 DEBUG_STRING("Evacuate CAFs and old generation roots:");
554 /* Evacuate CAFs in allocation region to New semispace */
555 /* Evacuate CAFs in New semispace to OldGen */
556 /* OldCAFlist = NewCAFlist ++ OldCAFlist */
557 /* NewCAFlist = CAFlist */
561 for (CAFptr = sm->CAFlist; CAFptr;
562 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
563 EVACUATE_CLOSURE(CAFptr); /* evac & upd */
567 for (CAFptr = genInfo.NewCAFlist,
568 prevCAF = ((P_)(&genInfo.NewCAFlist)) - FIXED_HS; /* see IND_CLOSURE_LINK */
569 CAFptr; CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
570 EVACUATE_CLOSURE(CAFptr); /* evac & upd */
573 new_cafs = genInfo.NewCAFno;
575 IND_CLOSURE_LINK(prevCAF) = (W_) genInfo.OldCAFlist;
576 genInfo.OldCAFlist = genInfo.NewCAFlist;
577 genInfo.OldCAFno += genInfo.NewCAFno;
579 genInfo.NewCAFlist = sm->CAFlist;
580 genInfo.NewCAFno = alloc_cafs;
584 /* Evacuate OldRoots roots to New semispace */
585 /* Evacuate OldInNew roots to OldGen, discard these roots */
586 /* OldInNew = OldRoots */
589 for (oldroot = genInfo.OldInNew; oldroot; oldroot = (P_) IND_CLOSURE_LINK(oldroot)) {
590 P_ evac = (P_) IND_CLOSURE_PTR(oldroot);
592 IND_CLOSURE_PTR(oldroot) = (W_) EVACUATE_CLOSURE(evac);
595 new_oldroots = genInfo.OldInNewno;
597 DEBUG_STRING("Scavenge evacuated old generation roots:");
598 while ((newscav <= ToHp) || (oldscav <= OldHp)) {
600 DEBUG_SCAN("Scav: NewScav", Scav, "ToHp", ToHp);
601 while (Scav <= ToHp) (SCAV_CODE(INFO_PTR(Scav)))();
605 DEBUG_SCAN("Scav: OldScav", Scav, "OldHp", OldHp);
606 while (Scav <= OldHp) (SCAV_CODE(INFO_PTR(Scav)))();
610 old_words = OldHp - oldstartOldHp; /* + (ToHp - oldstartToHp) */
613 /* record newly promoted mutuple roots */
614 MUT_LINK(prevmut) = (W_) genInfo.PromMutables;
615 genInfo.PromMutables = 0;
618 promote = OldHp - genInfo.oldlim;
619 resident = (ToHp - genInfo.newgen[genInfo.curnew].newbase + 1) + promote;
621 genInfo.newgen[genInfo.curnew].newlim = ToHp;
622 genInfo.oldlim = OldHp;
624 genInfo.minor_since_major++;
627 RebuildGAtables(rtsFalse);
629 reportDeadMallocPtrs(sm->MallocPtrList,
630 sm->OldMallocPtrList,
631 &(sm->OldMallocPtrList));
632 sm->MallocPtrList = NULL; /* all (new) MallocPtrs have been promoted */
635 if (SM_stats_verbose) {
636 char minor_str[BIG_STRING_LEN];
638 sprintf(minor_str, "%6lu %4lu %4lu %4ld %3ld %3ld %4ld %3ld %3ld %6ld Minor",
639 promote*sizeof(W_), genInfo.OldInNewno - alloc_oldroots,
640 (I_) (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
641 bstk_roots, sm->rootno, alloc_cafs + new_cafs,
642 mutable, alloc_oldroots, new_oldroots, old_words*sizeof(W_));
644 /* ToDo: come up with some interesting statistics for the parallel world */
645 sprintf(minor_str, "%6lu %4lu %4lu %4ld %3ld %3ld %4ld %3ld %3ld %6ld Minor",
646 promote*sizeof(W_), genInfo.OldInNewno - alloc_oldroots, 0,
647 0, sm->rootno, alloc_cafs + new_cafs,
648 mutable, alloc_oldroots, new_oldroots, old_words*sizeof(W_));
650 stat_endGC(alloc, collect, resident, minor_str);
652 stat_endGC(alloc, collect, resident, "");
655 /* ToDo: Decide to do major early ! */
657 if (genInfo.oldlim <= genInfo.oldthresh && !do_full_collection) {
659 sm->hp = hp_start = genInfo.allocbase - 1;
660 sm->hplim = genInfo.alloclim;
661 sm->OldLim = genInfo.oldlim;
664 fprintf(stderr, "GEN End: oldbase 0x%lx, oldlim 0x%lx, oldthresh 0x%lx, newbase 0x%lx, newlim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
665 (W_) genInfo.oldbase, (W_) genInfo.oldlim, (W_) genInfo.oldthresh,
666 (W_) genInfo.newgen[genInfo.curnew].newbase,
667 (W_) genInfo.newgen[genInfo.curnew].newlim,
668 (W_) sm->hp, (W_) sm->hplim, (W_) (sm->hplim - sm->hp) * sizeof(W_));
670 RESTORE_REGS(&ScavRegDump); /* Restore Registers */
672 return GC_SUCCESS; /* Heap OK -- Enough space to continue */
676 DEBUG_STRING("Major Collection Required");
679 alloc = genInfo.oldlim - genInfo.oldbase + 1;
681 /* Zero bit vector for marking phase of major collection */
683 bit_words = (alloc + BITS_IN(BitWord) - 1) / BITS_IN(BitWord);
684 { BitWord *ptr = genInfo.bit_vect,
685 *end = genInfo.bit_vect + bit_words;
686 while (ptr < end) { *(ptr++) = 0; };
689 /* Set are for old gen CAFs to be linked */
691 CAFlocs = (PP_) genInfo.newgen[(genInfo.curnew + 1) % 2].newbase;
692 if (genInfo.new_words < genInfo.OldCAFno) {
693 fprintf(stderr, "colectHeap: Too many CAFs %ld to link in new semi-space %ld\n",
694 genInfo.OldCAFno, genInfo.alloc_words);
695 fprintf(stderr, " Rerun using +RTS -A<size> to increase allocation area\n");
699 /* Change old generation root indirections to special OldRoot indirections */
700 /* These will be marked and not short circuted (like SPEC 2,1 closure) */
702 for (oldroot = genInfo.OldInNew; oldroot; oldroot = (P_) IND_CLOSURE_LINK(oldroot)) {
703 INFO_PTR(oldroot) = (W_) OldRoot_info;
706 /* Discard OldInNew roots: Scanning OldRoots will reconstruct live OldInNew root list */
707 genInfo.OldInNew = 0;
708 genInfo.OldInNewno = 0;
710 /* Discard OldMutable roots: Scanning Mutables will reconstruct live OldMutables root list */
713 /* bracket use of MARK_REG_MAP with RESTORE/SAVE of SCAV_REG_MAP */
714 RESTORE_REGS(&ScavRegDump);
716 markHeapRoots(sm, genInfo.NewCAFlist, genInfo.OldCAFlist,
717 genInfo.oldbase, genInfo.oldlim, genInfo.bit_vect);
719 SAVE_REGS(&ScavRegDump);
723 sweepUpDeadMallocPtrs(sm->OldMallocPtrList,
729 oldlim = genInfo.oldlim;
731 DEBUG_STRING("Linking Dummy CAF Ptr Locations:");
733 for (CAFptr = genInfo.OldCAFlist; CAFptr;
734 CAFptr = (P_) IND_CLOSURE_LINK(CAFptr)) {
735 DEBUG_LINK_CAF(CAFptr, CAFloc);
736 *CAFloc = (P_) IND_CLOSURE_PTR(CAFptr);
737 LINK_LOCATION_TO_CLOSURE(CAFloc, oldlim);
741 DEBUG_STRING("Linking Roots:");
742 for (root = 0; root < sm->rootno; root++) {
743 LINK_LOCATION_TO_CLOSURE(sm->roots+root, oldlim);
747 fall over here until we figure out how to link GAs
749 DEBUG_STRING("Linking Stable Pointer Table:");
750 LINK_LOCATION_TO_CLOSURE(&sm->StablePointerTable, oldlim);
751 DEBUG_STRING("Linking A Stack:");
752 for (stackptr = MAIN_SpA;
753 SUBTRACT_A_STK(stackptr, stackInfo.botA) >= 0;
754 stackptr = stackptr + AREL(1)) {
755 LINK_LOCATION_TO_CLOSURE(stackptr, oldlim);
757 DEBUG_STRING("Linking B Stack:");
758 for (updateFramePtr = MAIN_SuB; /* SuB points to topmost update frame */
759 SUBTRACT_B_STK(updateFramePtr, stackInfo.botB) > 0;
760 /* re-initialiser given explicitly */) {
762 P_ updateClosurePtr = updateFramePtr + BREL(UF_UPDATEE);
763 LINK_LOCATION_TO_CLOSURE(updateClosurePtr, oldlim);
765 updateFramePtr = GRAB_SuB(updateFramePtr);
769 /* Do Inplace Compaction */
770 /* Returns start of next closure, -1 gives last allocated word */
772 genInfo.oldlim = Inplace_Compaction(genInfo.oldbase,
774 genInfo.newgen[genInfo.curnew].newbase,
775 genInfo.newgen[genInfo.curnew].newlim,
776 genInfo.bit_vect, bit_words) - 1;
778 resident = (genInfo.oldlim - genInfo.oldbase) + 1;
779 total_resident = genInfo.newgen[genInfo.curnew].newlim -
780 genInfo.newgen[genInfo.curnew].newbase + 1 + resident;
782 sm->hp = hp_start = genInfo.allocbase - 1;
783 sm->hplim = genInfo.alloclim;
784 sm->OldLim = genInfo.oldlim;
786 genInfo.oldwas = genInfo.oldlim;
787 genInfo.minor_since_major = 0;
789 if (SM_stats_verbose) {
790 char major_str[BIG_STRING_LEN];
792 sprintf(major_str, "%6d %4ld %4u %4ld %3ld %3ld %4d %3d %3d %6.6s *Major* %4.1f%%",
793 0, genInfo.OldInNewno,
794 (SUBTRACT_A_STK(MAIN_SpA, stackInfo.botA) + 1),
795 bstk_roots, sm->rootno, genInfo.NewCAFno + genInfo.OldCAFno,
796 0, 0, 0, "", total_resident / (StgFloat) SM_word_heap_size * 100);
798 sprintf(major_str, "%6d %4ld %4u %4ld %3ld %3ld %4d %3d %3d %6.6s *Major* %4.1f%%",
799 0, genInfo.OldInNewno,
800 0, 0, sm->rootno, genInfo.NewCAFno + genInfo.OldCAFno,
801 0, 0, 0, "", total_resident / (StgFloat) SM_word_heap_size * 100);
803 stat_endGC(0, alloc, resident, major_str);
805 stat_endGC(0, alloc, resident, "");
809 fprintf(stderr, "GEN Major: oldbase 0x%lx, oldlim 0x%lx, oldthresh 0x%lx, newbase 0x%lx, newlim 0x%lx\n hp 0x%lx, hplim 0x%lx, free %lu\n",
810 (W_) genInfo.oldbase, (W_) genInfo.oldlim, (W_) genInfo.oldthresh,
811 (W_) genInfo.newgen[genInfo.curnew].newbase,
812 (W_) genInfo.newgen[genInfo.curnew].newlim,
813 (W_) sm->hp, (W_) sm->hplim, (W_) (sm->hplim - sm->hp) * sizeof(W_));
816 /* To help flush out bugs, we trash the part of the heap from
817 which we're about to start allocating. */
818 TrashMem(sm->hp+1, sm->hplim);
821 RESTORE_REGS(&ScavRegDump); /* Restore Registers */
823 if (genInfo.oldlim > genInfo.oldthresh)
824 return GC_HARD_LIMIT_EXCEEDED; /* Heap exhausted */
826 return GC_SUCCESS; /* Heap OK */