6 /* Certain special objects in the image are known to the runtime */
7 void factor_vm::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 void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
19 cell good_size = h->data_size + (1 << 20);
21 if(good_size > p->tenured_size)
22 p->tenured_size = good_size;
24 init_data_heap(p->gen_count,
32 zone *tenured = &data->generations[data->tenured()];
34 fixnum bytes_read = fread((void*)tenured->start,1,h->data_size,file);
36 if((cell)bytes_read != h->data_size)
38 print_string("truncated image: ");
39 print_fixnum(bytes_read);
40 print_string(" bytes read, ");
41 print_cell(h->data_size);
42 print_string(" bytes expected\n");
43 fatal_error("load_data_heap failed",0);
46 tenured->here = tenured->start + h->data_size;
47 data_relocation_base = h->data_relocation_base;
50 void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
52 if(h->code_size > p->code_size)
53 fatal_error("Code heap too small to fit image",h->code_size);
55 init_code_heap(p->code_size);
59 size_t bytes_read = fread(first_block(&code),1,h->code_size,file);
60 if(bytes_read != h->code_size)
62 print_string("truncated image: ");
63 print_fixnum(bytes_read);
64 print_string(" bytes read, ");
65 print_cell(h->code_size);
66 print_string(" bytes expected\n");
67 fatal_error("load_code_heap failed",0);
71 code_relocation_base = h->code_relocation_base;
72 build_free_list(&code,h->code_size);
75 /* Save the current image to disk */
76 bool factor_vm::save_image(const vm_char *filename)
81 file = OPEN_WRITE(filename);
84 print_string("Cannot open image file: "); print_native_string(filename); nl();
85 print_string(strerror(errno)); nl();
89 zone *tenured = &data->generations[data->tenured()];
91 h.magic = image_magic;
92 h.version = image_version;
93 h.data_relocation_base = tenured->start;
94 h.data_size = tenured->here - tenured->start;
95 h.code_relocation_base = code.seg->start;
96 h.code_size = heap_size(&code);
99 h.bignum_zero = bignum_zero;
100 h.bignum_pos_one = bignum_pos_one;
101 h.bignum_neg_one = bignum_neg_one;
103 for(cell i = 0; i < USER_ENV; i++)
104 h.userenv[i] = (save_env_p(i) ? userenv[i] : F);
108 if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
109 if(fwrite((void*)tenured->start,h.data_size,1,file) != 1) ok = false;
110 if(fwrite(first_block(&code),h.code_size,1,file) != 1) ok = false;
111 if(fclose(file)) ok = false;
115 print_string("save-image failed: "); print_string(strerror(errno)); nl();
121 inline void factor_vm::primitive_save_image()
123 /* do a full GC to push everything into tenured space */
126 gc_root<byte_array> path(dpop(),this);
127 path.untag_check(this);
128 save_image((vm_char *)(path.untagged() + 1));
131 PRIMITIVE(save_image)
133 PRIMITIVE_GETVM()->primitive_save_image();
136 inline void factor_vm::primitive_save_image_and_exit()
138 /* We unbox this before doing anything else. This is the only point
139 where we might throw an error, so we have to throw an error here since
140 later steps destroy the current image. */
141 gc_root<byte_array> path(dpop(),this);
142 path.untag_check(this);
144 /* strip out userenv data which is set on startup anyway */
145 for(cell i = 0; i < USER_ENV; i++)
147 if(!save_env_p(i)) userenv[i] = F;
150 /* do a full GC + code heap compaction */
151 performing_compaction = true;
153 performing_compaction = false;
156 if(save_image((vm_char *)(path.untagged() + 1)))
162 PRIMITIVE(save_image_and_exit)
164 PRIMITIVE_GETVM()->primitive_save_image_and_exit();
167 void factor_vm::data_fixup(cell *cell)
169 if(immediate_p(*cell))
172 zone *tenured = &data->generations[data->tenured()];
173 *cell += (tenured->start - data_relocation_base);
176 void data_fixup(cell *cell, factor_vm *myvm)
178 return myvm->data_fixup(cell);
181 template <typename TYPE> void factor_vm::code_fixup(TYPE **handle)
184 TYPE *new_ptr = (TYPE *)(((cell)ptr) + (code.seg->start - code_relocation_base));
188 void factor_vm::fixup_word(word *word)
191 code_fixup(&word->code);
193 code_fixup(&word->profiling);
194 code_fixup(&word->xt);
197 void factor_vm::fixup_quotation(quotation *quot)
201 code_fixup("->xt);
202 code_fixup("->code);
205 quot->xt = (void *)lazy_jit_compile;
208 void factor_vm::fixup_alien(alien *d)
213 void factor_vm::fixup_stack_frame(stack_frame *frame)
215 code_fixup(&frame->xt);
216 code_fixup(&FRAME_RETURN_ADDRESS(frame));
219 void fixup_stack_frame(stack_frame *frame, factor_vm *myvm)
221 return myvm->fixup_stack_frame(frame);
224 void factor_vm::fixup_callstack_object(callstack *stack)
226 iterate_callstack_object(stack,factor::fixup_stack_frame);
229 /* Initialize an object in a newly-loaded image */
230 void factor_vm::relocate_object(object *object)
232 cell hi_tag = object->h.hi_tag();
234 /* Tuple relocation is a bit trickier; we have to fix up the
235 layout object before we can get the tuple size, so do_slots is
236 out of the question */
237 if(hi_tag == TUPLE_TYPE)
239 tuple *t = (tuple *)object;
240 data_fixup(&t->layout);
242 cell *scan = t->data();
243 cell *end = (cell *)((cell)object + untagged_object_size(object));
245 for(; scan < end; scan++)
250 do_slots((cell)object,factor::data_fixup);
255 fixup_word((word *)object);
258 fixup_quotation((quotation *)object);
261 ffi_dlopen((dll *)object);
264 fixup_alien((alien *)object);
267 fixup_callstack_object((callstack *)object);
273 /* Since the image might have been saved with a different base address than
274 where it is loaded, we need to fix up pointers in the image. */
275 void factor_vm::relocate_data()
280 for(i = 0; i < USER_ENV; i++)
281 data_fixup(&userenv[i]);
284 data_fixup(&bignum_zero);
285 data_fixup(&bignum_pos_one);
286 data_fixup(&bignum_neg_one);
288 zone *tenured = &data->generations[data->tenured()];
290 for(relocating = tenured->start;
291 relocating < tenured->here;
292 relocating += untagged_object_size((object *)relocating))
294 object *obj = (object *)relocating;
296 relocate_object(obj);
300 void factor_vm::fixup_code_block(code_block *compiled)
302 /* relocate literal table data */
303 data_fixup(&compiled->relocation);
304 data_fixup(&compiled->literals);
306 relocate_code_block(compiled);
309 void fixup_code_block(code_block *compiled, factor_vm *myvm)
311 return myvm->fixup_code_block(compiled);
314 void factor_vm::relocate_code()
316 iterate_code_heap(factor::fixup_code_block);
319 /* Read an image file from disk, only done once during startup */
320 /* This function also initializes the data and code heaps */
321 void factor_vm::load_image(vm_parameters *p)
323 FILE *file = OPEN_READ(p->image_path);
326 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
327 print_string(strerror(errno)); nl();
332 if(fread(&h,sizeof(image_header),1,file) != 1)
333 fatal_error("Cannot read image header",0);
335 if(h.magic != image_magic)
336 fatal_error("Bad image: magic number check failed",h.magic);
338 if(h.version != image_version)
339 fatal_error("Bad image: version number check failed",h.version);
341 load_data_heap(file,&h,p);
342 load_code_heap(file,&h,p);
351 /* Store image path name */
352 userenv[IMAGE_ENV] = allot_alien(F,(cell)p->image_path);