6 /* Certain special objects in the image are known to the runtime */
7 void factorvm::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;
19 void factorvm::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;
54 void factorvm::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);
80 /* Save the current image to disk */
81 bool factorvm::save_image(const vm_char *filename)
86 file = OPEN_WRITE(filename);
89 print_string("Cannot open image file: "); print_native_string(filename); nl();
90 print_string(strerror(errno)); nl();
94 zone *tenured = &data->generations[data->tenured()];
96 h.magic = image_magic;
97 h.version = image_version;
98 h.data_relocation_base = tenured->start;
99 h.data_size = tenured->here - tenured->start;
100 h.code_relocation_base = code.seg->start;
101 h.code_size = heap_size(&code);
104 h.bignum_zero = bignum_zero;
105 h.bignum_pos_one = bignum_pos_one;
106 h.bignum_neg_one = bignum_neg_one;
108 for(cell i = 0; i < USER_ENV; i++)
109 h.userenv[i] = (save_env_p(i) ? userenv[i] : F);
113 if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
114 if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
115 if(fwrite(first_block(&code),h.code_size,1,file) != 1) ok = false;
116 if(fclose(file)) ok = false;
120 print_string("save-image failed: "); print_string(strerror(errno)); nl();
127 inline void factorvm::vmprim_save_image()
129 /* do a full GC to push everything into tenured space */
132 gc_root<byte_array> path(dpop(),this);
133 path.untag_check(this);
134 save_image((vm_char *)(path.untagged() + 1));
137 PRIMITIVE(save_image)
139 PRIMITIVE_GETVM()->vmprim_save_image();
142 inline void factorvm::vmprim_save_image_and_exit()
144 /* We unbox this before doing anything else. This is the only point
145 where we might throw an error, so we have to throw an error here since
146 later steps destroy the current image. */
147 gc_root<byte_array> path(dpop(),this);
148 path.untag_check(this);
150 /* strip out userenv data which is set on startup anyway */
151 for(cell i = 0; i < USER_ENV; i++)
153 if(!save_env_p(i)) userenv[i] = F;
156 /* do a full GC + code heap compaction */
157 performing_compaction = true;
159 performing_compaction = false;
162 if(save_image((vm_char *)(path.untagged() + 1)))
168 PRIMITIVE(save_image_and_exit)
170 PRIMITIVE_GETVM()->vmprim_save_image_and_exit();
173 void factorvm::data_fixup(cell *cell)
175 if(immediate_p(*cell))
178 zone *tenured = &data->generations[data->tenured()];
179 *cell += (tenured->start - data_relocation_base);
182 void data_fixup(cell *cell, factorvm *myvm)
184 return myvm->data_fixup(cell);
187 template <typename TYPE> void factorvm::code_fixup(TYPE **handle)
190 TYPE *new_ptr = (TYPE *)(((cell)ptr) + (code.seg->start - code_relocation_base));
195 void factorvm::fixup_word(word *word)
198 code_fixup(&word->code);
200 code_fixup(&word->profiling);
201 code_fixup(&word->xt);
205 void factorvm::fixup_quotation(quotation *quot)
209 code_fixup("->xt);
210 code_fixup("->code);
213 quot->xt = (void *)lazy_jit_compile;
217 void factorvm::fixup_alien(alien *d)
223 void factorvm::fixup_stack_frame(stack_frame *frame)
225 code_fixup(&frame->xt);
226 code_fixup(&FRAME_RETURN_ADDRESS(frame));
229 void fixup_stack_frame(stack_frame *frame, factorvm *myvm)
231 return myvm->fixup_stack_frame(frame);
234 void factorvm::fixup_callstack_object(callstack *stack)
236 iterate_callstack_object(stack,factor::fixup_stack_frame);
240 /* Initialize an object in a newly-loaded image */
241 void factorvm::relocate_object(object *object)
243 cell hi_tag = object->h.hi_tag();
245 /* Tuple relocation is a bit trickier; we have to fix up the
246 layout object before we can get the tuple size, so do_slots is
247 out of the question */
248 if(hi_tag == TUPLE_TYPE)
250 tuple *t = (tuple *)object;
251 data_fixup(&t->layout);
253 cell *scan = t->data();
254 cell *end = (cell *)((cell)object + untagged_object_size(object));
256 for(; scan < end; scan++)
261 do_slots((cell)object,factor::data_fixup);
266 fixup_word((word *)object);
269 fixup_quotation((quotation *)object);
272 ffi_dlopen((dll *)object);
275 fixup_alien((alien *)object);
278 fixup_callstack_object((callstack *)object);
285 /* Since the image might have been saved with a different base address than
286 where it is loaded, we need to fix up pointers in the image. */
287 void factorvm::relocate_data()
292 for(i = 0; i < USER_ENV; i++)
293 data_fixup(&userenv[i]);
296 data_fixup(&bignum_zero);
297 data_fixup(&bignum_pos_one);
298 data_fixup(&bignum_neg_one);
300 zone *tenured = &data->generations[data->tenured()];
302 for(relocating = tenured->start;
303 relocating < tenured->here;
304 relocating += untagged_object_size((object *)relocating))
306 object *obj = (object *)relocating;
308 relocate_object(obj);
313 void factorvm::fixup_code_block(code_block *compiled)
315 /* relocate literal table data */
316 data_fixup(&compiled->relocation);
317 data_fixup(&compiled->literals);
319 relocate_code_block(compiled);
322 void fixup_code_block(code_block *compiled,factorvm *myvm)
324 return myvm->fixup_code_block(compiled);
327 void factorvm::relocate_code()
329 iterate_code_heap(factor::fixup_code_block);
333 /* Read an image file from disk, only done once during startup */
334 /* This function also initializes the data and code heaps */
335 void factorvm::load_image(vm_parameters *p)
337 FILE *file = OPEN_READ(p->image_path);
340 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
341 print_string(strerror(errno)); nl();
346 if(fread(&h,sizeof(image_header),1,file) != 1)
347 fatal_error("Cannot read image header",0);
349 if(h.magic != image_magic)
350 fatal_error("Bad image: magic number check failed",h.magic);
352 if(h.version != image_version)
353 fatal_error("Bad image: version number check failed",h.version);
355 load_data_heap(file,&h,p);
356 load_code_heap(file,&h,p);
365 /* Store image path name */
366 userenv[IMAGE_ENV] = allot_alien(F,(cell)p->image_path);