Exemplo n.º 1
0
static Val   repair_word   (
    //       ===========
    //
    Val                w,
    Sibid*          oldBOOK2SIBID,
    //
    Punt  addrOffset  [ MAX_AGEGROUPS ][ MAX_PLAIN_SIBS ],
    //
    Addresstable*      hugechunk_region_table,
    Val*               externs
) {
    //
    if (IS_POINTER(w)) {
	//
	Punt	chunk = HEAP_POINTER_AS_UNT(w);
	Sibid	aid = SIBID_FOR_POINTER(oldBOOK2SIBID, chunk);

	if (SIBID_KIND_IS_CODE(aid)) {

	    Hugechunk_Relocation_Info* dp = address_to_relocation_info (oldBOOK2SIBID, hugechunk_region_table, aid, chunk);

	    return PTR_CAST( Val, (chunk - dp->old_address) + dp->new_chunk->chunk);

	} else {

	    int	g = GET_AGE_FROM_SIBID(aid)-1;
	    int	chunkc = GET_KIND_FROM_SIBID(aid)-1;
	    return PTR_CAST( Val,  PTR_CAST(char*, w) + addrOffset[g][chunkc]);
	}

    } else if (IS_EXTERNAL_TAG(w)) {
Exemplo n.º 2
0
int   get_chunk_age   (Val chunk) {
    //============= 
    // 
    // Get the agegroup of a chunk.
    // Return -1 for external/unboxed chunks.
    //
    // We are called (only) from
    //     src/c/heapcleaner/datastructure-pickler.c	

    if (! IS_POINTER( chunk )) {
	return -1;
    } else {
        //
	Sibid aid =  SIBID_FOR_POINTER( book_to_sibid__global, chunk );
        //
	if (SIBID_KIND_IS_CODE( aid )) {
	    //	

	    int  i;
	    for (i = GET_BOOK_CONTAINING_POINTEE(chunk);  !SIBID_ID_IS_BIGCHUNK_RECORD(aid);  aid = book_to_sibid__global[--i]) {
		continue;
	    }

	    Hugechunk_Quire*
		//
	        hq = (Hugechunk_Quire*) ADDRESS_OF_BOOK( i );

	    Hugechunk*
		//
	        dp =  get_hugechunk_holding_pointee( hq, chunk );

	    return dp->age;

	} else if (aid == AGEGROUP0_SIBID) {	    return  0;
	} else if (BOOK_IS_UNMAPPED(aid)) {	    return -1;
	} else {	 		    	    return  GET_AGE_FROM_SIBID( aid );
	}
    }

}
Exemplo n.º 3
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
Exemplo n.º 4
0
static void   process_task_heap_changelog   (Task* task, Heap* heap) {
    //        ===========================
    // 
    // As tasks run, they note all stores into pointer-valued					// Tagged-Int-valued refcells cannot contain cross-generation pointers so we don't track them in changelog.
    // refcells and rw_vectors in the 'heap_changelog',
    // a lisp-style list of "CONS cells" -- (val,next) pointer-pairs.
    // 
    // We need this done because such stores into the heap
    // can introduce pointers from one agegroup into a
    // younger agegroup, which we need to take into account
    // when doing partial heapcleanings ("garbage collections").
    //
    // Our job here is to promote to agegroup 1 all agegroup0
    // values referenced by a refcell/vectorslot in the heap_changelog.

    Val this_heap_changelog_cell =  task->heap_changelog; 
    if (this_heap_changelog_cell == HEAP_CHANGELOG_NIL)   return;				// Abort quickly if no work to do.

    int updates        = 0;									// Heapcleaner statistics.
    Agegroup* age1     =  heap->agegroup[ 0 ];							// Cache heap entry for speed.
    Sibid* b2s         =  book_to_sibid__global;						// Cache global locally for speed.   book_to_sibid__global	def in    src/c/heapcleaner/heapcleaner-initialization.c

    while (this_heap_changelog_cell != HEAP_CHANGELOG_NIL) {					// Over all entries in the heap_changelog.
	//
	++updates;										// Heapcleaner statistics.

	Val* pointer   	         =  HEAP_CHANGELOG_HEAD( this_heap_changelog_cell );		// Get pointer to next updated refcell/vector slot to process.
	this_heap_changelog_cell =  HEAP_CHANGELOG_TAIL( this_heap_changelog_cell );		// Step to next cell in heap_changelog list.

	Val pointee = *pointer;									// Get contents of updated refcell/vectorslot.

	if (!IS_POINTER( pointee ))   continue;							// Ignore refcells and vectorslots containing Tagged_Int values.

	Sibid src_sibid =  SIBID_FOR_POINTER(b2s, pointer );					// Get the Sibid tag for the ram-book containing the refcell/vectorslot.	Sibid  def in    src/c/h/sibid.h

	if (src_sibid == AGEGROUP0_SIBID)    continue;						// Ignore updates to agegroup0      refcells and vectorslots.
	if (BOOK_IS_UNMAPPED( src_sibid ))   continue;						// Ignore updates to runtime-global refcells and vectorslots, which are handled elsewhere.

	Sibid dst_sibid =  SIBID_FOR_POINTER(b2s, pointee );					// Get the Sibid tag for the ram-book containing the value referenced by the refcell/vectorslot.
	//
	int src_age =  GET_AGE_FROM_SIBID( src_sibid );						// agegroup of the updated refcell/vectorslot.
	int dst_age =  GET_AGE_FROM_SIBID( dst_sibid );						// agegroup of the chunk that the refcell/vectorslot points to.

	if (!SIBID_KIND_IS_CODE( dst_sibid )) {
	    //
	    if (dst_age == AGEGROUP0) {
		//
		*pointer =  forward_agegroup0_chunk_to_agegroup1( age1, pointee,task, 1);	// Promote pointee to agegroup 1.
		dst_age = 1;									// Remember pointee now has age 1, not 0.
		//
	    }

	} else {										// Refcell/vector slot is pointing to code.	

	    if (dst_age >= src_age)   continue;

            dst_age =  get_age_of_codechunk( pointee );
	}

	// Maybe update min_age value for
	// the card containing 'pointer':
	//
	if (src_age > dst_age) {
	    //
	    MAYBE_UPDATE_CARD_MIN_AGE_PER_POINTER(						// MAYBE_UPDATE_CARD_MIN_AGE_PER_POINTER	def in    src/c/h/coarse-inter-agegroup-pointers-map.h
		//
		heap->agegroup[ src_age-1 ]->coarse_inter_agegroup_pointers_map,
		pointer,
		dst_age
	    );
	}
    }

    update_count__global += updates;								// Cleaner statistics.  Apparently never used.

    task->heap_changelog =  HEAP_CHANGELOG_NIL;							// We're done with heap_changelog so clear it.

}												// fun process_task_heap_changelog