diff --git a/vm/code_block_visitor.hpp b/vm/code_block_visitor.hpp index e9ed1d88ef..db4d7ed51a 100644 --- a/vm/code_block_visitor.hpp +++ b/vm/code_block_visitor.hpp @@ -78,11 +78,7 @@ struct embedded_code_pointers_visitor { if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL) { instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt()); - cell literal = op.load_value(); - code_block *compiled = ((code_block *)literal - 1); - compiled = visitor(compiled); - literal = (cell)compiled->xt(); - op.store_value(literal); + op.store_code_block(visitor(op.load_code_block())); } } }; diff --git a/vm/code_blocks.cpp b/vm/code_blocks.cpp index 7234ec3ef9..1907b55e1d 100755 --- a/vm/code_blocks.cpp +++ b/vm/code_blocks.cpp @@ -41,6 +41,94 @@ void *factor_vm::word_xt_pic_tail(word *w) return xt_pic(w,w->pic_tail_def); } +cell factor_vm::code_block_owner(code_block *compiled) +{ + tagged owner(compiled->owner); + + /* Cold generic word call sites point to quotations that call the + inline-cache-miss and inline-cache-miss-tail primitives. */ + if(owner.type_p(QUOTATION_TYPE)) + { + tagged quot(owner.as()); + tagged elements(quot->array); +#ifdef FACTOR_DEBUG + assert(array_capacity(elements.untagged()) == 5); + assert(array_nth(elements.untagged(),4) == special_objects[PIC_MISS_WORD] + || array_nth(elements.untagged(),4) == special_objects[PIC_MISS_TAIL_WORD]); +#endif + tagged word_wrapper(array_nth(elements.untagged(),0)); + return word_wrapper->object; + } + else + { +#ifdef FACTOR_DEBUG + assert(owner.type_p(WORD_TYPE)); +#endif + return compiled->owner; + } +} + +struct word_references_updater { + factor_vm *parent; + + word_references_updater(factor_vm *parent_) : parent(parent_) {} + + void operator()(relocation_entry rel, cell index, code_block *compiled) + { + relocation_type type = rel.rel_type(); + instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt()); + + switch(type) + { + case RT_XT: + { + code_block *compiled = op.load_code_block(); + op.store_value((cell)parent->object_xt(compiled->owner)); + break; + } + case RT_XT_PIC: + { + code_block *compiled = op.load_code_block(); + op.store_value((cell)parent->word_xt_pic(untag(parent->code_block_owner(compiled)))); + break; + } + case RT_XT_PIC_TAIL: + { + code_block *compiled = op.load_code_block(); + op.store_value((cell)parent->word_xt_pic_tail(untag(parent->code_block_owner(compiled)))); + break; + } + default: + break; + } + } +}; + +/* Relocate new code blocks completely; updating references to literals, +dlsyms, and words. For all other words in the code heap, we only need +to update references to other words, without worrying about literals +or dlsyms. */ +void factor_vm::update_word_references(code_block *compiled) +{ + if(code->needs_fixup_p(compiled)) + relocate_code_block(compiled); + /* update_word_references() is always applied to every block in + the code heap. Since it resets all call sites to point to + their canonical XT (cold entry point for non-tail calls, + standard entry point for tail calls), it means that no PICs + are referenced after this is done. So instead of polluting + the code heap with dead PICs that will be freed on the next + GC, we add them to the free list immediately. */ + else if(compiled->pic_p()) + code->code_heap_free(compiled); + else + { + word_references_updater updater(this); + iterate_relocations(compiled,updater); + compiled->flush_icache(); + } +} + /* References to undefined symbols are patched up to call this function on image load */ void factor_vm::undefined_symbol() @@ -144,57 +232,6 @@ cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block #undef ARG } -/* Compute an address to store at a relocation */ -void factor_vm::relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled) -{ -#ifdef FACTOR_DEBUG - if(to_boolean(compiled->literals)) - tagged(compiled->literals).untag_check(this); - if(to_boolean(compiled->relocation)) - tagged(compiled->relocation).untag_check(this); -#endif - - instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt()); - op.store_value(compute_relocation(rel,index,compiled)); -} - -struct word_references_updater { - factor_vm *parent; - - explicit word_references_updater(factor_vm *parent_) : parent(parent_) {} - void operator()(relocation_entry rel, cell index, code_block *compiled) - { - relocation_type type = rel.rel_type(); - if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL) - parent->relocate_code_block_step(rel,index,compiled); - } -}; - -/* Relocate new code blocks completely; updating references to literals, -dlsyms, and words. For all other words in the code heap, we only need -to update references to other words, without worrying about literals -or dlsyms. */ -void factor_vm::update_word_references(code_block *compiled) -{ - if(code->needs_fixup_p(compiled)) - relocate_code_block(compiled); - /* update_word_references() is always applied to every block in - the code heap. Since it resets all call sites to point to - their canonical XT (cold entry point for non-tail calls, - standard entry point for tail calls), it means that no PICs - are referenced after this is done. So instead of polluting - the code heap with dead PICs that will be freed on the next - GC, we add them to the free list immediately. */ - else if(compiled->pic_p()) - code->code_heap_free(compiled); - else - { - word_references_updater updater(this); - iterate_relocations(compiled,updater); - compiled->flush_icache(); - } -} - void factor_vm::check_code_address(cell address) { #ifdef FACTOR_DEBUG @@ -209,7 +246,8 @@ struct code_block_relocator { void operator()(relocation_entry rel, cell index, code_block *compiled) { - parent->relocate_code_block_step(rel,index,compiled); + instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt()); + op.store_value(parent->compute_relocation(rel,index,compiled)); } }; diff --git a/vm/instruction_operands.cpp b/vm/instruction_operands.cpp index 1ee10ea06a..6ad6b44a24 100644 --- a/vm/instruction_operands.cpp +++ b/vm/instruction_operands.cpp @@ -55,6 +55,11 @@ fixnum instruction_operand::load_value() return load_value(pointer); } +code_block *instruction_operand::load_code_block() +{ + return ((code_block *)load_value() - 1); +} + /* Store a 32-bit value into a PowerPC LIS/ORI sequence */ void instruction_operand::store_value_2_2(fixnum value) { @@ -118,4 +123,9 @@ void instruction_operand::store_value(fixnum absolute_value) } } +void instruction_operand::store_code_block(code_block *compiled) +{ + store_value((cell)compiled->xt()); +} + } diff --git a/vm/instruction_operands.hpp b/vm/instruction_operands.hpp index fc6b9c74bd..cc801723b2 100644 --- a/vm/instruction_operands.hpp +++ b/vm/instruction_operands.hpp @@ -130,10 +130,12 @@ struct instruction_operand { fixnum load_value_masked(cell mask, fixnum shift); fixnum load_value(cell relative_to); fixnum load_value(); + code_block *load_code_block(); void store_value_2_2(fixnum value); void store_value_masked(fixnum value, cell mask, fixnum shift); void store_value(fixnum value); + void store_code_block(code_block *compiled); }; } diff --git a/vm/quotations.cpp b/vm/quotations.cpp index 2275b59833..c476c06c69 100755 --- a/vm/quotations.cpp +++ b/vm/quotations.cpp @@ -295,7 +295,7 @@ void factor_vm::set_quot_xt(quotation *quot, code_block *code) /* Allocates memory */ code_block *factor_vm::jit_compile_quot(cell owner_, cell quot_, bool relocating) { - data_root owner(owner_,this); + data_root owner(owner_,this); data_root quot(quot_,this); quotation_jit compiler(owner.value(),true,relocating,this); diff --git a/vm/vm.hpp b/vm/vm.hpp index 986332eb1f..0ed8343948 100755 --- a/vm/vm.hpp +++ b/vm/vm.hpp @@ -504,6 +504,7 @@ struct factor_vm void *xt_pic(word *w, cell tagged_quot); void *word_xt_pic(word *w); void *word_xt_pic_tail(word *w); + cell code_block_owner(code_block *compiled); void undefined_symbol(); void *get_rel_symbol(array *literals, cell index); cell compute_relocation(relocation_entry rel, cell index, code_block *compiled); @@ -526,7 +527,6 @@ struct factor_vm } } - void relocate_code_block_step(relocation_entry rel, cell index, code_block *compiled); void update_word_references(code_block *compiled); void check_code_address(cell address); void relocate_code_block(code_block *compiled);