Exemplo n.º 1
0
static void   read_heap   (
    //        =========
    //
    Inbuf*       bp,
    Heap_Header* header,
    Task*        task,
    Val*         externs
){
    Heap*		heap =  task->heap;

    Sib_Header*	sib_headers;
    Sib_Header*	p;
    Sib_Header*	q;

    int			sib_headers_bytesize;
    int			i, j, k;

    long		prevSzB[MAX_PLAIN_SIBS], size;
    Sibid*		oldBOOK2SIBID;
    Punt		addrOffset[MAX_AGEGROUPS][MAX_PLAIN_SIBS];

    Hugechunk_Quire_Relocation_Info*	boRelocInfo;

    Addresstable*	boRegionTable;

    // Allocate a book_to_sibid__global for the imported
    // heap image's address space:
    //
    #ifdef TWO_LEVEL_MAP
        #error two level map not supported
    #else
	oldBOOK2SIBID = MALLOC_VEC (Sibid, BOOK2SIBID_TABLE_SIZE_IN_SLOTS);
    #endif

    // Read in the hugechunk region descriptors
    // for the old address space:
    //
    {
	int		  size;
	Hugechunk_Quire_Header* boRgnHdr;

	boRegionTable = make_address_hashtable(LOG2_BOOK_BYTESIZE+1, header->hugechunk_quire_count);

	size = header->hugechunk_quire_count * sizeof(Hugechunk_Quire_Header);

	boRgnHdr = (Hugechunk_Quire_Header*) MALLOC (size);

	heapio__read_block( bp, boRgnHdr, size );

	boRelocInfo = MALLOC_VEC(Hugechunk_Quire_Relocation_Info, header->hugechunk_quire_count);

	for (i = 0;  i < header->hugechunk_quire_count;  i++) {

	    set_book2sibid_entries_for_range(oldBOOK2SIBID,
		(Val*)(boRgnHdr[i].base_address),
		BOOKROUNDED_BYTESIZE(boRgnHdr[i].bytesize),
		HUGECHUNK_DATA_SIBID(1)
            );

	    oldBOOK2SIBID[GET_BOOK_CONTAINING_POINTEE(boRgnHdr[i].base_address)] = HUGECHUNK_RECORD_SIBID(MAX_AGEGROUPS);

	    boRelocInfo[i].first_ram_quantum = boRgnHdr[i].first_ram_quantum;

	    boRelocInfo[i].page_count
                =
                (boRgnHdr[i].bytesize - (boRgnHdr[i].first_ram_quantum - boRgnHdr[i].base_address))
                >>
                LOG2_HUGECHUNK_RAM_QUANTUM_IN_BYTES;

	    boRelocInfo[i].hugechunk_page_to_hugechunk = MALLOC_VEC(Hugechunk_Relocation_Info*, boRelocInfo[i].page_count);

	    for (j = 0;  j < boRelocInfo[i].page_count;  j++) {
	        //
		boRelocInfo[i].hugechunk_page_to_hugechunk[j] = NULL;
            } 
	    addresstable_insert (boRegionTable, boRgnHdr[i].base_address, &(boRelocInfo[i]));
	}
	FREE (boRgnHdr);
    }

    // Read the sib headers:
    //
    sib_headers_bytesize = header->active_agegroups * TOTAL_SIBS * sizeof( Sib_Header );
    //
    sib_headers = (Sib_Header*) MALLOC( sib_headers_bytesize );
    //
    heapio__read_block( bp, sib_headers, sib_headers_bytesize );

    for (i = 0;  i < MAX_PLAIN_SIBS;  i++) {
        //
	prevSzB[i] = task->heap_allocation_buffer_bytesize;
    }

    // Allocate the sib buffers and read in the heap image:
    //
    for (p = sib_headers, i = 0;  i < header->active_agegroups;  i++) {
        //
	Agegroup*  age =  heap->agegroup[ i ];

	// Compute the space required for this agegroup,
	// and mark the oldBOOK2SIBID to reflect the old address space:
	//
	for (q = p, j = 0;  j < MAX_PLAIN_SIBS;  j++) {

	    set_book2sibid_entries_for_range (
		//
		oldBOOK2SIBID,

		(Val*) q->info.o.base_address,

		BOOKROUNDED_BYTESIZE( q->info.o.bytesize ),

		age->sib[ j ]->id
	    );

	    size = q->info.o.bytesize + prevSzB[j];

	    if (j == RO_CONSCELL_SIB
            &&  size > 0
            ){
		size += 2*WORD_BYTESIZE;
	    }

	    age->sib[ j ]->tospace.bytesize
		=
		BOOKROUNDED_BYTESIZE( size );

	    prevSzB[ j ] =  q->info.o.bytesize;

	    q++;
	}

	if (set_up_tospace_sib_buffers_for_agegroup(age) == FALSE) {
	    die ("unable to allocated space for agegroup %d\n", i+1);
        } 
	if (sib_is_active( age->sib[ RW_POINTERS_SIB ] )) {							// sib_is_active	def in    src/c/h/heap.h
	    //
	    make_new_coarse_inter_agegroup_pointers_map_for_agegroup (age);
        }

	// Read in the sib buffers for this agegroup
	// and initialize the address offset table:
	//
	for (int j = 0;  j < MAX_PLAIN_SIBS;  j++) {
	    //
	    Sib* ap = age->sib[ j ];

	    if (p->info.o.bytesize > 0) {

		addrOffset[i][j] = (Punt)(ap->tospace.start) - (Punt)(p->info.o.base_address);

		heapio__seek( bp, (long) p->offset );

		heapio__read_block( bp, (ap->tospace.start), p->info.o.bytesize );

		ap->tospace.used_end  = (Val *)((Punt)(ap->tospace.start) + p->info.o.bytesize);

		ap->fromspace.seniorchunks_end =  ap->tospace.start;

	    } else if (sib_is_active(ap)) {

		ap->fromspace.seniorchunks_end =  ap->tospace.start;
	    }

	    if (verbosity__global > 0)   say(".");

	    p++;
	}

        // Read in the hugechunk sib buffers (currently just codechunks):
        //
	for (int ilk = 0;  ilk < MAX_HUGE_SIBS;  ilk++) {			// MAX_HUGE_SIBS		def in    src/c/h/sibid.h
	    //	
	    Punt	 totSizeB;

	    Hugechunk* free_chunk;
	    Hugechunk* bdp = NULL;		// Without this initialization, gcc -Wall gives a 'possible uninitialized use' warning.

	    Hugechunk_Quire*	 free_quire;
	    Hugechunk_Header*	 boHdrs;

	    int			 boHdrSizeB;
	    int			 index;

	    Hugechunk_Quire_Relocation_Info*  region;

	    if (p->info.bo.hugechunk_quanta_count > 0) {
		//
		totSizeB = p->info.bo.hugechunk_quanta_count << LOG2_HUGECHUNK_RAM_QUANTUM_IN_BYTES;

		free_chunk = allocate_hugechunk_quire( heap, totSizeB );

		free_quire = free_chunk->hugechunk_quire;

		free_quire->age_of_youngest_live_chunk_in_quire
		    =
                    i;

		set_book2sibid_entries_for_range (
		    //
		    book_to_sibid__global,
                    (Val*) free_quire,
		    BYTESIZE_OF_QUIRE( free_quire->quire ),
		    HUGECHUNK_DATA_SIBID( i )
		);

		book_to_sibid__global[ GET_BOOK_CONTAINING_POINTEE( free_quire ) ]
		    =
		    HUGECHUNK_RECORD_SIBID( i );

	        // Read in the hugechunk headers:
                //
		boHdrSizeB = p->info.bo.hugechunk_count * sizeof(Hugechunk_Header);
		//
		boHdrs = (Hugechunk_Header*) MALLOC (boHdrSizeB);
		//
		heapio__read_block (bp, boHdrs, boHdrSizeB);

	        // Read in the hugechunks:
                //
		heapio__read_block( bp, (void *)(free_chunk->chunk), totSizeB );
		//
		if (ilk == CODE__HUGE_SIB) {					// ilk = 0 == CODE__HUGE_SIB	def in    src/c/h/sibid.h
		    //
		    flush_instruction_cache ((void *)(free_chunk->chunk), totSizeB);
		}

	        // Set up the hugechunk descriptors 
                // and per-chunk relocation info:
                //
		for (k = 0;  k < p->info.bo.hugechunk_count;  k++) {
		    //
		    // Find the region relocation info for the
		    // chunk's region in the exported heap:
		    //
		    for (index = GET_BOOK_CONTAINING_POINTEE(boHdrs[k].base_address);
			!SIBID_ID_IS_BIGCHUNK_RECORD(oldBOOK2SIBID[index]);
			index--)
			continue;

		    region = LOOK_UP_HUGECHUNK_REGION (boRegionTable, index);

		    // Allocate the hugechunk record for
		    // the chunk and link it into the list
                    // of hugechunks for its agegroup.
		    //
		    bdp = allocate_a_hugechunk( free_chunk, &(boHdrs[k]), region );

		    bdp->next = age->hugechunks[ ilk ];

		    age->hugechunks[ ilk ] = bdp;

		    ASSERT( bdp->gen == i+1 );

		    if (codechunk_comment_display_is_enabled__global
                    &&  ilk == CODE__HUGE_SIB
                    ){
		        // Dump the comment string of the code chunk.

			Unt8* namestring;
			//
			if ((namestring = get_codechunk_comment_string_else_null( bdp ))) {
			    debug_say ("[%6d bytes] %s\n", bdp->bytesize, (char*)namestring);
                        }
		    }
		}

		if (free_chunk != bdp) {					// if p->info.bo.hugechunk_count can be zero, 'bdp' value here may be bogus. XXX BUGGO FIXME.
		    //
		    // There was some extra space left in the region:
		    //
		    insert_hugechunk_in_doubly_linked_list( heap->hugechunk_freelist, free_chunk);						// insert_hugechunk_in_doubly_linked_list	def in   src/c/h/heap.h
		}

		FREE (boHdrs);
	    }

	    if (verbosity__global > 0)   say(".");

	    p++;
	}
    }

    repair_heap (heap, oldBOOK2SIBID, addrOffset, boRegionTable, externs);

    // Adjust the run-time globals
    // that point into the heap:
    //
    *PTR_CAST( Val*, PERVASIVE_PACKAGE_PICKLE_LIST_REFCELL__GLOBAL )
        =
        repair_word(
            *PTR_CAST( Val*, PERVASIVE_PACKAGE_PICKLE_LIST_REFCELL__GLOBAL ),
	    oldBOOK2SIBID,
            addrOffset,
            boRegionTable,
            externs
        );

    runtime_package__global = repair_word( runtime_package__global, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

#ifdef ASM_MATH
    mathvec__global = repair_word (mathvec__global, oldBOOK2SIBID, addrOffset, boRegionTable, externs);
#endif

    // Adjust the Mythryl registers
    // to the new address space:
    //
    ASSIGN(
        POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL,
	//
        repair_word (
	    //
	    DEREF( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL ),
	    oldBOOK2SIBID,
	    addrOffset,
	    boRegionTable,
            externs
	)
    );

    task->argument
	=
	repair_word( task->argument, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->fate
	=
	repair_word( task->fate, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->current_closure
	=
	repair_word( task->current_closure, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->program_counter
	=
	repair_word(  task->program_counter, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->link_register
	=
	repair_word (task->link_register, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->exception_fate
	=
	repair_word( task->exception_fate, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->current_thread
	=
	repair_word( task->current_thread, oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->callee_saved_registers[0]
	=
	repair_word( task->callee_saved_registers[0], oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->callee_saved_registers[1]
	=
	repair_word( task->callee_saved_registers[1], oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    task->callee_saved_registers[2]
	=
	repair_word( task->callee_saved_registers[2], oldBOOK2SIBID, addrOffset, boRegionTable, externs );

    // Release storage:
    //
    for (i = 0; i < header->hugechunk_quire_count;  i++) {
      //
	Hugechunk_Relocation_Info*	p;
	for (p = NULL, j = 0;  j < boRelocInfo[i].page_count;  j++) {
	    if ((boRelocInfo[i].hugechunk_page_to_hugechunk[j] != NULL)
	    && (boRelocInfo[i].hugechunk_page_to_hugechunk[j] != p)) {
		FREE (boRelocInfo[i].hugechunk_page_to_hugechunk[j]);
		p = boRelocInfo[i].hugechunk_page_to_hugechunk[j];
	    }
	}
    }

    free_address_table( boRegionTable, FALSE );

    FREE( boRelocInfo    );
    FREE( sib_headers  );
    FREE( oldBOOK2SIBID       );

    // Reset the tospace.swept_end pointers:
    //
    for (int i = 0;  i < heap->active_agegroups;  i++) {
        //
	Agegroup*	age =  heap->agegroup[i];
        //
	for (int j = 0;  j < MAX_PLAIN_SIBS;  j++) {
	    //
	    Sib* ap =  age->sib[ j ];
	    //
	    if (sib_is_active(ap)) {							// sib_is_active	def in    src/c/h/heap.h
		//
		ap->tospace.swept_end
		    =
		    ap->tospace.used_end;
	    }
	}
    }
}                                                       // fun read_heap
Exemplo n.º 2
0
static void   read_heap   (   inbuf_t*            bp,
                             lib7_heap_hdr_t*   header,
                             lib7_state_t*      lib7_state,
                             lib7_val_t*        externs
                         )
{
    heap_t*		heap = lib7_state->lib7_heap;
    heap_arena_hdr_t	*arenaHdrs, *p, *q;
    int			arenaHdrsSize;
    int			i, j, k;
    long		prevSzB[NUM_ARENAS], size;
    bibop_t		oldBIBOP;
    Addr_t		addrOffset[MAX_NUM_GENS][NUM_ARENAS];
    bo_region_reloc_t	*boRelocInfo;
    addr_table_t		*boRegionTable;

    /* Allocate a BIBOP for the imported
     * heap image's address space:
     */
#ifdef TWO_LEVEL_MAP
#  error two level map not supported
#else
    oldBIBOP = NEW_VEC (aid_t, BIBOP_SZ);
#endif

    /* Read in the big-chunk region descriptors
     * for the old address space:
     */
    {
	int		  size;
	bo_region_info_t* boRgnHdr;

	boRegionTable = MakeAddrTable(BIBOP_SHIFT+1, header->numBORegions);
	size = header->numBORegions * sizeof(bo_region_info_t);
	boRgnHdr = (bo_region_info_t *) MALLOC (size);
	HeapIO_ReadBlock (bp, boRgnHdr, size);

	boRelocInfo = NEW_VEC(bo_region_reloc_t, header->numBORegions);

	for (i = 0;  i < header->numBORegions;  i++) {
	    MarkRegion(oldBIBOP,
		(lib7_val_t *)(boRgnHdr[i].baseAddr),
		RND_HEAP_CHUNK_SZB(boRgnHdr[i].sizeB),
		AID_BIGCHUNK(1)
            );
	    oldBIBOP[BIBOP_ADDR_TO_INDEX(boRgnHdr[i].baseAddr)] = AID_BIGCHUNK_HDR(MAX_NUM_GENS);
	    boRelocInfo[i].firstPage = boRgnHdr[i].firstPage;

	    boRelocInfo[i].nPages
                =
                (boRgnHdr[i].sizeB - (boRgnHdr[i].firstPage - boRgnHdr[i].baseAddr))
                >>
                BIGCHUNK_PAGE_SHIFT;

	    boRelocInfo[i].chunkMap = NEW_VEC(bo_reloc_t *, boRelocInfo[i].nPages);

	    for (j = 0;  j < boRelocInfo[i].nPages;  j++) {
		boRelocInfo[i].chunkMap[j] = NULL;
            } 
	    AddrTableInsert (boRegionTable, boRgnHdr[i].baseAddr, &(boRelocInfo[i]));
	}
	FREE (boRgnHdr);
    }

    /* Read the arena headers: */
    arenaHdrsSize = header->numGens * NUM_CHUNK_KINDS * sizeof(heap_arena_hdr_t);
    arenaHdrs = (heap_arena_hdr_t *) MALLOC (arenaHdrsSize);
    HeapIO_ReadBlock (bp, arenaHdrs, arenaHdrsSize);

    for (i = 0;  i < NUM_ARENAS;  i++) {
	prevSzB[i] = heap->allocSzB;
    }

    /* Allocate the arenas and read in the heap image: */
    for (p = arenaHdrs, i = 0;  i < header->numGens;  i++) {
	gen_t	*gen = heap->gen[i];

	/* Compute the space required for this generation,
	 * and mark the oldBIBOP to reflect the old address space:
	 */
	for (q = p, j = 0;  j < NUM_ARENAS;  j++) {
	    MarkRegion (oldBIBOP,
		(lib7_val_t *)(q->info.o.baseAddr),
		RND_HEAP_CHUNK_SZB(q->info.o.sizeB),
		gen->arena[j]->id);
	    size = q->info.o.sizeB + prevSzB[j];
	    if ((j == PAIR_INDEX) && (size > 0))
		size += 2*WORD_SZB;
	    gen->arena[j]->tospSizeB = RND_HEAP_CHUNK_SZB(size);
	    prevSzB[j] = q->info.o.sizeB;
	    q++;
	}

        /* Allocate space for the generation: */
	if (NewGeneration(gen) == FAILURE) {
	    Die ("unable to allocated space for generation %d\n", i+1);
        } 
	if (isACTIVE(gen->arena[ARRAY_INDEX])) {
	    NewDirtyVector (gen);
        }

	/* Read in the arenas for this generation
	 * and initialize the address offset table:
	 */
	for (j = 0;  j < NUM_ARENAS;  j++) {

	    arena_t* ap = gen->arena[j];

	    if (p->info.o.sizeB > 0) {

		addrOffset[i][j] = (Addr_t)(ap->tospBase) - (Addr_t)(p->info.o.baseAddr);

		HeapIO_Seek (bp, (long)(p->offset));
		HeapIO_ReadBlock(bp, (ap->tospBase), p->info.o.sizeB);

		ap->nextw  = (lib7_val_t *)((Addr_t)(ap->tospBase) + p->info.o.sizeB);
		ap->oldTop = ap->tospBase;

	    } else if (isACTIVE(ap)) {

		ap->oldTop = ap->tospBase;
	    }

	    if (verbosity > 0)   say(".");

	    p++;
	}

        /* Read in the big-chunk arenas: */
	for (j = 0;  j < NUM_BIGCHUNK_KINDS;  j++) {
	    Addr_t		totSizeB;
	    bigchunk_desc_t	*freeChunk, *bdp;
	    bigchunk_region_t	*freeRegion;
	    bigchunk_hdr_t	*boHdrs;
	    int			boHdrSizeB, index;
	    bo_region_reloc_t   *region;

	    if (p->info.bo.numBOPages > 0) {
		totSizeB = p->info.bo.numBOPages << BIGCHUNK_PAGE_SHIFT;
		freeChunk = BO_AllocRegion (heap, totSizeB);
		freeRegion = freeChunk->region;
		freeRegion->minGen = i;
		MarkRegion (BIBOP, (lib7_val_t *)freeRegion,
		    HEAP_CHUNK_SZB( freeRegion->heap_chunk ), AID_BIGCHUNK(i));
		BIBOP[BIBOP_ADDR_TO_INDEX(freeRegion)] = AID_BIGCHUNK_HDR(i);

	        /* Read in the big-chunk headers */
		boHdrSizeB = p->info.bo.numBigChunks * sizeof(bigchunk_hdr_t);
		boHdrs = (bigchunk_hdr_t *) MALLOC (boHdrSizeB);
		HeapIO_ReadBlock (bp, boHdrs, boHdrSizeB);

	        /* Read in the big-chunks: */
		HeapIO_ReadBlock (bp, (void *)(freeChunk->chunk), totSizeB);
		if (j == CODE_INDEX) {
		    FlushICache ((void *)(freeChunk->chunk), totSizeB);
		}

	        /* Set up the big-chunk descriptors 
                 * and per-chunk relocation info:
                 */
		for (k = 0;  k < p->info.bo.numBigChunks;  k++) {
		  /* find the region relocation info for the chunk's region in
		   * the exported heap.
		   */
		    for (index = BIBOP_ADDR_TO_INDEX(boHdrs[k].baseAddr);
			!BO_IS_HDR(oldBIBOP[index]);
			index--)
			continue;
		    region = LookupBORegion (boRegionTable, index);

		    /* Allocate the big-chunk descriptor for
		     * the chunk and link it into the list
                     * of big-chunks for its generation.
		     */
		    bdp = AllocBODesc (freeChunk, &(boHdrs[k]), region);
		    bdp->next = gen->bigChunks[j];
		    gen->bigChunks[j] = bdp;
		    ASSERT(bdp->gen == i+1);

		    if (show_code_chunk_comments && (j == CODE_INDEX)) {

		        /* Dump the comment string of the code chunk: */
			char* namestring;
			if ((namestring = BO_GetCodeChunkTag(bdp))) {
			    SayDebug ("[%6d bytes] %s\n", bdp->sizeB, namestring);
                        }
		    }
		}

		if (freeChunk != bdp) {
		    /* There was some extra space left in the region: */
		    ADD_BODESC(heap->freeBigChunks, freeChunk);
		}

		FREE (boHdrs);
	    }

	    if (verbosity > 0)   say(".");

	    p++;
	}
    }

    repair_heap (heap, oldBIBOP, addrOffset, boRegionTable, externs);

    /* Adjust the run-time globals
     * that point into the heap:
     */
    *PTR_LIB7toC(lib7_val_t, PervasiveStruct) = repair_word (
	*PTR_LIB7toC(lib7_val_t, PervasiveStruct),
	oldBIBOP, addrOffset, boRegionTable, externs);

    runtimeCompileUnit = repair_word( runtimeCompileUnit, oldBIBOP, addrOffset, boRegionTable, externs );

#ifdef ASM_MATH
    MathVec = repair_word (MathVec, oldBIBOP, addrOffset, boRegionTable, externs);
#endif

    /* Adjust the Lib7 registers to the new address space */
    ASSIGN(Lib7SignalHandler, repair_word (
	DEREF(Lib7SignalHandler), oldBIBOP, addrOffset, boRegionTable, externs)
    );

    lib7_state->lib7_argument = repair_word (
        lib7_state->lib7_argument, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_fate = repair_word (
        lib7_state->lib7_fate, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_closure = repair_word (
        lib7_state->lib7_closure, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_program_counter = repair_word (
        lib7_state->lib7_program_counter, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_link_register = repair_word (
        lib7_state->lib7_link_register, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_exception_fate = repair_word (
        lib7_state->lib7_exception_fate, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_current_thread = repair_word (
        lib7_state->lib7_current_thread, oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_calleeSave[0] = repair_word (
        lib7_state->lib7_calleeSave[0], oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_calleeSave[1] = repair_word (
        lib7_state->lib7_calleeSave[1], oldBIBOP, addrOffset, boRegionTable, externs
    );

    lib7_state->lib7_calleeSave[2] = repair_word (
        lib7_state->lib7_calleeSave[2], oldBIBOP, addrOffset, boRegionTable, externs
    );

    /* Release storage: */
    for (i = 0; i < header->numBORegions;  i++) {
	bo_reloc_t	*p;
	for (p = NULL, j = 0;  j < boRelocInfo[i].nPages;  j++) {
	    if ((boRelocInfo[i].chunkMap[j] != NULL)
	    && (boRelocInfo[i].chunkMap[j] != p)) {
		FREE (boRelocInfo[i].chunkMap[j]);
		p = boRelocInfo[i].chunkMap[j];
	    }
	}
    }
    FreeAddrTable (boRegionTable, FALSE);
    FREE (boRelocInfo);
    FREE (arenaHdrs);
    FREE (oldBIBOP);

    /* Reset the sweep_nextw pointers: */
    for (i = 0;  i < heap->numGens;  i++) {
	gen_t	*gen = heap->gen[i];
	for (j = 0;  j < NUM_ARENAS;  j++) {
	    arena_t		*ap = gen->arena[j];
	    if (isACTIVE(ap))
		ap->sweep_nextw = ap->nextw;
	}
    }

}                                                       /* read_heap. */