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 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 void factor_vm::primitive_save_image_and_exit()
133 /* We unbox this before doing anything else. This is the only point
134 where we might throw an error, so we have to throw an error here since
135 later steps destroy the current image. */
136 gc_root<byte_array> path(dpop(),this);
137 path.untag_check(this);
139 /* strip out userenv data which is set on startup anyway */
140 for(cell i = 0; i < USER_ENV; i++)
142 if(!save_env_p(i)) userenv[i] = F;
145 /* do a full GC + code heap compaction */
146 performing_compaction = true;
148 performing_compaction = false;
151 if(save_image((vm_char *)(path.untagged() + 1)))
157 void factor_vm::data_fixup(cell *cell)
159 if(immediate_p(*cell))
162 zone *tenured = &data->generations[data->tenured()];
163 *cell += (tenured->start - data_relocation_base);
166 void data_fixup(cell *cell, factor_vm *myvm)
168 return myvm->data_fixup(cell);
171 template <typename TYPE> void factor_vm::code_fixup(TYPE **handle)
174 TYPE *new_ptr = (TYPE *)(((cell)ptr) + (code->seg->start - code_relocation_base));
178 void factor_vm::fixup_word(word *word)
181 code_fixup(&word->code);
183 code_fixup(&word->profiling);
184 code_fixup(&word->xt);
187 void factor_vm::fixup_quotation(quotation *quot)
191 code_fixup("->xt);
192 code_fixup("->code);
195 quot->xt = (void *)lazy_jit_compile;
198 void factor_vm::fixup_alien(alien *d)
203 void factor_vm::fixup_stack_frame(stack_frame *frame)
205 code_fixup(&frame->xt);
206 code_fixup(&FRAME_RETURN_ADDRESS(frame));
209 void fixup_stack_frame(stack_frame *frame, factor_vm *myvm)
211 return myvm->fixup_stack_frame(frame);
214 void factor_vm::fixup_callstack_object(callstack *stack)
216 iterate_callstack_object(stack,factor::fixup_stack_frame);
219 /* Initialize an object in a newly-loaded image */
220 void factor_vm::relocate_object(object *object)
222 cell hi_tag = object->h.hi_tag();
224 /* Tuple relocation is a bit trickier; we have to fix up the
225 layout object before we can get the tuple size, so do_slots is
226 out of the question */
227 if(hi_tag == TUPLE_TYPE)
229 tuple *t = (tuple *)object;
230 data_fixup(&t->layout);
232 cell *scan = t->data();
233 cell *end = (cell *)((cell)object + untagged_object_size(object));
235 for(; scan < end; scan++)
240 do_slots((cell)object,factor::data_fixup);
245 fixup_word((word *)object);
248 fixup_quotation((quotation *)object);
251 ffi_dlopen((dll *)object);
254 fixup_alien((alien *)object);
257 fixup_callstack_object((callstack *)object);
263 /* Since the image might have been saved with a different base address than
264 where it is loaded, we need to fix up pointers in the image. */
265 void factor_vm::relocate_data()
270 for(i = 0; i < USER_ENV; i++)
271 data_fixup(&userenv[i]);
274 data_fixup(&bignum_zero);
275 data_fixup(&bignum_pos_one);
276 data_fixup(&bignum_neg_one);
278 zone *tenured = &data->generations[data->tenured()];
280 for(relocating = tenured->start;
281 relocating < tenured->here;
282 relocating += untagged_object_size((object *)relocating))
284 object *obj = (object *)relocating;
286 relocate_object(obj);
290 void factor_vm::fixup_code_block(code_block *compiled)
292 /* relocate literal table data */
293 data_fixup(&compiled->relocation);
294 data_fixup(&compiled->literals);
296 relocate_code_block(compiled);
299 void fixup_code_block(code_block *compiled, factor_vm *myvm)
301 return myvm->fixup_code_block(compiled);
304 void factor_vm::relocate_code()
306 iterate_code_heap(factor::fixup_code_block);
309 /* Read an image file from disk, only done once during startup */
310 /* This function also initializes the data and code heaps */
311 void factor_vm::load_image(vm_parameters *p)
313 FILE *file = OPEN_READ(p->image_path);
316 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
317 print_string(strerror(errno)); nl();
322 if(fread(&h,sizeof(image_header),1,file) != 1)
323 fatal_error("Cannot read image header",0);
325 if(h.magic != image_magic)
326 fatal_error("Bad image: magic number check failed",h.magic);
328 if(h.version != image_version)
329 fatal_error("Bad image: version number check failed",h.version);
331 load_data_heap(file,&h,p);
332 load_code_heap(file,&h,p);
341 /* Store image path name */
342 userenv[IMAGE_ENV] = allot_alien(F,(cell)p->image_path);