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 gc_root<F_BYTE_ARRAY> path(dpop());
137 save_image((F_CHAR *)(path.untagged() + 1));
140 void primitive_save_image_and_exit(void)
142 /* We unbox this before doing anything else. This is the only point
143 where we might throw an error, so we have to throw an error here since
144 later steps destroy the current image. */
145 gc_root<F_BYTE_ARRAY> path(dpop());
148 /* strip out userenv data which is set on startup anyway */
150 for(i = 0; i < FIRST_SAVE_ENV; i++)
153 for(i = LAST_SAVE_ENV + 1; i < STACK_TRACES_ENV; i++)
156 /* do a full GC + code heap compaction */
157 performing_compaction = true;
159 performing_compaction = false;
162 if(save_image((F_CHAR *)(path.untagged() + 1)))
168 static void data_fixup(CELL *cell)
170 if(immediate_p(*cell))
173 F_ZONE *tenured = &data_heap->generations[TENURED];
174 *cell += (tenured->start - data_relocation_base);
177 static void code_fixup(CELL cell)
179 CELL value = get(cell);
180 put(cell,value + (code_heap.segment->start - code_relocation_base));
183 static void fixup_word(F_WORD *word)
186 code_fixup((CELL)&word->code);
188 code_fixup((CELL)&word->profiling);
189 code_fixup((CELL)&word->xt);
192 static void fixup_quotation(F_QUOTATION *quot)
194 if(quot->compiledp == F)
195 quot->xt = (void *)lazy_jit_compile;
198 code_fixup((CELL)"->xt);
199 code_fixup((CELL)"->code);
203 static void fixup_alien(F_ALIEN *d)
208 static void fixup_stack_frame(F_STACK_FRAME *frame)
210 code_fixup((CELL)&frame->xt);
211 code_fixup((CELL)&FRAME_RETURN_ADDRESS(frame));
214 static void fixup_callstack_object(F_CALLSTACK *stack)
216 iterate_callstack_object(stack,fixup_stack_frame);
219 /* Initialize an object in a newly-loaded image */
220 static void relocate_object(CELL relocating)
222 /* Tuple relocation is a bit trickier; we have to fix up the
223 fixup object before we can get the tuple size, so do_slots is
224 out of the question */
225 if(untag_header(get(relocating)) == TUPLE_TYPE)
227 data_fixup((CELL *)relocating + 1);
229 CELL scan = relocating + 2 * CELLS;
230 CELL size = untagged_object_size(relocating);
231 CELL end = relocating + size;
235 data_fixup((CELL *)scan);
241 do_slots(relocating,data_fixup);
243 switch(untag_header(get(relocating)))
246 fixup_word((F_WORD *)relocating);
249 fixup_quotation((F_QUOTATION *)relocating);
252 ffi_dlopen((F_DLL *)relocating);
255 fixup_alien((F_ALIEN *)relocating);
258 fixup_callstack_object((F_CALLSTACK *)relocating);
264 /* Since the image might have been saved with a different base address than
265 where it is loaded, we need to fix up pointers in the image. */
271 for(i = 0; i < USER_ENV; i++)
272 data_fixup(&userenv[i]);
275 data_fixup(&bignum_zero);
276 data_fixup(&bignum_pos_one);
277 data_fixup(&bignum_neg_one);
279 F_ZONE *tenured = &data_heap->generations[TENURED];
281 for(relocating = tenured->start;
282 relocating < tenured->here;
283 relocating += untagged_object_size(relocating))
285 allot_barrier(relocating);
286 relocate_object(relocating);
290 static void fixup_code_block(F_CODE_BLOCK *compiled)
292 /* relocate literal table data */
293 data_fixup(&compiled->relocation);
294 data_fixup(&compiled->literals);
296 relocate_code_block(compiled);
301 iterate_code_heap(fixup_code_block);
304 /* Read an image file from disk, only done once during startup */
305 /* This function also initializes the data and code heaps */
306 void load_image(F_PARAMETERS *p)
308 FILE *file = OPEN_READ(p->image_path);
311 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
312 print_string(strerror(errno)); nl();
317 if(fread(&h,sizeof(F_HEADER),1,file) != 1)
318 fatal_error("Cannot read image header",0);
320 if(h.magic != IMAGE_MAGIC)
321 fatal_error("Bad image: magic number check failed",h.magic);
323 if(h.version != IMAGE_VERSION)
324 fatal_error("Bad image: version number check failed",h.version);
326 load_data_heap(file,&h,p);
327 load_code_heap(file,&h,p);
336 /* Store image path name */
337 userenv[IMAGE_ENV] = allot_alien(F,(CELL)p->image_path);