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 107 - (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 :     __p[-1] = FOLLOW_FWDOBJ(__p, __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_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 :     ml_val_t *obj_start, *new_obj;
632 :     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 106 #ifdef POINTERS_INTO_OBJECTS
642 : monnier 2 for (obj_start = obj; !isDESC(desc = obj_start[-1]); obj_start--)
643 :     continue;
644 : monnier 106 #else
645 :     obj_start = obj;
646 :     desc = obj_start[-1];
647 :     #endif
648 : monnier 2 if (desc == DESC_forwarded)
649 :     /* This object has already been forwarded */
650 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj_start, obj));
651 :     len = GET_LEN(desc);
652 :     arena = heap->gen[gen-1]->arena[RECORD_INDX];
653 :     } break;
654 :    
655 :     case OBJC_pair: {
656 :     ml_val_t w;
657 :    
658 : monnier 106 #ifdef POINTERS_INTO_OBJECTS
659 : monnier 2 obj_start = (ml_val_t *)((Addr_t)obj & ~(2*WORD_SZB-1));
660 : monnier 106 #else
661 :     obj_start = obj;
662 :     #endif
663 : monnier 2 w = obj_start[0];
664 :     if (isDESC(w))
665 :     return PTR_CtoML(FOLLOW_FWDPAIR(w, obj_start, obj));
666 :     else {
667 :     /* forward the pair */
668 :     arena = heap->gen[gen-1]->arena[PAIR_INDX];
669 :     new_obj = arena->nextw;
670 :     arena->nextw += 2;
671 :     new_obj[0] = w;
672 :     new_obj[1] = obj_start[1];
673 :     /* setup the forward pointer in the old pair */
674 :     NOTE_REPAIR(arena, obj_start, w);
675 :     obj_start[0] = MAKE_PAIR_FP(new_obj);
676 : monnier 106 #ifdef POINTERS_INTO_OBJECTS
677 : monnier 2 return PTR_CtoML(new_obj + (obj - obj_start));
678 : monnier 106 #else
679 :     return PTR_CtoML(new_obj);
680 :     #endif
681 : monnier 2 }
682 :     } break;
683 :    
684 :     case OBJC_string: {
685 :     #ifdef ALIGN_REALDS
686 :     int align = 0;
687 :     #endif
688 :     obj_start = obj;
689 :     desc = obj_start[-1];
690 :     switch (GET_TAG(desc)) {
691 :     case DTAG_forwarded:
692 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj_start, obj));
693 :     case DTAG_string: {
694 :     int nChars = GET_LEN(desc);
695 :     len = BYTES_TO_WORDS(nChars);
696 :     /* include the 0 termination bytes */
697 :     if ((nChars & (WORD_SZB-1)) == 0) len++;
698 :     } break;
699 :     case DTAG_bytearray:
700 :     len = GET_STR_LEN(desc);
701 :     break;
702 :     case DTAG_reald:
703 :     len = REALD_SZW;
704 :     #ifdef ALIGN_REALDS
705 :     align = WORD_SZB;
706 :     #endif
707 :     break;
708 :     case DTAG_realdarray:
709 :     len = GET_REALDARR_LEN(desc);
710 :     #ifdef ALIGN_REALDS
711 :     align = WORD_SZB;
712 :     #endif
713 :     break;
714 :     default:
715 :     Die ("bad string tag %d, obj = %#x, desc = %#x",
716 :     GET_TAG(desc), obj, desc);
717 :     }
718 :     arena = heap->gen[gen-1]->arena[STRING_INDX];
719 :     #ifdef ALIGN_REALDS
720 :     arena->nextw = (ml_val_t *)(((Addr_t)arena->nextw) | align);
721 :     #endif
722 :     } break;
723 :    
724 :     case OBJC_array: {
725 : monnier 106 #ifdef POINTERS_INTO_OBJECTS
726 : monnier 2 for (obj_start = obj; !isDESC(desc = obj_start[-1]); obj_start--)
727 :     continue;
728 : monnier 106 #else
729 :     obj_start = obj;
730 :     desc = obj_start[-1];
731 :     #endif
732 : monnier 2 switch (GET_TAG(desc)) {
733 :     case DTAG_forwarded:
734 :     /* This object has already been forwarded */
735 :     return PTR_CtoML(FOLLOW_FWDOBJ(obj_start, obj));
736 :     case DTAG_array:
737 :     len = GET_LEN(desc);
738 :     break;
739 :     case DTAG_special:
740 :     /* we are conservative here, and never nullify special objects */
741 :     len = 1;
742 :     break;
743 :     default:
744 :     Die ("bad array tag %d, obj = %#x, desc = %#x",
745 :     GET_TAG(desc), obj, desc);
746 :     } /* end of switch */
747 :     arena = heap->gen[gen-1]->arena[ARRAY_INDX];
748 :     } break;
749 :    
750 :     case OBJC_bigobj:
751 :     default:
752 :     Die("BlastGC_ForwardObj: unknown object class %d @ %#x",
753 :     EXTRACT_OBJC(id), obj);
754 :     } /* end of switch */
755 :    
756 :     /* Allocate and initialize a to-space copy of the object */
757 :     new_obj = arena->nextw;
758 :     arena->nextw += (len + 1);
759 :     *new_obj++ = desc;
760 :     COPYLOOP(obj_start, new_obj, len);
761 :    
762 :     /* set up the forward pointer, and return the new object. */
763 :     NOTE_REPAIR(arena, obj_start, *obj_start);
764 :     obj_start[-1] = DESC_forwarded;
765 :     obj_start[0] = (ml_val_t)(Addr_t)new_obj;
766 : monnier 106 #ifdef POINTERS_INTO_OBJECTS
767 : monnier 2 return PTR_CtoML(new_obj + (obj - obj_start));
768 : monnier 106 #else
769 :     return PTR_CtoML(new_obj);
770 :     #endif
771 : monnier 2
772 :     } /* end of BlastGC_ForwardObj */
773 :    
774 :    
775 :     /* BlastGC_ForwardBigObj:
776 :     *
777 :     * Forward a big-object obj, where id is the BIBOP entry for obj, and return
778 :     * the big-object descriptor.
779 :     * NOTE: we do not ``promote'' big-objects here, because are not reclaimed
780 :     * when completing th collection.
781 :     */
782 :     PVT bigobj_desc_t *BlastGC_ForwardBigObj (
783 :     heap_t *heap,
784 :     ml_val_t *p,
785 :     ml_val_t obj,
786 :     aid_t aid)
787 :     {
788 :     int i;
789 :     bigobj_region_t *region;
790 :     bigobj_desc_t *dp;
791 :     embobj_info_t *codeInfo, *objInfo;
792 :     embobj_kind_t kind;
793 :    
794 :     for (i = BIBOP_ADDR_TO_INDEX(obj); !BO_IS_HDR(aid); aid = BIBOP[--i])
795 :     continue;
796 :     region = (bigobj_region_t *)BIBOP_INDEX_TO_ADDR(i);
797 :     dp = ADDR_TO_BODESC(region, obj);
798 :    
799 :     if (! finishGC) {
800 :     CHECK_GEN(heap, dp->gen);
801 :    
802 :     codeInfo = EmbObjLookup (EmbObjTbl, dp->obj, UNUSED_CODE);
803 :     switch (OBJ_TAG(obj)) {
804 :     case DTAG_string: kind = EMB_STRING; break;
805 :     case DTAG_reald: kind = EMB_REALD; break;
806 :     default: kind = USED_CODE; break;
807 :     }
808 :    
809 :     if ((kind != USED_CODE) && (codeInfo->kind == UNUSED_CODE)) {
810 :     /* an embedded literal in an UNUSED_CODE block */
811 :     objInfo = EmbObjLookup (EmbObjTbl, PTR_MLtoADDR(obj), kind);
812 :     objInfo->codeObj = codeInfo;
813 :     }
814 :     else
815 :     codeInfo->kind = USED_CODE;
816 :     }
817 :    
818 :     return dp;
819 :    
820 :     } /* end of BlastGC_ForwardBigObj */
821 :    
822 :    
823 :     /* EmbObjLookup:
824 :     */
825 :     PVT embobj_info_t *EmbObjLookup (addr_tbl_t *tbl, Addr_t addr, embobj_kind_t kind)
826 :     {
827 :     embobj_info_t *p = FindEmbObj(tbl, addr);
828 :    
829 :     if (p == NIL(embobj_info_t *)) {
830 :     p = NEW_OBJ(embobj_info_t);
831 :     p->kind = kind;
832 :     p->codeObj = NIL(embobj_info_t *);
833 :     AddrTblInsert(tbl, addr, p);
834 :     }
835 :    
836 :     ASSERT(kind == p->kind);
837 :    
838 :     return p;
839 :    
840 :     } /* end of EmbObjLookup */
841 :    
842 :     /* BlastGC_AssignLits:
843 :     *
844 :     * Calculate the location of the extracted literal strings in the blasted
845 :     * image, and record their addresses. This function is passed as an argument
846 :     * to AddrTblApply; its second argument is its "closure," and its third
847 :     * argument is the embedded object info.
848 :     */
849 :     PVT void BlastGC_AssignLits (Addr_t addr, void *_closure, void *_info)
850 :     {
851 :     struct assignlits_clos *closure = (struct assignlits_clos *) _closure;
852 :     embobj_info_t *info = (embobj_info_t *) _info;
853 :     int objSzB;
854 :    
855 :     switch (info->kind) {
856 :     case UNUSED_CODE:
857 :     case USED_CODE:
858 :     info->relAddr = (ml_val_t)0;
859 :     return;
860 :     case EMB_STRING: {
861 :     int nChars = OBJ_LEN(PTR_CtoML(addr));
862 :     int nWords = BYTES_TO_WORDS(nChars);
863 :     if ((nChars != 0) && ((nChars & 0x3) == 0))
864 :     nWords++;
865 :     objSzB = nWords * WORD_SZB;
866 :     } break;
867 :     case EMB_REALD:
868 :     objSzB = OBJ_LEN(PTR_CtoML(addr)) * REALD_SZB;
869 :     #ifdef ALIGN_REALDS
870 :     closure->offset |= WORD_SZB;
871 :     #endif
872 :     break;
873 :     }
874 :    
875 :     if (info->codeObj->kind == USED_CODE) {
876 :     /* the containing code object is also being exported */
877 :     info->relAddr = (ml_val_t)0;
878 :     return;
879 :     }
880 :    
881 :     if (objSzB == 0) {
882 :     info->relAddr = ExportCSymbol (ExportTbl,
883 :     (info->kind == EMB_STRING) ? ML_string0 : ML_realarray0);
884 :     }
885 :     else {
886 :     /* assign a relocation address to the object, and bump the offset counter */
887 :     closure->offset += WORD_SZB; /* space for the descriptor */
888 :     info->relAddr = HIO_TAG_PTR(closure->id, closure->offset);
889 :     closure->offset += objSzB;
890 :     }
891 :    
892 :     } /* end of BlastGC_AssignLits */
893 :    
894 :     /* BlastGC_ExtractLits:
895 :     *
896 :     * Extract the embedded literals that are in otherwise unreferenced code
897 :     * blocks. This function is passed as an argument to AddrTblApply; its
898 :     * second argument is its "closure," and its third argument is the
899 :     * embedded object info.
900 :     */
901 :     PVT void BlastGC_ExtractLits (Addr_t addr, void *_closure, void *_info)
902 :     {
903 :     struct extractlits_clos *closure = (struct extractlits_clos *) _closure;
904 :     embobj_info_t *info = (embobj_info_t *) _info;
905 :     int objSzB;
906 :    
907 :     if (info->relAddr == (ml_val_t)0)
908 :     return;
909 :    
910 :     switch (info->kind) {
911 :     case EMB_STRING: {
912 :     int nChars = OBJ_LEN(PTR_CtoML(addr));
913 :     int nWords = BYTES_TO_WORDS(nChars);
914 :     if ((nChars != 0) && ((nChars & 0x3) == 0))
915 :     nWords++;
916 :     objSzB = nWords * WORD_SZB;
917 :     } break;
918 :     case EMB_REALD:
919 :     objSzB = OBJ_LEN(PTR_CtoML(addr)) * REALD_SZB;
920 :     #ifdef ALIGN_REALDS
921 :     if ((closure->offset & (REALD_SZB-1)) == 0) {
922 :     /* the descriptor would be 8-byte aligned, which means that the
923 :     * real number would not be, so add some padding.
924 :     */
925 :     WR_Put(closure->wr, 0);
926 :     closure->offset += 4;
927 :     }
928 :     #endif
929 :     break;
930 :     }
931 :    
932 :     if (objSzB != 0) {
933 :     /* extract the object into the blast buffer (including the descriptor) */
934 :     WR_Write(closure->wr, (void *)(addr - WORD_SZB), objSzB + WORD_SZB);
935 :     closure->offset += (objSzB + WORD_SZB);
936 :     }
937 :    
938 :     } /* end of BlastGC_ExtractLits */

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