3 /* Certain special objects in the image are known to the runtime */
4 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;
13 stage2 = (userenv[STAGE2_ENV] != F);
16 INLINE 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,
29 F_ZONE *tenured = &data_heap->generations[TENURED];
31 F_FIXNUM bytes_read = fread((void*)tenured->start,1,h->data_size,file);
33 if(bytes_read != h->data_size)
35 print_string("truncated image: ");
36 print_fixnum(bytes_read);
37 print_string(" bytes read, ");
38 print_cell(h->data_size);
39 print_string(" bytes expected\n");
40 fatal_error("load_data_heap failed",0);
43 tenured->here = tenured->start + h->data_size;
44 data_relocation_base = h->data_relocation_base;
47 INLINE void load_code_heap(FILE *file, F_HEADER *h, F_PARAMETERS *p)
49 CELL good_size = h->code_size + (1 << 19);
51 if(good_size > p->code_size)
52 p->code_size = good_size;
54 init_code_heap(p->code_size);
58 F_FIXNUM bytes_read = fread(first_block(&code_heap),1,h->code_size,file);
59 if(bytes_read != h->code_size)
61 print_string("truncated image: ");
62 print_fixnum(bytes_read);
63 print_string(" bytes read, ");
64 print_cell(h->code_size);
65 print_string(" bytes expected\n");
66 fatal_error("load_code_heap failed",0);
70 code_relocation_base = h->code_relocation_base;
71 build_free_list(&code_heap,h->code_size);
74 /* Read an image file from disk, only done once during startup */
75 /* This function also initializes the data and code heaps */
76 void load_image(F_PARAMETERS *p)
78 FILE *file = OPEN_READ(p->image);
81 print_string("Cannot open image file: "); print_native_string(p->image); nl();
82 print_string(strerror(errno)); nl();
87 fread(&h,sizeof(F_HEADER),1,file);
89 if(h.magic != IMAGE_MAGIC)
90 fatal_error("Bad image: magic number check failed",h.magic);
92 if(h.version != IMAGE_VERSION)
93 fatal_error("Bad image: version number check failed",h.version);
95 load_data_heap(file,&h,p);
96 load_code_heap(file,&h,p);
105 /* Store image path name */
106 userenv[IMAGE_ENV] = tag_object(from_native_string(p->image));
109 /* Save the current image to disk */
110 bool save_image(const F_CHAR *filename)
115 file = OPEN_WRITE(filename);
118 print_string("Cannot open image file: "); print_native_string(filename); nl();
119 print_string(strerror(errno)); nl();
123 F_ZONE *tenured = &data_heap->generations[TENURED];
125 h.magic = IMAGE_MAGIC;
126 h.version = IMAGE_VERSION;
127 h.data_relocation_base = tenured->start;
128 h.data_size = tenured->here - tenured->start;
129 h.code_relocation_base = code_heap.segment->start;
130 h.code_size = heap_size(&code_heap);
133 h.bignum_zero = bignum_zero;
134 h.bignum_pos_one = bignum_pos_one;
135 h.bignum_neg_one = bignum_neg_one;
138 for(i = 0; i < USER_ENV; i++)
140 if(i < FIRST_SAVE_ENV)
143 h.userenv[i] = userenv[i];
146 fwrite(&h,sizeof(F_HEADER),1,file);
148 if(fwrite((void*)tenured->start,h.data_size,1,file) != 1)
150 print_string("Save data heap failed: "); print_string(strerror(errno)); nl();
154 if(fwrite(first_block(&code_heap),h.code_size,1,file) != 1)
156 print_string("Save code heap failed: "); print_string(strerror(errno)); nl();
162 print_string("Failed to close image file: "); print_string(strerror(errno)); nl();
169 void primitive_save_image(void)
171 /* do a full GC to push everything into tenured space */
174 save_image(unbox_native_string());
177 void primitive_save_image_and_exit(void)
179 /* We unbox this before doing anything else. This is the only point
180 where we might throw an error, so we have to throw an error here since
181 later steps destroy the current image. */
182 F_CHAR *path = unbox_native_string();
184 REGISTER_C_STRING(path);
186 /* strip out userenv data which is set on startup anyway */
188 for(i = 0; i < FIRST_SAVE_ENV; i++)
191 for(i = LAST_SAVE_ENV + 1; i < USER_ENV; i++)
194 /* do a full GC + code heap compaction */
197 UNREGISTER_C_STRING(path);
206 void fixup_word(F_WORD *word)
210 code_fixup((CELL)&word->code);
211 if(word->profiling) code_fixup((CELL)&word->profiling);
212 code_fixup((CELL)&word->xt);
216 void fixup_quotation(F_QUOTATION *quot)
218 if(quot->compiledp == F)
219 quot->xt = lazy_jit_compile;
222 code_fixup((CELL)"->xt);
223 code_fixup((CELL)"->code);
227 void fixup_alien(F_ALIEN *d)
232 void fixup_stack_frame(F_STACK_FRAME *frame)
234 code_fixup((CELL)&frame->xt);
235 code_fixup((CELL)&FRAME_RETURN_ADDRESS(frame));
238 void fixup_callstack_object(F_CALLSTACK *stack)
240 iterate_callstack_object(stack,fixup_stack_frame);
243 /* Initialize an object in a newly-loaded image */
244 void relocate_object(CELL relocating)
246 /* Tuple relocation is a bit trickier; we have to fix up the
247 fixup object before we can get the tuple size, so do_slots is
248 out of the question */
249 if(untag_header(get(relocating)) == TUPLE_TYPE)
251 data_fixup((CELL *)relocating + 1);
253 CELL scan = relocating + 2 * CELLS;
254 CELL size = untagged_object_size(relocating);
255 CELL end = relocating + size;
259 data_fixup((CELL *)scan);
265 do_slots(relocating,data_fixup);
267 switch(untag_header(get(relocating)))
270 fixup_word((F_WORD *)relocating);
273 fixup_quotation((F_QUOTATION *)relocating);
276 ffi_dlopen((F_DLL *)relocating);
279 fixup_alien((F_ALIEN *)relocating);
282 fixup_callstack_object((F_CALLSTACK *)relocating);
288 /* Since the image might have been saved with a different base address than
289 where it is loaded, we need to fix up pointers in the image. */
295 for(i = 0; i < USER_ENV; i++)
296 data_fixup(&userenv[i]);
299 data_fixup(&bignum_zero);
300 data_fixup(&bignum_pos_one);
301 data_fixup(&bignum_neg_one);
303 F_ZONE *tenured = &data_heap->generations[TENURED];
305 for(relocating = tenured->start;
306 relocating < tenured->here;
307 relocating += untagged_object_size(relocating))
309 allot_barrier(relocating);
310 relocate_object(relocating);
314 void fixup_code_block(F_COMPILED *compiled, CELL code_start, CELL literals_start)
316 /* relocate literal table data */
318 CELL literal_end = literals_start + compiled->literals_length;
320 data_fixup(&compiled->relocation);
322 for(scan = literals_start; scan < literal_end; scan += CELLS)
323 data_fixup((CELL*)scan);
325 relocate_code_block(compiled,code_start,literals_start);
330 iterate_code_heap(fixup_code_block);