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)
|
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());
|
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
|
||||||
cell literal = op.load_value();
|
op.store_code_block(visitor(op.load_code_block()));
|
||||||
code_block *compiled = ((code_block *)literal - 1);
|
|
||||||
compiled = visitor(compiled);
|
|
||||||
literal = (cell)compiled->xt();
|
|
||||||
op.store_value(literal);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,94 @@ void *factor_vm::word_xt_pic_tail(word *w)
|
||||||
return xt_pic(w,w->pic_tail_def);
|
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
|
/* References to undefined symbols are patched up to call this function on
|
||||||
image load */
|
image load */
|
||||||
void factor_vm::undefined_symbol()
|
void factor_vm::undefined_symbol()
|
||||||
|
|
@ -144,57 +232,6 @@ cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block
|
||||||
#undef ARG
|
#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)
|
void factor_vm::check_code_address(cell address)
|
||||||
{
|
{
|
||||||
#ifdef FACTOR_DEBUG
|
#ifdef FACTOR_DEBUG
|
||||||
|
|
@ -209,7 +246,8 @@ struct code_block_relocator {
|
||||||
|
|
||||||
void operator()(relocation_entry rel, cell index, code_block *compiled)
|
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);
|
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 */
|
/* Store a 32-bit value into a PowerPC LIS/ORI sequence */
|
||||||
void instruction_operand::store_value_2_2(fixnum value)
|
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_masked(cell mask, fixnum shift);
|
||||||
fixnum load_value(cell relative_to);
|
fixnum load_value(cell relative_to);
|
||||||
fixnum load_value();
|
fixnum load_value();
|
||||||
|
code_block *load_code_block();
|
||||||
|
|
||||||
void store_value_2_2(fixnum value);
|
void store_value_2_2(fixnum value);
|
||||||
void store_value_masked(fixnum value, cell mask, fixnum shift);
|
void store_value_masked(fixnum value, cell mask, fixnum shift);
|
||||||
void store_value(fixnum value);
|
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 */
|
/* Allocates memory */
|
||||||
code_block *factor_vm::jit_compile_quot(cell owner_, cell quot_, bool relocating)
|
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);
|
data_root<quotation> quot(quot_,this);
|
||||||
|
|
||||||
quotation_jit compiler(owner.value(),true,relocating,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 *xt_pic(word *w, cell tagged_quot);
|
||||||
void *word_xt_pic(word *w);
|
void *word_xt_pic(word *w);
|
||||||
void *word_xt_pic_tail(word *w);
|
void *word_xt_pic_tail(word *w);
|
||||||
|
cell code_block_owner(code_block *compiled);
|
||||||
void undefined_symbol();
|
void undefined_symbol();
|
||||||
void *get_rel_symbol(array *literals, cell index);
|
void *get_rel_symbol(array *literals, cell index);
|
||||||
cell compute_relocation(relocation_entry rel, cell index, code_block *compiled);
|
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 update_word_references(code_block *compiled);
|
||||||
void check_code_address(cell address);
|
void check_code_address(cell address);
|
||||||
void relocate_code_block(code_block *compiled);
|
void relocate_code_block(code_block *compiled);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue