Task* import_heap_image__may_heapclean (const char* fname, Heapcleaner_Args* params, Roots* extra_roots) { // ================================ // // This fn is called (only) by load_and_run_heap_image__may_heapclean in src/c/main/load-and-run-heap-image.c // Task* task; Heapfile_Header image_header; Heap_Header heap_header; Val *externs; Pthread_Image image; Inbuf inbuf; if (fname != NULL) { // // Resolve the name of the image. // If the file exists use it, otherwise try the // pathname with the machine ID as an extension. if ((inbuf.file = fopen(fname, "rb"))) { // if (verbosity__global > 0) say("loading %s ", fname); } else { // if ((inbuf.file = fopen(fname, "rb"))) { // if (verbosity__global > 0) say("loading %s ", fname); } else { die ("unable to open heap image \"%s\"\n", fname); } } inbuf.needs_to_be_byteswapped = FALSE; inbuf.buf = NULL; inbuf.nbytes = 0; } else { // // fname == NULL, so try to find // an in-core heap image: #if defined(DLOPEN) && !defined(OPSYS_WIN32) // void *lib = dlopen (NULL, RTLD_LAZY); void *vimg, *vimglenptr; if ((vimg = dlsym(lib,HEAP_IMAGE_SYMBOL )) == NULL) die("no in-core heap image found\n"); if ((vimglenptr = dlsym(lib,HEAP_IMAGE_LEN_SYMBOL)) == NULL) die("unable to find length of in-core heap image\n"); inbuf.file = NULL; inbuf.needs_to_be_byteswapped = FALSE; inbuf.base = vimg; inbuf.buf = inbuf.base; inbuf.nbytes = *(long*)vimglenptr; #else die("in-core heap images not implemented\n"); #endif } READ(&inbuf, image_header); if (image_header.byte_order != ORDER) die ("incorrect byte order in heap image\n"); if (image_header.magic != IMAGE_MAGIC) die ("bad magic number (%#x) in heap image\n", image_header.magic); if ((image_header.kind != EXPORT_HEAP_IMAGE) && (image_header.kind != EXPORT_FN_IMAGE)) die ("bad image kind (%d) in heap image\n", image_header.kind); READ(&inbuf, heap_header); // Check for command-line overrides of heap parameters: // if (params->agegroup0_buffer_bytesize == 0) { params->agegroup0_buffer_bytesize = heap_header.agegroup0_buffer_bytesize; } if (params->active_agegroups < heap_header.active_agegroups) { params->active_agegroups = heap_header.active_agegroups; } if (params->oldest_agegroup_retaining_fromspace_sibs_between_heapcleanings < 0) { params->oldest_agegroup_retaining_fromspace_sibs_between_heapcleanings = heap_header.oldest_agegroup_retaining_fromspace_sibs_between_heapcleanings; } task = make_task( /*is_boot:*/FALSE, params ); // make_task def in src/c/main/runtime-state.c // Get the run-time pointers into the heap: // *PTR_CAST( Val*, PERVASIVE_PACKAGE_PICKLE_LIST_REFCELL__GLOBAL ) = heap_header.pervasive_package_pickle_list; // This carefully constructed fake looks like a normal // compiled package from the Mythryl side but actually // links to compile C code -- see the hack in // // src/c/main/load-compiledfiles.c // runtime_package__global = heap_header.runtime_pseudopackage; #ifdef ASM_MATH mathvec__global = heap_header.math_package; #endif externs = heapio__read_externs_table (&inbuf); // Read the externals table. READ(&inbuf, image); // Read and initialize the Mythryl state info. // if (image_header.kind == EXPORT_HEAP_IMAGE) { // Load the live registers: // ASSIGN( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL, image.posix_interprocess_signal_handler ); // task->argument = image.stdArg; task->fate = image.stdCont; task->current_closure = image.stdClos; task->program_counter = image.pc; task->exception_fate = image.exception_fate; task->current_thread = image.current_thread; // task->callee_saved_registers[0] = image.calleeSave[0]; task->callee_saved_registers[1] = image.calleeSave[1]; task->callee_saved_registers[2] = image.calleeSave[2]; read_heap (&inbuf, &heap_header, task, externs); // Read the Mythryl heap. /* heapcleaner_messages_are_enabled__global = TRUE; */ // Heapcleaning messages are on by default for interactive images. } else { // EXPORT_FN_IMAGE // Restore the signal handler: // ASSIGN( POSIX_INTERPROCESS_SIGNAL_HANDLER_REFCELL__GLOBAL, image.posix_interprocess_signal_handler ); // Read the Mythryl heap: // task->argument = image.stdArg; read_heap (&inbuf, &heap_header, task, externs); // Initialize the calling context (taken from run_mythryl_function__may_heapclean): // run_mythryl_function__may_heapclean def in src/c/main/run-mythryl-code-and-runtime-eventloop.c // Val function_to_run = task->argument; // task->exception_fate = PTR_CAST( Val, handle_uncaught_exception_closure_v + 1 ); task->current_thread = HEAP_VOID; // task->fate = PTR_CAST( Val, return_to_c_level_c ); task->current_closure = function_to_run; // task->program_counter = task->link_register = GET_CODE_ADDRESS_FROM_CLOSURE( function_to_run ); // Last use of 'function_to_run'. // Set up the arguments to the imported function: // Val program_name = make_ascii_string_from_c_string__may_heapclean(task, mythryl_program_name__global, extra_roots); Roots roots1 = { &program_name, extra_roots }; // Val args = make_ascii_strings_from_vector_of_c_strings__may_heapclean (task, commandline_args_without_argv0_or_runtime_args__global, &roots1 ); task->argument = make_two_slot_record( task, program_name, args ); // debug_say("arg = %#x : [%#x, %#x]\n", task->argument, GET_TUPLE_SLOT_AS_VAL(task->argument, 0), GET_TUPLE_SLOT_AS_VAL(task->argument, 1)); // Heapcleaner messages are off by // default for spawn_to_disk images: // heapcleaner_messages_are_enabled__global = FALSE; } FREE( externs ); if (inbuf.file) fclose (inbuf.file); if (verbosity__global > 0) say(" done\n"); return task; } // fun import_heap_image__may_heapclean
/* ImportHeapImage: */ lib7_state_t *ImportHeapImage (const char *fname, heap_params_t *params) { lib7_state_t *lib7_state; lib7_image_hdr_t imHdr; lib7_heap_hdr_t heapHdr; lib7_val_t *externs; lib7_vproc_image_t image; inbuf_t inBuf; if (fname != NULL) { /* Resolve the name of the image. * If the file exists use it, otherwise try the * pathname with the machine ID as an extension. */ if ((inBuf.file = fopen(fname, "rb"))) { if (verbosity > 0) say("loading %s ", fname); } else { if ((inBuf.file = fopen(fname, "rb"))) { if (verbosity > 0) say("loading %s ", fname); } else { Die ("unable to open heap image \"%s\"\n", fname); } } inBuf.needsSwap = FALSE; inBuf.buf = NULL; inBuf.nbytes = 0; } else { /* fname == NULL, so try to find an in-core heap image */ #if defined(DLOPEN) && !defined(OPSYS_WIN32) void *lib = dlopen (NULL, RTLD_LAZY); void *vimg, *vimglenptr; if ((vimg = dlsym(lib,HEAP_IMAGE_SYMBOL)) == NULL) Die("no in-core heap image found\n"); if ((vimglenptr = dlsym(lib,HEAP_IMAGE_LEN_SYMBOL)) == NULL) Die("unable to find length of in-core heap image\n"); inBuf.file = NULL; inBuf.needsSwap = FALSE; inBuf.base = vimg; inBuf.buf = inBuf.base; inBuf.nbytes = *(long*)vimglenptr; #else Die("in-core heap images not implemented\n"); #endif } READ(&inBuf, imHdr); if (imHdr.byteOrder != ORDER) Die ("incorrect byte order in heap image\n"); if (imHdr.magic != IMAGE_MAGIC) Die ("bad magic number (%#x) in heap image\n", imHdr.magic); if ((imHdr.kind != EXPORT_HEAP_IMAGE) && (imHdr.kind != EXPORT_FN_IMAGE)) Die ("bad image kind (%d) in heap image\n", imHdr.kind); READ(&inBuf, heapHdr); /* Check for command-line overrides of heap parameters: */ if (params->allocSz == 0) params->allocSz = heapHdr.allocSzB; if (params->numGens < heapHdr.numGens) params->numGens = heapHdr.numGens; if (params->cacheGen < 0) params->cacheGen = heapHdr.cacheGen; lib7_state = AllocLib7state (FALSE, params); /* Get the run-time pointers into the heap: */ *PTR_LIB7toC(lib7_val_t, PervasiveStruct) = heapHdr.pervasiveStruct; runtimeCompileUnit = heapHdr.runtimeCompileUnit; #ifdef ASM_MATH MathVec = heapHdr.mathVec; #endif /* Read the externals table: */ externs = HeapIO_ReadExterns (&inBuf); /* Read and initialize the Lib7 state info: */ READ(&inBuf, image); if (imHdr.kind == EXPORT_HEAP_IMAGE) { /* Load the live registers */ ASSIGN(Lib7SignalHandler, image.sigHandler); lib7_state->lib7_argument = image.stdArg; lib7_state->lib7_fate = image.stdCont; lib7_state->lib7_closure = image.stdClos; lib7_state->lib7_program_counter= image.pc; lib7_state->lib7_exception_fate = image.exception_fate; lib7_state->lib7_current_thread = image.current_thread; lib7_state->lib7_calleeSave[0] = image.calleeSave[0]; lib7_state->lib7_calleeSave[1] = image.calleeSave[1]; lib7_state->lib7_calleeSave[2] = image.calleeSave[2]; /* Read the Lib7 heap */ read_heap (&inBuf, &heapHdr, lib7_state, externs); /* GC message are on by default for interactive images */ /* GCMessages = TRUE; */ } else { /* EXPORT_FN_IMAGE */ lib7_val_t funct, cmdName, args; /* Restore the signal handler: */ ASSIGN(Lib7SignalHandler, image.sigHandler); /* Read the Lib7 heap: */ lib7_state->lib7_argument = image.stdArg; read_heap (&inBuf, &heapHdr, lib7_state, externs); /* Initialize the calling context (taken from ApplyLib7Fn) */ funct = lib7_state->lib7_argument; lib7_state->lib7_exception_fate = PTR_CtoLib7(handle_v+1); lib7_state->lib7_current_thread = LIB7_void; lib7_state->lib7_fate = PTR_CtoLib7(return_c); lib7_state->lib7_closure = funct; lib7_state->lib7_program_counter= lib7_state->lib7_link_register = GET_CODE_ADDR(funct); /* Set up the arguments to the imported function */ cmdName = LIB7_CString(lib7_state, Lib7CommandName); args = LIB7_CStringList (lib7_state, commandline_arguments); REC_ALLOC2(lib7_state, lib7_state->lib7_argument, cmdName, args); /* SayDebug("arg = %#x : [%#x, %#x]\n", lib7_state->lib7_argument, REC_SEL(lib7_state->lib7_argument, 0), REC_SEL(lib7_state->lib7_argument, 1)); */ /* GC message are off by default for spawn_to_disk images */ GCMessages = FALSE; } FREE (externs); if (inBuf.file) fclose (inBuf.file); if (verbosity > 0) say(" done\n"); return lib7_state; } /* ImportHeapImage */