VM: new method visit_instruction_operands(), it replaces the instruction
operand iteration code in compaction.cpp and image.cppdb4
parent
e565b0291f
commit
03d861976c
|
@ -52,37 +52,6 @@ struct compaction_fixup {
|
|||
}
|
||||
};
|
||||
|
||||
template <typename Fixup>
|
||||
fixnum compute_operand_value(factor_vm* parent,
|
||||
cell old_entry_point,
|
||||
Fixup fixup,
|
||||
instruction_operand op) {
|
||||
cell old_offset = op.rel_offset() + old_entry_point;
|
||||
switch (op.rel_type()) {
|
||||
case RT_LITERAL: {
|
||||
cell value = op.load_value(old_offset);
|
||||
if (immediate_p(value))
|
||||
return value;
|
||||
return RETAG(fixup.fixup_data(untag<object>(value)), TAG(value));
|
||||
}
|
||||
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);
|
||||
return (cell)fixup.fixup_code(compiled) + offset;
|
||||
}
|
||||
case RT_THIS:
|
||||
case RT_CARDS_OFFSET:
|
||||
case RT_DECKS_OFFSET:
|
||||
return parent->compute_external_address(op);
|
||||
default:
|
||||
return op.load_value(old_offset);
|
||||
}
|
||||
}
|
||||
|
||||
/* After a compaction, invalidate any code heap roots which are not
|
||||
marked, and also slide the valid roots up so that call sites can be updated
|
||||
correctly in case an inline cache compilation triggered compaction. */
|
||||
|
@ -148,20 +117,14 @@ void factor_vm::collect_compact_impl() {
|
|||
|
||||
/* Slide everything in the code heap up, and update data and code heap
|
||||
pointers inside code blocks. */
|
||||
auto compact_data_func = [&](code_block* old_addr,
|
||||
auto compact_code_func = [&](code_block* old_addr,
|
||||
code_block* new_addr,
|
||||
cell size) {
|
||||
forwarder.visit_code_block_objects(new_addr);
|
||||
cell old_entry_point = old_addr->entry_point();
|
||||
auto update_func = [&](instruction_operand op) {
|
||||
op.store_value(compute_operand_value(this,
|
||||
old_entry_point,
|
||||
forwarder.fixup,
|
||||
op));
|
||||
forwarder.visit_instruction_operands(new_addr, old_entry_point);
|
||||
};
|
||||
new_addr->each_instruction_operand(update_func);
|
||||
};
|
||||
code->allocator->compact(compact_data_func, fixup, &code_finger);
|
||||
code->allocator->compact(compact_code_func, fixup, &code_finger);
|
||||
|
||||
forwarder.visit_all_roots();
|
||||
forwarder.visit_context_code_blocks();
|
||||
|
|
48
vm/image.cpp
48
vm/image.cpp
|
@ -109,57 +109,13 @@ void factor_vm::fixup_data(cell data_offset, cell code_offset) {
|
|||
data->tenured->iterate(start_object_updater, fixup);
|
||||
}
|
||||
|
||||
struct startup_code_block_relocation_visitor {
|
||||
factor_vm* parent;
|
||||
startup_fixup fixup;
|
||||
slot_visitor<startup_fixup> visitor;
|
||||
|
||||
startup_code_block_relocation_visitor(factor_vm* parent,
|
||||
startup_fixup fixup)
|
||||
: parent(parent),
|
||||
fixup(fixup),
|
||||
visitor(slot_visitor<startup_fixup>(parent, fixup)) {}
|
||||
|
||||
fixnum compute_operand_value(instruction_operand op) {
|
||||
code_block* compiled = op.compiled;
|
||||
cell old_offset =
|
||||
op.rel_offset() + compiled->entry_point() - fixup.code_offset;
|
||||
switch (op.rel_type()) {
|
||||
case RT_LITERAL: {
|
||||
cell value = op.load_value(old_offset);
|
||||
if (immediate_p(value))
|
||||
return value;
|
||||
return RETAG(fixup.fixup_data(untag<object>(value)), TAG(value));
|
||||
}
|
||||
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);
|
||||
return (cell)fixup.fixup_code(compiled) + offset;
|
||||
}
|
||||
case RT_UNTAGGED:
|
||||
return op.load_value(old_offset);
|
||||
default:
|
||||
return parent->compute_external_address(op);
|
||||
}
|
||||
}
|
||||
|
||||
void operator()(instruction_operand op) {
|
||||
op.store_value(compute_operand_value(op));
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::fixup_code(cell data_offset, cell code_offset) {
|
||||
startup_fixup fixup(data_offset, code_offset);
|
||||
auto updater = [&](code_block* compiled, cell size) {
|
||||
slot_visitor<startup_fixup> visitor(this, fixup);
|
||||
visitor.visit_code_block_objects(compiled);
|
||||
|
||||
startup_code_block_relocation_visitor code_visitor(this, fixup);
|
||||
compiled->each_instruction_operand(code_visitor);
|
||||
cell rel_base = compiled->entry_point() - fixup.code_offset;
|
||||
visitor.visit_instruction_operands(compiled, rel_base);
|
||||
};
|
||||
code->allocator->iterate(updater, fixup);
|
||||
}
|
||||
|
|
|
@ -141,6 +141,7 @@ template <typename Fixup> struct slot_visitor {
|
|||
void visit_embedded_code_pointers(code_block* compiled);
|
||||
void visit_object(object* obj);
|
||||
void visit_mark_stack(std::vector<cell>* mark_stack);
|
||||
void visit_instruction_operands(code_block* block, cell rel_base);
|
||||
};
|
||||
|
||||
template <typename Fixup>
|
||||
|
@ -466,4 +467,40 @@ void slot_visitor<Fixup>::visit_mark_stack(std::vector<cell>* mark_stack) {
|
|||
}
|
||||
}
|
||||
|
||||
/* Visits the instruction operands in a code block. If the operand is
|
||||
a pointer to a code block or data object, then the fixup is applied
|
||||
to it. Otherwise, if it is an external addess, that address is
|
||||
recomputed. If it is an untagged number literal (RT_UNTAGGED) or an
|
||||
immediate value, then nothing is done with it. */
|
||||
template <typename Fixup>
|
||||
void slot_visitor<Fixup>::visit_instruction_operands(code_block* block,
|
||||
cell rel_base) {
|
||||
auto visit_func = [&](instruction_operand op){
|
||||
cell old_offset = rel_base + op.rel_offset();
|
||||
cell value = op.load_value(old_offset);
|
||||
switch (op.rel_type()) {
|
||||
case RT_LITERAL: {
|
||||
value = visit_pointer(value);
|
||||
break;
|
||||
}
|
||||
case RT_ENTRY_POINT:
|
||||
case RT_ENTRY_POINT_PIC:
|
||||
case RT_ENTRY_POINT_PIC_TAIL:
|
||||
case RT_HERE: {
|
||||
cell offset = TAG(value);
|
||||
code_block* compiled = (code_block*)UNTAG(value);
|
||||
value = RETAG(fixup.fixup_code(compiled), offset);
|
||||
break;
|
||||
}
|
||||
case RT_UNTAGGED:
|
||||
break;
|
||||
default:
|
||||
value = parent->compute_external_address(op);
|
||||
break;
|
||||
}
|
||||
op.store_value(value);
|
||||
};
|
||||
block->each_instruction_operand(visit_func);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue