void factor_vm::fixup_data(cell data_offset, cell code_offset) { startup_fixup fixup(data_offset, code_offset); slot_visitor<startup_fixup> visitor(this, fixup); visitor.visit_all_roots(); auto start_object_updater = [&](object *obj, cell size) { data->tenured->starts.record_object_start_offset(obj); 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 = special_objects[OBJ_CANONICAL_TRUE]; break; } case DLL_TYPE: { ffi_dlopen((dll*)obj); break; } default: { visitor.visit_object_code_block(obj); break; } } }; data->tenured->iterate(start_object_updater, fixup); }
// open a native library and push a handle // Allocates memory void factor_vm::primitive_dlopen() { data_root<byte_array> path(ctx->pop(), this); check_tagged(path); data_root<dll> library(allot<dll>(sizeof(dll)), this); library->path = path.value(); ffi_dlopen(library.untagged()); ctx->push(library.value()); }
/* open a native library and push a handle */ inline void factorvm::vmprim_dlopen() { gc_root<byte_array> path(dpop(),this); path.untag_check(this); gc_root<dll> library(allot<dll>(sizeof(dll)),this); library->path = path.value(); ffi_dlopen(library.untagged()); dpush(library.value()); }
/* Initialize an object in a newly-loaded image */ void factor_vm::relocate_object(object *object, cell data_relocation_base, cell code_relocation_base) { cell hi_tag = object->h.hi_tag(); /* Tuple relocation is a bit trickier; we have to fix up the layout object before we can get the tuple size, so do_slots is out of the question */ if(hi_tag == TUPLE_TYPE) { tuple *t = (tuple *)object; data_fixup(&t->layout,data_relocation_base); cell *scan = t->data(); cell *end = (cell *)((cell)object + untagged_object_size(object)); for(; scan < end; scan++) data_fixup(scan,data_relocation_base); } else { object_fixupper fixupper(this,data_relocation_base); do_slots((cell)object,fixupper); switch(hi_tag) { case WORD_TYPE: fixup_word((word *)object,code_relocation_base); break; case QUOTATION_TYPE: fixup_quotation((quotation *)object,code_relocation_base); break; case DLL_TYPE: ffi_dlopen((dll *)object); break; case ALIEN_TYPE: fixup_alien((alien *)object); break; case CALLSTACK_TYPE: fixup_callstack_object((callstack *)object,code_relocation_base); break; } } }
/* Initialize an object in a newly-loaded image */ void relocate_object(CELL relocating) { /* Tuple relocation is a bit trickier; we have to fix up the fixup object before we can get the tuple size, so do_slots is out of the question */ if(untag_header(get(relocating)) == TUPLE_TYPE) { data_fixup((CELL *)relocating + 1); CELL scan = relocating + 2 * CELLS; CELL size = untagged_object_size(relocating); CELL end = relocating + size; while(scan < end) { data_fixup((CELL *)scan); scan += CELLS; } } else { do_slots(relocating,data_fixup); switch(untag_header(get(relocating))) { case WORD_TYPE: fixup_word((F_WORD *)relocating); break; case QUOTATION_TYPE: fixup_quotation((F_QUOTATION *)relocating); break; case DLL_TYPE: ffi_dlopen((F_DLL *)relocating); break; case ALIEN_TYPE: fixup_alien((F_ALIEN *)relocating); break; case CALLSTACK_TYPE: fixup_callstack_object((F_CALLSTACK *)relocating); break; } } }
void factor_vm::fixup_heaps(cell data_offset, cell code_offset) { startup_fixup fixup(data_offset, code_offset); slot_visitor<startup_fixup> visitor(this, fixup); visitor.visit_all_roots(); auto start_object_updater = [&](object *obj, cell size) { data->tenured->starts.record_object_start_offset(obj); 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 = special_objects[OBJ_CANONICAL_TRUE]; break; } case DLL_TYPE: { ffi_dlopen((dll*)obj); break; } default: { visitor.visit_object_code_block(obj); break; } } }; data->tenured->iterate(start_object_updater, fixup); auto updater = [&](code_block* compiled, cell size) { visitor.visit_code_block_objects(compiled); cell rel_base = compiled->entry_point() - fixup.code_offset; visitor.visit_instruction_operands(compiled, rel_base); }; code->allocator->iterate(updater, fixup); }