VM: Refactor image.cpp/hpp to Factor style

db4
Erik Charlebois 2013-05-11 22:05:00 -04:00
parent 4ea2e9ed06
commit cae6a5e855
2 changed files with 297 additions and 331 deletions

View File

@ -1,11 +1,9 @@
#include "master.hpp"
namespace factor
{
namespace factor {
/* 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));
true_object = h->true_object;
@ -14,18 +12,15 @@ void factor_vm::init_objects(image_header *h)
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);
init_data_heap(p->young_size,
p->aging_size,
p->tenured_size);
init_data_heap(p->young_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 << h->data_size << " bytes expected\n";
fatal_error("load_data_heap failed", 0);
@ -34,18 +29,16 @@ void factor_vm::load_data_heap(FILE *file, image_header *h, vm_parameters *p)
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)
fatal_error("Code heap too small to fit image", h->code_size);
init_code_heap(p->code_size);
if(h->code_size != 0)
{
size_t bytes_read = safe_fread(code->allocator->first_block(),1,h->code_size,file);
if(bytes_read != h->code_size)
{
if (h->code_size != 0) {
size_t bytes_read =
safe_fread(code->allocator->first_block(), 1, h->code_size, file);
if (bytes_read != h->code_size) {
std::cout << "truncated image: " << bytes_read << " bytes read, ";
std::cout << h->code_size << " bytes expected\n";
fatal_error("load_code_heap failed", 0);
@ -62,38 +55,26 @@ struct 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_) {}
explicit startup_fixup(cell data_offset_, cell 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);
}
code_block *fixup_code(code_block *obj)
{
code_block* fixup_code(code_block* obj) {
return (code_block*)((cell) obj + code_offset);
}
object *translate_data(const object *obj)
{
return fixup_data((object *)obj);
}
object* translate_data(const 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);
}
cell size(const object *obj)
{
return obj->size(*this);
}
cell size(const object* obj) { return obj->size(*this); }
cell size(code_block *compiled)
{
return compiled->size(*this);
}
cell size(code_block* compiled) { return compiled->size(*this); }
};
struct start_object_updater {
@ -102,22 +83,19 @@ struct start_object_updater {
slot_visitor<startup_fixup> data_visitor;
code_block_visitor<startup_fixup> code_visitor;
start_object_updater(factor_vm *parent_, startup_fixup fixup_) :
parent(parent_),
start_object_updater(factor_vm* parent_, startup_fixup fixup_)
: parent(parent_),
fixup(fixup_),
data_visitor(slot_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);
data_visitor.visit_slots(obj);
switch(obj->type())
{
case ALIEN_TYPE:
{
switch (obj->type()) {
case ALIEN_TYPE: {
alien* ptr = (alien*)obj;
@ -127,13 +105,11 @@ struct start_object_updater {
ptr->expired = parent->true_object;
break;
}
case DLL_TYPE:
{
case DLL_TYPE: {
parent->ffi_dlopen((dll*)obj);
break;
}
default:
{
default: {
code_visitor.visit_object_code_block(obj);
break;
}
@ -141,8 +117,7 @@ struct start_object_updater {
}
};
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);
slot_visitor<startup_fixup> data_workhorse(this, fixup);
data_workhorse.visit_roots();
@ -156,32 +131,31 @@ struct startup_code_block_relocation_visitor {
startup_fixup fixup;
slot_visitor<startup_fixup> data_visitor;
startup_code_block_relocation_visitor(factor_vm *parent_, startup_fixup fixup_) :
parent(parent_),
startup_code_block_relocation_visitor(factor_vm* parent_,
startup_fixup fixup_)
: parent(parent_),
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;
cell old_offset = op.rel_offset() + (cell)compiled->entry_point() - fixup.code_offset;
cell old_offset =
op.rel_offset() + (cell) compiled->entry_point() - fixup.code_offset;
switch(op.rel_type())
{
case RT_LITERAL:
{
switch (op.rel_type()) {
case RT_LITERAL: {
cell value = op.load_value(old_offset);
if (immediate_p(value))
op.store_value(value);
else
op.store_value(RETAG(fixup.fixup_data(untag<object>(value)),TAG(value)));
op.store_value(
RETAG(fixup.fixup_data(untag<object>(value)), TAG(value)));
break;
}
case RT_ENTRY_POINT:
case RT_ENTRY_POINT_PIC:
case RT_ENTRY_POINT_PIC_TAIL:
case RT_HERE:
{
case RT_HERE: {
cell value = op.load_value(old_offset);
cell offset = TAG(value);
code_block* compiled = (code_block*)UNTAG(value);
@ -201,11 +175,10 @@ struct startup_code_block_updater {
factor_vm* parent;
startup_fixup fixup;
startup_code_block_updater(factor_vm *parent_, startup_fixup fixup_) :
parent(parent_), fixup(fixup_) {}
startup_code_block_updater(factor_vm* parent_, startup_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);
data_visitor.visit_code_block_objects(compiled);
@ -214,51 +187,43 @@ struct startup_code_block_updater {
}
};
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_code_block_updater updater(this, 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_fread(footer, (off_t) sizeof(embedded_image_footer), 1, file);
return footer->magic == image_magic;
}
FILE* factor_vm::open_image(vm_parameters *p)
{
if (p->embedded_image)
{
FILE* factor_vm::open_image(vm_parameters* p) {
if (p->embedded_image) {
FILE* file = OPEN_READ(p->executable_path);
if (file == NULL)
{
if (file == NULL) {
std::cout << "Cannot open embedded image" << std::endl;
std::cout << strerror(errno) << std::endl;
exit(1);
}
embedded_image_footer footer;
if (!read_embedded_image_footer(file, &footer))
{
if (!read_embedded_image_footer(file, &footer)) {
std::cout << "No embedded image" << std::endl;
exit(1);
}
safe_fseek(file, (off_t) footer.image_offset, SEEK_SET);
return file;
}
else
} else
return OPEN_READ(p->image_path);
}
/* Read an image file from disk, only done once during startup */
/* 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);
if(file == NULL)
{
if (file == NULL) {
std::cout << "Cannot open image file: " << p->image_path << std::endl;
std::cout << strerror(errno) << std::endl;
exit(1);
@ -292,14 +257,13 @@ void factor_vm::load_image(vm_parameters *p)
}
/* 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;
image_header h;
file = OPEN_WRITE(saving_filename);
if(file == NULL)
{
if (file == NULL) {
std::cout << "Cannot open image file: " << saving_filename << std::endl;
std::cout << strerror(errno) << std::endl;
return false;
@ -318,13 +282,17 @@ bool factor_vm::save_image(const vm_char *saving_filename, const vm_char *filena
h.bignum_neg_one = bignum_neg_one;
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;
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;
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;
safe_fclose(file);
if (!ok)
@ -335,8 +303,7 @@ bool factor_vm::save_image(const vm_char *saving_filename, const vm_char *filena
return ok;
}
void factor_vm::primitive_save_image()
{
void factor_vm::primitive_save_image() {
/* do a full GC to push everything into tenured space */
primitive_compact_gc();
@ -344,11 +311,11 @@ void factor_vm::primitive_save_image()
path2.untag_check(this);
data_root<byte_array> path1(ctx->pop(), 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
where we might throw an error, so we have to throw an error here since
later steps destroy the current image. */
@ -359,21 +326,21 @@ void factor_vm::primitive_save_image_and_exit()
/* strip out special_objects data which is set on startup anyway */
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,
0, /* requested size */
gc(collect_compact_op, 0, /* requested size */
false /* discard objects only reachable from stacks */);
/* Save the image */
if(save_image((vm_char *)(path1.untagged() + 1), (vm_char *)(path2.untagged() + 1)))
if (save_image((vm_char*)(path1.untagged() + 1),
(vm_char*)(path2.untagged() + 1)))
exit(0);
else
exit(1);
}
bool factor_vm::embedded_image_p()
{
bool factor_vm::embedded_image_p() {
const vm_char* vm_path = vm_executable_path();
if (!vm_path)
return false;

View File

@ -1,5 +1,4 @@
namespace factor
{
namespace factor {
static const cell image_magic = 0x0f0e0d0c;
static const cell image_version = 4;