Example #1
0
static void   check_ro_ptrpair_sib   (Sib* ap) {
    //        ====================
    //
    Val* p;
    Val* stop;
    Val	 w;

    int gen =  GET_AGE_FROM_SIBID(ap->id);

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  pairs [%d]: [%#x..%#x:%#x)\n",
	gen, ap->tospace, ap->tospace.first_free, ap->tospace.limit);

    p = ap->tospace + 2;
    stop = ap->tospace.first_free;
    while (p < stop) {
	w = *p++;
	if (IS_TAGWORD(w)) {
	    ERROR;
	    debug_say (
		"** @%#x: unexpected tagword %#x in pair sib\n",
		p-1, w);
	    return;
	}
	else if (IS_POINTER(w)) {
	    check_pointer(p, w, gen, RO_CONSCELL_KIND, CHUNKC_any);
	}
    }
}
Example #2
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
Example #3
0
static void   check_ro_pointer_sib   (Sib* ap) {
    //        ====================
    Val* p;
    Val* stop;
    Val  tagword;
    Val  w;
    int	 i;
    int	 len;

    int gen =  GET_AGE_FROM_SIBID( ap->id );

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  records [%d]: [%#x..%#x:%#x)\n",
	//
        gen,
        ap->tospace,
	ap->tospace.first_free,
	ap->tospace.limit
    );

    p = ap->tospace;
    stop = ap->tospace.first_free;

    while (p < stop) {
	//
	tagword = *p++;

	if (*IS_TAGWORD(tagword)) {
	    ERROR;
	    debug_say (
		"** @%#x: expected tagword, but found %#x in record sib\n",
		p-1, tagword);
	    return;
	}

	switch (GET_BTAG_FROM_TAGWORD tagword) {
	    //
	case PAIRS_AND_RECORDS_BTAG:
	    #
	    len =  GET_LENGTH_IN_WORDS_FROM_TAGWORD( tagword );			// Length excludes tagword.
	    #
	    for (i = 0;  i < len;  i++, p++) {
		w = *p;
		if (IS_TAGWORD(w)) {
		    ERROR;
		    debug_say (
			"** @%#x: unexpected tagword %#x in slot %d of %d\n",
			p, w, i, GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword));
		    return;
		}
		else if (IS_POINTER(w)) {
		    check_pointer(p, w, gen, RO_POINTERS_KIND, CHUNKC_any);
		}
	    }
	    break;

	case RW_VECTOR_HEADER_BTAG:
	case RO_VECTOR_HEADER_BTAG:
	    //
	    switch (GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword)) {
		//
	    case TYPEAGNOSTIC_VECTOR_CTAG:
		if (GET_BTAG_FROM_TAGWORD(tagword) == RW_VECTOR_HEADER_BTAG)	check_pointer (p, *p, gen, RO_POINTERS_KIND, CHUNKC__IS_RW_POINTERS);
		else					    			check_pointer (p, *p, gen, RO_POINTERS_KIND, CHUNKC__IS_RO_POINTERS|CHUNKC__IS_RO_CONSCELL);
		break;

	    case VECTOR_OF_ONE_BYTE_UNTS_CTAG:
	    case UNT16_VECTOR_CTAG:
	    case TAGGED_INT_VECTOR_CTAG:
	    case INT1_VECTOR_CTAG:
	    case VECTOR_OF_FOUR_BYTE_FLOATS_CTAG:
	    case VECTOR_OF_EIGHT_BYTE_FLOATS_CTAG:
		check_pointer (p, *p, gen, RO_POINTERS_KIND, CHUNKC__IS_NONPTR_DATA);
		break;

	    default:
		ERROR;
		debug_say ("** @%#x: strange sequence kind %d in record sib\n",
		    p-1, GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword));
		return;
	    }

	    if (*IS_TAGGED_INT(p[1])) {
		ERROR;
		debug_say ("** @%#x: sequence header length field not an in (%#x)\n",
		    p+1, p[1]);
	    }
	    p += 2;
	    break;

	default:
	    ERROR;
	    debug_say ("** @%#x: strange tag (%#x) in record sib\n",
		p-1, GET_BTAG_FROM_TAGWORD(tagword));
	    return;
	}
    }
}											// fun check_ro_pointer_sib
Example #4
0
static void   check_rw_pointer_sib   (Sib* ap,  Coarse_Inter_Agegroup_Pointers_Map* map)   {		// 'map' is nowhere used in the code?! Should be deleted or used.  XXX BUGGO FIXME
    //        ====================
    //
    Val* p;
    Val* stop;
    Val  tagword;
    Val  w;

    int  i, j;
    int  len;

    int  gen =  GET_AGE_FROM_SIBID(ap->id);

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  arrays [%d]: [%#x..%#x:%#x)\n",
	//
	gen,
	ap->tospace,
	ap->tospace.first_free,
	ap->tospace.limit
    );

    p = ap->tospace;
    stop = ap->tospace.first_free;

    while (p < stop) {
	tagword = *p++;
	if (*IS_TAGWORD(tagword)) {
	    ERROR;
	    debug_say (
		"** @%#x: expected tagword, but found %#x in vector sib\n",
		p-1, tagword);
	    return;
	}

	switch (GET_BTAG_FROM_TAGWORD(tagword)) {
	    //
	case RW_VECTOR_DATA_BTAG:
	    len = GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword);
	    break;

	case WEAK_POINTER_OR_SUSPENSION_BTAG:
	    len = 1;
	    break;

	default:
	    ERROR;
	    debug_say ("** @%#x: strange tag (%#x) in vector sib\n",
		p-1, GET_BTAG_FROM_TAGWORD(tagword));
	    return;
	}

	for (int i = 0;  i < len;  i++, p++) {
	    //
	    w = *p;
	    if (IS_TAGWORD(w)) {
		ERROR;
		debug_say (
		    "** @%#x: Unexpected tagword %#x in rw_vector slot %d of %d\n",
		    p, w, i, GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword));
		for (p -= (i+1), j = 0;  j <= len;  j++, p++) {
		    debug_say ("  %#x: %#10x\n", p, *p);
		}
		return;
	    } else if (IS_POINTER(w)) {
		check_pointer(p, w, gen, RW_POINTERS_KIND, CHUNKC_any);
	    }
	}
    }
}								// fun check_rw_pointer_sib
Example #5
0
static void   check_nonpointer_sib   (Sib* ap)   {
    //        ================
    // 
    // Check a string sib for consistency.

    Val* p;
    Val* stop;
    Val* prevTagword;
    Val  tagword;
    Val	 next;

    int  len;
    int  gen =  GET_AGE_FROM_SIBID( ap->id );

    if (*sib_is_active(ap))   return;							// sib_is_active	def in    src/c/h/heap.h

    debug_say ("  strings [%d]: [%#x..%#x:%#x)\n",
	//
	gen,
	ap->tospace,
	ap->tospace.first_free,
	ap->tospace.limit
    );

    p = ap->tospace;
    stop = ap->tospace.first_free;
    prevTagword = NULL;
    while (p < stop) {
	tagword = *p++;
	if (IS_TAGWORD(tagword)) {
	    //
	    switch (GET_BTAG_FROM_TAGWORD(tagword)) {
	        //
	    case FOUR_BYTE_ALIGNED_NONPOINTER_DATA_BTAG:
	    case EIGHT_BYTE_ALIGNED_NONPOINTER_DATA_BTAG:
		len = GET_LENGTH_IN_WORDS_FROM_TAGWORD(tagword);
		break;

	    default:
		ERROR;
		debug_say ("** @%#x: strange tag (%#x) in string sib\n",
		    p-1, GET_BTAG_FROM_TAGWORD(tagword));
		if (prevTagword != NULL)
		    debug_say ("   previous string started @ %#x\n", prevTagword);
		return;
	    }
	    prevTagword = p-1;
	    p += len;
	}
#ifdef ALIGN_FLOAT64S
	else if ((tagword == 0) && (((Vunt)p & WORD_BYTESIZE) != 0))
	    continue;	    // Assume this is alignment padding.
#endif
	else {
	    ERROR;

	    debug_say ("** @%#x: expected tagword, but found %#x in string sib\n", p-1, tagword);

	    if (prevTagword != NULL)   debug_say ("   previous string started @ %#x\n", prevTagword);

	    return;
	}
    }

}								// fun check_nonpointer_sib
Example #6
0
static Status   read_image  (Task* task,  Inbuf* bp,  Val* chunk_ref) {
    //          ==========
    //
    Pickle_Header	pickle_header;
    Val*		externs;

    Sib_Header*	sib_headers[ TOTAL_SIBS ];
    Sib_Header*	sib_headers_buffer;

    int sib_headers_size;

    Agegroup*  age1 =   task->heap->agegroup[ 0 ];

    if (heapio__read_block( bp, &pickle_header, sizeof(pickle_header) ) == FALSE
    ||  pickle_header.smallchunk_sibs_count > MAX_PLAIN_SIBS				// MAX_PLAIN_SIBS		def in    src/c/h/sibid.h
    ||  pickle_header.hugechunk_sibs_count  > MAX_HUGE_SIBS				// MAX_HUGE_SIBS		def in    src/c/h/sibid.h
    ){
	return FALSE;									// XXX BUGGO FIXME we gotta do better than this.
    }

    // Read the externals table:
    //
    externs = heapio__read_externs_table( bp );



    // Read the sib headers:
    //
    sib_headers_size =  (pickle_header.smallchunk_sibs_count + pickle_header.hugechunk_sibs_count)
		        *
                        sizeof( Sib_Header );
    //
    sib_headers_buffer =  (Sib_Header*) MALLOC (sib_headers_size);
    //
    if (heapio__read_block( bp, sib_headers_buffer, sib_headers_size ) == FALSE) {
	//
	FREE( sib_headers_buffer );
	return FALSE;
    }
    //
    for (int ilk = 0;  ilk < TOTAL_SIBS;  ilk++) {
        //
	sib_headers[ ilk ] =  NULL;
    }
    //
    for (int sib = 0;  sib < pickle_header.smallchunk_sibs_count;  sib++) {
        //
	Sib_Header* p =  &sib_headers_buffer[ sib ];
	//
	sib_headers[ p->chunk_ilk ] =  p;
    }



    // DO BIG CHUNK HEADERS TOO

    // Check the heap to see if there is
    // enough free space in agegroup 1:
    //
    {   Punt	agegroup0_buffer_bytesize =   agegroup0_buffer_size_in_bytes( task );
        //
	Bool needs_cleaning  =   FALSE;

	for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	    //
	    Sib* sib = age1->sib[ ilk ];

	    if (sib_headers[ilk] != NULL
		&&
               (!sib_is_active(sib)								// sib_is_active		def in    src/c/h/heap.h
	       || sib_freespace_in_bytes(sib) < sib_headers[ ilk ]->info.o.bytesize		// sib_freespace_in_bytes	def in    src/c/h/heap.h
                                               +
                                               agegroup0_buffer_bytesize
               )
            ){
		needs_cleaning = TRUE;
		sib->requested_extra_free_bytes = sib_headers[ ilk ]->info.o.bytesize;
	    }
	}

	if (needs_cleaning) {
	    //
	    if (bp->nbytes <= 0) {
		//
		call_heapcleaner( task, 1 );							// call_heapcleaner		def in   /src/c/heapcleaner/call-heapcleaner.c

	    } else {
		//
	        // The cleaning may move the buffer, so:
                
		Val buffer =  PTR_CAST( Val,  bp->base );

		{   Roots extra_roots = { &buffer, NULL };
		    //
		    call_heapcleaner_with_extra_roots (task, 1, &extra_roots );
		}

		if (buffer != PTR_CAST( Val,  bp->base )) {
		    //
		    // The buffer moved, so adjust the buffer pointers:

		    Unt8* new_base = PTR_CAST( Unt8*, buffer );

		    bp->buf  = new_base + (bp->buf - bp->base);
		    bp->base = new_base;
		}
            }
	}
    }
Example #7
0
static Val   pickle_heap_datastructure   (Task *task,  Val root_chunk,  Pickler_Result* result)   {
    //       =========================
    //
    Heap* heap    =  task->heap;
    int	  max_age =  result->oldest_agegroup_included_in_pickle;

    Vunt  total_sib_buffer_bytesize[ MAX_PLAIN_SIBS ];
    Vunt  total_bytesize;

    struct {
	Vunt		    base;	// Base address of the sib buffer in the heap.
	Vunt		    offset;	// Relative position in the merged sib buffer.
	//
    } adjust[ MAX_AGEGROUPS ][ MAX_PLAIN_SIBS ];

    Sib_Header*  p;										// Sib_Header		def in    src/c/heapcleaner/runtime-heap-image.h
    Sib_Header*  sib_headers[ TOTAL_SIBS ];
    Sib_Header*  sib_header_buffer;

    int  sib_header_bytesize;
    int	 smallchunk_sibs_count;

    Val     pickle;
    Writer* wr;

    // Compute the sib offsets in the heap image:
    //
    for (int ilk = 0;   ilk < MAX_PLAIN_SIBS;   ilk++) {
        //
	total_sib_buffer_bytesize[ ilk ] = 0;
    }

    // The embedded literals go first:
    //
    total_sib_buffer_bytesize[ NONPTR_DATA_SIB ]						// pickler__relocate_embedded_literals	def in   src/c/heapcleaner/datastructure-pickler-cleaner.c
	=
	pickler__relocate_embedded_literals( result, NONPTR_DATA_SIB, 0 );

    // DEBUG debug_say("%d bytes of string literals\n", total_sib_buffer_bytesize[NONPTR_DATA_SIB]);

    for     (int age = 0;  age < max_age;         age++) {
	for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	    //
	    Sib* sib =  heap->agegroup[ age ]->sib[ ilk ];

	    adjust[ age ][ ilk ].offset
		=
		total_sib_buffer_bytesize[ ilk ];

	    if (!sib_is_active(sib)) {								// sib_is_active	def in    src/c/h/heap.h
	        //
		adjust[ age ][ ilk ].base =  0;
		//
	    } else {
		//
		total_sib_buffer_bytesize[ ilk ]
		   +=
		    (Vunt)  sib->tospace.first_free
		    -
		    (Vunt)  sib->tospace.start;

		adjust[ age ][ ilk ].base =  (Vunt) sib->tospace.start;
	    }
	}
    }

    // DEBUG for (ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) debug_say ("sib %d: %d bytes\n", ilk+1, total_sib_buffer_bytesize[ilk]);

    // WHAT ABOUT THE BIG CHUNKS??? XXX BUGGO FIXME

    // Compute the total size of the pickled datastructure:
    //
    smallchunk_sibs_count = 0;
    total_bytesize   = 0;
    //
    for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	//
	if (total_sib_buffer_bytesize[ilk] > 0) {
	    smallchunk_sibs_count++;
	    total_bytesize += total_sib_buffer_bytesize[ilk];
	}
    }

    total_bytesize
       +=
	sizeof( Heapfile_Header )
        +
	sizeof( Pickle_Header    )
	+
	(smallchunk_sibs_count * sizeof( Sib_Header ));

    // COUNT SPACE FOR BIG CHUNKS

    total_bytesize
       +=
	sizeof(Externs_Header)
        +
	heapfile_cfun_table_bytesize( result->cfun_table );    // Include the space for the external symbols (i.e., runtime C functions referenced within the heapgraph).

    // Allocate the heap bytevector for the pickled
    // datastructure representation and initialize
    // the bytevector-writer.
    //
    pickle
	=
	allocate_heap_ram_for_pickle( task, total_bytesize );
    //
    wr =  WR_OpenMem( PTR_CAST(Unt8*, pickle), total_bytesize );							// WR_OpenMem				def in    src/c/heapcleaner/mem-writer.c

    // Initialize the sib headers:
    //
    sib_header_bytesize =  smallchunk_sibs_count * sizeof(Sib_Header);
    //
    sib_header_buffer        =  (Sib_Header*) MALLOC (sib_header_bytesize);
    //
    p = sib_header_buffer;
    //
    for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
        //
	if (total_sib_buffer_bytesize[ ilk ] <= 0) {
	    //
	    sib_headers[ilk] = NULL;
	    //
	} else {
	    //
	    p->age		    	    = 0;
	    p->chunk_ilk	    	    = ilk;
	    //
	    p->info.o.base_address	    = 0;   					// Not used.
	    p->info.o.bytesize	    = total_sib_buffer_bytesize[ ilk ];
	    p->info.o.rounded_bytesize = -1;					// Not used.
	    //
	    p->offset		            = -1;  					// Not used.
	    sib_headers[ ilk ]	            = p;
	    p++;
	}
    }

    // What about big chunks? XXX BUGGO FIXME

    // Write the pickle image header:
    //
    if (heapio__write_image_header (wr, NORMAL_DATASTRUCTURE_PICKLE) == FALSE) {								// heapio__write_image_header		def in    src/c/heapcleaner/export-heap-stuff.c
	//
	FREE( sib_header_buffer );

	return PICKLER_ERROR;
    }

    // Write the pickle header:
    //	
    {   Pickle_Header	header;

	header.smallchunk_sibs_count     =  smallchunk_sibs_count;
	header.hugechunk_sibs_count      =  0;			// FIX THIS   XXX BUGGO FIXME
	header.hugechunk_quire_count =  0;			// FIX THIS   XXX BUGGO FIXME

	if (!IS_EXTERNAL_TAG( root_chunk )) {

	    Sibid sibid =  SIBID_FOR_POINTER( book_to_sibid__global, root_chunk );

	    if (!SIBID_KIND_IS_CODE(sibid)) {

		// This is the normal case  --
		// we're saving a vanilla heap value.

		Vunt  addr =  HEAP_POINTER_AS_UNT( root_chunk );

		int age  =  GET_AGE_FROM_SIBID( sibid) - 1;
		int kind =  GET_KIND_FROM_SIBID(sibid) - 1;									// GET_KIND_FROM_SIBID			def in    src/c/h/sibid.h

		addr -= adjust[ age ][ kind ].base;
		addr += adjust[ age ][ kind ].offset;

		header.root_chunk = HIO_TAG_PTR(kind, addr);									// HIO_TAG_PTR				def in    src/c/heapcleaner/runtime-heap-image.h

	    } else {

		//
		Embedded_Chunk_Info*  p
		    =
		    FIND_EMBEDDED_CHUNK( result->embedded_chunk_table, root_chunk );

		if ((p == NULL) || (p->kind == USED_CODE)) {
		    //
		    say_error( "Pickling compiled Mythryl code not implemented\n" );
		    FREE (sib_header_buffer);
		    return PICKLER_ERROR;
		} else {
		    header.root_chunk = p->relocated_address;
		}
	    }

	} else {	// IS_EXTERNAL_TAG( root_chunk )
	    //
	    ASSERT( smallchunk_sibs_count == 0 );

	    header.root_chunk = root_chunk;
	}

	WR_WRITE(wr, &header, sizeof(header));											// WR_WRITE					def in    src/c/heapcleaner/writer.h
	//
	if (WR_ERROR(wr)) {
	    FREE (sib_header_buffer);
	    return PICKLER_ERROR;
	}
    }

    // Record in the pickle the table of heap-referenced
    // runtime C functions.  May also include
    // a handful of assembly fns, exceptions
    // and refcells:
    //
    {   int bytes_written =   heapio__write_cfun_table( wr, result->cfun_table );					// heapio__write_cfun_table			def in    src/c/heapcleaner/export-heap-stuff.c

	if (bytes_written == -1) {
	    FREE( sib_header_buffer );
	    return PICKLER_ERROR;
	}
    }

    // Write the pickle sib headers:
    //
    WR_WRITE (wr, sib_header_buffer, sib_header_bytesize);
    //
    if (WR_ERROR(wr)) {
	FREE (sib_header_buffer);
	return PICKLER_ERROR;
    }

    // Write the pickled datastructure proper:
    //
    for (int ilk = 0;  ilk < MAX_PLAIN_SIBS;  ilk++) {
	//
	if (ilk == NONPTR_DATA_SIB) {

	    // Write into the pickle the required embedded literals:
            //
	    pickler__pickle_embedded_literals( wr );										// pickler__pickle_embedded_literals		def in    src/c/heapcleaner/datastructure-pickler-cleaner.c

	    // Write into the pickle remaining required strings:
            //
	    for (int age = 0;  age < max_age;  age++) {
		//
		Sib* sib = heap->agegroup[ age ]->sib[ ilk ];

		if (sib_is_active(sib)) {											// sib_is_active				def in    src/c/h/heap.h
		    //
		    WR_WRITE(
                        wr,
                        sib->tospace.start,
			(Vunt) sib->tospace.first_free
                       -(Vunt) sib->tospace.start
                    );
		}
	    }

	} else {

	    for (int age = 0;  age < max_age;  age++) {
		//
		Sib* sib = heap->agegroup[ age ]->sib[ ilk ];

		if (sib_is_active( sib )) {
		    //
		    Val*  top =  sib->tospace.first_free;
		    //
		    for (Val*
			p =  sib->tospace.start;
                        p <  top;
                        p++
		    ){
			Val w =  *p;

			if (IS_POINTER(w)) {
			    //
			    Sibid sibid =  SIBID_FOR_POINTER( book_to_sibid__global, w );

			    if (BOOK_IS_UNMAPPED(sibid)) {
				//
				w =  add_cfun_to_heapfile_cfun_table( result->cfun_table, w);

				ASSERT (w != HEAP_VOID);

			    } else if (SIBID_KIND_IS_CODE(sibid)) {

				Embedded_Chunk_Info*  chunk_info
				    =
				    FIND_EMBEDDED_CHUNK( result->embedded_chunk_table, w );

				if (chunk_info == NULL
				||  chunk_info->kind == USED_CODE
				){
				    die("Pickling of Mythryl compiled code not implemented");
				} else {
				    w = chunk_info->relocated_address;
                                }

			    } else {

			        // Adjust the pointer:
                                //
				int  age  =  GET_AGE_FROM_SIBID( sibid)-1;
				int  kind =  GET_KIND_FROM_SIBID(sibid)-1;

				Vunt addr =  HEAP_POINTER_AS_UNT(w);

				addr -=  adjust[ age ][ kind ].base;
				addr +=  adjust[ age ][ kind ].offset;

				w = HIO_TAG_PTR( kind, addr );
			    }
			}								// if (IS_POINTER(w))
			WR_PUT(wr, (Vunt)w);
		    }									// for
		}
	    }
	}
    }

    FREE( sib_header_buffer );

    if (WR_ERROR(wr))	return PICKLER_ERROR;

    return  make_vector_header(task, STRING_TAGWORD, pickle, total_bytesize);
}											// fun pickle_heap_datastructure