6 /* Certain special objects in the image are known to the runtime */
7 static void init_objects(image_header *h)
9 memcpy(userenv,h->userenv,sizeof(userenv));
12 bignum_zero = h->bignum_zero;
13 bignum_pos_one = h->bignum_pos_one;
14 bignum_neg_one = h->bignum_neg_one;
17 cell data_relocation_base;
19 static void load_data_heap(FILE *file, image_header *h, vm_parameters *p)
21 cell good_size = h->data_size + (1 << 20);
23 if(good_size > p->tenured_size)
24 p->tenured_size = good_size;
26 init_data_heap(p->gen_count,
34 zone *tenured = &data->generations[data->tenured()];
36 fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file);
38 if((cell)bytes_read != h->data_size)
40 print_string("truncated image: ");
41 print_fixnum(bytes_read);
42 print_string(" bytes read, ");
43 print_cell(h->data_size);
44 print_string(" bytes expected\n");
45 fatal_error("load_data_heap failed",0);
48 tenured->here = tenured->start + h->data_size;
49 data_relocation_base = h->data_relocation_base;
52 cell code_relocation_base;
54 static void load_code_heap(FILE *file, image_header *h, vm_parameters *p)
56 if(h->code_size > p->code_size)
57 fatal_error("Code heap too small to fit image",h->code_size);
59 init_code_heap(p->code_size);
63 size_t bytes_read = fread(first_block(&code),1,h->code_size,file);
64 if(bytes_read != h->code_size)
66 print_string("truncated image: ");
67 print_fixnum(bytes_read);
68 print_string(" bytes read, ");
69 print_cell(h->code_size);
70 print_string(" bytes expected\n");
71 fatal_error("load_code_heap failed",0);
75 code_relocation_base = h->code_relocation_base;
76 build_free_list(&code,h->code_size);
79 /* Save the current image to disk */
80 bool save_image(const vm_char *filename)
85 file = OPEN_WRITE(filename);
88 print_string("Cannot open image file: "); print_native_string(filename); nl();
89 print_string(strerror(errno)); nl();
93 zone *tenured = &data->generations[data->tenured()];
95 h.magic = image_magic;
96 h.version = image_version;
97 h.data_relocation_base = tenured->start;
98 h.data_size = tenured->here - tenured->start;
99 h.code_relocation_base = code.seg->start;
100 h.code_size = heap_size(&code);
103 h.bignum_zero = bignum_zero;
104 h.bignum_pos_one = bignum_pos_one;
105 h.bignum_neg_one = bignum_neg_one;
107 for(cell i = 0; i < USER_ENV; i++)
108 h.userenv[i] = (save_env_p(i) ? userenv[i] : F);
112 if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
113 if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
114 if(fwrite(first_block(&code),h.code_size,1,file) != 1) ok = false;
115 if(fclose(file)) ok = false;
119 print_string("save-image failed: "); print_string(strerror(errno)); nl();
125 PRIMITIVE(save_image)
127 /* do a full GC to push everything into tenured space */
130 gc_root<byte_array> path(dpop());
132 save_image((vm_char *)(path.untagged() + 1));
135 PRIMITIVE(save_image_and_exit)
137 /* We unbox this before doing anything else. This is the only point
138 where we might throw an error, so we have to throw an error here since
139 later steps destroy the current image. */
140 gc_root<byte_array> path(dpop());
143 /* strip out userenv data which is set on startup anyway */
144 for(cell i = 0; i < USER_ENV; i++)
146 if(!save_env_p(i)) userenv[i] = F;
149 /* do a full GC + code heap compaction */
150 performing_compaction = true;
152 performing_compaction = false;
155 if(save_image((vm_char *)(path.untagged() + 1)))
161 static void data_fixup(cell *cell)
163 if(immediate_p(*cell))
166 zone *tenured = &data->generations[data->tenured()];
167 *cell += (tenured->start - data_relocation_base);
170 template <typename T> void code_fixup(T **handle)
173 T *new_ptr = (T *)(((cell)ptr) + (code.seg->start - code_relocation_base));
177 static void fixup_word(word *word)
180 code_fixup(&word->code);
182 code_fixup(&word->profiling);
183 code_fixup(&word->xt);
186 static void fixup_quotation(quotation *quot)
190 code_fixup("->xt);
191 code_fixup("->code);
194 quot->xt = (void *)lazy_jit_compile;
197 static void fixup_alien(alien *d)
202 static void fixup_stack_frame(stack_frame *frame)
204 code_fixup(&frame->xt);
205 code_fixup(&FRAME_RETURN_ADDRESS(frame));
208 static void fixup_callstack_object(callstack *stack)
210 iterate_callstack_object(stack,fixup_stack_frame);
213 /* Initialize an object in a newly-loaded image */
214 static void relocate_object(object *object)
216 cell hi_tag = object->h.hi_tag();
218 /* Tuple relocation is a bit trickier; we have to fix up the
219 layout object before we can get the tuple size, so do_slots is
220 out of the question */
221 if(hi_tag == TUPLE_TYPE)
223 tuple *t = (tuple *)object;
224 data_fixup(&t->layout);
226 cell *scan = t->data();
227 cell *end = (cell *)((cell)object + untagged_object_size(object));
229 for(; scan < end; scan++)
234 do_slots((cell)object,data_fixup);
239 fixup_word((word *)object);
242 fixup_quotation((quotation *)object);
245 ffi_dlopen((dll *)object);
248 fixup_alien((alien *)object);
251 fixup_callstack_object((callstack *)object);
257 /* Since the image might have been saved with a different base address than
258 where it is loaded, we need to fix up pointers in the image. */
264 for(i = 0; i < USER_ENV; i++)
265 data_fixup(&userenv[i]);
268 data_fixup(&bignum_zero);
269 data_fixup(&bignum_pos_one);
270 data_fixup(&bignum_neg_one);
272 zone *tenured = &data->generations[data->tenured()];
274 for(relocating = tenured->start;
275 relocating < tenured->here;
276 relocating += untagged_object_size((object *)relocating))
278 object *obj = (object *)relocating;
280 relocate_object(obj);
284 static void fixup_code_block(code_block *compiled)
286 /* relocate literal table data */
287 data_fixup(&compiled->relocation);
288 data_fixup(&compiled->literals);
290 relocate_code_block(compiled);
295 iterate_code_heap(fixup_code_block);
298 /* Read an image file from disk, only done once during startup */
299 /* This function also initializes the data and code heaps */
300 void load_image(vm_parameters *p)
302 FILE *file = OPEN_READ(p->image_path);
305 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
306 print_string(strerror(errno)); nl();
311 if(fread(&h,sizeof(image_header),1,file) != 1)
312 fatal_error("Cannot read image header",0);
314 if(h.magic != image_magic)
315 fatal_error("Bad image: magic number check failed",h.magic);
317 if(h.version != image_version)
318 fatal_error("Bad image: version number check failed",h.version);
320 load_data_heap(file,&h,p);
321 load_code_heap(file,&h,p);
330 /* Store image path name */
331 userenv[IMAGE_ENV] = allot_alien(F,(cell)p->image_path);