Esempio 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)) {
Esempio n. 2
0
static int   check_pointer   (Val* p,  Val w,  int src_age,  int srcKind,  int dstKind)   {
    //       =============
    //
    Sibid sibid  = SIBID_FOR_POINTER( book_to_sibid__global, w);
    int	  dstGen = GET_AGE_FROM_SIBID(sibid);
    int	  chunkc = GET_KIND_FROM_SIBID(sibid);

    switch (chunkc) {
        //
    case RO_POINTERS_KIND:
    case RO_CONSCELL_KIND:
    case NONPTR_DATA_KIND:
    case RW_POINTERS_KIND:
	if (!(dstKind & (1 << chunkc))) {
	    ERROR;
	    debug_say (
		"** @%#x: sequence data kind mismatch (expected %d, found %d)\n",
		p, dstKind, chunkc);
	}

	if (dstGen < src_age) {
	    if (srcKind != RW_POINTERS_KIND) {
		ERROR;
	        debug_say (
		    "** @%#x: reference to younger chunk @%#x (gen = %d)\n",
		    p, w, dstGen);
	    }
	}

	if ((chunkc != RO_CONSCELL_KIND) && (*IS_TAGWORD(((Val *)w)[-1]))) {
	    ERROR;
	    debug_say ("** @%#x: reference into chunk middle @#x\n", p, w);
	}
	break;

    case CODE_KIND:
	break;

    case NEW_KIND:
	ERROR;
	debug_say ("** @%#x: unexpected new-space reference\n", p);
	dstGen = MAX_AGEGROUPS;
	break;

    default:
	if (sibid != UNMAPPED_BOOK_SIBID) {
	    die("bogus chunk ilk in book_to_sibid__global\n");
	} else {
	    if (name_of_cfun(w) == NULL) {					// name_of_cfun	def in   src/c/heapcleaner/mythryl-callable-cfun-hashtable.c
		ERROR;
		debug_say (
		    "** @%#x: reference to unregistered external address %#x\n",
		    p, w);
	    }
	    dstGen = MAX_AGEGROUPS;
	}
	break;
    }

    return dstGen;
}								// fun check_pointer
Esempio 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