/* gc-util.c
*
* COPYRIGHT (c) 1993 by AT&T Bell Laboratories.
*
* Garbage collection utility routines.
*
*/
#include <stdarg.h>
#include <string.h>
#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 */
syntax highlighted by Code2HTML, v. 0.9.1