Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/runtime/gc/blast-gc.c
ViewVC logotype

Annotation of /sml/trunk/src/runtime/gc/blast-gc.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 250 - (view) (download) (as text)

1 : monnier 249 /* blast-gc.c
2 :     *
3 :     * COPYRIGHT (c) 1993 by AT&T Bell Laboratories.
4 :     *
5 :     * This is the garbage collector for compacting a blasted object.
6 :     *
7 :     * NOTE: the extraction of literals could cause a space overflow.
8 :     */
9 :    
10 :     #include <stdio.h>
11 :     #include "ml-base.h"
12 :     #include "ml-limits.h"
13 :     #include "ml-state.h"
14 :     #include "ml-values.h"
15 :     #include "memory.h"
16 :     #include "card-map.h"
17 :     #include "heap.h"
18 :     #include "tags.h"
19 :     #include "copy-loop.h"
20 :     #include "heap-monitor.h"
21 :     #include "ml-timer.h"
22 :     #include "ml-heap-image.h"
23 :     #include "blast-out.h"
24 :     #include "addr-hash.h"
25 :     #include "c-globals-tbl.h"
26 :     #include "ml-objects.h"
27 :     #include "ml-globals.h"
28 :    
29 :    
30 :     PVT bool_t repairHeap; /* this is TRUE, as long as it is cheaper */
31 :     /* to repair the heap, than to complete */
32 :     /* the collection */
33 :     PVT bool_t finishGC; /* this is TRUE, when we are finishing a */
34 :     /* garbage collection after blasting. */
35 :     PVT int maxCollectedGen; /* the oldest generation being collected */
36 :     PVT ml_val_t *savedTop /* save to-space top pointers */
37 :     [MAX_NUM_GENS][NUM_ARENAS];
38 :     PVT export_table_t *ExportTbl; /* the table of exported symbols */
39 :     PVT addr_tbl_t *EmbObjTbl; /* the table of embedded object references */
40 :    
41 :     /* typedef struct repair repair_t; */ /* in heap.h */
42 :     struct repair {
43 :     ml_val_t *loc; /* the location to repair */
44 :     ml_val_t val; /* the old value */
45 :     };
46 :    
47 :     /* record a location in a given arena for repair */
48 :     #define NOTE_REPAIR(ap, location, value) { \
49 :     arena_t *__ap = (ap); \
50 :     if (repairHeap) { \
51 :     repair_t *__rp = __ap->repairList - 1; \
52 :     if ((ml_val_t *)__rp > __ap->nextw) { \
53 :     __rp->loc = (location); \
54 :     __rp->val = (value); \
55 :     __ap->repairList = __rp; \
56 :     } \
57 :     else \
58 :     repairHeap = FALSE; \
59 :     } \
60 :     }
61 :    
62 :     /* local routines */
63 :     PVT void BlastGC_RepairHeap (ml_state_t *msp, int maxGen);
64 :     PVT void BlastGC_FinishGC (ml_state_t *msp, int maxGen);
65 :     PVT void BlastGC_Flip (heap_t *heap, int gen);
66 :     PVT status_t BlastGC_SweepToSpace (heap_t *heap, aid_t maxAid);
67 :     PVT bool_t BlastGC_SweepToSpArrays (heap_t *heap, arena_t *tosp, card_map_t *cm);
68 :     PVT ml_val_t BlastGC_ForwardObj (heap_t *heap, ml_val_t obj, aid_t id);
69 :     PVT bigobj_desc_t *BlastGC_ForwardBigObj (
70 :     heap_t *heap, ml_val_t *p, ml_val_t obj, aid_t aid);
71 :     PVT embobj_info_t *EmbObjLookup (addr_tbl_t *tbl, Addr_t addr, embobj_kind_t kind);
72 :     PVT void BlastGC_AssignLits (Addr_t addr, void *_closure, void *_info);
73 :     PVT void BlastGC_ExtractLits (Addr_t addr, void *_closure, void *_info);
74 :    
75 :     struct assignlits_clos { /* the closure for BlastGC_AssignLits */
76 :     Word_t id; /* the heap image chunk index for */
77 :     /* embedded literals */
78 :     Word_t offset; /* the offset of the next literal */
79 :     };
80 :    
81 :     struct extractlits_clos { /* the closure for BlastGC_ExtractLits */
82 :     writer_t *wr;
83 :     Word_t offset; /* the offset of the next literal; this is */
84 :     /* used to align reals. */
85 :     };
86 :    
87 :    
88 :     /* check to see if we need to extend the number of flipped generations */
89 :     #define CHECK_GEN(heap, g) { \
90 :     int __g = (g); \
91 :     if (__g > maxCollectedGen) \
92 :     BlastGC_Flip ((heap), __g); \
93 :     }
94 :    
95 :     /* BlastGC_CheckWord:
96 :     *
97 :     * Check an ML value for external references, etc.
98 :     */
99 :     #define BlastGC_CheckWord(heap, bibop, p, maxAid, errFlg) { \
100 :     ml_val_t __w = *(p); \
101 :     /*SayDebug ("CheckWord @ %#x --> %#x: ", p, __w);*/\
102 :     if (isBOXED(__w)) { \
103 :     aid_t __aid = ADDR_TO_PAGEID(bibop, __w); \
104 :     if (isUNMAPPED(__aid)) { \
105 :     /* an external reference */ \
106 :     /*SayDebug ("external reference\n");*/\
107 :     if ((! finishGC) && (ExportCSymbol(ExportTbl, __w) == ML_unit)) \
108 :     (errFlg) = TRUE; \
109 :     } \
110 :     else if (IS_BIGOBJ_AID(__aid)) \
111 :     /*{SayDebug ("big-object\n");*/\
112 :     BlastGC_ForwardBigObj(heap, p, __w, __aid); \
113 :     /*}*/\
114 :     else if (IS_FROM_SPACE(__aid, maxAid)) \
115 :     /*{SayDebug ("regular object\n");*/\
116 :     *(p) = BlastGC_ForwardObj(heap, __w, __aid); \
117 :     /*}*/\
118 :     } \
119 :     /*else SayDebug ("unboxed \n");*/\
120 :     }
121 :    
122 :    
123 :     /* BlastGC:
124 :     *
125 :     */
126 :     blast_res_t BlastGC (ml_state_t *msp, ml_val_t *root, int gen)
127 :     {
128 :     heap_t *heap = msp->ml_heap;
129 :     bibop_t bibop = BIBOP;
130 :     int i, j;
131 :     blast_res_t result;
132 :     bool_t errFlg = FALSE;
133 :    
134 :     /* Allocates the export and embedded object tables */
135 :     ExportTbl = NewExportTbl();
136 :     EmbObjTbl = MakeAddrTbl(LOG_BYTES_PER_WORD, 64);
137 :    
138 :     result.exportTbl = ExportTbl;
139 :     result.embobjTbl = EmbObjTbl;
140 :    
141 :     /* Initialize, by flipping the generations upto the one including the object */
142 :     repairHeap = TRUE;
143 :     finishGC = FALSE;
144 :     maxCollectedGen = 0;
145 :     BlastGC_Flip (heap, gen);
146 :    
147 :     /* Scan the object root */
148 :     BlastGC_CheckWord (heap, bibop, root, AID_MAX, errFlg);
149 :     if (errFlg) {
150 :     result.error = TRUE;
151 :     return result;
152 :     }
153 :    
154 :     /* Sweep to-space */
155 :     if (BlastGC_SweepToSpace(heap, AID_MAX) == FAILURE) {
156 :     result.error = TRUE;
157 :     return result;
158 :     }
159 :    
160 :     result.error = FALSE;
161 :     result.needsRepair = repairHeap;
162 :     result.maxGen = maxCollectedGen;
163 :    
164 :     return result;
165 :    
166 :     } /* end of BlastGC. */
167 :    
168 :    
169 :     /* BlastGC_AssignLitAddrs:
170 :     *
171 :     * Assign relocation addresses to the embedded literals that are going to be
172 :     * extracted. The arguments to this are the blast result (containing the
173 :     * embedded literal table), the ID of the heap image chunk that the string
174 :     * literals are to be stored in, and the starting offset in that chunk.
175 :     * This returns the address immediately following the last embedded literal.
176 :     *
177 :     * NOTE: this code will break if the size of the string space, plus embedded
178 :     * literals exceeds 16Mb.
179 :     */
180 :     Addr_t BlastGC_AssignLitAddrs (blast_res_t *res, int id, Addr_t offset)
181 :     {
182 :     struct assignlits_clos closure;
183 :    
184 :     closure.offset = offset;
185 :     closure.id = id;
186 :     AddrTblApply (EmbObjTbl, &closure, BlastGC_AssignLits);
187 :    
188 :     return closure.offset;
189 :    
190 :     } /* end of BlastGC_AssignLitAddrs */
191 :    
192 :    
193 :     /* BlastGC_BlastLits:
194 :     *
195 :     * Blast out the embedded literals.
196 :     */
197 :     void BlastGC_BlastLits (writer_t *wr)
198 :     {
199 :     struct extractlits_clos closure;
200 :    
201 :     closure.wr = wr;
202 :     closure.offset = 0;
203 :     AddrTblApply (EmbObjTbl, &closure, BlastGC_ExtractLits);
204 :    
205 :     } /* end of BlastGC_BlastLits */
206 :    
207 :    
208 :     /* BlastGC_FinishUp:
209 :     *
210 :     * Finish up the blast-out operation. This means either repairing the heap,
211 :     * or completing the GC.
212 :     */
213 :     void BlastGC_FinishUp (ml_state_t *msp, blast_res_t *res)
214 :     {
215 :     if (res->needsRepair)
216 :     BlastGC_RepairHeap (msp, res->maxGen);
217 :     else
218 :     BlastGC_FinishGC (msp, res->maxGen);
219 :    
220 :     FreeExportTbl (ExportTbl);
221 :     FreeAddrTbl (EmbObjTbl, TRUE);
222 :    
223 :     } /* BlastGC_FinishUp */
224 :    
225 :     /* BlastGC_RepairHeap:
226 :     */
227 :     PVT void BlastGC_RepairHeap (ml_state_t *msp, int maxGen)
228 :     {
229 :     heap_t *heap = msp->ml_heap;
230 :     int i, j;
231 :    
232 :     #ifdef VERBOSE
233 :     SayDebug ("Repairing blast GC (maxGen = %d of %d)\n", maxGen, heap->numGens);
234 :     #endif
235 :     for (i = 0; i < maxGen; i++) {
236 :     gen_t *gen = heap->gen[i];
237 :    
238 :     #define REPAIR(INDX) { \
239 :     arena_t *__ap = gen->arena[INDX]; \
240 :     if (isACTIVE(__ap)) { \
241 :     repair_t *__stop, *__rp; \
242 :     __stop = (repair_t *)(__ap->tospTop); \
243 :     for (__rp = __ap->repairList; __rp < __stop; __rp++) { \
244 :     ml_val_t *__p = __rp->loc; \
245 :     if (INDX != PAIR_INDX) \
246 :     __p[-1] = FOLLOW_FWDOBJ(__p)[-1]; \
247 :     __p[0] = __rp->val; \
248 :     } \
249 :     } \
250 :     } /* end of REPAIR */
251 :    
252 :     /* repair the arenas */
253 :     REPAIR(RECORD_INDX);
254 :     REPAIR(PAIR_INDX);
255 :     REPAIR(STRING_INDX);
256 :     REPAIR(ARRAY_INDX);
257 :    
258 :     /* free the to-space object, and reset the BIBOP marks */
259 :     for (j = 0; j < NUM_ARENAS; j++) {
260 :     arena_t *ap = gen->arena[j];
261 :     if (isACTIVE(ap)) {
262 :     /* un-flip the spaces; note that FreeGeneration needs the from-space
263 :     * information.
264 :     */
265 :     ml_val_t *tmpBase = ap->tospBase;
266 :     Addr_t tmpSizeB = ap->tospSizeB;
267 :     ml_val_t *tmpTop = ap->tospTop;
268 :     ap->nextw =
269 :     ap->sweep_nextw = ap->frspTop;
270 :     ap->tospBase = ap->frspBase;
271 :     ap->frspBase = tmpBase;
272 :     ap->tospSizeB = ap->frspSizeB;
273 :     ap->frspSizeB = tmpSizeB;
274 :     ap->tospTop = savedTop[i][j];
275 :     ap->frspTop = tmpTop;
276 :     }
277 :     } /* end of for */
278 :     /* free the to-space memory object */
279 :     {
280 :     mem_obj_t *tmpObj = gen->fromObj;
281 :     gen->fromObj = gen->toObj;
282 :     gen->toObj = tmpObj;
283 :     FreeGeneration (heap, i);
284 :     }
285 :     } /* end of for */
286 :    
287 :     } /* end of BlastGC_RepairHeap */
288 :    
289 :    
290 :     /* BlastGC_FinishGC:
291 :     *
292 :     * Complete the partial garbage collection.
293 :     */
294 :     PVT void BlastGC_FinishGC (ml_state_t *msp, int maxGen)
295 :     {
296 :     heap_t *heap = msp->ml_heap;
297 :     bibop_t bibop = BIBOP;
298 :     bool_t dummy = FALSE;
299 :     Word_t mask;
300 :     int i, j;
301 :     aid_t maxAid;
302 :    
303 :     #ifdef VERBOSE
304 :     SayDebug ("Completing blast GC (maxGen = %d of %d)\n", maxGen, heap->numGens);
305 :     #endif
306 :     finishGC = TRUE;
307 :     maxAid = MAKE_MAX_AID(maxGen);
308 :    
309 :     /* allocate new dirty vectors for the flipped generations */
310 :     for (i = 0; i < maxGen; i++) {
311 :     gen_t *gen = heap->gen[i];
312 :     if (isACTIVE(gen->arena[ARRAY_INDX]))
313 :     NewDirtyVector(gen);
314 :     }
315 :    
316 :     /* collect the roots */
317 :     #define CheckRoot(p) { \
318 :     ml_val_t *__p = (p); \
319 :     BlastGC_CheckWord (heap, bibop, __p, maxAid, dummy); \
320 :     }
321 :    
322 :     for (i = 0; i < NumCRoots; i++)
323 :     CheckRoot(CRoots[i]);
324 :    
325 :     CheckRoot(&(msp->ml_arg));
326 :     CheckRoot(&(msp->ml_cont));
327 :     CheckRoot(&(msp->ml_closure));
328 :     CheckRoot(&(msp->ml_linkReg));
329 :     CheckRoot(&(msp->ml_pc));
330 :     CheckRoot(&(msp->ml_exnCont));
331 :     CheckRoot(&(msp->ml_varReg));
332 :     CheckRoot(&(msp->ml_calleeSave[0]));
333 :     CheckRoot(&(msp->ml_calleeSave[1]));
334 :     CheckRoot(&(msp->ml_calleeSave[2]));
335 :    
336 :     /* sweep the dirty pages of generations over maxGen */
337 :     for (i = maxGen; i < heap->numGens; i++) {
338 :     gen_t *gen = heap->gen[i];
339 :     if (isACTIVE(gen->arena[ARRAY_INDX])) {
340 :     card_map_t *cm = gen->dirty;
341 :     if (cm != NIL(card_map_t *)) {
342 :     ml_val_t *maxSweep = gen->arena[ARRAY_INDX]->sweep_nextw;
343 :     int card;
344 :     #if (!defined(BIT_CARDS) && defined(TOSPACE_ID))
345 :     FOR_DIRTY_CARD (cm, maxGen, card, {
346 :     ml_val_t *p = (cm->baseAddr + (card*CARD_SZW));
347 :     ml_val_t *q = p + CARD_SZW;
348 :     int mark = i+1;
349 :     if (q > maxSweep)
350 :     /* don't sweep above the allocation high-water mark */
351 :     q = maxSweep;
352 :     for (; p < q; p++) {
353 :     ml_val_t w = *p;
354 :     if (isBOXED(w)) {
355 :     aid_t aid = ADDR_TO_PAGEID(bibop, w);
356 :     int targetGen;
357 :     if (IS_FROM_SPACE(aid, maxAid)) {
358 :     /* this is a from-space object */
359 :     if (IS_BIGOBJ_AID(aid)) {
360 :     bigobj_desc_t *dp;
361 :     dp = BlastGC_ForwardBigObj (heap, p, w, aid);
362 :     targetGen = dp->gen;
363 :     }
364 :     else {
365 :     *p =
366 :     w = BlastGC_ForwardObj(heap, w, aid);
367 :     aid = ADDR_TO_PAGEID(bibop, w);
368 :     if (IS_TOSPACE_AID(aid))
369 :     targetGen = TOSPACE_GEN(aid);
370 :     else
371 :     targetGen = EXTRACT_GEN(aid);
372 :     }
373 :     if (targetGen < mark)
374 :     mark = targetGen;
375 :     }
376 :     }
377 :     } /* end of for */
378 :     /* re-mark the card */
379 :     ASSERT(cm->map[card] <= mark);
380 :     if (mark <= i)
381 :     cm->map[card] = mark;
382 :     else if (i == maxGen)
383 :     cm->map[card] = CARD_CLEAN;
384 :     });
385 :     #elif (!defined(BIT_CARDS))
386 :     FOR_DIRTY_CARD (cm, maxGen, card, {
387 :     ml_val_t *p = (cm->baseAddr + (card*CARD_SZW));
388 :     ml_val_t *q = p + CARD_SZW;
389 :     int mark = i+1;
390 :     if (q > maxSweep)
391 :     /* don't sweep above the allocation high-water mark */
392 :     q = maxSweep;
393 :     for (; p < q; p++) {
394 :     ml_val_t w = *p;
395 :     if (isBOXED(w)) {
396 :     aid_t aid = ADDR_TO_PAGEID(bibop, w);
397 :     int targetGen;
398 :     if (IS_FROM_SPACE(aid, maxAid)) {
399 :     /* this is a from-space object */
400 :     if (IS_BIGOBJ_AID(aid)) {
401 :     bigobj_desc_t *dp;
402 :     dp = BlastGC_ForwardBigObj (heap, p, w, aid);
403 :     targetGen = dp->gen;
404 :     }
405 :     else {
406 :     *p =
407 :     w = BlastGC_ForwardObj(heap, w, aid);
408 :     targetGen = EXTRACT_GEN(ADDR_TO_PAGEID(bibop, w));
409 :     }
410 :     if (targetGen < mark)
411 :     mark = targetGen;
412 :     }
413 :     }
414 :     } /* end of for */
415 :     /* re-mark the card */
416 :     ASSERT(cm->map[card] <= mark);
417 :     if (mark <= i)
418 :     cm->map[card] = mark;
419 :     else if (i == maxGen)
420 :     cm->map[card] = CARD_CLEAN;
421 :     });
422 :     #else
423 :     /* BIT_CARDS */
424 :     #endif
425 :     }
426 :     }
427 :     }
428 :    
429 :     /* sweep to-space */
430 :     BlastGC_SweepToSpace (heap, maxAid);
431 :    
432 :     /* Scan the array spaces of the flipped generations, marking dirty pages */
433 :     for (i = 1; i < maxGen; i++) {
434 :     gen_t *gen = heap->gen[i];
435 :     arena_t *ap = gen->arena[ARRAY_INDX];
436 :     if (isACTIVE(ap)) {
437 :     card_map_t *cm = gen->dirty;
438 :     int card;
439 :     ml_val_t *p, *stop, w;
440 :    
441 :     p = ap->tospBase;
442 :     card = 0;
443 :     while (p < ap->nextw) {
444 :     int mark = i+1;
445 :     stop = (ml_val_t *)(((Addr_t)p + CARD_SZB) & ~(CARD_SZB - 1));
446 :     if (stop > ap->nextw)
447 :     stop = ap->nextw;
448 :     while (p < stop) {
449 :     if (isBOXED(w = *p++)) {
450 :     aid_t aid = ADDR_TO_PAGEID(bibop, w);
451 :     int targetGen;
452 :    
453 :     if (IS_BIGOBJ_AID(aid)) {
454 :     bigobj_desc_t *dp = BO_GetDesc(w);
455 :     targetGen = dp->gen;
456 :     }
457 :     else
458 :     targetGen = EXTRACT_GEN(aid);
459 :     if (targetGen < mark) {
460 :     mark = targetGen;
461 :     if (mark == 1) {
462 :     p = stop;
463 :     break; /* nothing dirtier than 1st generation */
464 :     }
465 :     }
466 :     }
467 :     }
468 :     if (mark <= i)
469 :     cm->map[card] = mark;
470 :     else
471 :     cm->map[card] = CARD_CLEAN;
472 :     card++;
473 :     }
474 :     }
475 :     }
476 :    
477 :     /* reclaim space */
478 :     for (i = 0; i < maxGen; i++) {
479 :     FreeGeneration (heap, i);
480 :     #ifdef TOSPACE_ID
481 :     for (j = 0; j < NUM_ARENAS; j++) {
482 :     arena_t *ap = heap->gen[i]->arena[j];
483 :     if (isACTIVE(ap))
484 :     MarkRegion (bibop, ap->tospBase, ap->tospSizeB, ap->id);
485 :     }
486 :     #endif
487 :     }
488 :    
489 :     /* remember the top of to-space in the collected generations */
490 :     for (i = 0; i < maxGen; i++) {
491 :     gen_t *g = heap->gen[i];
492 :     if (i == heap->numGens-1) {
493 :     /* the oldest generation has only "young" objects */
494 :     for (j = 0; j < NUM_ARENAS; j++) {
495 :     if (isACTIVE(g->arena[j]))
496 :     g->arena[j]->oldTop = g->arena[j]->tospBase;
497 :     else
498 :     g->arena[j]->oldTop = NIL(ml_val_t *);
499 :     }
500 :     }
501 :     else {
502 :     for (j = 0; j < NUM_ARENAS; j++) {
503 :     if (isACTIVE(g->arena[j]))
504 :     g->arena[j]->oldTop = g->arena[j]->nextw;
505 :     else
506 :     g->arena[j]->oldTop = NIL(ml_val_t *);
507 :     }
508 :     }
509 :     }
510 :    
511 :     HeapMon_UpdateHeap (heap, maxSweptGen);
512 :    
513 :     #ifdef GC_STATS
514 :     /* Count the number of forwarded bytes */
515 :     for (i = 0; i < maxGen; i++) {
516 :     for (j = 0; j < NUM_ARENAS; j++) {
517 :     arena_t *ap = heap->gen[i]->arena[j];
518 :     if (isACTIVE(ap)) {
519 :     CNTR_INCR(&(heap->numCopied[i][j]), ap->nextw - ap->tospBase);
520 :     }
521 :     }
522 :     }
523 :     #endif
524 :    
525 :     } /* end of BlastGC_FinishGC */
526 :    
527 :    
528 :     /* BlastGC_Flip:
529 :     *
530 :     * Flip additional generations from maxCollectedGen+1 .. gen. We allocate
531 :     * a to-space that is the same size as the existing from-space.
532 :     */
533 :     PVT void BlastGC_Flip (heap_t *heap, int gen)
534 :     {
535 :     int i, j;
536 :     Addr_t newSz;
537 :    
538 :     for (i = maxCollectedGen; i < gen; i++) {
539 :     gen_t *g = heap->gen[i];
540 :     for (j = 0; j < NUM_ARENAS; j++) {
541 :     arena_t *ap = g->arena[j];
542 :     if (isACTIVE(ap)) {
543 :     ASSERT ((j == STRING_INDX) || (ap->nextw == ap->sweep_nextw));
544 :     savedTop[i][j] = ap->tospTop;
545 :     FLIP_ARENA(ap);
546 :     newSz = (Addr_t)(ap->frspTop) - (Addr_t)(ap->frspBase);
547 :     if (i == 0)
548 :     /* need to guarantee space for future minor collections */
549 :     newSz += heap->allocSzB;
550 :     if (j == PAIR_INDX)
551 :     newSz += 2*WORD_SZB;
552 :     ap->tospSizeB = RND_MEMOBJ_SZB(newSz);
553 :     }
554 :     }
555 :     g->fromObj = g->toObj;
556 :     #ifdef VERBOSE
557 :     SayDebug ("New Generation %d:\n", i+1);
558 :     #endif
559 :     if (NewGeneration(g) == FAILURE)
560 :     Die ("unable to allocate to-space for generation %d\n", i+1);
561 :     /* initialize the repair lists */
562 :     for (j = 0; j < NUM_ARENAS; j++) {
563 :     arena_t *ap = g->arena[j];
564 :     #ifdef VERBOSE
565 :     if (isACTIVE(ap)) SayDebug (" %#x: [%#x, %#x)\n", ap->id, ap->tospBase, ap->tospTop);
566 :     #endif
567 :     if (isACTIVE(ap))
568 :     ap->repairList = (repair_t *)(ap->tospTop);
569 :     }
570 :     }
571 :    
572 :     maxCollectedGen = gen;
573 :    
574 :     } /* end of BlastGC_Flip */
575 :    
576 :     /* BlastGC_SweepToSpace:
577 :     * Sweep the to-space arenas. Because there are few references forward in time, we
578 :     * try to completely scavenge a younger generation before moving on to the
579 :     * next oldest.
580 :     */
581 :     PVT status_t BlastGC_SweepToSpace (heap_t *heap, aid_t maxAid)
582 :     {
583 :     int i;
584 :     bool_t swept;
585 :     bibop_t bibop = BIBOP;
586 :     bool_t errFlg = FALSE;
587 :    
588 :     #define SweepToSpArena(gen, indx) { \
589 :     arena_t *__ap = (gen)->arena[(indx)]; \
590 :     if (isACTIVE(__ap)) { \
591 :     ml_val_t *__p, *__q; \
592 :     __p = __ap->sweep_nextw; \
593 :     if (__p < __ap->nextw) { \
594 :     swept = TRUE; \
595 :     do { \
596 :     for (__q = __ap->nextw; __p < __q; __p++) { \
597 :     BlastGC_CheckWord(heap, bibop, __p, maxAid, errFlg); \
598 :     } \
599 :     } while (__q != __ap->nextw); \
600 :     __ap->sweep_nextw = __q; \
601 :     } \
602 :     } \
603 :     } /* SweepToSpArena */
604 :    
605 :     do {
606 :     swept = FALSE;
607 :     for (i = 0; i < maxCollectedGen; i++) {
608 :     gen_t *gen = heap->gen[i];
609 :    
610 :     /* Sweep the record and pair arenas */
611 :     SweepToSpArena(gen, RECORD_INDX);
612 :     SweepToSpArena(gen, PAIR_INDX);
613 :     SweepToSpArena(gen, ARRAY_INDX);
614 :     }
615 :     } while (swept && (!errFlg));
616 :    
617 :     return (errFlg ? FAILURE : SUCCESS);
618 :    
619 :     } /* end of SweepToSpace */
620 :    
621 :    
622 :     /* BlastGC_ForwardObj:
623 :     *
624 :     * Forward an object.
625 :     */
626 :     PVT ml_val_t BlastGC_ForwardObj (heap_t *heap, ml_val_t v, aid_t id)
627 :     {
628 :     ml_val_t *obj = PTR_MLtoC(ml_val_t, v);
629 :     int gen = EXTRACT_GEN(id);
630 :     ml_val_t *new_obj;
631 :     ml_val_t desc;
632 :     Word_t len;
633 :     arena_t *arena;
634 :    
635 :     if (! finishGC)
636 :     CHECK_GEN(heap, gen);
637 :    
638 :     switch (EXTRACT_OBJC(id)) {
639 :     case OBJC_record: {
640 :     desc = obj[-1];
641 :     switch (GET_TAG(desc)) {
642 :     case DTAG_vec_hdr:
643 :     case DTAG_arr_hdr:
644 :     len = 2;
645 :     break;
646 :     case DTAG_forward:
647 :     /* This object has already been forwarded */
648 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj));
649 :     default:
650 :     len = GET_LEN(desc);
651 :     }
652 :     arena = heap->gen[gen-1]->arena[RECORD_INDX];
653 :     } break;
654 :    
655 :     case OBJC_pair: {
656 :     ml_val_t w;
657 :    
658 :     w = obj[0];
659 :     if (isDESC(w))
660 :     return PTR_CtoML(FOLLOW_FWDPAIR(w, obj));
661 :     else {
662 :     /* forward the pair */
663 :     arena = heap->gen[gen-1]->arena[PAIR_INDX];
664 :     new_obj = arena->nextw;
665 :     arena->nextw += 2;
666 :     new_obj[0] = w;
667 :     new_obj[1] = obj[1];
668 :     /* setup the forward pointer in the old pair */
669 :     NOTE_REPAIR(arena, obj, w);
670 :     obj[0] = MAKE_PAIR_FP(new_obj);
671 :     return PTR_CtoML(new_obj);
672 :     }
673 :     } break;
674 :    
675 :     case OBJC_string: {
676 :     arena = heap->gen[gen-1]->arena[STRING_INDX];
677 :     desc = obj[-1];
678 :     switch (GET_TAG(desc)) {
679 :     case DTAG_forward:
680 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj));
681 :     case DTAG_raw32:
682 :     len = GET_LEN(desc);
683 :     break;
684 :     case DTAG_raw64:
685 :     len = GET_LEN(desc);
686 :     #ifdef ALIGN_REALDS
687 :     # ifdef CHECK_HEAP
688 :     if (((Addr_t)arena->nextw & WORD_SZB) == 0) {
689 :     *(arena->nextw) = (ml_val_t)0;
690 :     arena->nextw++;
691 :     }
692 :     # else
693 :     arena->nextw = (ml_val_t *)(((Addr_t)arena->nextw) | WORD_SZB);
694 :     # endif
695 :     #endif
696 :     break;
697 :     default:
698 :     Die ("bad string tag %d, obj = %#x, desc = %#x",
699 :     GET_TAG(desc), obj, desc);
700 :     }
701 :     } break;
702 :    
703 :     case OBJC_array: {
704 :     desc = obj[-1];
705 :     switch (GET_TAG(desc)) {
706 :     case DTAG_forward:
707 :     /* This object has already been forwarded */
708 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj));
709 :     case DTAG_arr_data:
710 :     len = GET_LEN(desc);
711 :     break;
712 :     case DTAG_special:
713 :     /* we are conservative here, and never nullify special objects */
714 :     len = 1;
715 :     break;
716 :     default:
717 :     Die ("bad array tag %d, obj = %#x, desc = %#x",
718 :     GET_TAG(desc), obj, desc);
719 :     } /* end of switch */
720 :     arena = heap->gen[gen-1]->arena[ARRAY_INDX];
721 :     } break;
722 :    
723 :     case OBJC_bigobj:
724 :     default:
725 :     Die("BlastGC_ForwardObj: unknown object class %d @ %#x",
726 :     EXTRACT_OBJC(id), obj);
727 :     } /* end of switch */
728 :    
729 :     /* Allocate and initialize a to-space copy of the object */
730 :     new_obj = arena->nextw;
731 :     arena->nextw += (len + 1);
732 :     *new_obj++ = desc;
733 :     COPYLOOP(obj, new_obj, len);
734 :    
735 :     /* set up the forward pointer, and return the new object. */
736 :     NOTE_REPAIR(arena, obj, *obj);
737 :     obj[-1] = DESC_forwarded;
738 :     obj[0] = (ml_val_t)(Addr_t)new_obj;
739 :     return PTR_CtoML(new_obj);
740 :    
741 :     } /* end of BlastGC_ForwardObj */
742 :    
743 :    
744 :     /* BlastGC_ForwardBigObj:
745 :     *
746 :     * Forward a big-object obj, where id is the BIBOP entry for obj, and return
747 :     * the big-object descriptor.
748 :     * NOTE: we do not ``promote'' big-objects here, because are not reclaimed
749 :     * when completing th collection.
750 :     */
751 :     PVT bigobj_desc_t *BlastGC_ForwardBigObj (
752 :     heap_t *heap,
753 :     ml_val_t *p,
754 :     ml_val_t obj,
755 :     aid_t aid)
756 :     {
757 :     int i;
758 :     bigobj_region_t *region;
759 :     bigobj_desc_t *dp;
760 :     embobj_info_t *codeInfo, *objInfo;
761 :     embobj_kind_t kind;
762 :    
763 :     for (i = BIBOP_ADDR_TO_INDEX(obj); !BO_IS_HDR(aid); aid = BIBOP[--i])
764 :     continue;
765 :     region = (bigobj_region_t *)BIBOP_INDEX_TO_ADDR(i);
766 :     dp = ADDR_TO_BODESC(region, obj);
767 :    
768 :     if (! finishGC) {
769 :     CHECK_GEN(heap, dp->gen);
770 :     codeInfo = EmbObjLookup (EmbObjTbl, dp->obj, UNUSED_CODE);
771 :     codeInfo->kind = USED_CODE;
772 :     }
773 :    
774 :     return dp;
775 :    
776 :     } /* end of BlastGC_ForwardBigObj */
777 :    
778 :    
779 :     /* EmbObjLookup:
780 :     */
781 :     PVT embobj_info_t *EmbObjLookup (addr_tbl_t *tbl, Addr_t addr, embobj_kind_t kind)
782 :     {
783 :     embobj_info_t *p = FindEmbObj(tbl, addr);
784 :    
785 :     if (p == NIL(embobj_info_t *)) {
786 :     p = NEW_OBJ(embobj_info_t);
787 :     p->kind = kind;
788 :     p->codeObj = NIL(embobj_info_t *);
789 :     AddrTblInsert(tbl, addr, p);
790 :     }
791 :    
792 :     ASSERT(kind == p->kind);
793 :    
794 :     return p;
795 :    
796 :     } /* end of EmbObjLookup */
797 :    
798 :     /* BlastGC_AssignLits:
799 :     *
800 :     * Calculate the location of the extracted literal strings in the blasted
801 :     * image, and record their addresses. This function is passed as an argument
802 :     * to AddrTblApply; its second argument is its "closure," and its third
803 :     * argument is the embedded object info.
804 :     */
805 :     PVT void BlastGC_AssignLits (Addr_t addr, void *_closure, void *_info)
806 :     {
807 :     #ifdef XXX
808 :     struct assignlits_clos *closure = (struct assignlits_clos *) _closure;
809 :     embobj_info_t *info = (embobj_info_t *) _info;
810 :     int objSzB;
811 :    
812 :     switch (info->kind) {
813 :     case UNUSED_CODE:
814 :     case USED_CODE:
815 :     info->relAddr = (ml_val_t)0;
816 :     return;
817 :     case EMB_STRING: {
818 :     int nChars = OBJ_LEN(PTR_CtoML(addr));
819 :     int nWords = BYTES_TO_WORDS(nChars);
820 :     if ((nChars != 0) && ((nChars & 0x3) == 0))
821 :     nWords++;
822 :     objSzB = nWords * WORD_SZB;
823 :     } break;
824 :     case EMB_REALD:
825 :     objSzB = OBJ_LEN(PTR_CtoML(addr)) * REALD_SZB;
826 :     #ifdef ALIGN_REALDS
827 :     closure->offset |= WORD_SZB;
828 :     #endif
829 :     break;
830 :     }
831 :    
832 :     if (info->codeObj->kind == USED_CODE) {
833 :     /* the containing code object is also being exported */
834 :     info->relAddr = (ml_val_t)0;
835 :     return;
836 :     }
837 :    
838 :     if (objSzB == 0) {
839 :     info->relAddr = ExportCSymbol (ExportTbl,
840 :     (info->kind == EMB_STRING) ? ML_string0 : ML_realarray0);
841 :     }
842 :     else {
843 :     /* assign a relocation address to the object, and bump the offset counter */
844 :     closure->offset += WORD_SZB; /* space for the descriptor */
845 :     info->relAddr = HIO_TAG_PTR(closure->id, closure->offset);
846 :     closure->offset += objSzB;
847 :     }
848 :     #else
849 :     Die ("BlastGC_AssignLits");
850 :     #endif
851 :     } /* end of BlastGC_AssignLits */
852 :    
853 :     /* BlastGC_ExtractLits:
854 :     *
855 :     * Extract the embedded literals that are in otherwise unreferenced code
856 :     * blocks. This function is passed as an argument to AddrTblApply; its
857 :     * second argument is its "closure," and its third argument is the
858 :     * embedded object info.
859 :     */
860 :     PVT void BlastGC_ExtractLits (Addr_t addr, void *_closure, void *_info)
861 :     {
862 :     struct extractlits_clos *closure = (struct extractlits_clos *) _closure;
863 :     embobj_info_t *info = (embobj_info_t *) _info;
864 :     int objSzB;
865 :    
866 :     if (info->relAddr == (ml_val_t)0)
867 :     return;
868 :    
869 :     switch (info->kind) {
870 :     case EMB_STRING: {
871 :     int nChars = OBJ_LEN(PTR_CtoML(addr));
872 :     int nWords = BYTES_TO_WORDS(nChars);
873 :     if ((nChars != 0) && ((nChars & 0x3) == 0))
874 :     nWords++;
875 :     objSzB = nWords * WORD_SZB;
876 :     } break;
877 :     case EMB_REALD:
878 :     objSzB = OBJ_LEN(PTR_CtoML(addr)) * REALD_SZB;
879 :     #ifdef ALIGN_REALDS
880 :     if ((closure->offset & (REALD_SZB-1)) == 0) {
881 :     /* the descriptor would be 8-byte aligned, which means that the
882 :     * real number would not be, so add some padding.
883 :     */
884 :     WR_Put(closure->wr, 0);
885 :     closure->offset += 4;
886 :     }
887 :     #endif
888 :     break;
889 :     }
890 :    
891 :     if (objSzB != 0) {
892 :     /* extract the object into the blast buffer (including the descriptor) */
893 :     WR_Write(closure->wr, (void *)(addr - WORD_SZB), objSzB + WORD_SZB);
894 :     closure->offset += (objSzB + WORD_SZB);
895 :     }
896 :    
897 :     } /* end of BlastGC_ExtractLits */

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0