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 224 - (view) (download) (as text)

1 : monnier 2 /* 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 : monnier 223 __p[-1] = FOLLOW_FWDOBJ(__p)[-1]; \
247 : monnier 2 __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_exnCont));
326 :     CheckRoot(&(msp->ml_varReg));
327 :     #ifdef BASE_INDX
328 :     CheckRoot(&(msp->ml_baseReg));
329 :     #endif
330 :     mask = msp->ml_liveRegMask;
331 :     for (i = 0; mask != 0; i++, mask >>= 1) {
332 :     if ((mask & 1) != 0)
333 :     CheckRoot(&(msp->ml_roots[ArgRegMap[i]]));
334 :     }
335 :     CheckRoot(&(msp->ml_pc));
336 :    
337 :     /* sweep the dirty pages of generations over maxGen */
338 :     for (i = maxGen; i < heap->numGens; i++) {
339 :     gen_t *gen = heap->gen[i];
340 :     if (isACTIVE(gen->arena[ARRAY_INDX])) {
341 :     card_map_t *cm = gen->dirty;
342 :     if (cm != NIL(card_map_t *)) {
343 :     ml_val_t *maxSweep = gen->arena[ARRAY_INDX]->sweep_nextw;
344 :     int card;
345 :     #if (!defined(BIT_CARDS) && defined(TOSPACE_ID))
346 :     FOR_DIRTY_CARD (cm, maxGen, card, {
347 :     ml_val_t *p = (cm->baseAddr + (card*CARD_SZW));
348 :     ml_val_t *q = p + CARD_SZW;
349 :     int mark = i+1;
350 :     if (q > maxSweep)
351 :     /* don't sweep above the allocation high-water mark */
352 :     q = maxSweep;
353 :     for (; p < q; p++) {
354 :     ml_val_t w = *p;
355 :     if (isBOXED(w)) {
356 :     aid_t aid = ADDR_TO_PAGEID(bibop, w);
357 :     int targetGen;
358 :     if (IS_FROM_SPACE(aid, maxAid)) {
359 :     /* this is a from-space object */
360 :     if (IS_BIGOBJ_AID(aid)) {
361 :     bigobj_desc_t *dp;
362 :     dp = BlastGC_ForwardBigObj (heap, p, w, aid);
363 :     targetGen = dp->gen;
364 :     }
365 :     else {
366 :     *p =
367 :     w = BlastGC_ForwardObj(heap, w, aid);
368 :     aid = ADDR_TO_PAGEID(bibop, w);
369 :     if (IS_TOSPACE_AID(aid))
370 :     targetGen = TOSPACE_GEN(aid);
371 :     else
372 :     targetGen = EXTRACT_GEN(aid);
373 :     }
374 :     if (targetGen < mark)
375 :     mark = targetGen;
376 :     }
377 :     }
378 :     } /* end of for */
379 :     /* re-mark the card */
380 :     ASSERT(cm->map[card] <= mark);
381 :     if (mark <= i)
382 :     cm->map[card] = mark;
383 :     else if (i == maxGen)
384 :     cm->map[card] = CARD_CLEAN;
385 :     });
386 :     #elif (!defined(BIT_CARDS))
387 :     FOR_DIRTY_CARD (cm, maxGen, card, {
388 :     ml_val_t *p = (cm->baseAddr + (card*CARD_SZW));
389 :     ml_val_t *q = p + CARD_SZW;
390 :     int mark = i+1;
391 :     if (q > maxSweep)
392 :     /* don't sweep above the allocation high-water mark */
393 :     q = maxSweep;
394 :     for (; p < q; p++) {
395 :     ml_val_t w = *p;
396 :     if (isBOXED(w)) {
397 :     aid_t aid = ADDR_TO_PAGEID(bibop, w);
398 :     int targetGen;
399 :     if (IS_FROM_SPACE(aid, maxAid)) {
400 :     /* this is a from-space object */
401 :     if (IS_BIGOBJ_AID(aid)) {
402 :     bigobj_desc_t *dp;
403 :     dp = BlastGC_ForwardBigObj (heap, p, w, aid);
404 :     targetGen = dp->gen;
405 :     }
406 :     else {
407 :     *p =
408 :     w = BlastGC_ForwardObj(heap, w, aid);
409 :     targetGen = EXTRACT_GEN(ADDR_TO_PAGEID(bibop, w));
410 :     }
411 :     if (targetGen < mark)
412 :     mark = targetGen;
413 :     }
414 :     }
415 :     } /* end of for */
416 :     /* re-mark the card */
417 :     ASSERT(cm->map[card] <= mark);
418 :     if (mark <= i)
419 :     cm->map[card] = mark;
420 :     else if (i == maxGen)
421 :     cm->map[card] = CARD_CLEAN;
422 :     });
423 :     #else
424 :     /* BIT_CARDS */
425 :     #endif
426 :     }
427 :     }
428 :     }
429 :    
430 :     /* sweep to-space */
431 :     BlastGC_SweepToSpace (heap, maxAid);
432 :    
433 :     /* Scan the array spaces of the flipped generations, marking dirty pages */
434 :     for (i = 1; i < maxGen; i++) {
435 :     gen_t *gen = heap->gen[i];
436 :     arena_t *ap = gen->arena[ARRAY_INDX];
437 :     if (isACTIVE(ap)) {
438 :     card_map_t *cm = gen->dirty;
439 :     int card;
440 :     ml_val_t *p, *stop, w;
441 :    
442 :     p = ap->tospBase;
443 :     card = 0;
444 :     while (p < ap->nextw) {
445 :     int mark = i+1;
446 :     stop = (ml_val_t *)(((Addr_t)p + CARD_SZB) & ~(CARD_SZB - 1));
447 :     if (stop > ap->nextw)
448 :     stop = ap->nextw;
449 :     while (p < stop) {
450 :     if (isBOXED(w = *p++)) {
451 :     aid_t aid = ADDR_TO_PAGEID(bibop, w);
452 :     int targetGen;
453 :    
454 :     if (IS_BIGOBJ_AID(aid)) {
455 :     bigobj_desc_t *dp = BO_GetDesc(w);
456 :     targetGen = dp->gen;
457 :     }
458 :     else
459 :     targetGen = EXTRACT_GEN(aid);
460 :     if (targetGen < mark) {
461 :     mark = targetGen;
462 :     if (mark == 1) {
463 :     p = stop;
464 :     break; /* nothing dirtier than 1st generation */
465 :     }
466 :     }
467 :     }
468 :     }
469 :     if (mark <= i)
470 :     cm->map[card] = mark;
471 :     else
472 :     cm->map[card] = CARD_CLEAN;
473 :     card++;
474 :     }
475 :     }
476 :     }
477 :    
478 :     /* reclaim space */
479 :     for (i = 0; i < maxGen; i++) {
480 :     FreeGeneration (heap, i);
481 :     #ifdef TOSPACE_ID
482 :     for (j = 0; j < NUM_ARENAS; j++) {
483 :     arena_t *ap = heap->gen[i]->arena[j];
484 :     if (isACTIVE(ap))
485 :     MarkRegion (bibop, ap->tospBase, ap->tospSizeB, ap->id);
486 :     }
487 :     #endif
488 :     }
489 :    
490 :     /* remember the top of to-space in the collected generations */
491 :     for (i = 0; i < maxGen; i++) {
492 :     gen_t *g = heap->gen[i];
493 :     if (i == heap->numGens-1) {
494 :     /* the oldest generation has only "young" objects */
495 :     for (j = 0; j < NUM_ARENAS; j++) {
496 :     if (isACTIVE(g->arena[j]))
497 :     g->arena[j]->oldTop = g->arena[j]->tospBase;
498 :     else
499 :     g->arena[j]->oldTop = NIL(ml_val_t *);
500 :     }
501 :     }
502 :     else {
503 :     for (j = 0; j < NUM_ARENAS; j++) {
504 :     if (isACTIVE(g->arena[j]))
505 :     g->arena[j]->oldTop = g->arena[j]->nextw;
506 :     else
507 :     g->arena[j]->oldTop = NIL(ml_val_t *);
508 :     }
509 :     }
510 :     }
511 :    
512 :     HeapMon_UpdateHeap (heap, maxSweptGen);
513 :    
514 :     #ifdef GC_STATS
515 :     /* Count the number of forwarded bytes */
516 :     for (i = 0; i < maxGen; i++) {
517 :     for (j = 0; j < NUM_ARENAS; j++) {
518 :     arena_t *ap = heap->gen[i]->arena[j];
519 :     if (isACTIVE(ap)) {
520 :     CNTR_INCR(&(heap->numCopied[i][j]), ap->nextw - ap->tospBase);
521 :     }
522 :     }
523 :     }
524 :     #endif
525 :    
526 :     } /* end of BlastGC_FinishGC */
527 :    
528 :    
529 :     /* BlastGC_Flip:
530 :     *
531 :     * Flip additional generations from maxCollectedGen+1 .. gen. We allocate
532 :     * a to-space that is the same size as the existing from-space.
533 :     */
534 :     PVT void BlastGC_Flip (heap_t *heap, int gen)
535 :     {
536 :     int i, j;
537 :     Addr_t newSz;
538 :    
539 :     for (i = maxCollectedGen; i < gen; i++) {
540 :     gen_t *g = heap->gen[i];
541 :     for (j = 0; j < NUM_ARENAS; j++) {
542 :     arena_t *ap = g->arena[j];
543 :     if (isACTIVE(ap)) {
544 :     ASSERT ((j == STRING_INDX) || (ap->nextw == ap->sweep_nextw));
545 :     savedTop[i][j] = ap->tospTop;
546 :     FLIP_ARENA(ap);
547 :     newSz = (Addr_t)(ap->frspTop) - (Addr_t)(ap->frspBase);
548 :     if (i == 0)
549 :     /* need to guarantee space for future minor collections */
550 :     newSz += heap->allocSzB;
551 :     if (j == PAIR_INDX)
552 :     newSz += 2*WORD_SZB;
553 :     ap->tospSizeB = RND_MEMOBJ_SZB(newSz);
554 :     }
555 :     }
556 :     g->fromObj = g->toObj;
557 :     #ifdef VERBOSE
558 :     SayDebug ("New Generation %d:\n", i+1);
559 :     #endif
560 :     if (NewGeneration(g) == FAILURE)
561 :     Die ("unable to allocate to-space for generation %d\n", i+1);
562 :     /* initialize the repair lists */
563 :     for (j = 0; j < NUM_ARENAS; j++) {
564 :     arena_t *ap = g->arena[j];
565 :     #ifdef VERBOSE
566 :     if (isACTIVE(ap)) SayDebug (" %#x: [%#x, %#x)\n", ap->id, ap->tospBase, ap->tospTop);
567 :     #endif
568 :     if (isACTIVE(ap))
569 :     ap->repairList = (repair_t *)(ap->tospTop);
570 :     }
571 :     }
572 :    
573 :     maxCollectedGen = gen;
574 :    
575 :     } /* end of BlastGC_Flip */
576 :    
577 :     /* BlastGC_SweepToSpace:
578 :     * Sweep the to-space arenas. Because there are few references forward in time, we
579 :     * try to completely scavenge a younger generation before moving on to the
580 :     * next oldest.
581 :     */
582 :     PVT status_t BlastGC_SweepToSpace (heap_t *heap, aid_t maxAid)
583 :     {
584 :     int i;
585 :     bool_t swept;
586 :     bibop_t bibop = BIBOP;
587 :     bool_t errFlg = FALSE;
588 :    
589 :     #define SweepToSpArena(gen, indx) { \
590 :     arena_t *__ap = (gen)->arena[(indx)]; \
591 :     if (isACTIVE(__ap)) { \
592 :     ml_val_t *__p, *__q; \
593 :     __p = __ap->sweep_nextw; \
594 :     if (__p < __ap->nextw) { \
595 :     swept = TRUE; \
596 :     do { \
597 :     for (__q = __ap->nextw; __p < __q; __p++) { \
598 :     BlastGC_CheckWord(heap, bibop, __p, maxAid, errFlg); \
599 :     } \
600 :     } while (__q != __ap->nextw); \
601 :     __ap->sweep_nextw = __q; \
602 :     } \
603 :     } \
604 :     } /* SweepToSpArena */
605 :    
606 :     do {
607 :     swept = FALSE;
608 :     for (i = 0; i < maxCollectedGen; i++) {
609 :     gen_t *gen = heap->gen[i];
610 :    
611 :     /* Sweep the record and pair arenas */
612 :     SweepToSpArena(gen, RECORD_INDX);
613 :     SweepToSpArena(gen, PAIR_INDX);
614 :     SweepToSpArena(gen, ARRAY_INDX);
615 :     }
616 :     } while (swept && (!errFlg));
617 :    
618 :     return (errFlg ? FAILURE : SUCCESS);
619 :    
620 :     } /* end of SweepToSpace */
621 :    
622 :    
623 :     /* BlastGC_ForwardObj:
624 :     *
625 :     * Forward an object.
626 :     */
627 :     PVT ml_val_t BlastGC_ForwardObj (heap_t *heap, ml_val_t v, aid_t id)
628 :     {
629 :     ml_val_t *obj = PTR_MLtoC(ml_val_t, v);
630 :     int gen = EXTRACT_GEN(id);
631 : monnier 223 ml_val_t *new_obj;
632 : monnier 2 ml_val_t desc;
633 :     Word_t len;
634 :     arena_t *arena;
635 :    
636 :     if (! finishGC)
637 :     CHECK_GEN(heap, gen);
638 :    
639 :     switch (EXTRACT_OBJC(id)) {
640 :     case OBJC_record: {
641 : monnier 223 desc = obj[-1];
642 :     switch (GET_TAG(desc)) {
643 :     case DTAG_vec_hdr:
644 :     case DTAG_arr_hdr:
645 :     len = 2;
646 :     break;
647 :     case DTAG_forward:
648 : monnier 2 /* This object has already been forwarded */
649 : monnier 223 return PTR_CtoML(FOLLOW_FWDOBJ(obj));
650 :     default:
651 :     len = GET_LEN(desc);
652 :     }
653 : monnier 2 arena = heap->gen[gen-1]->arena[RECORD_INDX];
654 :     } break;
655 :    
656 :     case OBJC_pair: {
657 :     ml_val_t w;
658 :    
659 : monnier 223 w = obj[0];
660 : monnier 2 if (isDESC(w))
661 : monnier 223 return PTR_CtoML(FOLLOW_FWDPAIR(w, obj));
662 : monnier 2 else {
663 :     /* forward the pair */
664 :     arena = heap->gen[gen-1]->arena[PAIR_INDX];
665 :     new_obj = arena->nextw;
666 :     arena->nextw += 2;
667 :     new_obj[0] = w;
668 : monnier 223 new_obj[1] = obj[1];
669 : monnier 2 /* setup the forward pointer in the old pair */
670 : monnier 223 NOTE_REPAIR(arena, obj, w);
671 :     obj[0] = MAKE_PAIR_FP(new_obj);
672 : monnier 106 return PTR_CtoML(new_obj);
673 : monnier 2 }
674 :     } break;
675 :    
676 :     case OBJC_string: {
677 : monnier 223 arena = heap->gen[gen-1]->arena[STRING_INDX];
678 :     desc = obj[-1];
679 : monnier 2 switch (GET_TAG(desc)) {
680 : monnier 223 case DTAG_forward:
681 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj));
682 :     case DTAG_raw32:
683 :     len = GET_LEN(desc);
684 : monnier 2 break;
685 : monnier 223 case DTAG_raw64:
686 :     len = GET_LEN(desc);
687 : monnier 2 #ifdef ALIGN_REALDS
688 : monnier 223 # ifdef CHECK_HEAP
689 :     if (((Addr_t)arena->nextw & WORD_SZB) == 0) {
690 :     *(arena->nextw) = (ml_val_t)0;
691 :     arena->nextw++;
692 :     }
693 :     # else
694 :     arena->nextw = (ml_val_t *)(((Addr_t)arena->nextw) | WORD_SZB);
695 :     # endif
696 : monnier 2 #endif
697 :     break;
698 :     default:
699 :     Die ("bad string tag %d, obj = %#x, desc = %#x",
700 :     GET_TAG(desc), obj, desc);
701 :     }
702 :     } break;
703 :    
704 :     case OBJC_array: {
705 : monnier 223 desc = obj[-1];
706 : monnier 2 switch (GET_TAG(desc)) {
707 : monnier 223 case DTAG_forward:
708 : monnier 2 /* This object has already been forwarded */
709 : monnier 223 return PTR_CtoML(FOLLOW_FWDOBJ(obj));
710 :     case DTAG_arr_data:
711 : monnier 2 len = GET_LEN(desc);
712 :     break;
713 :     case DTAG_special:
714 :     /* we are conservative here, and never nullify special objects */
715 :     len = 1;
716 :     break;
717 :     default:
718 :     Die ("bad array tag %d, obj = %#x, desc = %#x",
719 :     GET_TAG(desc), obj, desc);
720 :     } /* end of switch */
721 :     arena = heap->gen[gen-1]->arena[ARRAY_INDX];
722 :     } break;
723 :    
724 :     case OBJC_bigobj:
725 :     default:
726 :     Die("BlastGC_ForwardObj: unknown object class %d @ %#x",
727 :     EXTRACT_OBJC(id), obj);
728 :     } /* end of switch */
729 :    
730 :     /* Allocate and initialize a to-space copy of the object */
731 :     new_obj = arena->nextw;
732 :     arena->nextw += (len + 1);
733 :     *new_obj++ = desc;
734 : monnier 223 COPYLOOP(obj, new_obj, len);
735 : monnier 2
736 :     /* set up the forward pointer, and return the new object. */
737 : monnier 223 NOTE_REPAIR(arena, obj, *obj);
738 :     obj[-1] = DESC_forwarded;
739 :     obj[0] = (ml_val_t)(Addr_t)new_obj;
740 : monnier 106 return PTR_CtoML(new_obj);
741 : monnier 2
742 :     } /* end of BlastGC_ForwardObj */
743 :    
744 :    
745 :     /* BlastGC_ForwardBigObj:
746 :     *
747 :     * Forward a big-object obj, where id is the BIBOP entry for obj, and return
748 :     * the big-object descriptor.
749 :     * NOTE: we do not ``promote'' big-objects here, because are not reclaimed
750 :     * when completing th collection.
751 :     */
752 :     PVT bigobj_desc_t *BlastGC_ForwardBigObj (
753 :     heap_t *heap,
754 :     ml_val_t *p,
755 :     ml_val_t obj,
756 :     aid_t aid)
757 :     {
758 :     int i;
759 :     bigobj_region_t *region;
760 :     bigobj_desc_t *dp;
761 :     embobj_info_t *codeInfo, *objInfo;
762 :     embobj_kind_t kind;
763 :    
764 :     for (i = BIBOP_ADDR_TO_INDEX(obj); !BO_IS_HDR(aid); aid = BIBOP[--i])
765 :     continue;
766 :     region = (bigobj_region_t *)BIBOP_INDEX_TO_ADDR(i);
767 :     dp = ADDR_TO_BODESC(region, obj);
768 :    
769 :     if (! finishGC) {
770 :     CHECK_GEN(heap, dp->gen);
771 :     codeInfo = EmbObjLookup (EmbObjTbl, dp->obj, UNUSED_CODE);
772 : monnier 223 codeInfo->kind = USED_CODE;
773 : monnier 2 }
774 :    
775 :     return dp;
776 :    
777 :     } /* end of BlastGC_ForwardBigObj */
778 :    
779 :    
780 :     /* EmbObjLookup:
781 :     */
782 :     PVT embobj_info_t *EmbObjLookup (addr_tbl_t *tbl, Addr_t addr, embobj_kind_t kind)
783 :     {
784 :     embobj_info_t *p = FindEmbObj(tbl, addr);
785 :    
786 :     if (p == NIL(embobj_info_t *)) {
787 :     p = NEW_OBJ(embobj_info_t);
788 :     p->kind = kind;
789 :     p->codeObj = NIL(embobj_info_t *);
790 :     AddrTblInsert(tbl, addr, p);
791 :     }
792 :    
793 :     ASSERT(kind == p->kind);
794 :    
795 :     return p;
796 :    
797 :     } /* end of EmbObjLookup */
798 :    
799 :     /* BlastGC_AssignLits:
800 :     *
801 :     * Calculate the location of the extracted literal strings in the blasted
802 :     * image, and record their addresses. This function is passed as an argument
803 :     * to AddrTblApply; its second argument is its "closure," and its third
804 :     * argument is the embedded object info.
805 :     */
806 :     PVT void BlastGC_AssignLits (Addr_t addr, void *_closure, void *_info)
807 :     {
808 : monnier 223 #ifdef XXX
809 : monnier 2 struct assignlits_clos *closure = (struct assignlits_clos *) _closure;
810 :     embobj_info_t *info = (embobj_info_t *) _info;
811 :     int objSzB;
812 :    
813 :     switch (info->kind) {
814 :     case UNUSED_CODE:
815 :     case USED_CODE:
816 :     info->relAddr = (ml_val_t)0;
817 :     return;
818 :     case EMB_STRING: {
819 :     int nChars = OBJ_LEN(PTR_CtoML(addr));
820 :     int nWords = BYTES_TO_WORDS(nChars);
821 :     if ((nChars != 0) && ((nChars & 0x3) == 0))
822 :     nWords++;
823 :     objSzB = nWords * WORD_SZB;
824 :     } break;
825 :     case EMB_REALD:
826 :     objSzB = OBJ_LEN(PTR_CtoML(addr)) * REALD_SZB;
827 :     #ifdef ALIGN_REALDS
828 :     closure->offset |= WORD_SZB;
829 :     #endif
830 :     break;
831 :     }
832 :    
833 :     if (info->codeObj->kind == USED_CODE) {
834 :     /* the containing code object is also being exported */
835 :     info->relAddr = (ml_val_t)0;
836 :     return;
837 :     }
838 :    
839 :     if (objSzB == 0) {
840 :     info->relAddr = ExportCSymbol (ExportTbl,
841 :     (info->kind == EMB_STRING) ? ML_string0 : ML_realarray0);
842 :     }
843 :     else {
844 :     /* assign a relocation address to the object, and bump the offset counter */
845 :     closure->offset += WORD_SZB; /* space for the descriptor */
846 :     info->relAddr = HIO_TAG_PTR(closure->id, closure->offset);
847 :     closure->offset += objSzB;
848 :     }
849 : monnier 223 #else
850 :     Die ("BlastGC_AssignLits");
851 :     #endif
852 : monnier 2 } /* end of BlastGC_AssignLits */
853 :    
854 :     /* BlastGC_ExtractLits:
855 :     *
856 :     * Extract the embedded literals that are in otherwise unreferenced code
857 :     * blocks. This function is passed as an argument to AddrTblApply; its
858 :     * second argument is its "closure," and its third argument is the
859 :     * embedded object info.
860 :     */
861 :     PVT void BlastGC_ExtractLits (Addr_t addr, void *_closure, void *_info)
862 :     {
863 :     struct extractlits_clos *closure = (struct extractlits_clos *) _closure;
864 :     embobj_info_t *info = (embobj_info_t *) _info;
865 :     int objSzB;
866 :    
867 :     if (info->relAddr == (ml_val_t)0)
868 :     return;
869 :    
870 :     switch (info->kind) {
871 :     case EMB_STRING: {
872 :     int nChars = OBJ_LEN(PTR_CtoML(addr));
873 :     int nWords = BYTES_TO_WORDS(nChars);
874 :     if ((nChars != 0) && ((nChars & 0x3) == 0))
875 :     nWords++;
876 :     objSzB = nWords * WORD_SZB;
877 :     } break;
878 :     case EMB_REALD:
879 :     objSzB = OBJ_LEN(PTR_CtoML(addr)) * REALD_SZB;
880 :     #ifdef ALIGN_REALDS
881 :     if ((closure->offset & (REALD_SZB-1)) == 0) {
882 :     /* the descriptor would be 8-byte aligned, which means that the
883 :     * real number would not be, so add some padding.
884 :     */
885 :     WR_Put(closure->wr, 0);
886 :     closure->offset += 4;
887 :     }
888 :     #endif
889 :     break;
890 :     }
891 :    
892 :     if (objSzB != 0) {
893 :     /* extract the object into the blast buffer (including the descriptor) */
894 :     WR_Write(closure->wr, (void *)(addr - WORD_SZB), objSzB + WORD_SZB);
895 :     closure->offset += (objSzB + WORD_SZB);
896 :     }
897 :    
898 :     } /* end of BlastGC_ExtractLits */

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