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_) {} parent(parent_), visitor(visitor_) {}
void visit_object_code_block(object *obj); 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_context_code_blocks();
void visit_callback_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> template<typename Visitor>
struct referenced_code_blocks_visitor { struct embedded_code_pointers_visitor {
Visitor 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) void operator()(relocation_entry rel, cell index, code_block *compiled)
{ {
relocation_type type = rel.rel_type(); relocation_type type = rel.rel_type();
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 + 1)); instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
cell literal = op.load_value(); cell literal = op.load_value();
code_block *compiled = ((code_block *)literal - 1); code_block *compiled = ((code_block *)literal - 1);
compiled = visitor(compiled); compiled = visitor(compiled);
@ -88,11 +88,11 @@ struct referenced_code_blocks_visitor {
}; };
template<typename 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)) 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); 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: case RT_HERE:
{ {
fixnum arg = untag_fixnum(ARG); 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: case RT_THIS:
return (cell)(compiled + 1); return (cell)compiled->xt();
case RT_CONTEXT: case RT_CONTEXT:
return (cell)&ctx; return (cell)&ctx;
case RT_UNTAGGED: 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 offset = untag_fixnum(array_nth(labels,i + 1));
cell target = untag_fixnum(array_nth(labels,i + 2)); cell target = untag_fixnum(array_nth(labels,i + 2));
instruction_operand op(rel_class,offset + (cell)(compiled + 1)); instruction_operand op(rel_class,offset + (cell)compiled->xt());
op.store_value(target + (cell)(compiled + 1)); op.store_value(target + (cell)compiled->xt());
} }
} }

View File

@ -103,19 +103,6 @@ void factor_vm::update_code_heap_words()
iterate_code_heap(updater); 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() void factor_vm::primitive_modify_code_heap()
{ {
data_root<array> alist(dpop(),this); data_root<array> alist(dpop(),this);

View File

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

View File

@ -2,6 +2,21 @@
namespace factor { 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 { template<typename Block> struct forwarder {
mark_bits<Block> *forwarding_map; 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; factor_vm *parent;
SlotForwarder slot_forwarder; code_block *old_address;
explicit code_block_compaction_updater(factor_vm *parent_, SlotForwarder slot_forwarder_) : explicit relative_address_updater(factor_vm *parent_, code_block *old_address_) :
parent(parent_), slot_forwarder(slot_forwarder_) {} 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) void operator()(code_block *old_address, code_block *new_address, cell size)
{ {
memmove(new_address,old_address,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(); data_forwarding_map->compute_forwarding();
code_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)); 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)); 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 /* Slide everything in the code heap up, and update data and code heap
pointers inside code blocks. */ 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; standard_sizer<code_block> code_block_sizer;
code->allocator->compact(code_block_updater,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 { 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_) : explicit object_code_block_updater(code_block_visitor<forwarder<code_block> > code_forwarder_) :
visitor(visitor_) {} code_forwarder(code_forwarder_) {}
void operator()(object *obj) void operator()(object *obj)
{ {
visitor->visit_object_code_block(obj); code_forwarder.visit_object_code_block(obj);
} }
}; };
struct dummy_slot_forwarder { struct code_block_grow_heap_updater {
void visit_referenced_literals(code_block *compiled) {} 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) void factor_vm::collect_compact_code_impl(bool trace_contexts_p)
{ {
/* Figure out where blocks are going to go */ /* Figure out where blocks are going to go */
mark_bits<code_block> *code_forwarding_map = &code->allocator->state; mark_bits<code_block> *code_forwarding_map = &code->allocator->state;
code_forwarding_map->compute_forwarding(); 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)); code_block_visitor<forwarder<code_block> > code_forwarder(this,forwarder<code_block>(code_forwarding_map));
if(trace_contexts_p) 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 */ /* Update code heap references in data heap */
object_code_block_updater updater(&code_forwarder); object_code_block_updater updater(code_forwarder);
each_object(updater); each_object(updater);
/* Slide everything in the code heap up, and update code heap /* Slide everything in the code heap up, and update code heap
pointers inside code blocks. */ pointers inside code blocks. */
dummy_slot_forwarder slot_forwarder; code_block_grow_heap_updater code_block_updater(this);
code_block_compaction_updater<dummy_slot_forwarder> code_block_updater(this,slot_forwarder);
standard_sizer<code_block> code_block_sizer; standard_sizer<code_block> code_block_sizer;
code->allocator->compact(code_block_updater,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) void full_collector::trace_code_block(code_block *compiled)
{ {
data_visitor.visit_referenced_literals(compiled); data_visitor.visit_code_block_objects(compiled);
code_visitor.visit_referenced_code_blocks(compiled); data_visitor.visit_embedded_literals(compiled);
code_visitor.visit_embedded_code_pointers(compiled);
} }
void full_collector::trace_context_code_blocks() 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; return (*ptr & mask) << shift;
} }
fixnum instruction_operand::load_value() fixnum instruction_operand::load_value(cell relative_to)
{ {
switch(rel_class) switch(rel_class)
{ {
@ -29,27 +29,32 @@ fixnum instruction_operand::load_value()
case RC_ABSOLUTE: case RC_ABSOLUTE:
return *(u32*)pointer; return *(u32*)pointer;
case RC_RELATIVE: case RC_RELATIVE:
return *(s32*)pointer + pointer + sizeof(u32); return *(s32*)pointer + relative_to + sizeof(u32);
case RC_ABSOLUTE_PPC_2_2: case RC_ABSOLUTE_PPC_2_2:
return load_value_2_2(); return load_value_2_2();
case RC_ABSOLUTE_PPC_2: case RC_ABSOLUTE_PPC_2:
return load_value_masked(rel_absolute_ppc_2_mask,0); return load_value_masked(rel_absolute_ppc_2_mask,0);
case RC_RELATIVE_PPC_2: 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: 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: 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: 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: 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: default:
critical_error("Bad rel class",rel_class); critical_error("Bad rel class",rel_class);
return 0; return 0;
} }
} }
fixnum instruction_operand::load_value()
{
return load_value(pointer);
}
/* 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)
{ {

View File

@ -128,6 +128,7 @@ struct instruction_operand {
fixnum load_value_2_2(); fixnum load_value_2_2();
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(); fixnum load_value();
void store_value_2_2(fixnum 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_bignum_roots();
void visit_roots(); void visit_roots();
void visit_contexts(); 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> template<typename Visitor>
@ -133,21 +134,25 @@ struct literal_references_visitor {
{ {
if(rel.rel_type() == RT_IMMEDIATE) if(rel.rel_type() == RT_IMMEDIATE)
{ {
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_address(); cell literal = op.load_value();
literal = visitor->visit_pointer(literal); literal = visitor->visit_pointer(literal);
op.store_address(literal); op.store_value(literal);
} }
} }
}; };
template<typename Visitor> 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->owner);
visit_handle(&compiled->literals); visit_handle(&compiled->literals);
visit_handle(&compiled->relocation); visit_handle(&compiled->relocation);
}
template<typename Visitor>
void slot_visitor<Visitor>::visit_embedded_literals(code_block *compiled)
{
if(!parent->code->needs_fixup_p(compiled)) if(!parent->code->needs_fixup_p(compiled))
{ {
literal_references_visitor<Visitor> visitor(this); 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_mark_impl(bool trace_contexts_p);
void collect_sweep_impl(); void collect_sweep_impl();
void collect_full(bool trace_contexts_p); 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_impl(bool trace_contexts_p);
void collect_compact_code_impl(bool trace_contexts_p); void collect_compact_code_impl(bool trace_contexts_p);
void collect_compact(bool trace_contexts_p); void collect_compact(bool trace_contexts_p);