/* blast-out.c
*
* COPYRIGHT (c) 1993 by AT&T Bell Laboratories.
*/
#include "ml-osdep.h"
#include "ml-base.h"
#include "ml-values.h"
#include "ml-objects.h"
#include "ml-heap-image.h"
#include "c-globals-tbl.h"
#include "addr-hash.h"
#include "gc.h"
#include "blast-out.h"
#include "heap-output.h"
#include "heap-io.h"
#define BLAST_ERROR ML_unit
/* local routines */
PVT ml_val_t BlastUnboxed (ml_state_t *msp, ml_val_t obj);
PVT ml_val_t BlastHeap (ml_state_t *msp, ml_val_t obj, blast_res_t *info);
PVT ml_val_t AllocBlastData (ml_state_t *msp, Addr_t sizeB);
/* BlastOut:
*
* Linearize an ML object into a vector of bytes; return ML_unit on errors.
*/
ml_val_t BlastOut (ml_state_t *msp, ml_val_t obj)
{
blast_res_t res;
int gen;
ml_val_t blastedObj;
/* Collect allocation space */
InvokeGCWithRoots (msp, 0, &obj, NIL(ml_val_t *));
gen = GetObjGen (obj);
if (gen == -1) {
/* unboxed */
blastedObj = BlastUnboxed (msp, obj);
}
else { /* a regular ML object */
/* do the blast GC */
/* DEBUG CheckHeap (msp->ml_heap, msp->ml_heap->numGens); */
res = BlastGC (msp, &obj, gen);
/* blast out the image */
blastedObj = BlastHeap (msp, obj, &res);
/* repair the heap or finish the GC */
BlastGC_FinishUp (msp, &res);
/* DEBUG CheckHeap (msp->ml_heap, res.maxGen); */
}
return blastedObj;
} /* end of BlastOut */
/* BlastUnboxed:
*
* Blast out an unboxed value.
*/
PVT ml_val_t BlastUnboxed (ml_state_t *msp, ml_val_t obj)
{
ml_blast_hdr_t blastHdr;
int szB = sizeof(ml_image_hdr_t) + sizeof(ml_blast_hdr_t);
ml_val_t blastedObj;
writer_t *wr;
/* allocate space for the object */
blastedObj = AllocBlastData (msp, szB);
wr = WR_OpenMem (PTR_MLtoC(Byte_t, blastedObj), szB);
HeapIO_WriteImageHeader (wr, BLAST_UNBOXED);
blastHdr.numArenas = 0;
blastHdr.numBOKinds = 0;
blastHdr.numBORegions = 0;
blastHdr.hasCode = FALSE;
blastHdr.rootObj = obj;
WR_Write(wr, &blastHdr, sizeof(blastHdr));
if (WR_Error(wr))
return ML_unit;
else {
WR_Free(wr);
SEQHDR_ALLOC (msp, blastedObj, DESC_string, blastedObj, szB);
return blastedObj;
}
} /* end of BlastUnboxed */
/* BlastHeap:
*
* Blast out the heap image.
*/
PVT ml_val_t BlastHeap (ml_state_t *msp, ml_val_t obj, blast_res_t *info)
{
heap_t *heap = msp->ml_heap;
int maxGen = info->maxGen;
Addr_t totArenaSzB[NUM_ARENAS], totSzB;
struct {
Addr_t base; /* the base address of the arena in the heap */
Addr_t offset; /* the relative position in the merged */
/* arena. */
} adjust[MAX_NUM_GENS][NUM_ARENAS];
heap_arena_hdr_t *p, *arenaHdrs[NUM_OBJ_KINDS], *arenaHdrsBuf;
int arenaHdrSz, i, j, numArenas;
ml_val_t blastedObj;
writer_t *wr;
/* compute the arena offsets in the heap image */
for (i = 0; i < NUM_ARENAS; i++)
totArenaSzB[i] = 0;
/* the embedded literals go first */
totArenaSzB[STRING_INDX] = BlastGC_AssignLitAddrs (info, STRING_INDX, 0);
/* DEBUG SayDebug("%d bytes of string literals\n", totArenaSzB[STRING_INDX]); */
for (i = 0; i < maxGen; i++) {
for (j = 0; j < NUM_ARENAS; j++) {
arena_t *ap = heap->gen[i]->arena[j];
adjust[i][j].offset = totArenaSzB[j];
if (isACTIVE(ap)) {
/* DEBUG SayDebug("[%d][%d] base = %#x, nextw = %#x, %d bytes\n", */
/* DEBUG i, j, ap->tospBase, ap->nextw, (Addr_t)(ap->nextw) - (Addr_t)(ap->tospBase)); */
totArenaSzB[j] += (Addr_t)(ap->nextw) - (Addr_t)(ap->tospBase);
adjust[i][j].base = (Addr_t)(ap->tospBase);
}
else
adjust[i][j].base = 0;
}
}
/* DEBUG for (i = 0; i < NUM_ARENAS; i++) SayDebug ("arena %d: %d bytes\n", i+1, totArenaSzB[i]); */
/** WHAT ABOUT THE BIG OBJECTS??? **/
/* Compute the total size of the blasted object */
for (i = 0, numArenas = 0, totSzB = 0; i < NUM_ARENAS; i++) {
if (totArenaSzB[i] > 0) {
numArenas++;
totSzB += totArenaSzB[i];
}
}
totSzB += (sizeof(ml_image_hdr_t) + sizeof(ml_blast_hdr_t)
+ (numArenas * sizeof(heap_arena_hdr_t)));
/** COUNT SPACE FOR BIG OBJECTS **/
/* include the space for the external symbols */
totSzB += sizeof(extern_tbl_hdr_t) + ExportTableSz(info->exportTbl);
/* allocate the heap object for the blasted representation, and initialize
* the writer.
*/
blastedObj = AllocBlastData (msp, totSzB);
wr = WR_OpenMem (PTR_MLtoC(Byte_t, blastedObj), totSzB);
/* initialize the arena headers */
arenaHdrSz = numArenas * sizeof(heap_arena_hdr_t);
arenaHdrsBuf = (heap_arena_hdr_t *) MALLOC (arenaHdrSz);
for (p = arenaHdrsBuf, i = 0; i < NUM_ARENAS; i++) {
if (totArenaSzB[i] > 0) {
p->gen = 0;
p->objKind = i;
p->info.o.baseAddr = 0; /* not used */
p->info.o.sizeB = totArenaSzB[i];
p->info.o.roundedSzB = -1; /* not used */
p->offset = -1; /* not used */
arenaHdrs[i] = p;
p++;
}
else
arenaHdrs[i] = NIL(heap_arena_hdr_t *);
}
/** WHAT ABOUT BIG OBJECTS **/
/* blast out the image header */
if (HeapIO_WriteImageHeader (wr, BLAST_IMAGE) == FAILURE) {
FREE (arenaHdrsBuf);
return BLAST_ERROR;
}
/* blast out the blast header */
{
ml_blast_hdr_t hdr;
hdr.numArenas = numArenas;
hdr.numBOKinds = 0; /** FIX THIS **/
hdr.numBORegions = 0; /** FIX THIS **/
if (isEXTERNTAG(obj)) {
ASSERT(numArenas == 0);
hdr.rootObj = obj;
}
else {
aid_t aid = ADDR_TO_PAGEID(BIBOP, obj);
if (IS_BIGOBJ_AID(aid)) {
embobj_info_t *p = FindEmbObj(info->embobjTbl, obj);
if ((p == NIL(embobj_info_t *)) || (p->kind == USED_CODE)) {
Error ("blasting big objects not implemented\n");
FREE (arenaHdrsBuf);
return BLAST_ERROR;
}
else
hdr.rootObj = p->relAddr;
}
else {
Addr_t addr = PTR_MLtoADDR(obj);
int gen = EXTRACT_GEN(aid) - 1;
int kind = EXTRACT_OBJC(aid) - 1;
addr -= adjust[gen][kind].base;
addr += adjust[gen][kind].offset;
hdr.rootObj = HIO_TAG_PTR(kind, addr);
}
}
WR_Write(wr, &hdr, sizeof(hdr));
if (WR_Error(wr)) {
FREE (arenaHdrsBuf);
return BLAST_ERROR;
}
}
/* blast out the externals table */
if (HeapIO_WriteExterns(wr, info->exportTbl) == -1) {
FREE (arenaHdrsBuf);
return BLAST_ERROR;
}
/* blast out the arena headers */
WR_Write (wr, arenaHdrsBuf, arenaHdrSz);
if (WR_Error(wr)) {
FREE (arenaHdrsBuf);
return BLAST_ERROR;
}
/* blast out the heap itself */
for (i = 0; i < NUM_ARENAS; i++) {
if (i == STRING_INDX) {
/* blast out the embedded literals */
BlastGC_BlastLits (wr);
/* blast out the rest of the strings */
for (j = 0; j < maxGen; j++) {
arena_t *ap = heap->gen[j]->arena[i];
if (isACTIVE(ap)) {
WR_Write(wr, ap->tospBase,
(Addr_t)(ap->nextw)-(Addr_t)(ap->tospBase));
}
} /* end for */
}
else {
for (j = 0; j < maxGen; j++) {
arena_t *ap = heap->gen[j]->arena[i];
ml_val_t *p, *top;
if (isACTIVE(ap)) {
for (p = ap->tospBase, top = ap->nextw; p < top; p++) {
ml_val_t w = *p;
if (isBOXED(w)) {
aid_t aid = ADDR_TO_PAGEID(BIBOP, w);
if (isUNMAPPED(aid)) {
w = ExportCSymbol(info->exportTbl, w);
ASSERT (w != ML_unit);
}
else if (IS_BIGOBJ_AID(aid)) {
embobj_info_t *objInfo
= FindEmbObj(info->embobjTbl, w);
if ((objInfo == NIL(embobj_info_t *))
|| (objInfo->kind == USED_CODE))
Die("blast bigobj unimplemented");
else
w = objInfo->relAddr;
}
else {
/* adjust the pointer */
int gen = EXTRACT_GEN(aid)-1;
int kind = EXTRACT_OBJC(aid)-1;
Addr_t addr = PTR_MLtoADDR(w);
addr -= adjust[gen][kind].base;
addr += adjust[gen][kind].offset;
w = HIO_TAG_PTR(kind, addr);
}
}
WR_Put(wr, (Word_t)w);
}
}
} /* end for */
}
}
FREE (arenaHdrsBuf);
if (WR_Error(wr))
return BLAST_ERROR;
else {
SEQHDR_ALLOC (msp, blastedObj, DESC_string, blastedObj, totSzB);
return blastedObj;
}
} /* end of BlastHeap */
/* AllocBlastData:
*
* Allocate some heap memory for blasting an object.
*/
PVT ml_val_t AllocBlastData (ml_state_t *msp, Addr_t sizeB)
{
heap_t *heap = msp->ml_heap;
int nWords = BYTES_TO_WORDS(sizeB);
ml_val_t desc = MAKE_DESC(nWords, DTAG_raw32);
ml_val_t res;
/** we probably should allocate space in the big-object region for these objects **/
if (sizeB < heap->allocSzB-(8*ONE_K)) {
ML_AllocWrite (msp, 0, desc);
res = ML_Alloc (msp, nWords);
return res;
}
else {
Die ("blasting out of %d bytes not supported yet! Increase allocation arena size.", sizeB);
}
} /* end of AllocBlastData */
syntax highlighted by Code2HTML, v. 0.9.1