/* gc-util.c * * COPYRIGHT (c) 1993 by AT&T Bell Laboratories. * * Garbage collection utility routines. * */ #include #include #include "ml-base.h" #include "ml-limits.h" #include "ml-values.h" #include "memory.h" #include "card-map.h" #include "heap.h" #include "heap-monitor.h" /* NewGeneration: * * Allocate and partition the space for a generation. */ status_t NewGeneration (gen_t *gen) { int i; Addr_t tot_sz; ml_val_t *p; mem_obj_t *memobj; arena_t *ap; /* Compute the total size */ for (tot_sz = 0, i = 0; i < NUM_ARENAS; i++) { if (isACTIVE(gen->arena[i])) tot_sz += gen->arena[i]->tospSizeB; } if ((gen->cacheObj != NIL(mem_obj_t *)) && (MEMOBJ_SZB(gen->cacheObj) >= tot_sz)) { memobj = gen->cacheObj; gen->cacheObj = NIL(mem_obj_t *); } else if ((memobj = MEM_AllocMemObj(tot_sz)) == NIL(mem_obj_t *)) { /** Eventually we should try to allocate the generation as separate ** chunks instead of failing. **/ return FAILURE; } /* Initialize the chunks */ gen->toObj = memobj; #ifdef VERBOSE SayDebug ("NewGeneration[%d]: tot_sz = %d, [%#x, %#x)\n", gen->genNum, tot_sz, MEMOBJ_BASE(memobj), MEMOBJ_BASE(memobj) + MEMOBJ_SZB(memobj)); #endif for (p = (ml_val_t *)MEMOBJ_BASE(memobj), i = 0; i < NUM_ARENAS; i++) { ap = gen->arena[i]; if (isACTIVE(ap)) { ap->tospBase = p; ap->nextw = p; ap->sweep_nextw = p; p = (ml_val_t *)((Addr_t)p + ap->tospSizeB); ap->tospTop = p; MarkRegion (BIBOP, ap->tospBase, ap->tospSizeB, ap->id); HeapMon_MarkRegion (gen->heap, ap->tospBase, ap->tospSizeB, ap->id); #ifdef VERBOSE SayDebug (" %#x: [%#x, %#x)\n", ap->id, ap->nextw, p); #endif } else { ap->tospBase = NIL(ml_val_t *); ap->nextw = NIL(ml_val_t *); ap->sweep_nextw = NIL(ml_val_t *); ap->tospTop = NIL(ml_val_t *); } } ap = gen->arena[PAIR_INDX]; if (isACTIVE(ap)) { /* The first slot of pair-space cannot be used, so that poly-equal won't fault */ *(ap->nextw++) = ML_unit; *(ap->nextw++) = ML_unit; ap->tospBase = ap->nextw; ap->tospSizeB -= (2*WORD_SZB); ap->sweep_nextw = ap->nextw; } return SUCCESS; } /* end of NewGeneration */ /* FreeGeneration: */ void FreeGeneration (heap_t *heap, int g) { gen_t *gen = heap->gen[g]; int i; if (gen->fromObj == NIL(mem_obj_t *)) return; #ifdef VERBOSE SayDebug ("FreeGeneration [%d]: [%#x, %#x)\n", g+1, MEMOBJ_BASE(gen->fromObj), MEMOBJ_BASE(gen->fromObj) + MEMOBJ_SZB(gen->fromObj)); #endif if (g < heap->cacheGen) { if (gen->cacheObj != NIL(mem_obj_t *)) { if (MEMOBJ_SZB(gen->cacheObj) > MEMOBJ_SZB(gen->fromObj)) MEM_FreeMemObj (gen->fromObj); else { MEM_FreeMemObj (gen->cacheObj); gen->cacheObj = gen->fromObj; } } else gen->cacheObj = gen->fromObj; } else MEM_FreeMemObj (gen->fromObj); /** NOTE: since the arenas are contiguous, we could do this in one call **/ gen->fromObj = NIL(mem_obj_t *); for (i = 0; i < NUM_ARENAS; i++) { arena_t *ap = gen->arena[i]; if (ap->frspBase != NIL(ml_val_t *)) { MarkRegion (BIBOP, ap->frspBase, ap->frspSizeB, AID_UNMAPPED); HeapMon_MarkRegion (heap, ap->frspBase, ap->frspSizeB, AID_UNMAPPED); ap->frspBase = NIL(ml_val_t *); ap->frspSizeB = 0; ap->frspTop = NIL(ml_val_t *); } } } /* end of FreeGeneration */ /* NewDirtyVector: * Bind in a new dirty vector for the given generation, reclaiming the old * vector. */ void NewDirtyVector (gen_t *gen) { arena_t *ap = gen->arena[ARRAY_INDX]; int vecSz = (ap->tospSizeB / CARD_SZB); int allocSzB = CARD_MAP_SZ(vecSz); if (gen->dirty == NIL(card_map_t *)) { gen->dirty = (card_map_t *)MALLOC(allocSzB); gen->dirty->mapSzB = allocSzB; } else if (allocSzB > gen->dirty->mapSzB) { FREE(gen->dirty); gen->dirty = (card_map_t *)MALLOC(allocSzB); gen->dirty->mapSzB = allocSzB; } if (gen->dirty == NIL(card_map_t *)) { Die ("unable to malloc dirty vector"); } gen->dirty->baseAddr = ap->tospBase; gen->dirty->numCards = vecSz; #ifndef BIT_CARDS memset (gen->dirty->map, CARD_CLEAN, allocSzB - (sizeof(card_map_t) - WORD_SZB)); #else memset (gen->dirty->map, 0, allocSzB - (sizeof(card_map_t) - WORD_SZB)); #endif } /* end of NewDirtyVector. */ /* MarkRegion: * * Mark the BIBOP entries corresponding to the range [baseAddr, baseAddr+szB) * with aid. */ void MarkRegion (bibop_t bibop, ml_val_t *baseAddr, Word_t szB, aid_t aid) { #ifdef TWO_LEVEL_MAP # error two level map not supported #else int start = BIBOP_ADDR_TO_INDEX(baseAddr); int end = BIBOP_ADDR_TO_INDEX(((Addr_t)baseAddr)+szB); #ifdef VERBOSE /*SayDebug("MarkRegion [%#x..%#x) as %#x\n", baseAddr, ((Addr_t)baseAddr)+szB, aid); */ #endif while (start < end) { bibop[start++] = aid; } #endif } /* end of MarkRegion */ /* ScanWeakPtrs: * * Scan the list of weak pointers, nullifying those that refer to dead * (i.e., from-space) objects. */ void ScanWeakPtrs (heap_t *heap) { ml_val_t *p, *q, *obj, desc; /* SayDebug ("ScanWeakPtrs:\n"); */ for (p = heap->weakList; p != NIL(ml_val_t *); p = q) { q = PTR_MLtoC(ml_val_t, UNMARK_PTR(p[0])); obj = (ml_val_t *)(Addr_t)UNMARK_PTR(p[1]); /* SayDebug (" %#x --> %#x ", p+1, obj); */ switch (EXTRACT_OBJC(ADDR_TO_PAGEID(BIBOP, obj))) { case OBJC_new: case OBJC_record: case OBJC_string: case OBJC_array: desc = obj[-1]; if (desc == DESC_forwarded) { p[0] = DESC_weak; p[1] = PTR_CtoML(FOLLOW_FWDOBJ(obj)); /* SayDebug ("forwarded to %#x\n", FOLLOW_FWDOBJ(obj)); */ } else { p[0] = DESC_null_weak; p[1] = ML_unit; /* SayDebug ("nullified\n"); */ } break; case OBJC_pair: if (isDESC(desc = obj[0])) { p[0] = DESC_weak; p[1] = PTR_CtoML(FOLLOW_FWDPAIR(desc, obj)); /* SayDebug ("(pair) forwarded to %#x\n", FOLLOW_FWDPAIR(desc, obj)); */ } else { p[0] = DESC_null_weak; p[1] = ML_unit; /* SayDebug ("(pair) nullified\n"); */ } break; case OBJC_bigobj: Die ("weak big object"); break; } /* end of switch */ } heap->weakList = NIL(ml_val_t *); } /* end of ScanWeakPtrs */