vm: new implementation of modify-code-heap that doesn't use literal tables
parent
4ebaf956c3
commit
77a877789a
|
@ -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()));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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<object> 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<quotation> quot(owner.as<quotation>());
|
||||
tagged<array> 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<wrapper> 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<word>(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<word>(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<array>(compiled->literals).untag_check(this);
|
||||
if(to_boolean(compiled->relocation))
|
||||
tagged<byte_array>(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));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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<word> owner(owner_,this);
|
||||
data_root<object> owner(owner_,this);
|
||||
data_root<quotation> quot(quot_,this);
|
||||
|
||||
quotation_jit compiler(owner.value(),true,relocating,this);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue