| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | #include "master.hpp"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | namespace factor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Certain special objects in the image are known to the runtime */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void factor_vm::init_objects(image_header *h) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-23 01:33:53 -04:00
										 |  |  | 	memcpy(special_objects,h->special_objects,sizeof(special_objects)); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-18 21:26:21 -04:00
										 |  |  | 	true_object = h->true_object; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	bignum_zero = h->bignum_zero; | 
					
						
							|  |  |  | 	bignum_pos_one = h->bignum_pos_one; | 
					
						
							|  |  |  | 	bignum_neg_one = h->bignum_neg_one; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-10-25 14:27:40 -04:00
										 |  |  | 	p->tenured_size = std::max((h->data_size * 3) / 2,p->tenured_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-06 03:39:12 -04:00
										 |  |  | 	init_data_heap(p->young_size, | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		p->aging_size, | 
					
						
							| 
									
										
										
										
											2009-11-01 04:47:09 -05:00
										 |  |  | 		p->tenured_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 15:01:11 -05:00
										 |  |  | 	fixnum bytes_read = safe_fread((void*)data->tenured->start,1,h->data_size,file); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	if((cell)bytes_read != h->data_size) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-21 21:12:57 -04:00
										 |  |  | 		std::cout << "truncated image: " << bytes_read << " bytes read, "; | 
					
						
							|  |  |  | 		std::cout << h->data_size << " bytes expected\n"; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		fatal_error("load_data_heap failed",0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-22 00:24:35 -04:00
										 |  |  | 	data->tenured->initial_free_list(h->data_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-08-01 00:23:29 -04:00
										 |  |  | 	if(h->code_size > p->code_size) | 
					
						
							|  |  |  | 		fatal_error("Code heap too small to fit image",h->code_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	init_code_heap(p->code_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(h->code_size != 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-01-19 15:01:11 -05:00
										 |  |  | 		size_t bytes_read = safe_fread(code->allocator->first_block(),1,h->code_size,file); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		if(bytes_read != h->code_size) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-10-21 21:12:57 -04:00
										 |  |  | 			std::cout << "truncated image: " << bytes_read << " bytes read, "; | 
					
						
							|  |  |  | 			std::cout << h->code_size << " bytes expected\n"; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 			fatal_error("load_code_heap failed",0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-22 00:24:35 -04:00
										 |  |  | 	code->allocator->initial_free_list(h->code_size); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | struct data_fixupper { | 
					
						
							|  |  |  | 	cell offset; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	explicit data_fixupper(cell offset_) : offset(offset_) {} | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	object *operator()(object *obj) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return (object *)((char *)obj + offset); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | struct code_fixupper { | 
					
						
							|  |  |  | 	cell offset; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	explicit code_fixupper(cell offset_) : offset(offset_) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	code_block *operator()(code_block *compiled) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		return (code_block *)((char *)compiled + offset); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | static inline cell tuple_size_with_fixup(cell offset, object *obj) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	tuple_layout *layout = (tuple_layout *)((char *)UNTAG(((tuple *)obj)->layout) + offset); | 
					
						
							|  |  |  | 	return tuple_size(layout); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | struct fixup_sizer { | 
					
						
							|  |  |  | 	cell offset; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	explicit fixup_sizer(cell offset_) : offset(offset_) {} | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	cell operator()(object *obj) | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		if(obj->type() == TUPLE_TYPE) | 
					
						
							|  |  |  | 			return align(tuple_size_with_fixup(offset,obj),data_alignment); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			return obj->size(); | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | struct object_fixupper { | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	cell data_offset; | 
					
						
							|  |  |  | 	slot_visitor<data_fixupper> data_visitor; | 
					
						
							|  |  |  | 	code_block_visitor<code_fixupper> code_visitor; | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	object_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) : | 
					
						
							|  |  |  | 		parent(parent_), | 
					
						
							|  |  |  | 		data_offset(data_offset_), | 
					
						
							|  |  |  | 		data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))), | 
					
						
							|  |  |  | 		code_visitor(code_block_visitor<code_fixupper>(parent_,code_fixupper(code_offset_))) {} | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	void operator()(object *obj, cell size) | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		parent->data->tenured->starts.record_object_start_offset(obj); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch(obj->type()) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		case ALIEN_TYPE: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				cell payload_start = obj->binary_payload_start(); | 
					
						
							|  |  |  | 				data_visitor.visit_slots(obj,payload_start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				alien *ptr = (alien *)obj; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 				if(to_boolean(ptr->base)) | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 					ptr->update_address(); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 				else | 
					
						
							|  |  |  | 					ptr->expired = parent->true_object; | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case DLL_TYPE: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				cell payload_start = obj->binary_payload_start(); | 
					
						
							|  |  |  | 				data_visitor.visit_slots(obj,payload_start); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				parent->ffi_dlopen((dll *)obj); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		case TUPLE_TYPE: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				cell payload_start = tuple_size_with_fixup(data_offset,obj); | 
					
						
							|  |  |  | 				data_visitor.visit_slots(obj,payload_start); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				cell payload_start = obj->binary_payload_start(); | 
					
						
							|  |  |  | 				data_visitor.visit_slots(obj,payload_start); | 
					
						
							|  |  |  | 				code_visitor.visit_object_code_block(obj); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | void factor_vm::fixup_data(cell data_offset, cell code_offset) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	slot_visitor<data_fixupper> data_workhorse(this,data_fixupper(data_offset)); | 
					
						
							|  |  |  | 	data_workhorse.visit_roots(); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	object_fixupper fixupper(this,data_offset,code_offset); | 
					
						
							|  |  |  | 	fixup_sizer sizer(data_offset); | 
					
						
							|  |  |  | 	data->tenured->iterate(fixupper,sizer); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | struct code_block_fixup_relocation_visitor { | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	factor_vm *parent; | 
					
						
							|  |  |  | 	cell code_offset; | 
					
						
							|  |  |  | 	slot_visitor<data_fixupper> data_visitor; | 
					
						
							|  |  |  | 	code_fixupper code_visitor; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 	code_block_fixup_relocation_visitor(factor_vm *parent_, cell data_offset_, cell code_offset_) : | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		parent(parent_), | 
					
						
							|  |  |  | 		code_offset(code_offset_), | 
					
						
							|  |  |  | 		data_visitor(slot_visitor<data_fixupper>(parent_,data_fixupper(data_offset_))), | 
					
						
							|  |  |  | 		code_visitor(code_fixupper(code_offset_)) {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 	void operator()(instruction_operand op) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		code_block *compiled = op.parent_code_block(); | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		cell old_offset = op.rel_offset() + (cell)compiled->entry_point() - code_offset; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		switch(op.rel_type()) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2009-12-15 07:20:09 -05:00
										 |  |  | 		case RT_LITERAL: | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 			op.store_value(data_visitor.visit_pointer(op.load_value(old_offset))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2010-01-18 02:51:27 -05:00
										 |  |  | 		case RT_ENTRY_POINT: | 
					
						
							|  |  |  | 		case RT_ENTRY_POINT_PIC: | 
					
						
							|  |  |  | 		case RT_ENTRY_POINT_PIC_TAIL: | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 			op.store_code_block(code_visitor(op.load_code_block(old_offset))); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-12-02 05:55:48 -05:00
										 |  |  | 		case RT_HERE: | 
					
						
							|  |  |  | 			op.store_value(op.load_value(old_offset) + code_offset); | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-12-02 05:28:15 -05:00
										 |  |  | 		case RT_UNTAGGED: | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		default: | 
					
						
							| 
									
										
										
										
											2009-12-02 02:09:08 -05:00
										 |  |  | 			parent->store_external_address(op); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | struct code_block_fixupper { | 
					
						
							| 
									
										
										
										
											2009-10-18 21:31:59 -04:00
										 |  |  | 	factor_vm *parent; | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	cell data_offset; | 
					
						
							|  |  |  | 	cell code_offset; | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	code_block_fixupper(factor_vm *parent_, cell data_offset_, cell code_offset_) : | 
					
						
							|  |  |  | 		parent(parent_), | 
					
						
							|  |  |  | 		data_offset(data_offset_), | 
					
						
							|  |  |  | 		code_offset(code_offset_) {} | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-19 04:05:20 -04:00
										 |  |  | 	void operator()(code_block *compiled, cell size) | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 		slot_visitor<data_fixupper> data_visitor(parent,data_fixupper(data_offset)); | 
					
						
							|  |  |  | 		data_visitor.visit_code_block_objects(compiled); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-28 20:48:26 -05:00
										 |  |  | 		code_block_fixup_relocation_visitor code_visitor(parent,data_offset,code_offset); | 
					
						
							| 
									
										
										
										
											2009-12-02 01:48:41 -05:00
										 |  |  | 		compiled->each_instruction_operand(code_visitor); | 
					
						
							| 
									
										
										
										
											2009-10-03 09:47:05 -04:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | void factor_vm::fixup_code(cell data_offset, cell code_offset) | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:08 -04:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	code_block_fixupper fixupper(this,data_offset,code_offset); | 
					
						
							|  |  |  | 	code->allocator->iterate(fixupper); | 
					
						
							| 
									
										
										
										
											2009-08-17 16:37:08 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | /* Read an image file from disk, only done once during startup */ | 
					
						
							|  |  |  | /* This function also initializes the data and code heaps */ | 
					
						
							| 
									
										
										
										
											2009-09-23 14:05:46 -04:00
										 |  |  | void factor_vm::load_image(vm_parameters *p) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE *file = OPEN_READ(p->image_path); | 
					
						
							|  |  |  | 	if(file == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-10-21 21:12:57 -04:00
										 |  |  | 		std::cout << "Cannot open image file: " << p->image_path << std::endl; | 
					
						
							|  |  |  | 		std::cout << strerror(errno) << std::endl; | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		exit(1); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 05:50:24 -04:00
										 |  |  | 	image_header h; | 
					
						
							| 
									
										
										
										
											2010-01-19 15:01:11 -05:00
										 |  |  | 	if(safe_fread(&h,sizeof(image_header),1,file) != 1) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		fatal_error("Cannot read image header",0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	if(h.magic != image_magic) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		fatal_error("Bad image: magic number check failed",h.magic); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-08 16:05:55 -04:00
										 |  |  | 	if(h.version != image_version) | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 		fatal_error("Bad image: version number check failed",h.version); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	load_data_heap(file,&h,p); | 
					
						
							|  |  |  | 	load_code_heap(file,&h,p); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 15:01:11 -05:00
										 |  |  | 	safe_fclose(file); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	init_objects(&h); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-27 18:05:08 -05:00
										 |  |  | 	cell data_offset = data->tenured->start - h.data_relocation_base; | 
					
						
							|  |  |  | 	cell code_offset = code->seg->start - h.code_relocation_base; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fixup_data(data_offset,code_offset); | 
					
						
							|  |  |  | 	fixup_code(data_offset,code_offset); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Store image path name */ | 
					
						
							| 
									
										
										
										
											2009-10-23 01:33:53 -04:00
										 |  |  | 	special_objects[OBJ_IMAGE] = allot_alien(false_object,(cell)p->image_path); | 
					
						
							| 
									
										
										
										
											2009-05-02 05:04:19 -04:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | /* Save the current image to disk */ | 
					
						
							| 
									
										
										
										
											2010-01-20 23:40:25 -05:00
										 |  |  | bool factor_vm::save_image(const vm_char *saving_filename, const vm_char *filename) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | { | 
					
						
							|  |  |  | 	FILE* file; | 
					
						
							|  |  |  | 	image_header h; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 23:40:25 -05:00
										 |  |  | 	file = OPEN_WRITE(saving_filename); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	if(file == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2010-01-22 02:17:18 -05:00
										 |  |  | 		std::cout << "Cannot open image file: " << saving_filename << std::endl; | 
					
						
							| 
									
										
										
										
											2009-10-21 21:12:57 -04:00
										 |  |  | 		std::cout << strerror(errno) << std::endl; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	h.magic = image_magic; | 
					
						
							|  |  |  | 	h.version = image_version; | 
					
						
							|  |  |  | 	h.data_relocation_base = data->tenured->start; | 
					
						
							| 
									
										
										
										
											2009-10-26 23:08:35 -04:00
										 |  |  | 	h.data_size = data->tenured->occupied_space(); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	h.code_relocation_base = code->seg->start; | 
					
						
							| 
									
										
										
										
											2009-10-26 23:08:35 -04:00
										 |  |  | 	h.code_size = code->allocator->occupied_space(); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-18 21:54:13 -04:00
										 |  |  | 	h.true_object = true_object; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 	h.bignum_zero = bignum_zero; | 
					
						
							|  |  |  | 	h.bignum_pos_one = bignum_pos_one; | 
					
						
							|  |  |  | 	h.bignum_neg_one = bignum_neg_one; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:33:53 -04:00
										 |  |  | 	for(cell i = 0; i < special_object_count; i++) | 
					
						
							| 
									
										
										
										
											2009-11-20 01:55:16 -05:00
										 |  |  | 		h.special_objects[i] = (save_special_p(i) ? special_objects[i] : false_object); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	bool ok = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-19 15:01:11 -05:00
										 |  |  | 	if(safe_fwrite(&h,sizeof(image_header),1,file) != 1) ok = false; | 
					
						
							|  |  |  | 	if(safe_fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false; | 
					
						
							|  |  |  | 	if(safe_fwrite(code->allocator->first_block(),h.code_size,1,file) != 1) ok = false; | 
					
						
							| 
									
										
										
										
											2010-02-05 00:52:55 -05:00
										 |  |  | 	safe_fclose(file); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(!ok) | 
					
						
							| 
									
										
										
										
											2009-10-21 21:12:57 -04:00
										 |  |  | 		std::cout << "save-image failed: " << strerror(errno) << std::endl; | 
					
						
							| 
									
										
										
										
											2010-01-22 02:17:18 -05:00
										 |  |  | 	else | 
					
						
							| 
									
										
										
										
											2010-02-03 16:12:13 -05:00
										 |  |  | 		move_file(saving_filename,filename);  | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return ok; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_save_image() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* do a full GC to push everything into tenured space */ | 
					
						
							|  |  |  | 	primitive_compact_gc(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-20 23:40:25 -05:00
										 |  |  | 	data_root<byte_array> path2(ctx->pop(),this); | 
					
						
							|  |  |  | 	path2.untag_check(this); | 
					
						
							| 
									
										
										
										
											2010-01-22 02:17:18 -05:00
										 |  |  | 	data_root<byte_array> path1(ctx->pop(),this); | 
					
						
							|  |  |  | 	path1.untag_check(this); | 
					
						
							| 
									
										
										
										
											2010-01-20 23:40:25 -05:00
										 |  |  | 	save_image((vm_char *)(path1.untagged() + 1 ),(vm_char *)(path2.untagged() + 1)); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void factor_vm::primitive_save_image_and_exit() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* We unbox this before doing anything else. This is the only point
 | 
					
						
							|  |  |  | 	where we might throw an error, so we have to throw an error here since | 
					
						
							|  |  |  | 	later steps destroy the current image. */ | 
					
						
							| 
									
										
										
										
											2010-01-20 23:40:25 -05:00
										 |  |  | 	data_root<byte_array> path2(ctx->pop(),this); | 
					
						
							|  |  |  | 	path2.untag_check(this); | 
					
						
							| 
									
										
										
										
											2010-01-22 02:17:18 -05:00
										 |  |  | 	data_root<byte_array> path1(ctx->pop(),this); | 
					
						
							|  |  |  | 	path1.untag_check(this); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-23 01:33:53 -04:00
										 |  |  | 	/* strip out special_objects data which is set on startup anyway */ | 
					
						
							|  |  |  | 	for(cell i = 0; i < special_object_count; i++) | 
					
						
							| 
									
										
										
										
											2009-11-20 01:55:16 -05:00
										 |  |  | 		if(!save_special_p(i)) special_objects[i] = false_object; | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-25 15:02:14 -04:00
										 |  |  | 	gc(collect_compact_op, | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 		0, /* requested size */ | 
					
						
							| 
									
										
										
										
											2009-10-25 15:02:14 -04:00
										 |  |  | 		false /* discard objects only reachable from stacks */); | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* Save the image */ | 
					
						
							| 
									
										
										
										
											2010-01-20 23:40:25 -05:00
										 |  |  | 	if(save_image((vm_char *)(path1.untagged() + 1), (vm_char *)(path2.untagged() + 1))) | 
					
						
							| 
									
										
										
										
											2009-10-16 15:41:40 -04:00
										 |  |  | 		exit(0); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		exit(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-04 02:46:13 -04:00
										 |  |  | } |