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));
11 true_object = h->true_object;
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 void factor_vm::data_fixup(cell *handle, cell data_relocation_base)
72 if(immediate_p(*handle))
75 *handle += (data->tenured->start - data_relocation_base);
78 template<typename Type> void factor_vm::code_fixup(Type **handle, cell code_relocation_base)
81 Type *new_ptr = (Type *)(((cell)ptr) + (code->seg->start - code_relocation_base));
85 void factor_vm::fixup_word(word *word, cell code_relocation_base)
88 code_fixup(&word->code,code_relocation_base);
90 code_fixup(&word->profiling,code_relocation_base);
91 code_fixup(&word->xt,code_relocation_base);
94 void factor_vm::fixup_quotation(quotation *quot, cell code_relocation_base)
98 code_fixup("->xt,code_relocation_base);
99 code_fixup("->code,code_relocation_base);
102 quot->xt = (void *)lazy_jit_compile;
105 void factor_vm::fixup_alien(alien *d)
107 if(!to_boolean(d->base)) d->expired = true_object;
110 struct stack_frame_fixupper {
112 cell code_relocation_base;
114 explicit stack_frame_fixupper(factor_vm *parent_, cell code_relocation_base_) :
115 parent(parent_), code_relocation_base(code_relocation_base_) {}
116 void operator()(stack_frame *frame)
118 parent->code_fixup(&frame->xt,code_relocation_base);
119 parent->code_fixup(&FRAME_RETURN_ADDRESS(frame,parent),code_relocation_base);
123 void factor_vm::fixup_callstack_object(callstack *stack, cell code_relocation_base)
125 stack_frame_fixupper fixupper(this,code_relocation_base);
126 iterate_callstack_object(stack,fixupper);
129 struct object_fixupper {
131 cell data_relocation_base;
133 explicit object_fixupper(factor_vm *parent_, cell data_relocation_base_) :
134 parent(parent_), data_relocation_base(data_relocation_base_) { }
136 void operator()(cell *scan)
138 parent->data_fixup(scan,data_relocation_base);
142 /* Initialize an object in a newly-loaded image */
143 void factor_vm::relocate_object(object *object,
144 cell data_relocation_base,
145 cell code_relocation_base)
147 cell hi_tag = object->h.hi_tag();
149 /* Tuple relocation is a bit trickier; we have to fix up the
150 layout object before we can get the tuple size, so do_slots is
151 out of the question */
152 if(hi_tag == TUPLE_TYPE)
154 tuple *t = (tuple *)object;
155 data_fixup(&t->layout,data_relocation_base);
157 cell *scan = t->data();
158 cell *end = (cell *)((cell)object + untagged_object_size(object));
160 for(; scan < end; scan++)
161 data_fixup(scan,data_relocation_base);
165 object_fixupper fixupper(this,data_relocation_base);
166 do_slots((cell)object,fixupper);
171 fixup_word((word *)object,code_relocation_base);
174 fixup_quotation((quotation *)object,code_relocation_base);
177 ffi_dlopen((dll *)object);
180 fixup_alien((alien *)object);
183 fixup_callstack_object((callstack *)object,code_relocation_base);
189 /* Since the image might have been saved with a different base address than
190 where it is loaded, we need to fix up pointers in the image. */
191 void factor_vm::relocate_data(cell data_relocation_base, cell code_relocation_base)
193 for(cell i = 0; i < USER_ENV; i++)
194 data_fixup(&userenv[i],data_relocation_base);
196 data_fixup(&true_object,data_relocation_base);
197 data_fixup(&bignum_zero,data_relocation_base);
198 data_fixup(&bignum_pos_one,data_relocation_base);
199 data_fixup(&bignum_neg_one,data_relocation_base);
201 cell obj = data->tenured->start;
205 relocate_object((object *)obj,data_relocation_base,code_relocation_base);
206 data->tenured->record_object_start_offset((object *)obj);
207 obj = data->tenured->next_object_after(this,obj);
211 void factor_vm::fixup_code_block(code_block *compiled, cell data_relocation_base)
213 /* relocate literal table data */
214 data_fixup(&compiled->owner,data_relocation_base);
215 data_fixup(&compiled->literals,data_relocation_base);
216 data_fixup(&compiled->relocation,data_relocation_base);
218 relocate_code_block(compiled);
221 struct code_block_fixupper {
223 cell data_relocation_base;
225 code_block_fixupper(factor_vm *parent_, cell data_relocation_base_) :
226 parent(parent_), data_relocation_base(data_relocation_base_) { }
228 void operator()(code_block *compiled)
230 parent->fixup_code_block(compiled,data_relocation_base);
234 void factor_vm::relocate_code(cell data_relocation_base)
236 code_block_fixupper fixupper(this,data_relocation_base);
237 iterate_code_heap(fixupper);
240 /* Read an image file from disk, only done once during startup */
241 /* This function also initializes the data and code heaps */
242 void factor_vm::load_image(vm_parameters *p)
244 FILE *file = OPEN_READ(p->image_path);
247 print_string("Cannot open image file: "); print_native_string(p->image_path); nl();
248 print_string(strerror(errno)); nl();
253 if(fread(&h,sizeof(image_header),1,file) != 1)
254 fatal_error("Cannot read image header",0);
256 if(h.magic != image_magic)
257 fatal_error("Bad image: magic number check failed",h.magic);
259 if(h.version != image_version)
260 fatal_error("Bad image: version number check failed",h.version);
262 load_data_heap(file,&h,p);
263 load_code_heap(file,&h,p);
269 relocate_data(h.data_relocation_base,h.code_relocation_base);
270 relocate_code(h.data_relocation_base);
272 /* Store image path name */
273 userenv[IMAGE_ENV] = allot_alien(false_object,(cell)p->image_path);
276 /* Save the current image to disk */
277 bool factor_vm::save_image(const vm_char *filename)
282 file = OPEN_WRITE(filename);
285 print_string("Cannot open image file: "); print_native_string(filename); nl();
286 print_string(strerror(errno)); nl();
290 h.magic = image_magic;
291 h.version = image_version;
292 h.data_relocation_base = data->tenured->start;
293 h.data_size = data->tenured->here - data->tenured->start;
294 h.code_relocation_base = code->seg->start;
295 h.code_size = code->heap_size();
297 h.true_object = true_object;
298 h.bignum_zero = bignum_zero;
299 h.bignum_pos_one = bignum_pos_one;
300 h.bignum_neg_one = bignum_neg_one;
302 for(cell i = 0; i < USER_ENV; i++)
303 h.userenv[i] = (save_env_p(i) ? userenv[i] : false_object);
307 if(fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
308 if(fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false;
309 if(fwrite(code->first_block(),h.code_size,1,file) != 1) ok = false;
310 if(fclose(file)) ok = false;
314 print_string("save-image failed: "); print_string(strerror(errno)); nl();
320 void factor_vm::primitive_save_image()
322 /* do a full GC to push everything into tenured space */
323 primitive_compact_gc();
325 gc_root<byte_array> path(dpop(),this);
326 path.untag_check(this);
327 save_image((vm_char *)(path.untagged() + 1));
330 void factor_vm::primitive_save_image_and_exit()
332 /* We unbox this before doing anything else. This is the only point
333 where we might throw an error, so we have to throw an error here since
334 later steps destroy the current image. */
335 gc_root<byte_array> path(dpop(),this);
336 path.untag_check(this);
338 /* strip out userenv data which is set on startup anyway */
339 for(cell i = 0; i < USER_ENV; i++)
340 if(!save_env_p(i)) userenv[i] = false_object;
343 0, /* requested size */
344 false, /* discard objects only reachable from stacks */
345 true /* compact the code heap */);
348 if(save_image((vm_char *)(path.untagged() + 1)))