VM: Refactor image.cpp/hpp to Factor style
							parent
							
								
									4ea2e9ed06
								
							
						
					
					
						commit
						cae6a5e855
					
				
							
								
								
									
										559
									
								
								vm/image.cpp
								
								
								
								
							
							
						
						
									
										559
									
								
								vm/image.cpp
								
								
								
								
							| 
						 | 
					@ -1,389 +1,356 @@
 | 
				
			||||||
#include "master.hpp"
 | 
					#include "master.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace factor
 | 
					namespace factor {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Certain special objects in the image are known to the runtime */
 | 
					/* Certain special objects in the image are known to the runtime */
 | 
				
			||||||
void factor_vm::init_objects(image_header *h)
 | 
					void factor_vm::init_objects(image_header* h) {
 | 
				
			||||||
{
 | 
					  memcpy(special_objects, h->special_objects, sizeof(special_objects));
 | 
				
			||||||
	memcpy(special_objects,h->special_objects,sizeof(special_objects));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	true_object = h->true_object;
 | 
					  true_object = h->true_object;
 | 
				
			||||||
	bignum_zero = h->bignum_zero;
 | 
					  bignum_zero = h->bignum_zero;
 | 
				
			||||||
	bignum_pos_one = h->bignum_pos_one;
 | 
					  bignum_pos_one = h->bignum_pos_one;
 | 
				
			||||||
	bignum_neg_one = h->bignum_neg_one;
 | 
					  bignum_neg_one = h->bignum_neg_one;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
 | 
					void factor_vm::load_data_heap(FILE* file, image_header* h, vm_parameters* p) {
 | 
				
			||||||
{
 | 
					  p->tenured_size = std::max((h->data_size * 3) / 2, p->tenured_size);
 | 
				
			||||||
	p->tenured_size = std::max((h->data_size * 3) / 2,p->tenured_size);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_data_heap(p->young_size,
 | 
					  init_data_heap(p->young_size, p->aging_size, p->tenured_size);
 | 
				
			||||||
		p->aging_size,
 | 
					 | 
				
			||||||
		p->tenured_size);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fixnum bytes_read = safe_fread((void*)data->tenured->start,1,h->data_size,file);
 | 
					  fixnum bytes_read =
 | 
				
			||||||
 | 
					      safe_fread((void*)data->tenured->start, 1, h->data_size, file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if((cell)bytes_read != h->data_size)
 | 
					  if ((cell) bytes_read != h->data_size) {
 | 
				
			||||||
	{
 | 
					    std::cout << "truncated image: " << bytes_read << " bytes read, ";
 | 
				
			||||||
		std::cout << "truncated image: " << bytes_read << " bytes read, ";
 | 
					    std::cout << h->data_size << " bytes expected\n";
 | 
				
			||||||
		std::cout << h->data_size << " bytes expected\n";
 | 
					    fatal_error("load_data_heap failed", 0);
 | 
				
			||||||
		fatal_error("load_data_heap failed",0);
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data->tenured->initial_free_list(h->data_size);
 | 
					  data->tenured->initial_free_list(h->data_size);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void factor_vm::load_code_heap(FILE *file, image_header *h, vm_parameters *p)
 | 
					void factor_vm::load_code_heap(FILE* file, image_header* h, vm_parameters* p) {
 | 
				
			||||||
{
 | 
					  if (h->code_size > p->code_size)
 | 
				
			||||||
	if(h->code_size > p->code_size)
 | 
					    fatal_error("Code heap too small to fit image", h->code_size);
 | 
				
			||||||
		fatal_error("Code heap too small to fit image",h->code_size);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_code_heap(p->code_size);
 | 
					  init_code_heap(p->code_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(h->code_size != 0)
 | 
					  if (h->code_size != 0) {
 | 
				
			||||||
	{
 | 
					    size_t bytes_read =
 | 
				
			||||||
		size_t bytes_read = safe_fread(code->allocator->first_block(),1,h->code_size,file);
 | 
					        safe_fread(code->allocator->first_block(), 1, h->code_size, file);
 | 
				
			||||||
		if(bytes_read != h->code_size)
 | 
					    if (bytes_read != h->code_size) {
 | 
				
			||||||
		{
 | 
					      std::cout << "truncated image: " << bytes_read << " bytes read, ";
 | 
				
			||||||
			std::cout << "truncated image: " << bytes_read << " bytes read, ";
 | 
					      std::cout << h->code_size << " bytes expected\n";
 | 
				
			||||||
			std::cout << h->code_size << " bytes expected\n";
 | 
					      fatal_error("load_code_heap failed", 0);
 | 
				
			||||||
			fatal_error("load_code_heap failed",0);
 | 
					    }
 | 
				
			||||||
		}
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	code->allocator->initial_free_list(h->code_size);
 | 
					  code->allocator->initial_free_list(h->code_size);
 | 
				
			||||||
	code->initialize_all_blocks_set();
 | 
					  code->initialize_all_blocks_set();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct startup_fixup {
 | 
					struct startup_fixup {
 | 
				
			||||||
	static const bool translated_code_block_map = true;
 | 
					  static const bool translated_code_block_map = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cell data_offset;
 | 
					  cell data_offset;
 | 
				
			||||||
	cell code_offset;
 | 
					  cell code_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	explicit startup_fixup(cell data_offset_, cell code_offset_) :
 | 
					  explicit startup_fixup(cell data_offset_, cell code_offset_)
 | 
				
			||||||
		data_offset(data_offset_), code_offset(code_offset_) {}
 | 
					      : data_offset(data_offset_), code_offset(code_offset_) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	object *fixup_data(object *obj)
 | 
					  object* fixup_data(object* obj) {
 | 
				
			||||||
	{
 | 
					    return (object*)((cell) obj + data_offset);
 | 
				
			||||||
		return (object *)((cell)obj + data_offset);
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	code_block *fixup_code(code_block *obj)
 | 
					  code_block* fixup_code(code_block* obj) {
 | 
				
			||||||
	{
 | 
					    return (code_block*)((cell) obj + code_offset);
 | 
				
			||||||
		return (code_block *)((cell)obj + code_offset);
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	object *translate_data(const object *obj)
 | 
					  object* translate_data(const object* obj) { return fixup_data((object*)obj); }
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return fixup_data((object *)obj);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	code_block *translate_code(const code_block *compiled)
 | 
					  code_block* translate_code(const code_block* compiled) {
 | 
				
			||||||
	{
 | 
					    return fixup_code((code_block*)compiled);
 | 
				
			||||||
		return fixup_code((code_block *)compiled);
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cell size(const object *obj)
 | 
					  cell size(const object* obj) { return obj->size(*this); }
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return obj->size(*this);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cell size(code_block *compiled)
 | 
					  cell size(code_block* compiled) { return compiled->size(*this); }
 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		return compiled->size(*this);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct start_object_updater {
 | 
					struct start_object_updater {
 | 
				
			||||||
	factor_vm *parent;
 | 
					  factor_vm* parent;
 | 
				
			||||||
	startup_fixup fixup;
 | 
					  startup_fixup fixup;
 | 
				
			||||||
	slot_visitor<startup_fixup> data_visitor;
 | 
					  slot_visitor<startup_fixup> data_visitor;
 | 
				
			||||||
	code_block_visitor<startup_fixup> code_visitor;
 | 
					  code_block_visitor<startup_fixup> code_visitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	start_object_updater(factor_vm *parent_, startup_fixup fixup_) :
 | 
					  start_object_updater(factor_vm* parent_, startup_fixup fixup_)
 | 
				
			||||||
		parent(parent_),
 | 
					      : parent(parent_),
 | 
				
			||||||
		fixup(fixup_),
 | 
					        fixup(fixup_),
 | 
				
			||||||
		data_visitor(slot_visitor<startup_fixup>(parent_,fixup_)),
 | 
					        data_visitor(slot_visitor<startup_fixup>(parent_, fixup_)),
 | 
				
			||||||
		code_visitor(code_block_visitor<startup_fixup>(parent_,fixup_)) {}
 | 
					        code_visitor(code_block_visitor<startup_fixup>(parent_, fixup_)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void operator()(object *obj, cell size)
 | 
					  void operator()(object* obj, cell size) {
 | 
				
			||||||
	{
 | 
					    parent->data->tenured->starts.record_object_start_offset(obj);
 | 
				
			||||||
		parent->data->tenured->starts.record_object_start_offset(obj);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		data_visitor.visit_slots(obj);
 | 
					    data_visitor.visit_slots(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch(obj->type())
 | 
					    switch (obj->type()) {
 | 
				
			||||||
		{
 | 
					      case ALIEN_TYPE: {
 | 
				
			||||||
		case ALIEN_TYPE:
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				alien *ptr = (alien *)obj;
 | 
					        alien* ptr = (alien*)obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if(to_boolean(ptr->base))
 | 
					        if (to_boolean(ptr->base))
 | 
				
			||||||
					ptr->update_address();
 | 
					          ptr->update_address();
 | 
				
			||||||
				else
 | 
					        else
 | 
				
			||||||
					ptr->expired = parent->true_object;
 | 
					          ptr->expired = parent->true_object;
 | 
				
			||||||
				break;
 | 
					        break;
 | 
				
			||||||
			}
 | 
					      }
 | 
				
			||||||
		case DLL_TYPE:
 | 
					      case DLL_TYPE: {
 | 
				
			||||||
			{
 | 
					        parent->ffi_dlopen((dll*)obj);
 | 
				
			||||||
				parent->ffi_dlopen((dll *)obj);
 | 
					        break;
 | 
				
			||||||
				break;
 | 
					      }
 | 
				
			||||||
			}
 | 
					      default: {
 | 
				
			||||||
		default:
 | 
					        code_visitor.visit_object_code_block(obj);
 | 
				
			||||||
			{
 | 
					        break;
 | 
				
			||||||
				code_visitor.visit_object_code_block(obj);
 | 
					      }
 | 
				
			||||||
				break;
 | 
					    }
 | 
				
			||||||
			}
 | 
					  }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void factor_vm::fixup_data(cell data_offset, cell code_offset)
 | 
					void factor_vm::fixup_data(cell data_offset, cell code_offset) {
 | 
				
			||||||
{
 | 
					  startup_fixup fixup(data_offset, code_offset);
 | 
				
			||||||
	startup_fixup fixup(data_offset,code_offset);
 | 
					  slot_visitor<startup_fixup> data_workhorse(this, fixup);
 | 
				
			||||||
	slot_visitor<startup_fixup> data_workhorse(this,fixup);
 | 
					  data_workhorse.visit_roots();
 | 
				
			||||||
	data_workhorse.visit_roots();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	start_object_updater updater(this,fixup);
 | 
					  start_object_updater updater(this, fixup);
 | 
				
			||||||
	data->tenured->iterate(updater,fixup);
 | 
					  data->tenured->iterate(updater, fixup);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct startup_code_block_relocation_visitor {
 | 
					struct startup_code_block_relocation_visitor {
 | 
				
			||||||
	factor_vm *parent;
 | 
					  factor_vm* parent;
 | 
				
			||||||
	startup_fixup fixup;
 | 
					  startup_fixup fixup;
 | 
				
			||||||
	slot_visitor<startup_fixup> data_visitor;
 | 
					  slot_visitor<startup_fixup> data_visitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	startup_code_block_relocation_visitor(factor_vm *parent_, startup_fixup fixup_) :
 | 
					  startup_code_block_relocation_visitor(factor_vm* parent_,
 | 
				
			||||||
		parent(parent_),
 | 
					                                        startup_fixup fixup_)
 | 
				
			||||||
		fixup(fixup_),
 | 
					      : parent(parent_),
 | 
				
			||||||
		data_visitor(slot_visitor<startup_fixup>(parent_,fixup_)) {}
 | 
					        fixup(fixup_),
 | 
				
			||||||
 | 
					        data_visitor(slot_visitor<startup_fixup>(parent_, fixup_)) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void operator()(instruction_operand op)
 | 
					  void operator()(instruction_operand op) {
 | 
				
			||||||
	{
 | 
					    code_block* compiled = op.compiled;
 | 
				
			||||||
		code_block *compiled = op.compiled;
 | 
					    cell old_offset =
 | 
				
			||||||
		cell old_offset = op.rel_offset() + (cell)compiled->entry_point() - fixup.code_offset;
 | 
					        op.rel_offset() + (cell) compiled->entry_point() - fixup.code_offset;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch(op.rel_type())
 | 
					    switch (op.rel_type()) {
 | 
				
			||||||
		{
 | 
					      case RT_LITERAL: {
 | 
				
			||||||
		case RT_LITERAL:
 | 
					        cell value = op.load_value(old_offset);
 | 
				
			||||||
			{
 | 
					        if (immediate_p(value))
 | 
				
			||||||
				cell value = op.load_value(old_offset);
 | 
					          op.store_value(value);
 | 
				
			||||||
				if(immediate_p(value))
 | 
					        else
 | 
				
			||||||
					op.store_value(value);
 | 
					          op.store_value(
 | 
				
			||||||
				else
 | 
					              RETAG(fixup.fixup_data(untag<object>(value)), TAG(value)));
 | 
				
			||||||
					op.store_value(RETAG(fixup.fixup_data(untag<object>(value)),TAG(value)));
 | 
					        break;
 | 
				
			||||||
				break;
 | 
					      }
 | 
				
			||||||
			}
 | 
					      case RT_ENTRY_POINT:
 | 
				
			||||||
		case RT_ENTRY_POINT:
 | 
					      case RT_ENTRY_POINT_PIC:
 | 
				
			||||||
		case RT_ENTRY_POINT_PIC:
 | 
					      case RT_ENTRY_POINT_PIC_TAIL:
 | 
				
			||||||
		case RT_ENTRY_POINT_PIC_TAIL:
 | 
					      case RT_HERE: {
 | 
				
			||||||
		case RT_HERE:
 | 
					        cell value = op.load_value(old_offset);
 | 
				
			||||||
			{
 | 
					        cell offset = TAG(value);
 | 
				
			||||||
				cell value = op.load_value(old_offset);
 | 
					        code_block* compiled = (code_block*)UNTAG(value);
 | 
				
			||||||
				cell offset = TAG(value);
 | 
					        op.store_value((cell) fixup.fixup_code(compiled) + offset);
 | 
				
			||||||
				code_block *compiled = (code_block *)UNTAG(value);
 | 
					        break;
 | 
				
			||||||
				op.store_value((cell)fixup.fixup_code(compiled) + offset);
 | 
					      }
 | 
				
			||||||
				break;
 | 
					      case RT_UNTAGGED:
 | 
				
			||||||
			}
 | 
					        break;
 | 
				
			||||||
		case RT_UNTAGGED:
 | 
					      default:
 | 
				
			||||||
			break;
 | 
					        parent->store_external_address(op);
 | 
				
			||||||
		default:
 | 
					        break;
 | 
				
			||||||
			parent->store_external_address(op);
 | 
					    }
 | 
				
			||||||
			break;
 | 
					  }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct startup_code_block_updater {
 | 
					struct startup_code_block_updater {
 | 
				
			||||||
	factor_vm *parent;
 | 
					  factor_vm* parent;
 | 
				
			||||||
	startup_fixup fixup;
 | 
					  startup_fixup fixup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	startup_code_block_updater(factor_vm *parent_, startup_fixup fixup_) :
 | 
					  startup_code_block_updater(factor_vm* parent_, startup_fixup fixup_)
 | 
				
			||||||
		parent(parent_), fixup(fixup_) {}
 | 
					      : parent(parent_), fixup(fixup_) {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void operator()(code_block *compiled, cell size)
 | 
					  void operator()(code_block* compiled, cell size) {
 | 
				
			||||||
	{
 | 
					    slot_visitor<startup_fixup> data_visitor(parent, fixup);
 | 
				
			||||||
		slot_visitor<startup_fixup> data_visitor(parent,fixup);
 | 
					    data_visitor.visit_code_block_objects(compiled);
 | 
				
			||||||
		data_visitor.visit_code_block_objects(compiled);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		startup_code_block_relocation_visitor code_visitor(parent,fixup);
 | 
					    startup_code_block_relocation_visitor code_visitor(parent, fixup);
 | 
				
			||||||
		compiled->each_instruction_operand(code_visitor);
 | 
					    compiled->each_instruction_operand(code_visitor);
 | 
				
			||||||
	}
 | 
					  }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void factor_vm::fixup_code(cell data_offset, cell code_offset)
 | 
					void factor_vm::fixup_code(cell data_offset, cell code_offset) {
 | 
				
			||||||
{
 | 
					  startup_fixup fixup(data_offset, code_offset);
 | 
				
			||||||
	startup_fixup fixup(data_offset,code_offset);
 | 
					  startup_code_block_updater updater(this, fixup);
 | 
				
			||||||
	startup_code_block_updater updater(this,fixup);
 | 
					  code->allocator->iterate(updater, fixup);
 | 
				
			||||||
	code->allocator->iterate(updater,fixup);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool factor_vm::read_embedded_image_footer(FILE *file, embedded_image_footer *footer)
 | 
					bool factor_vm::read_embedded_image_footer(FILE* file,
 | 
				
			||||||
{
 | 
					                                           embedded_image_footer* footer) {
 | 
				
			||||||
	safe_fseek(file, -(off_t)sizeof(embedded_image_footer), SEEK_END);
 | 
					  safe_fseek(file, -(off_t) sizeof(embedded_image_footer), SEEK_END);
 | 
				
			||||||
	safe_fread(footer, (off_t)sizeof(embedded_image_footer), 1, file);
 | 
					  safe_fread(footer, (off_t) sizeof(embedded_image_footer), 1, file);
 | 
				
			||||||
	return footer->magic == image_magic;
 | 
					  return footer->magic == image_magic;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FILE* factor_vm::open_image(vm_parameters *p)
 | 
					FILE* factor_vm::open_image(vm_parameters* p) {
 | 
				
			||||||
{
 | 
					  if (p->embedded_image) {
 | 
				
			||||||
	if (p->embedded_image)
 | 
					    FILE* file = OPEN_READ(p->executable_path);
 | 
				
			||||||
	{
 | 
					    if (file == NULL) {
 | 
				
			||||||
		FILE *file = OPEN_READ(p->executable_path);
 | 
					      std::cout << "Cannot open embedded image" << std::endl;
 | 
				
			||||||
		if (file == NULL)
 | 
					      std::cout << strerror(errno) << std::endl;
 | 
				
			||||||
		{
 | 
					      exit(1);
 | 
				
			||||||
			std::cout << "Cannot open embedded image" << std::endl;
 | 
					    }
 | 
				
			||||||
			std::cout << strerror(errno) << std::endl;
 | 
					    embedded_image_footer footer;
 | 
				
			||||||
			exit(1);
 | 
					    if (!read_embedded_image_footer(file, &footer)) {
 | 
				
			||||||
		}
 | 
					      std::cout << "No embedded image" << std::endl;
 | 
				
			||||||
		embedded_image_footer footer;
 | 
					      exit(1);
 | 
				
			||||||
		if (!read_embedded_image_footer(file, &footer))
 | 
					    }
 | 
				
			||||||
		{
 | 
					    safe_fseek(file, (off_t) footer.image_offset, SEEK_SET);
 | 
				
			||||||
			std::cout << "No embedded image" << std::endl;
 | 
					    return file;
 | 
				
			||||||
			exit(1);
 | 
					  } else
 | 
				
			||||||
		}
 | 
					    return OPEN_READ(p->image_path);
 | 
				
			||||||
		safe_fseek(file, (off_t)footer.image_offset, SEEK_SET);
 | 
					 | 
				
			||||||
		return file;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
		return OPEN_READ(p->image_path);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Read an image file from disk, only done once during startup */
 | 
					/* Read an image file from disk, only done once during startup */
 | 
				
			||||||
/* This function also initializes the data and code heaps */
 | 
					/* This function also initializes the data and code heaps */
 | 
				
			||||||
void factor_vm::load_image(vm_parameters *p)
 | 
					void factor_vm::load_image(vm_parameters* p) {
 | 
				
			||||||
{
 | 
					  FILE* file = open_image(p);
 | 
				
			||||||
	FILE *file = open_image(p);
 | 
					  if (file == NULL) {
 | 
				
			||||||
	if(file == NULL)
 | 
					    std::cout << "Cannot open image file: " << p->image_path << std::endl;
 | 
				
			||||||
	{
 | 
					    std::cout << strerror(errno) << std::endl;
 | 
				
			||||||
		std::cout << "Cannot open image file: " << p->image_path << std::endl;
 | 
					    exit(1);
 | 
				
			||||||
		std::cout << strerror(errno) << std::endl;
 | 
					  }
 | 
				
			||||||
		exit(1);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	image_header h;
 | 
					  image_header h;
 | 
				
			||||||
	if(safe_fread(&h,sizeof(image_header),1,file) != 1)
 | 
					  if (safe_fread(&h, sizeof(image_header), 1, file) != 1)
 | 
				
			||||||
		fatal_error("Cannot read image header",0);
 | 
					    fatal_error("Cannot read image header", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(h.magic != image_magic)
 | 
					  if (h.magic != image_magic)
 | 
				
			||||||
		fatal_error("Bad image: magic number check failed",h.magic);
 | 
					    fatal_error("Bad image: magic number check failed", h.magic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(h.version != image_version)
 | 
					  if (h.version != image_version)
 | 
				
			||||||
		fatal_error("Bad image: version number check failed",h.version);
 | 
					    fatal_error("Bad image: version number check failed", h.version);
 | 
				
			||||||
	
 | 
					 | 
				
			||||||
	load_data_heap(file,&h,p);
 | 
					 | 
				
			||||||
	load_code_heap(file,&h,p);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	safe_fclose(file);
 | 
					  load_data_heap(file, &h, p);
 | 
				
			||||||
 | 
					  load_code_heap(file, &h, p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	init_objects(&h);
 | 
					  safe_fclose(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	cell data_offset = data->tenured->start - h.data_relocation_base;
 | 
					  init_objects(&h);
 | 
				
			||||||
	cell code_offset = code->allocator->start - h.code_relocation_base;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fixup_data(data_offset,code_offset);
 | 
					  cell data_offset = data->tenured->start - h.data_relocation_base;
 | 
				
			||||||
	fixup_code(data_offset,code_offset);
 | 
					  cell code_offset = code->allocator->start - h.code_relocation_base;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Store image path name */
 | 
					  fixup_data(data_offset, code_offset);
 | 
				
			||||||
	special_objects[OBJ_IMAGE] = allot_alien(false_object,(cell)p->image_path);
 | 
					  fixup_code(data_offset, code_offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  /* Store image path name */
 | 
				
			||||||
 | 
					  special_objects[OBJ_IMAGE] = allot_alien(false_object, (cell) p->image_path);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Save the current image to disk */
 | 
					/* Save the current image to disk */
 | 
				
			||||||
bool factor_vm::save_image(const vm_char *saving_filename, const vm_char *filename)
 | 
					bool factor_vm::save_image(const vm_char* saving_filename,
 | 
				
			||||||
{
 | 
					                           const vm_char* filename) {
 | 
				
			||||||
	FILE* file;
 | 
					  FILE* file;
 | 
				
			||||||
	image_header h;
 | 
					  image_header h;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	file = OPEN_WRITE(saving_filename);
 | 
					  file = OPEN_WRITE(saving_filename);
 | 
				
			||||||
	if(file == NULL)
 | 
					  if (file == NULL) {
 | 
				
			||||||
	{
 | 
					    std::cout << "Cannot open image file: " << saving_filename << std::endl;
 | 
				
			||||||
		std::cout << "Cannot open image file: " << saving_filename << std::endl;
 | 
					    std::cout << strerror(errno) << std::endl;
 | 
				
			||||||
		std::cout << strerror(errno) << std::endl;
 | 
					    return false;
 | 
				
			||||||
		return false;
 | 
					  }
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.magic = image_magic;
 | 
					  h.magic = image_magic;
 | 
				
			||||||
	h.version = image_version;
 | 
					  h.version = image_version;
 | 
				
			||||||
	h.data_relocation_base = data->tenured->start;
 | 
					  h.data_relocation_base = data->tenured->start;
 | 
				
			||||||
	h.data_size = data->tenured->occupied_space();
 | 
					  h.data_size = data->tenured->occupied_space();
 | 
				
			||||||
	h.code_relocation_base = code->allocator->start;
 | 
					  h.code_relocation_base = code->allocator->start;
 | 
				
			||||||
	h.code_size = code->allocator->occupied_space();
 | 
					  h.code_size = code->allocator->occupied_space();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.true_object = true_object;
 | 
					  h.true_object = true_object;
 | 
				
			||||||
	h.bignum_zero = bignum_zero;
 | 
					  h.bignum_zero = bignum_zero;
 | 
				
			||||||
	h.bignum_pos_one = bignum_pos_one;
 | 
					  h.bignum_pos_one = bignum_pos_one;
 | 
				
			||||||
	h.bignum_neg_one = bignum_neg_one;
 | 
					  h.bignum_neg_one = bignum_neg_one;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for(cell i = 0; i < special_object_count; i++)
 | 
					  for (cell i = 0; i < special_object_count; i++)
 | 
				
			||||||
		h.special_objects[i] = (save_special_p(i) ? special_objects[i] : false_object);
 | 
					    h.special_objects[i] =
 | 
				
			||||||
 | 
					        (save_special_p(i) ? special_objects[i] : false_object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	bool ok = true;
 | 
					  bool ok = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(safe_fwrite(&h,sizeof(image_header),1,file) != 1) ok = false;
 | 
					  if (safe_fwrite(&h, sizeof(image_header), 1, file) != 1)
 | 
				
			||||||
	if(safe_fwrite((void*)data->tenured->start,h.data_size,1,file) != 1) ok = false;
 | 
					    ok = false;
 | 
				
			||||||
	if(safe_fwrite(code->allocator->first_block(),h.code_size,1,file) != 1) ok = false;
 | 
					  if (safe_fwrite((void*)data->tenured->start, h.data_size, 1, file) != 1)
 | 
				
			||||||
	safe_fclose(file);
 | 
					    ok = false;
 | 
				
			||||||
 | 
					  if (safe_fwrite(code->allocator->first_block(), h.code_size, 1, file) != 1)
 | 
				
			||||||
 | 
					    ok = false;
 | 
				
			||||||
 | 
					  safe_fclose(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!ok)
 | 
					  if (!ok)
 | 
				
			||||||
		std::cout << "save-image failed: " << strerror(errno) << std::endl;
 | 
					    std::cout << "save-image failed: " << strerror(errno) << std::endl;
 | 
				
			||||||
	else
 | 
					  else
 | 
				
			||||||
		move_file(saving_filename,filename); 
 | 
					    move_file(saving_filename, filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ok;
 | 
					  return ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void factor_vm::primitive_save_image()
 | 
					void factor_vm::primitive_save_image() {
 | 
				
			||||||
{
 | 
					  /* do a full GC to push everything into tenured space */
 | 
				
			||||||
	/* do a full GC to push everything into tenured space */
 | 
					  primitive_compact_gc();
 | 
				
			||||||
	primitive_compact_gc();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data_root<byte_array> path2(ctx->pop(),this);
 | 
					  data_root<byte_array> path2(ctx->pop(), this);
 | 
				
			||||||
	path2.untag_check(this);
 | 
					  path2.untag_check(this);
 | 
				
			||||||
	data_root<byte_array> path1(ctx->pop(),this);
 | 
					  data_root<byte_array> path1(ctx->pop(), this);
 | 
				
			||||||
	path1.untag_check(this);
 | 
					  path1.untag_check(this);
 | 
				
			||||||
	save_image((vm_char *)(path1.untagged() + 1 ),(vm_char *)(path2.untagged() + 1));
 | 
					  save_image((vm_char*)(path1.untagged() + 1),
 | 
				
			||||||
 | 
					             (vm_char*)(path2.untagged() + 1));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void factor_vm::primitive_save_image_and_exit()
 | 
					void factor_vm::primitive_save_image_and_exit() {
 | 
				
			||||||
{
 | 
					  /* We unbox this before doing anything else. This is the only point
 | 
				
			||||||
	/* 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
 | 
				
			||||||
	where we might throw an error, so we have to throw an error here since
 | 
					     later steps destroy the current image. */
 | 
				
			||||||
	later steps destroy the current image. */
 | 
					  data_root<byte_array> path2(ctx->pop(), this);
 | 
				
			||||||
	data_root<byte_array> path2(ctx->pop(),this);
 | 
					  path2.untag_check(this);
 | 
				
			||||||
	path2.untag_check(this);
 | 
					  data_root<byte_array> path1(ctx->pop(), this);
 | 
				
			||||||
	data_root<byte_array> path1(ctx->pop(),this);
 | 
					  path1.untag_check(this);
 | 
				
			||||||
	path1.untag_check(this);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* strip out special_objects data which is set on startup anyway */
 | 
					  /* strip out special_objects data which is set on startup anyway */
 | 
				
			||||||
	for(cell i = 0; i < special_object_count; i++)
 | 
					  for (cell i = 0; i < special_object_count; i++)
 | 
				
			||||||
		if(!save_special_p(i)) special_objects[i] = false_object;
 | 
					    if (!save_special_p(i))
 | 
				
			||||||
 | 
					      special_objects[i] = false_object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	gc(collect_compact_op,
 | 
					  gc(collect_compact_op, 0, /* requested size */
 | 
				
			||||||
		0, /* requested size */
 | 
					     false /* discard objects only reachable from stacks */);
 | 
				
			||||||
		false /* discard objects only reachable from stacks */);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Save the image */
 | 
					  /* Save the image */
 | 
				
			||||||
	if(save_image((vm_char *)(path1.untagged() + 1), (vm_char *)(path2.untagged() + 1)))
 | 
					  if (save_image((vm_char*)(path1.untagged() + 1),
 | 
				
			||||||
		exit(0);
 | 
					                 (vm_char*)(path2.untagged() + 1)))
 | 
				
			||||||
	else
 | 
					    exit(0);
 | 
				
			||||||
		exit(1);
 | 
					  else
 | 
				
			||||||
 | 
					    exit(1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool factor_vm::embedded_image_p()
 | 
					bool factor_vm::embedded_image_p() {
 | 
				
			||||||
{
 | 
					  const vm_char* vm_path = vm_executable_path();
 | 
				
			||||||
	const vm_char *vm_path = vm_executable_path();
 | 
					  if (!vm_path)
 | 
				
			||||||
	if (!vm_path)
 | 
					    return false;
 | 
				
			||||||
		return false;
 | 
					  FILE* file = OPEN_READ(vm_path);
 | 
				
			||||||
	FILE *file = OPEN_READ(vm_path);
 | 
					  if (!file)
 | 
				
			||||||
	if (!file)
 | 
					    return false;
 | 
				
			||||||
		return false;
 | 
					  embedded_image_footer footer;
 | 
				
			||||||
	embedded_image_footer footer;
 | 
					  bool embedded_p = read_embedded_image_footer(file, &footer);
 | 
				
			||||||
	bool embedded_p = read_embedded_image_footer(file, &footer);
 | 
					  fclose(file);
 | 
				
			||||||
	fclose(file);
 | 
					  return embedded_p;
 | 
				
			||||||
	return embedded_p;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										69
									
								
								vm/image.hpp
								
								
								
								
							
							
						
						
									
										69
									
								
								vm/image.hpp
								
								
								
								
							| 
						 | 
					@ -1,49 +1,48 @@
 | 
				
			||||||
namespace factor
 | 
					namespace factor {
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const cell image_magic = 0x0f0e0d0c;
 | 
					static const cell image_magic = 0x0f0e0d0c;
 | 
				
			||||||
static const cell image_version = 4;
 | 
					static const cell image_version = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct embedded_image_footer {
 | 
					struct embedded_image_footer {
 | 
				
			||||||
	cell magic;
 | 
					  cell magic;
 | 
				
			||||||
	cell image_offset;
 | 
					  cell image_offset;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct image_header {
 | 
					struct image_header {
 | 
				
			||||||
	cell magic;
 | 
					  cell magic;
 | 
				
			||||||
	cell version;
 | 
					  cell version;
 | 
				
			||||||
	/* base address of data heap when image was saved */
 | 
					  /* base address of data heap when image was saved */
 | 
				
			||||||
	cell data_relocation_base;
 | 
					  cell data_relocation_base;
 | 
				
			||||||
	/* size of heap */
 | 
					  /* size of heap */
 | 
				
			||||||
	cell data_size;
 | 
					  cell data_size;
 | 
				
			||||||
	/* base address of code heap when image was saved */
 | 
					  /* base address of code heap when image was saved */
 | 
				
			||||||
	cell code_relocation_base;
 | 
					  cell code_relocation_base;
 | 
				
			||||||
	/* size of code heap */
 | 
					  /* size of code heap */
 | 
				
			||||||
	cell code_size;
 | 
					  cell code_size;
 | 
				
			||||||
	/* tagged pointer to t singleton */
 | 
					  /* tagged pointer to t singleton */
 | 
				
			||||||
	cell true_object;
 | 
					  cell true_object;
 | 
				
			||||||
	/* tagged pointer to bignum 0 */
 | 
					  /* tagged pointer to bignum 0 */
 | 
				
			||||||
	cell bignum_zero;
 | 
					  cell bignum_zero;
 | 
				
			||||||
	/* tagged pointer to bignum 1 */
 | 
					  /* tagged pointer to bignum 1 */
 | 
				
			||||||
	cell bignum_pos_one;
 | 
					  cell bignum_pos_one;
 | 
				
			||||||
	/* tagged pointer to bignum -1 */
 | 
					  /* tagged pointer to bignum -1 */
 | 
				
			||||||
	cell bignum_neg_one;
 | 
					  cell bignum_neg_one;
 | 
				
			||||||
	/* Initial user environment */
 | 
					  /* Initial user environment */
 | 
				
			||||||
	cell special_objects[special_object_count];
 | 
					  cell special_objects[special_object_count];
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct vm_parameters {
 | 
					struct vm_parameters {
 | 
				
			||||||
	bool embedded_image;
 | 
					  bool embedded_image;
 | 
				
			||||||
	const vm_char *image_path;
 | 
					  const vm_char* image_path;
 | 
				
			||||||
	const vm_char *executable_path;
 | 
					  const vm_char* executable_path;
 | 
				
			||||||
	cell datastack_size, retainstack_size, callstack_size;
 | 
					  cell datastack_size, retainstack_size, callstack_size;
 | 
				
			||||||
	cell young_size, aging_size, tenured_size;
 | 
					  cell young_size, aging_size, tenured_size;
 | 
				
			||||||
	cell code_size;
 | 
					  cell code_size;
 | 
				
			||||||
	bool fep;
 | 
					  bool fep;
 | 
				
			||||||
	bool console;
 | 
					  bool console;
 | 
				
			||||||
	bool signals;
 | 
					  bool signals;
 | 
				
			||||||
	cell max_pic_size;
 | 
					  cell max_pic_size;
 | 
				
			||||||
	cell callback_size;
 | 
					  cell callback_size;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue