3 /* Certain special objects in the image are known to the runtime */
4 static void init_objects(F_HEADER *h)
6 memcpy(userenv,h->userenv,sizeof(userenv));
9 bignum_zero = h->bignum_zero;
10 bignum_pos_one = h->bignum_pos_one;
11 bignum_neg_one = h->bignum_neg_one;
14 CELL data_relocation_base;
16 static void load_data_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p)
18 CELL good_size = h->data_size + (1 << 20);
20 if(good_size > p->tenured_size)
21 p->tenured_size = good_size;
23 init_data_heap(p->gen_count,
31 F_ZONE *tenured = &data_heap->generations[TENURED];
33 F_FIXNUM bytes_read = fread((void*)tenured->start,1,h->data_size,file);
35 if((CELL)bytes_read != h->data_size)
37 print_string("truncated image: ");
38 print_fixnum(bytes_read);
39 print_string(" bytes read, ");
40 print_cell(h->data_size);
41 print_string(" bytes expected\n");
42 fatal_error("load_data_heap failed",0);
45 tenured->here = tenured->start + h->data_size;
46 data_relocation_base = h->data_relocation_base;
49 CELL code_relocation_base;
51 static void load_code_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p)
53 CELL good_size = h->code_size + (1 << 19);
55 if(good_size > p->code_size)
56 p->code_size = good_size;
58 init_code_heap(p->code_size);
62 size_t bytes_read = fread(first_block(&code_heap),1,h->code_size,file);
63 if(bytes_read != h->code_size)
65 print_string("truncated image: ");
66 print_fixnum(bytes_read);
67 print_string(" bytes read, ");
68 print_cell(h->code_size);
69 print_string(" bytes expected\n");
70 fatal_error("load_code_heap failed",0);
74 code_relocation_base = h->code_relocation_base;
75 build_free_list(&code_heap,h->code_size);
78 /* Save the current image to disk */
79 bool save_image(const F_CHAR *filename)
84 file = OPEN_WRITE(filename);
87 print_string("Cannot open image file: "); print_native_string(filename); nl();
88 print_string(strerror(errno)); nl();
92 F_ZONE *tenured = &data_heap->generations[TENURED];
94 h.magic = IMAGE_MAGIC;
95 h.version = IMAGE_VERSION;
96 h.data_relocation_base = tenured->start;
97 h.data_size = tenured->here - tenured->start;
98 h.code_relocation_base = code_heap.segment->start;
99 h.code_size = heap_size(&code_heap);
102 h.bignum_zero = bignum_zero;
103 h.bignum_pos_one = bignum_pos_one;
104 h.bignum_neg_one = bignum_neg_one;
107 for(i = 0; i < USER_ENV; i++)
109 if(i < FIRST_SAVE_ENV)
112 h.userenv[i] = userenv[i];
117 if(fwrite(&h,sizeof(F_HEADER),1,file) != 1) ok = false;
118 if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
119 if(fwrite(first_block(&code_heap),h.code_size,1,file) != 1) ok = false;
120 if(fclose(file)) ok = false;
124 print_string("save-image failed: "); print_string(strerror(errno)); nl();
130 void primitive_save_image(void)
132 /* do a full GC to push everything into tenured space */
135 save_image(unbox_native_string());
138 void primitive_save_image_and_exit(void)
140 /* We unbox this before doing anything else. This is the only point
141 where we might throw an error, so we have to throw an error here since
142 later steps destroy the current image. */
143 F_CHAR *path = unbox_native_string();
145 REGISTER_C_STRING(path);
147 /* strip out userenv data which is set on startup anyway */
149 for(i = 0; i < FIRST_SAVE_ENV; i++)
152 for(i = LAST_SAVE_ENV + 1; i < STACK_TRACES_ENV; i++)
155 /* do a full GC + code heap compaction */
156 performing_compaction = true;
158 performing_compaction = false;
160 UNREGISTER_C_STRING(F_CHAR,path);
169 static void data_fixup(CELL *cell)
171 if(immediate_p(*cell))
174 F_ZONE *tenured = &data_heap->generations[TENURED];
175 *cell += (tenured->start - data_relocation_base);
178 static void code_fixup(CELL cell)
180 CELL value = get(cell);
181 put(cell,value + (code_heap.segment->start - code_relocation_base));
184 static void fixup_word(F_WORD *word)
187 code_fixup((CELL)&word->code);
189 code_fixup((CELL)&word->profiling);
190 code_fixup((CELL)&word->xt);
193 static void fixup_quotation(F_QUOTATION *quot)
195 if(quot->compiledp == F)
196 quot->xt = (void *)lazy_jit_compile;
199 code_fixup((CELL)"->xt);
200 code_fixup((CELL)"->code);
204 static void fixup_alien(F_ALIEN *d)
209 static void fixup_stack_frame(F_STACK_FRAME *frame)
211 code_fixup((CELL)&frame->xt);
212 code_fixup((CELL)&FRAME_RETURN_ADDRESS(frame));
215 static void fixup_callstack_object(F_CALLSTACK *stack)
217 iterate_callstack_object(stack,fixup_stack_frame);
220 /* Initialize an object in a newly-loaded image */
221 static void relocate_object(CELL relocating)
223 /* Tuple relocation is a bit trickier; we have to fix up the
224 fixup object before we can get the tuple size, so do_slots is
225 out of the question */
226 if(untag_header(get(relocating)) == TUPLE_TYPE)
228 data_fixup((CELL *)relocating + 1);
230 CELL scan = relocating + 2 * CELLS;
231 CELL size = untagged_object_size(relocating);
232 CELL end = relocating + size;
236 data_fixup((CELL *)scan);
242 do_slots(relocating,data_fixup);
244 switch(untag_header(get(relocating)))
247 fixup_word((F_WORD *)relocating);
250 fixup_quotation((F_QUOTATION *)relocating);
253 ffi_dlopen((F_DLL *)relocating);
256 fixup_alien((F_ALIEN *)relocating);
259 fixup_callstack_object((F_CALLSTACK *)relocating);
265 /* Since the image might have been saved with a different base address than
266 where it is loaded, we need to fix up pointers in the image. */
272 for(i = 0; i < USER_ENV; i++)
273 data_fixup(&userenv[i]);
276 data_fixup(&bignum_zero);
277 data_fixup(&bignum_pos_one);
278 data_fixup(&bignum_neg_one);
280 F_ZONE *tenured = &data_heap->generations[TENURED];
282 for(relocating = tenured->start;
283 relocating < tenured->here;
284 relocating += untagged_object_size(relocating))
286 allot_barrier(relocating);
287 relocate_object(relocating);
291 static void fixup_code_block(F_CODE_BLOCK *compiled)
293 /* relocate literal table data */
294 data_fixup(&compiled->relocation);
295 data_fixup(&compiled->literals);
297 relocate_code_block(compiled);
302 iterate_code_heap(fixup_code_block);
305 /* Read an image file from disk, only done once during startup */
306 /* This function also initializes the data and code heaps */
307 void load_image(F_PARAMETERS *p)
309 FILE *file = OPEN_READ(p->image_path);
312 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
313 print_string(strerror(errno)); nl();
318 if(fread(&h,sizeof(F_HEADER),1,file) != 1)
319 fatal_error("Cannot read image header",0);
321 if(h.magic != IMAGE_MAGIC)
322 fatal_error("Bad image: magic number check failed",h.magic);
324 if(h.version != IMAGE_VERSION)
325 fatal_error("Bad image: version number check failed",h.version);
327 load_data_heap(file,&h,p);
328 load_code_heap(file,&h,p);
337 /* Store image path name */
338 userenv[IMAGE_ENV] = tag_object(from_native_string(p->image_path));