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();
};
}
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);
};
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);
}
}
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:
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());
}
}
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);
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)
for(; iter != end; iter++)
{
- trace_referenced_literals(*iter);
+ trace_code_block_objects(*iter);
+ trace_embedded_literals(*iter);
code_blocks_scanned++;
}
}
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;
}
};
-template<typename SlotForwarder> struct code_block_compaction_updater {
+struct relative_address_updater {
+ factor_vm *parent;
+ code_block *old_address;
+
+ 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;
- SlotForwarder slot_forwarder;
+ slot_visitor<forwarder<object> > slot_forwarder;
+ code_block_visitor<forwarder<code_block> > code_forwarder;
- explicit code_block_compaction_updater(factor_vm *parent_, SlotForwarder slot_forwarder_) :
- parent(parent_), slot_forwarder(slot_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);
}
};
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));
/* 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);
}
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)
}
/* 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);
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()
return (*ptr & mask) << shift;
}
-fixnum instruction_operand::load_value()
+fixnum instruction_operand::load_value(cell relative_to)
{
switch(rel_class)
{
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)
{
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);
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>
{
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);
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);