vm: compaction now updates the needs_fixup set

db4
Slava Pestov 2009-11-24 19:29:59 -06:00
parent 001a3f2847
commit bfd4cce364
10 changed files with 122 additions and 58 deletions

View File

@ -9,7 +9,7 @@ template<typename Visitor> struct code_block_visitor {
parent(parent_), visitor(visitor_) {}
void visit_object_code_block(object *obj);
void visit_referenced_code_blocks(code_block *compiled);
void visit_embedded_code_pointers(code_block *compiled);
void visit_context_code_blocks();
void visit_callback_code_blocks();
};
@ -67,17 +67,17 @@ void code_block_visitor<Visitor>::visit_object_code_block(object *obj)
}
template<typename Visitor>
struct referenced_code_blocks_visitor {
struct embedded_code_pointers_visitor {
Visitor visitor;
explicit referenced_code_blocks_visitor(Visitor visitor_) : visitor(visitor_) {}
explicit embedded_code_pointers_visitor(Visitor visitor_) : visitor(visitor_) {}
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)
{
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
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);
@ -88,11 +88,11 @@ struct referenced_code_blocks_visitor {
};
template<typename Visitor>
void code_block_visitor<Visitor>::visit_referenced_code_blocks(code_block *compiled)
void code_block_visitor<Visitor>::visit_embedded_code_pointers(code_block *compiled)
{
if(!parent->code->needs_fixup_p(compiled))
{
referenced_code_blocks_visitor<Visitor> visitor(this->visitor);
embedded_code_pointers_visitor<Visitor> visitor(this->visitor);
parent->iterate_relocations(compiled,visitor);
}
}

View File

@ -127,10 +127,10 @@ cell factor_vm::compute_relocation(relocation_entry rel, cell index, code_block
case RT_HERE:
{
fixnum arg = untag_fixnum(ARG);
return (arg >= 0 ? offset + arg : (cell)(compiled + 1) - arg);
return (arg >= 0 ? offset + arg : (cell)compiled->xt() - arg);
}
case RT_THIS:
return (cell)(compiled + 1);
return (cell)compiled->xt();
case RT_CONTEXT:
return (cell)&ctx;
case RT_UNTAGGED:
@ -241,8 +241,8 @@ void factor_vm::fixup_labels(array *labels, code_block *compiled)
cell offset = untag_fixnum(array_nth(labels,i + 1));
cell target = untag_fixnum(array_nth(labels,i + 2));
instruction_operand op(rel_class,offset + (cell)(compiled + 1));
op.store_value(target + (cell)(compiled + 1));
instruction_operand op(rel_class,offset + (cell)compiled->xt());
op.store_value(target + (cell)compiled->xt());
}
}

View File

@ -103,19 +103,6 @@ void factor_vm::update_code_heap_words()
iterate_code_heap(updater);
}
/* After growing the heap, we have to perform a full relocation to update
references to card and deck arrays. */
struct code_heap_relocator {
factor_vm *parent;
explicit code_heap_relocator(factor_vm *parent_) : parent(parent_) {}
void operator()(code_block *block, cell size)
{
parent->relocate_code_block(block);
}
};
void factor_vm::primitive_modify_code_heap()
{
data_root<array> alist(dpop(),this);

View File

@ -128,10 +128,14 @@ struct collector {
data_visitor.visit_contexts();
}
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
void trace_referenced_literals(code_block *compiled)
void trace_code_block_objects(code_block *compiled)
{
data_visitor.visit_referenced_literals(compiled);
data_visitor.visit_code_block_objects(compiled);
}
void trace_embedded_literals(code_block *compiled)
{
data_visitor.visit_embedded_literals(compiled);
}
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
@ -141,7 +145,8 @@ struct collector {
for(; iter != end; iter++)
{
trace_referenced_literals(*iter);
trace_code_block_objects(*iter);
trace_embedded_literals(*iter);
code_blocks_scanned++;
}
}

View File

@ -2,6 +2,21 @@
namespace factor {
void factor_vm::update_fixup_set_for_compaction(mark_bits<code_block> *forwarding_map)
{
std::set<code_block *>::const_iterator iter = code->needs_fixup.begin();
std::set<code_block *>::const_iterator end = code->needs_fixup.end();
std::set<code_block *> new_needs_fixup;
for(; iter != end; iter++)
{
printf("a block needs fixup\n");
new_needs_fixup.insert(forwarding_map->forward_block(*iter));
}
code->needs_fixup = new_needs_fixup;
}
template<typename Block> struct forwarder {
mark_bits<Block> *forwarding_map;
@ -85,18 +100,50 @@ struct object_compaction_updater {
}
};
template<typename SlotForwarder> struct code_block_compaction_updater {
struct relative_address_updater {
factor_vm *parent;
SlotForwarder slot_forwarder;
code_block *old_address;
explicit code_block_compaction_updater(factor_vm *parent_, SlotForwarder slot_forwarder_) :
parent(parent_), slot_forwarder(slot_forwarder_) {}
explicit relative_address_updater(factor_vm *parent_, code_block *old_address_) :
parent(parent_), old_address(old_address_) {}
void operator()(relocation_entry rel, cell index, code_block *compiled)
{
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
relocation_type type = rel.rel_type();
cell value;
if(type == RT_HERE || type == RT_THIS)
value = parent->compute_relocation(rel,index,compiled);
else
value = op.load_value(rel.rel_offset() + (cell)old_address->xt());
op.store_value(value);
}
};
template<typename SlotForwarder, typename CodeBlockForwarder>
struct code_block_compaction_updater {
factor_vm *parent;
slot_visitor<forwarder<object> > slot_forwarder;
code_block_visitor<forwarder<code_block> > code_forwarder;
explicit code_block_compaction_updater(factor_vm *parent_,
slot_visitor<forwarder<object> > slot_forwarder_,
code_block_visitor<forwarder<code_block> > code_forwarder_) :
parent(parent_), slot_forwarder(slot_forwarder_), code_forwarder(code_forwarder_) {}
void operator()(code_block *old_address, code_block *new_address, cell size)
{
memmove(new_address,old_address,size);
slot_forwarder.visit_referenced_literals(new_address);
parent->relocate_code_block(new_address);
slot_forwarder.visit_code_block_objects(new_address);
relative_address_updater updater(parent,old_address);
parent->iterate_relocations(new_address,updater);
slot_forwarder.visit_embedded_literals(new_address);
code_forwarder.visit_embedded_code_pointers(new_address);
}
};
@ -113,6 +160,8 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
data_forwarding_map->compute_forwarding();
code_forwarding_map->compute_forwarding();
update_fixup_set_for_compaction(code_forwarding_map);
slot_visitor<forwarder<object> > slot_forwarder(this,forwarder<object>(data_forwarding_map));
code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
@ -127,7 +176,7 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
/* Slide everything in the code heap up, and update data and code heap
pointers inside code blocks. */
code_block_compaction_updater<slot_visitor<forwarder<object> > > code_block_updater(this,slot_forwarder);
code_block_compaction_updater<slot_visitor<forwarder<object> >, code_block_visitor<forwarder<code_block> > > code_block_updater(this,slot_forwarder,code_forwarder);
standard_sizer<code_block> code_block_sizer;
code->allocator->compact(code_block_updater,code_block_sizer);
@ -145,27 +194,38 @@ void factor_vm::collect_compact_impl(bool trace_contexts_p)
}
struct object_code_block_updater {
code_block_visitor<forwarder<code_block> > *visitor;
code_block_visitor<forwarder<code_block> > code_forwarder;
explicit object_code_block_updater(code_block_visitor<forwarder<code_block> > *visitor_) :
visitor(visitor_) {}
explicit object_code_block_updater(code_block_visitor<forwarder<code_block> > code_forwarder_) :
code_forwarder(code_forwarder_) {}
void operator()(object *obj)
{
visitor->visit_object_code_block(obj);
code_forwarder.visit_object_code_block(obj);
}
};
struct dummy_slot_forwarder {
void visit_referenced_literals(code_block *compiled) {}
struct code_block_grow_heap_updater {
factor_vm *parent;
explicit code_block_grow_heap_updater(factor_vm *parent_) : parent(parent_) {}
void operator()(code_block *old_address, code_block *new_address, cell size)
{
memmove(new_address,old_address,size);
parent->relocate_code_block(new_address);
}
};
/* Compact just the code heap */
/* Compact just the code heap, after growing the data heap */
void factor_vm::collect_compact_code_impl(bool trace_contexts_p)
{
/* Figure out where blocks are going to go */
mark_bits<code_block> *code_forwarding_map = &code->allocator->state;
code_forwarding_map->compute_forwarding();
update_fixup_set_for_compaction(code_forwarding_map);
code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
if(trace_contexts_p)
@ -175,13 +235,12 @@ void factor_vm::collect_compact_code_impl(bool trace_contexts_p)
}
/* Update code heap references in data heap */
object_code_block_updater updater(&code_forwarder);
object_code_block_updater updater(code_forwarder);
each_object(updater);
/* Slide everything in the code heap up, and update code heap
pointers inside code blocks. */
dummy_slot_forwarder slot_forwarder;
code_block_compaction_updater<dummy_slot_forwarder> code_block_updater(this,slot_forwarder);
code_block_grow_heap_updater code_block_updater(this);
standard_sizer<code_block> code_block_sizer;
code->allocator->compact(code_block_updater,code_block_sizer);

View File

@ -17,8 +17,9 @@ full_collector::full_collector(factor_vm *parent_) :
void full_collector::trace_code_block(code_block *compiled)
{
data_visitor.visit_referenced_literals(compiled);
code_visitor.visit_referenced_code_blocks(compiled);
data_visitor.visit_code_block_objects(compiled);
data_visitor.visit_embedded_literals(compiled);
code_visitor.visit_embedded_code_pointers(compiled);
}
void full_collector::trace_context_code_blocks()

View File

@ -20,7 +20,7 @@ fixnum instruction_operand::load_value_masked(cell mask, fixnum shift)
return (*ptr & mask) << shift;
}
fixnum instruction_operand::load_value()
fixnum instruction_operand::load_value(cell relative_to)
{
switch(rel_class)
{
@ -29,27 +29,32 @@ fixnum instruction_operand::load_value()
case RC_ABSOLUTE:
return *(u32*)pointer;
case RC_RELATIVE:
return *(s32*)pointer + pointer + sizeof(u32);
return *(s32*)pointer + relative_to + sizeof(u32);
case RC_ABSOLUTE_PPC_2_2:
return load_value_2_2();
case RC_ABSOLUTE_PPC_2:
return load_value_masked(rel_absolute_ppc_2_mask,0);
case RC_RELATIVE_PPC_2:
return load_value_masked(rel_relative_ppc_2_mask,0) + pointer;
return load_value_masked(rel_relative_ppc_2_mask,0) + relative_to;
case RC_RELATIVE_PPC_3:
return load_value_masked(rel_relative_ppc_3_mask,0) + pointer;
return load_value_masked(rel_relative_ppc_3_mask,0) + relative_to;
case RC_RELATIVE_ARM_3:
return load_value_masked(rel_relative_arm_3_mask,2) + pointer + sizeof(cell) * 2;
return load_value_masked(rel_relative_arm_3_mask,2) + relative_to + sizeof(cell) * 2;
case RC_INDIRECT_ARM:
return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell);
return load_value_masked(rel_indirect_arm_mask,0) + relative_to + sizeof(cell);
case RC_INDIRECT_ARM_PC:
return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell) * 2;
return load_value_masked(rel_indirect_arm_mask,0) + relative_to + sizeof(cell) * 2;
default:
critical_error("Bad rel class",rel_class);
return 0;
}
}
fixnum instruction_operand::load_value()
{
return load_value(pointer);
}
/* Store a 32-bit value into a PowerPC LIS/ORI sequence */
void instruction_operand::store_value_2_2(fixnum value)
{

View File

@ -128,6 +128,7 @@ struct instruction_operand {
fixnum load_value_2_2();
fixnum load_value_masked(cell mask, fixnum shift);
fixnum load_value(cell relative_to);
fixnum load_value();
void store_value_2_2(fixnum value);

View File

@ -17,7 +17,8 @@ template<typename Visitor> struct slot_visitor {
void visit_bignum_roots();
void visit_roots();
void visit_contexts();
void visit_referenced_literals(code_block *compiled);
void visit_code_block_objects(code_block *compiled);
void visit_embedded_literals(code_block *compiled);
};
template<typename Visitor>
@ -133,21 +134,25 @@ struct literal_references_visitor {
{
if(rel.rel_type() == RT_IMMEDIATE)
{
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
cell literal = op.load_address();
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
cell literal = op.load_value();
literal = visitor->visit_pointer(literal);
op.store_address(literal);
op.store_value(literal);
}
}
};
template<typename Visitor>
void slot_visitor<Visitor>::visit_referenced_literals(code_block *compiled)
void slot_visitor<Visitor>::visit_code_block_objects(code_block *compiled)
{
visit_handle(&compiled->owner);
visit_handle(&compiled->literals);
visit_handle(&compiled->relocation);
}
template<typename Visitor>
void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
{
if(!parent->code->needs_fixup_p(compiled))
{
literal_references_visitor<Visitor> visitor(this);

View File

@ -288,6 +288,7 @@ struct factor_vm
void collect_mark_impl(bool trace_contexts_p);
void collect_sweep_impl();
void collect_full(bool trace_contexts_p);
void update_fixup_set_for_compaction(mark_bits<code_block> *forwarding_map);
void collect_compact_impl(bool trace_contexts_p);
void collect_compact_code_impl(bool trace_contexts_p);
void collect_compact(bool trace_contexts_p);