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->young_size,
31 fixnum bytes_read = fread((void*)data->tenured->start,1,h->data_size,file);
33 if((cell)bytes_read != h->data_size)
35 print_string("truncated image: ");
36 print_fixnum(bytes_read);
37 print_string(" bytes read, ");
38 print_cell(h->data_size);
39 print_string(" bytes expected\n");
40 fatal_error("load_data_heap failed",0);
43 data->tenured->here = data->tenured->start + h->data_size;
46 void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
48 if(h->code_size > p->code_size)
49 fatal_error("Code heap too small to fit image",h->code_size);
51 init_code_heap(p->code_size);
55 size_t bytes_read = fread(code->first_block(),1,h->code_size,file);
56 if(bytes_read != h->code_size)
58 print_string("truncated image: ");
59 print_fixnum(bytes_read);
60 print_string(" bytes read, ");
61 print_cell(h->code_size);
62 print_string(" bytes expected\n");
63 fatal_error("load_code_heap failed",0);
67 code->build_free_list(h->code_size);
70 /* Save the current image to disk */
71 bool factor_vm::save_image(const vm_char *filename)
76 file = OPEN_WRITE(filename);
79 print_string("Cannot open image file: "); print_native_string(filename); nl();
80 print_string(strerror(errno)); nl();
84 h.magic = image_magic;
85 h.version = image_version;
86 h.data_relocation_base = data->tenured->start;
87 h.data_size = data->tenured->here - data->tenured->start;
88 h.code_relocation_base = code->seg->start;
89 h.code_size = code->heap_size();
92 h.bignum_zero = bignum_zero;
93 h.bignum_pos_one = bignum_pos_one;
94 h.bignum_neg_one = bignum_neg_one;
96 for(cell i = 0; i < USER_ENV; i++)
97 h.userenv[i] = (save_env_p(i) ? userenv[i] : F);
101 if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
102 if(fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false;
103 if(fwrite(code->first_block(),h.code_size,1,file) != 1) ok = false;
104 if(fclose(file)) ok = false;
108 print_string("save-image failed: "); print_string(strerror(errno)); nl();
114 void factor_vm::primitive_save_image()
116 /* do a full GC to push everything into tenured space */
117 primitive_compact_gc();
119 gc_root<byte_array> path(dpop(),this);
120 path.untag_check(this);
121 save_image((vm_char *)(path.untagged() + 1));
124 void factor_vm::primitive_save_image_and_exit()
126 /* We unbox this before doing anything else. This is the only point
127 where we might throw an error, so we have to throw an error here since
128 later steps destroy the current image. */
129 gc_root<byte_array> path(dpop(),this);
130 path.untag_check(this);
132 /* strip out userenv data which is set on startup anyway */
133 for(cell i = 0; i < USER_ENV; i++)
135 if(!save_env_p(i)) userenv[i] = F;
139 0, /* requested size */
140 false, /* discard objects only reachable from stacks */
141 true /* compact the code heap */);
144 if(save_image((vm_char *)(path.untagged() + 1)))
150 void factor_vm::data_fixup(cell *handle, cell data_relocation_base)
152 if(immediate_p(*handle))
155 *handle += (data->tenured->start - data_relocation_base);
158 template<typename Type> void factor_vm::code_fixup(Type **handle, cell code_relocation_base)
161 Type *new_ptr = (Type *)(((cell)ptr) + (code->seg->start - code_relocation_base));
165 void factor_vm::fixup_word(word *word, cell code_relocation_base)
168 code_fixup(&word->code,code_relocation_base);
170 code_fixup(&word->profiling,code_relocation_base);
171 code_fixup(&word->xt,code_relocation_base);
174 void factor_vm::fixup_quotation(quotation *quot, cell code_relocation_base)
178 code_fixup("->xt,code_relocation_base);
179 code_fixup("->code,code_relocation_base);
182 quot->xt = (void *)lazy_jit_compile;
185 void factor_vm::fixup_alien(alien *d)
187 if(d->base == F) d->expired = T;
190 struct stack_frame_fixupper {
192 cell code_relocation_base;
194 explicit stack_frame_fixupper(factor_vm *myvm_, cell code_relocation_base_) :
195 myvm(myvm_), code_relocation_base(code_relocation_base_) {}
196 void operator()(stack_frame *frame)
198 myvm->code_fixup(&frame->xt,code_relocation_base);
199 myvm->code_fixup(&FRAME_RETURN_ADDRESS(frame,myvm),code_relocation_base);
203 void factor_vm::fixup_callstack_object(callstack *stack, cell code_relocation_base)
205 stack_frame_fixupper fixupper(this,code_relocation_base);
206 iterate_callstack_object(stack,fixupper);
209 struct object_fixupper {
211 cell data_relocation_base;
213 explicit object_fixupper(factor_vm *myvm_, cell data_relocation_base_) :
214 myvm(myvm_), data_relocation_base(data_relocation_base_) { }
216 void operator()(cell *scan)
218 myvm->data_fixup(scan,data_relocation_base);
222 /* Initialize an object in a newly-loaded image */
223 void factor_vm::relocate_object(object *object,
224 cell data_relocation_base,
225 cell code_relocation_base)
227 cell hi_tag = object->h.hi_tag();
229 /* Tuple relocation is a bit trickier; we have to fix up the
230 layout object before we can get the tuple size, so do_slots is
231 out of the question */
232 if(hi_tag == TUPLE_TYPE)
234 tuple *t = (tuple *)object;
235 data_fixup(&t->layout,data_relocation_base);
237 cell *scan = t->data();
238 cell *end = (cell *)((cell)object + untagged_object_size(object));
240 for(; scan < end; scan++)
241 data_fixup(scan,data_relocation_base);
245 object_fixupper fixupper(this,data_relocation_base);
246 do_slots((cell)object,fixupper);
251 fixup_word((word *)object,code_relocation_base);
254 fixup_quotation((quotation *)object,code_relocation_base);
257 ffi_dlopen((dll *)object);
260 fixup_alien((alien *)object);
263 fixup_callstack_object((callstack *)object,code_relocation_base);
269 /* Since the image might have been saved with a different base address than
270 where it is loaded, we need to fix up pointers in the image. */
271 void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_base)
273 for(cell i = 0; i < USER_ENV; i++)
274 data_fixup(&userenv[i],data_relocation_base);
276 data_fixup(&T,data_relocation_base);
277 data_fixup(&bignum_zero,data_relocation_base);
278 data_fixup(&bignum_pos_one,data_relocation_base);
279 data_fixup(&bignum_neg_one,data_relocation_base);
281 cell obj = data->tenured->start;
285 relocate_object((object *)obj,data_relocation_base,code_relocation_base);
286 data->tenured->record_object_start_offset((object *)obj);
287 obj = data->tenured->next_object_after(this,obj);
291 void factor_vm::fixup_code_block(code_block *compiled, cell data_relocation_base)
293 /* relocate literal table data */
294 data_fixup(&compiled->owner,data_relocation_base);
295 data_fixup(&compiled->literals,data_relocation_base);
296 data_fixup(&compiled->relocation,data_relocation_base);
298 relocate_code_block(compiled);
301 struct code_block_fixupper {
303 cell data_relocation_base;
305 code_block_fixupper(factor_vm *myvm_, cell data_relocation_base_) :
306 myvm(myvm_), data_relocation_base(data_relocation_base_) { }
308 void operator()(code_block *compiled)
310 myvm->fixup_code_block(compiled,data_relocation_base);
314 void factor_vm::relocate_code(cell data_relocation_base)
316 code_block_fixupper fixupper(this,data_relocation_base);
317 iterate_code_heap(fixupper);
320 /* Read an image file from disk, only done once during startup */
321 /* This function also initializes the data and code heaps */
322 void factor_vm::load_image(vm_parameters *p)
324 FILE *file = OPEN_READ(p->image_path);
327 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
328 print_string(strerror(errno)); nl();
333 if(fread(&h,sizeof(image_header),1,file) != 1)
334 fatal_error("Cannot read image header",0);
336 if(h.magic != image_magic)
337 fatal_error("Bad image: magic number check failed",h.magic);
339 if(h.version != image_version)
340 fatal_error("Bad image: version number check failed",h.version);
342 load_data_heap(file,&h,p);
343 load_code_heap(file,&h,p);
349 relocate_data(h.data_relocation_base,h.code_relocation_base);
350 relocate_code(h.data_relocation_base);
352 /* Store image path name */
353 userenv[IMAGE_ENV] = allot_alien(F,(cell)p->image_path);