3 /* Certain special objects in the image are known to the runtime */
4 void init_objects(F_HEADER
*h
)
6 memcpy(userenv
,h
->userenv
,sizeof(userenv
));
9 bignum_zero
= h
->bignum_zero
;
10 bignum_pos_one
= h
->bignum_pos_one
;
11 bignum_neg_one
= h
->bignum_neg_one
;
13 stage2
= (userenv
[STAGE2_ENV
] != F
);
16 INLINE
void load_data_heap(FILE *file
, F_HEADER
*h
, F_PARAMETERS
*p
)
18 CELL good_size
= h
->data_size
+ (1 << 20);
20 if(good_size
> p
->tenured_size
)
21 p
->tenured_size
= good_size
;
23 init_data_heap(p
->gen_count
,
31 F_ZONE
*tenured
= &data_heap
->generations
[TENURED
];
33 F_FIXNUM bytes_read
= fread((void*)tenured
->start
,1,h
->data_size
,file
);
35 if(bytes_read
!= h
->data_size
)
37 print_string("truncated image: ");
38 print_fixnum(bytes_read
);
39 print_string(" bytes read, ");
40 print_cell(h
->data_size
);
41 print_string(" bytes expected\n");
42 fatal_error("load_data_heap failed",0);
45 tenured
->here
= tenured
->start
+ h
->data_size
;
46 data_relocation_base
= h
->data_relocation_base
;
49 INLINE
void load_code_heap(FILE *file
, F_HEADER
*h
, F_PARAMETERS
*p
)
51 CELL good_size
= h
->code_size
+ (1 << 19);
53 if(good_size
> p
->code_size
)
54 p
->code_size
= good_size
;
56 init_code_heap(p
->code_size
);
60 F_FIXNUM bytes_read
= fread(first_block(&code_heap
),1,h
->code_size
,file
);
61 if(bytes_read
!= h
->code_size
)
63 print_string("truncated image: ");
64 print_fixnum(bytes_read
);
65 print_string(" bytes read, ");
66 print_cell(h
->code_size
);
67 print_string(" bytes expected\n");
68 fatal_error("load_code_heap failed",0);
72 code_relocation_base
= h
->code_relocation_base
;
73 build_free_list(&code_heap
,h
->code_size
);
76 /* Read an image file from disk, only done once during startup */
77 /* This function also initializes the data and code heaps */
78 void load_image(F_PARAMETERS
*p
)
80 FILE *file
= OPEN_READ(p
->image_path
);
83 print_string("Cannot open image file: "); print_native_string(p
->image_path
); nl();
84 print_string(strerror(errno
)); nl();
89 fread(&h
,sizeof(F_HEADER
),1,file
);
91 if(h
.magic
!= IMAGE_MAGIC
)
92 fatal_error("Bad image: magic number check failed",h
.magic
);
94 if(h
.version
!= IMAGE_VERSION
)
95 fatal_error("Bad image: version number check failed",h
.version
);
97 load_data_heap(file
,&h
,p
);
98 load_code_heap(file
,&h
,p
);
107 /* Store image path name */
108 userenv
[IMAGE_ENV
] = tag_object(from_native_string(p
->image_path
));
111 /* Save the current image to disk */
112 bool save_image(const F_CHAR
*filename
)
117 file
= OPEN_WRITE(filename
);
120 print_string("Cannot open image file: "); print_native_string(filename
); nl();
121 print_string(strerror(errno
)); nl();
125 F_ZONE
*tenured
= &data_heap
->generations
[TENURED
];
127 h
.magic
= IMAGE_MAGIC
;
128 h
.version
= IMAGE_VERSION
;
129 h
.data_relocation_base
= tenured
->start
;
130 h
.data_size
= tenured
->here
- tenured
->start
;
131 h
.code_relocation_base
= code_heap
.segment
->start
;
132 h
.code_size
= heap_size(&code_heap
);
135 h
.bignum_zero
= bignum_zero
;
136 h
.bignum_pos_one
= bignum_pos_one
;
137 h
.bignum_neg_one
= bignum_neg_one
;
140 for(i
= 0; i
< USER_ENV
; i
++)
142 if(i
< FIRST_SAVE_ENV
)
145 h
.userenv
[i
] = userenv
[i
];
148 fwrite(&h
,sizeof(F_HEADER
),1,file
);
150 if(fwrite((void*)tenured
->start
,h
.data_size
,1,file
) != 1)
152 print_string("Save data heap failed: "); print_string(strerror(errno
)); nl();
156 if(fwrite(first_block(&code_heap
),h
.code_size
,1,file
) != 1)
158 print_string("Save code heap failed: "); print_string(strerror(errno
)); nl();
164 print_string("Failed to close image file: "); print_string(strerror(errno
)); nl();
171 void primitive_save_image(void)
173 /* do a full GC to push everything into tenured space */
176 save_image(unbox_native_string());
179 void primitive_save_image_and_exit(void)
181 /* We unbox this before doing anything else. This is the only point
182 where we might throw an error, so we have to throw an error here since
183 later steps destroy the current image. */
184 F_CHAR
*path
= unbox_native_string();
186 REGISTER_C_STRING(path
);
188 /* strip out userenv data which is set on startup anyway */
190 for(i
= 0; i
< FIRST_SAVE_ENV
; i
++)
193 for(i
= LAST_SAVE_ENV
+ 1; i
< USER_ENV
; i
++)
196 /* do a full GC + code heap compaction */
199 UNREGISTER_C_STRING(path
);
208 void fixup_word(F_WORD
*word
)
212 code_fixup((CELL
)&word
->code
);
213 if(word
->profiling
) code_fixup((CELL
)&word
->profiling
);
214 code_fixup((CELL
)&word
->xt
);
218 void fixup_quotation(F_QUOTATION
*quot
)
220 if(quot
->compiledp
== F
)
221 quot
->xt
= lazy_jit_compile
;
224 code_fixup((CELL
)"
->xt
);
225 code_fixup((CELL
)"
->code
);
229 void fixup_alien(F_ALIEN
*d
)
234 void fixup_stack_frame(F_STACK_FRAME
*frame
)
236 code_fixup((CELL
)&frame
->xt
);
237 code_fixup((CELL
)&FRAME_RETURN_ADDRESS(frame
));
240 void fixup_callstack_object(F_CALLSTACK
*stack
)
242 iterate_callstack_object(stack
,fixup_stack_frame
);
245 /* Initialize an object in a newly-loaded image */
246 void relocate_object(CELL relocating
)
248 /* Tuple relocation is a bit trickier; we have to fix up the
249 fixup object before we can get the tuple size, so do_slots is
250 out of the question */
251 if(untag_header(get(relocating
)) == TUPLE_TYPE
)
253 data_fixup((CELL
*)relocating
+ 1);
255 CELL scan
= relocating
+ 2 * CELLS
;
256 CELL size
= untagged_object_size(relocating
);
257 CELL end
= relocating
+ size
;
261 data_fixup((CELL
*)scan
);
267 do_slots(relocating
,data_fixup
);
269 switch(untag_header(get(relocating
)))
272 fixup_word((F_WORD
*)relocating
);
275 fixup_quotation((F_QUOTATION
*)relocating
);
278 ffi_dlopen((F_DLL
*)relocating
);
281 fixup_alien((F_ALIEN
*)relocating
);
284 fixup_callstack_object((F_CALLSTACK
*)relocating
);
290 /* Since the image might have been saved with a different base address than
291 where it is loaded, we need to fix up pointers in the image. */
297 for(i
= 0; i
< USER_ENV
; i
++)
298 data_fixup(&userenv
[i
]);
301 data_fixup(&bignum_zero
);
302 data_fixup(&bignum_pos_one
);
303 data_fixup(&bignum_neg_one
);
305 F_ZONE
*tenured
= &data_heap
->generations
[TENURED
];
307 for(relocating
= tenured
->start
;
308 relocating
< tenured
->here
;
309 relocating
+= untagged_object_size(relocating
))
311 allot_barrier(relocating
);
312 relocate_object(relocating
);
316 void fixup_code_block(F_CODE_BLOCK
*compiled
)
318 /* relocate literal table data */
319 data_fixup(&compiled
->relocation
);
320 data_fixup(&compiled
->literals
);
322 relocate_code_block(compiled
);
327 iterate_code_heap(fixup_code_block
);