From cae6a5e8554a745573f01151db9956fec06dce5f Mon Sep 17 00:00:00 2001 From: Erik Charlebois Date: Sat, 11 May 2013 22:05:00 -0400 Subject: [PATCH] VM: Refactor image.cpp/hpp to Factor style --- vm/image.cpp | 623 ++++++++++++++++++++++++--------------------------- vm/image.hpp | 69 +++--- 2 files changed, 329 insertions(+), 363 deletions(-) diff --git a/vm/image.cpp b/vm/image.cpp index a1a930b325..e37b49e0d8 100644 --- a/vm/image.cpp +++ b/vm/image.cpp @@ -1,389 +1,356 @@ #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) -{ - memcpy(special_objects,h->special_objects,sizeof(special_objects)); - - true_object = h->true_object; - bignum_zero = h->bignum_zero; - bignum_pos_one = h->bignum_pos_one; - bignum_neg_one = h->bignum_neg_one; +void factor_vm::init_objects(image_header* h) { + memcpy(special_objects, h->special_objects, sizeof(special_objects)); + + true_object = h->true_object; + bignum_zero = h->bignum_zero; + bignum_pos_one = h->bignum_pos_one; + bignum_neg_one = h->bignum_neg_one; } -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); +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) - { - std::cout << "truncated image: " << bytes_read << " bytes read, "; - std::cout << h->data_size << " bytes expected\n"; - fatal_error("load_data_heap failed",0); - } + 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); + } - 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) -{ - 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) - { - std::cout << "truncated image: " << bytes_read << " bytes read, "; - std::cout << h->code_size << " bytes expected\n"; - fatal_error("load_code_heap failed",0); - } - } - - code->allocator->initial_free_list(h->code_size); - code->initialize_all_blocks_set(); +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) { + std::cout << "truncated image: " << bytes_read << " bytes read, "; + std::cout << h->code_size << " bytes expected\n"; + fatal_error("load_code_heap failed", 0); + } + } + + code->allocator->initial_free_list(h->code_size); + code->initialize_all_blocks_set(); } struct startup_fixup { - static const bool translated_code_block_map = true; - - cell data_offset; - cell code_offset; - - explicit startup_fixup(cell data_offset_, cell code_offset_) : - data_offset(data_offset_), code_offset(code_offset_) {} - - object *fixup_data(object *obj) - { - return (object *)((cell)obj + data_offset); - } - - 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); - } - - 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(code_block *compiled) - { - return compiled->size(*this); - } + static const bool translated_code_block_map = true; + + cell data_offset; + cell code_offset; + + explicit startup_fixup(cell data_offset_, cell code_offset_) + : data_offset(data_offset_), code_offset(code_offset_) {} + + object* fixup_data(object* obj) { + return (object*)((cell) obj + data_offset); + } + + 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); } + + 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(code_block* compiled) { return compiled->size(*this); } }; struct start_object_updater { - factor_vm *parent; - startup_fixup fixup; - slot_visitor data_visitor; - code_block_visitor code_visitor; - - start_object_updater(factor_vm *parent_, startup_fixup fixup_) : - parent(parent_), - fixup(fixup_), - data_visitor(slot_visitor(parent_,fixup_)), - code_visitor(code_block_visitor(parent_,fixup_)) {} - - 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: - { - - alien *ptr = (alien *)obj; - - if(to_boolean(ptr->base)) - ptr->update_address(); - else - ptr->expired = parent->true_object; - break; - } - case DLL_TYPE: - { - parent->ffi_dlopen((dll *)obj); - break; - } - default: - { - code_visitor.visit_object_code_block(obj); - break; - } - } - } + factor_vm* parent; + startup_fixup fixup; + slot_visitor data_visitor; + code_block_visitor code_visitor; + + start_object_updater(factor_vm* parent_, startup_fixup fixup_) + : parent(parent_), + fixup(fixup_), + data_visitor(slot_visitor(parent_, fixup_)), + code_visitor(code_block_visitor(parent_, fixup_)) {} + + 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: { + + alien* ptr = (alien*)obj; + + if (to_boolean(ptr->base)) + ptr->update_address(); + else + ptr->expired = parent->true_object; + break; + } + case DLL_TYPE: { + parent->ffi_dlopen((dll*)obj); + break; + } + default: { + code_visitor.visit_object_code_block(obj); + break; + } + } + } }; -void factor_vm::fixup_data(cell data_offset, cell code_offset) -{ - startup_fixup fixup(data_offset,code_offset); - slot_visitor data_workhorse(this,fixup); - data_workhorse.visit_roots(); +void factor_vm::fixup_data(cell data_offset, cell code_offset) { + startup_fixup fixup(data_offset, code_offset); + slot_visitor data_workhorse(this, fixup); + data_workhorse.visit_roots(); - start_object_updater updater(this,fixup); - data->tenured->iterate(updater,fixup); + start_object_updater updater(this, fixup); + data->tenured->iterate(updater, fixup); } struct startup_code_block_relocation_visitor { - factor_vm *parent; - startup_fixup fixup; - slot_visitor data_visitor; - - startup_code_block_relocation_visitor(factor_vm *parent_, startup_fixup fixup_) : - parent(parent_), - fixup(fixup_), - data_visitor(slot_visitor(parent_,fixup_)) {} - - void operator()(instruction_operand op) - { - code_block *compiled = op.compiled; - cell old_offset = op.rel_offset() + (cell)compiled->entry_point() - fixup.code_offset; - - 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(value)),TAG(value))); - break; - } - case RT_ENTRY_POINT: - case RT_ENTRY_POINT_PIC: - case RT_ENTRY_POINT_PIC_TAIL: - case RT_HERE: - { - cell value = op.load_value(old_offset); - cell offset = TAG(value); - code_block *compiled = (code_block *)UNTAG(value); - op.store_value((cell)fixup.fixup_code(compiled) + offset); - break; - } - case RT_UNTAGGED: - break; - default: - parent->store_external_address(op); - break; - } - } + factor_vm* parent; + startup_fixup fixup; + slot_visitor data_visitor; + + startup_code_block_relocation_visitor(factor_vm* parent_, + startup_fixup fixup_) + : parent(parent_), + fixup(fixup_), + data_visitor(slot_visitor(parent_, fixup_)) {} + + void operator()(instruction_operand op) { + code_block* compiled = op.compiled; + cell old_offset = + op.rel_offset() + (cell) compiled->entry_point() - fixup.code_offset; + + 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(value)), TAG(value))); + break; + } + case RT_ENTRY_POINT: + case RT_ENTRY_POINT_PIC: + case RT_ENTRY_POINT_PIC_TAIL: + case RT_HERE: { + cell value = op.load_value(old_offset); + cell offset = TAG(value); + code_block* compiled = (code_block*)UNTAG(value); + op.store_value((cell) fixup.fixup_code(compiled) + offset); + break; + } + case RT_UNTAGGED: + break; + default: + parent->store_external_address(op); + break; + } + } }; struct startup_code_block_updater { - factor_vm *parent; - startup_fixup fixup; + 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) - { - slot_visitor data_visitor(parent,fixup); - data_visitor.visit_code_block_objects(compiled); + void operator()(code_block* compiled, cell size) { + slot_visitor data_visitor(parent, fixup); + data_visitor.visit_code_block_objects(compiled); - startup_code_block_relocation_visitor code_visitor(parent,fixup); - compiled->each_instruction_operand(code_visitor); - } + startup_code_block_relocation_visitor code_visitor(parent, fixup); + compiled->each_instruction_operand(code_visitor); + } }; -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); +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) -{ - 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; +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 *file = OPEN_READ(p->executable_path); - 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)) - { - std::cout << "No embedded image" << std::endl; - exit(1); - } - safe_fseek(file, (off_t)footer.image_offset, SEEK_SET); - return file; - } - else - return OPEN_READ(p->image_path); +FILE* factor_vm::open_image(vm_parameters* p) { + if (p->embedded_image) { + FILE* file = OPEN_READ(p->executable_path); + 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)) { + std::cout << "No embedded image" << std::endl; + exit(1); + } + 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 */ /* This function also initializes the data and code heaps */ -void factor_vm::load_image(vm_parameters *p) -{ - FILE *file = open_image(p); - if(file == NULL) - { - std::cout << "Cannot open image file: " << p->image_path << std::endl; - std::cout << strerror(errno) << std::endl; - exit(1); - } +void factor_vm::load_image(vm_parameters* p) { + FILE* file = open_image(p); + if (file == NULL) { + std::cout << "Cannot open image file: " << p->image_path << std::endl; + std::cout << strerror(errno) << std::endl; + exit(1); + } + + image_header h; + if (safe_fread(&h, sizeof(image_header), 1, file) != 1) + fatal_error("Cannot read image header", 0); - image_header h; - if(safe_fread(&h,sizeof(image_header),1,file) != 1) - fatal_error("Cannot read image header",0); + if (h.magic != image_magic) + fatal_error("Bad image: magic number check failed", h.magic); - if(h.magic != image_magic) - fatal_error("Bad image: magic number check failed",h.magic); + if (h.version != image_version) + fatal_error("Bad image: version number check failed", h.version); - if(h.version != image_version) - fatal_error("Bad image: version number check failed",h.version); - - load_data_heap(file,&h,p); - load_code_heap(file,&h,p); + load_data_heap(file, &h, p); + load_code_heap(file, &h, p); - safe_fclose(file); + safe_fclose(file); - init_objects(&h); + init_objects(&h); - cell data_offset = data->tenured->start - h.data_relocation_base; - cell code_offset = code->allocator->start - h.code_relocation_base; + cell data_offset = data->tenured->start - h.data_relocation_base; + cell code_offset = code->allocator->start - h.code_relocation_base; - fixup_data(data_offset,code_offset); - fixup_code(data_offset,code_offset); + fixup_data(data_offset, code_offset); + fixup_code(data_offset, code_offset); - /* Store image path name */ - special_objects[OBJ_IMAGE] = allot_alien(false_object,(cell)p->image_path); + /* Store image path name */ + special_objects[OBJ_IMAGE] = allot_alien(false_object, (cell) p->image_path); } /* Save the current image to disk */ -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) - { - std::cout << "Cannot open image file: " << saving_filename << std::endl; - std::cout << strerror(errno) << std::endl; - return false; - } - - h.magic = image_magic; - h.version = image_version; - h.data_relocation_base = data->tenured->start; - h.data_size = data->tenured->occupied_space(); - h.code_relocation_base = code->allocator->start; - h.code_size = code->allocator->occupied_space(); - - h.true_object = true_object; - h.bignum_zero = bignum_zero; - h.bignum_pos_one = bignum_pos_one; - 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); - - 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; - safe_fclose(file); - - if(!ok) - std::cout << "save-image failed: " << strerror(errno) << std::endl; - else - move_file(saving_filename,filename); - - return ok; +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) { + std::cout << "Cannot open image file: " << saving_filename << std::endl; + std::cout << strerror(errno) << std::endl; + return false; + } + + h.magic = image_magic; + h.version = image_version; + h.data_relocation_base = data->tenured->start; + h.data_size = data->tenured->occupied_space(); + h.code_relocation_base = code->allocator->start; + h.code_size = code->allocator->occupied_space(); + + h.true_object = true_object; + h.bignum_zero = bignum_zero; + h.bignum_pos_one = bignum_pos_one; + 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); + + 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; + safe_fclose(file); + + if (!ok) + std::cout << "save-image failed: " << strerror(errno) << std::endl; + else + move_file(saving_filename, filename); + + return ok; } -void factor_vm::primitive_save_image() -{ - /* do a full GC to push everything into tenured space */ - primitive_compact_gc(); +void factor_vm::primitive_save_image() { + /* do a full GC to push everything into tenured space */ + primitive_compact_gc(); - data_root path2(ctx->pop(),this); - path2.untag_check(this); - data_root path1(ctx->pop(),this); - path1.untag_check(this); - save_image((vm_char *)(path1.untagged() + 1 ),(vm_char *)(path2.untagged() + 1)); + data_root path2(ctx->pop(), this); + path2.untag_check(this); + data_root path1(ctx->pop(), this); + path1.untag_check(this); + save_image((vm_char*)(path1.untagged() + 1), + (vm_char*)(path2.untagged() + 1)); } -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. */ - data_root path2(ctx->pop(),this); - path2.untag_check(this); - data_root path1(ctx->pop(),this); - path1.untag_check(this); - - /* 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; - - 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))) - exit(0); - else - exit(1); +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. */ + data_root path2(ctx->pop(), this); + path2.untag_check(this); + data_root path1(ctx->pop(), this); + path1.untag_check(this); + + /* 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; + + 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))) + exit(0); + else + exit(1); } -bool factor_vm::embedded_image_p() -{ - const vm_char *vm_path = vm_executable_path(); - if (!vm_path) - return false; - FILE *file = OPEN_READ(vm_path); - if (!file) - return false; - embedded_image_footer footer; - bool embedded_p = read_embedded_image_footer(file, &footer); - fclose(file); - return embedded_p; +bool factor_vm::embedded_image_p() { + const vm_char* vm_path = vm_executable_path(); + if (!vm_path) + return false; + FILE* file = OPEN_READ(vm_path); + if (!file) + return false; + embedded_image_footer footer; + bool embedded_p = read_embedded_image_footer(file, &footer); + fclose(file); + return embedded_p; } } diff --git a/vm/image.hpp b/vm/image.hpp index 21cf8944d1..efc0c82856 100644 --- a/vm/image.hpp +++ b/vm/image.hpp @@ -1,49 +1,48 @@ -namespace factor -{ +namespace factor { static const cell image_magic = 0x0f0e0d0c; static const cell image_version = 4; struct embedded_image_footer { - cell magic; - cell image_offset; + cell magic; + cell image_offset; }; struct image_header { - cell magic; - cell version; - /* base address of data heap when image was saved */ - cell data_relocation_base; - /* size of heap */ - cell data_size; - /* base address of code heap when image was saved */ - cell code_relocation_base; - /* size of code heap */ - cell code_size; - /* tagged pointer to t singleton */ - cell true_object; - /* tagged pointer to bignum 0 */ - cell bignum_zero; - /* tagged pointer to bignum 1 */ - cell bignum_pos_one; - /* tagged pointer to bignum -1 */ - cell bignum_neg_one; - /* Initial user environment */ - cell special_objects[special_object_count]; + cell magic; + cell version; + /* base address of data heap when image was saved */ + cell data_relocation_base; + /* size of heap */ + cell data_size; + /* base address of code heap when image was saved */ + cell code_relocation_base; + /* size of code heap */ + cell code_size; + /* tagged pointer to t singleton */ + cell true_object; + /* tagged pointer to bignum 0 */ + cell bignum_zero; + /* tagged pointer to bignum 1 */ + cell bignum_pos_one; + /* tagged pointer to bignum -1 */ + cell bignum_neg_one; + /* Initial user environment */ + cell special_objects[special_object_count]; }; struct vm_parameters { - bool embedded_image; - const vm_char *image_path; - const vm_char *executable_path; - cell datastack_size, retainstack_size, callstack_size; - cell young_size, aging_size, tenured_size; - cell code_size; - bool fep; - bool console; - bool signals; - cell max_pic_size; - cell callback_size; + bool embedded_image; + const vm_char* image_path; + const vm_char* executable_path; + cell datastack_size, retainstack_size, callstack_size; + cell young_size, aging_size, tenured_size; + cell code_size; + bool fep; + bool console; + bool signals; + cell max_pic_size; + cell callback_size; }; } -- 2.34.1