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(code->first_block(),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 code->build_free_list(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 = code->heap_size();
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(code->first_block(),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_FORWARD(save_image)
133 inline void factor_vm::primitive_save_image_and_exit()
135 /* We unbox this before doing anything else. This is the only point
136 where we might throw an error, so we have to throw an error here since
137 later steps destroy the current image. */
138 gc_root<byte_array> path(dpop(),this);
139 path.untag_check(this);
141 /* strip out userenv data which is set on startup anyway */
142 for(cell i = 0; i < USER_ENV; i++)
144 if(!save_env_p(i)) userenv[i] = F;
147 /* do a full GC + code heap compaction */
148 performing_compaction = true;
150 performing_compaction = false;
153 if(save_image((vm_char *)(path.untagged() + 1)))
159 PRIMITIVE_FORWARD(save_image_and_exit)
161 void factor_vm::data_fixup(cell *cell)
163 if(immediate_p(*cell))
166 zone *tenured = &data->generations[data->tenured()];
167 *cell += (tenured->start - data_relocation_base);
170 void data_fixup(cell *cell, factor_vm *myvm)
172 return myvm->data_fixup(cell);
175 template <typename TYPE> void factor_vm::code_fixup(TYPE **handle)
178 TYPE *new_ptr = (TYPE *)(((cell)ptr) + (code->seg->start - code_relocation_base));
182 void factor_vm::fixup_word(word *word)
185 code_fixup(&word->code);
187 code_fixup(&word->profiling);
188 code_fixup(&word->xt);
191 void factor_vm::fixup_quotation(quotation *quot)
195 code_fixup("->xt);
196 code_fixup("->code);
199 quot->xt = (void *)lazy_jit_compile;
202 void factor_vm::fixup_alien(alien *d)
207 void factor_vm::fixup_stack_frame(stack_frame *frame)
209 code_fixup(&frame->xt);
210 code_fixup(&FRAME_RETURN_ADDRESS(frame));
213 void fixup_stack_frame(stack_frame *frame, factor_vm *myvm)
215 return myvm->fixup_stack_frame(frame);
218 void factor_vm::fixup_callstack_object(callstack *stack)
220 iterate_callstack_object(stack,factor::fixup_stack_frame);
223 /* Initialize an object in a newly-loaded image */
224 void factor_vm::relocate_object(object *object)
226 cell hi_tag = object->h.hi_tag();
228 /* Tuple relocation is a bit trickier; we have to fix up the
229 layout object before we can get the tuple size, so do_slots is
230 out of the question */
231 if(hi_tag == TUPLE_TYPE)
233 tuple *t = (tuple *)object;
234 data_fixup(&t->layout);
236 cell *scan = t->data();
237 cell *end = (cell *)((cell)object + untagged_object_size(object));
239 for(; scan < end; scan++)
244 do_slots((cell)object,factor::data_fixup);
249 fixup_word((word *)object);
252 fixup_quotation((quotation *)object);
255 ffi_dlopen((dll *)object);
258 fixup_alien((alien *)object);
261 fixup_callstack_object((callstack *)object);
267 /* Since the image might have been saved with a different base address than
268 where it is loaded, we need to fix up pointers in the image. */
269 void factor_vm::relocate_data()
274 for(i = 0; i < USER_ENV; i++)
275 data_fixup(&userenv[i]);
278 data_fixup(&bignum_zero);
279 data_fixup(&bignum_pos_one);
280 data_fixup(&bignum_neg_one);
282 zone *tenured = &data->generations[data->tenured()];
284 for(relocating = tenured->start;
285 relocating < tenured->here;
286 relocating += untagged_object_size((object *)relocating))
288 object *obj = (object *)relocating;
290 relocate_object(obj);
294 void factor_vm::fixup_code_block(code_block *compiled)
296 /* relocate literal table data */
297 data_fixup(&compiled->relocation);
298 data_fixup(&compiled->literals);
300 relocate_code_block(compiled);
303 void fixup_code_block(code_block *compiled, factor_vm *myvm)
305 return myvm->fixup_code_block(compiled);
308 void factor_vm::relocate_code()
310 iterate_code_heap(factor::fixup_code_block);
313 /* Read an image file from disk, only done once during startup */
314 /* This function also initializes the data and code heaps */
315 void factor_vm::load_image(vm_parameters *p)
317 FILE *file = OPEN_READ(p->image_path);
320 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
321 print_string(strerror(errno)); nl();
326 if(fread(&h,sizeof(image_header),1,file) != 1)
327 fatal_error("Cannot read image header",0);
329 if(h.magic != image_magic)
330 fatal_error("Bad image: magic number check failed",h.magic);
332 if(h.version != image_version)
333 fatal_error("Bad image: version number check failed",h.version);
335 load_data_heap(file,&h,p);
336 load_code_heap(file,&h,p);
345 /* Store image path name */
346 userenv[IMAGE_ENV] = allot_alien(F,(cell)p->image_path);