vm: mark sweep now traces code block references; rename embedded_pointer to instruction_operand
parent
f96b127ba9
commit
001a3f2847
2
Makefile
2
Makefile
|
@ -47,7 +47,6 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
|
|||
vm/data_heap_checker.o \
|
||||
vm/debug.o \
|
||||
vm/dispatch.o \
|
||||
vm/embedded_pointers.o \
|
||||
vm/errors.o \
|
||||
vm/factor.o \
|
||||
vm/free_list.o \
|
||||
|
@ -55,6 +54,7 @@ DLL_OBJS = $(PLAF_DLL_OBJS) \
|
|||
vm/gc.o \
|
||||
vm/image.o \
|
||||
vm/inline_cache.o \
|
||||
vm/instruction_operands.o \
|
||||
vm/io.o \
|
||||
vm/jit.o \
|
||||
vm/math.o \
|
||||
|
|
|
@ -22,7 +22,7 @@ void factor_vm::collect_aging()
|
|||
|
||||
to_tenured_collector collector(this);
|
||||
|
||||
current_gc->event->started_code_scan();
|
||||
current_gc->event->started_card_scan();
|
||||
collector.trace_cards(data->tenured,
|
||||
card_points_to_aging,
|
||||
full_unmarker());
|
||||
|
|
|
@ -26,8 +26,8 @@ void callback_heap::update(callback *stub)
|
|||
cell rel_class = untag_fixnum(array_nth(code_template.untagged(),1));
|
||||
cell offset = untag_fixnum(array_nth(code_template.untagged(),3));
|
||||
|
||||
embedded_pointer ptr(rel_class,offset + (cell)(stub + 1));
|
||||
ptr.store_address((cell)(stub->compiled + 1));
|
||||
instruction_operand op(rel_class,offset + (cell)(stub + 1));
|
||||
op.store_value((cell)(stub->compiled + 1));
|
||||
|
||||
flush_icache((cell)stub,stub->size);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,21 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
template<typename Visitor> struct call_frame_code_block_visitor {
|
||||
template<typename Visitor> struct code_block_visitor {
|
||||
factor_vm *parent;
|
||||
Visitor visitor;
|
||||
|
||||
explicit code_block_visitor(factor_vm *parent_, Visitor visitor_) :
|
||||
parent(parent_), visitor(visitor_) {}
|
||||
|
||||
void visit_object_code_block(object *obj);
|
||||
void visit_referenced_code_blocks(code_block *compiled);
|
||||
void visit_context_code_blocks();
|
||||
void visit_callback_code_blocks();
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
struct call_frame_code_block_visitor {
|
||||
factor_vm *parent;
|
||||
Visitor visitor;
|
||||
|
||||
|
@ -19,29 +33,9 @@ template<typename Visitor> struct call_frame_code_block_visitor {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename Visitor> struct callback_code_block_visitor {
|
||||
callback_heap *callbacks;
|
||||
Visitor visitor;
|
||||
|
||||
explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
|
||||
callbacks(callbacks_), visitor(visitor_) {}
|
||||
|
||||
void operator()(callback *stub)
|
||||
{
|
||||
stub->compiled = visitor(stub->compiled);
|
||||
callbacks->update(stub);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Visitor> struct code_block_visitor {
|
||||
factor_vm *parent;
|
||||
Visitor visitor;
|
||||
|
||||
explicit code_block_visitor(factor_vm *parent_, Visitor visitor_) :
|
||||
parent(parent_), visitor(visitor_) {}
|
||||
|
||||
void visit_object_code_block(object *obj)
|
||||
{
|
||||
template<typename Visitor>
|
||||
void code_block_visitor<Visitor>::visit_object_code_block(object *obj)
|
||||
{
|
||||
switch(obj->type())
|
||||
{
|
||||
case WORD_TYPE:
|
||||
|
@ -70,20 +64,66 @@ template<typename Visitor> struct code_block_visitor {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void visit_context_code_blocks()
|
||||
template<typename Visitor>
|
||||
struct referenced_code_blocks_visitor {
|
||||
Visitor visitor;
|
||||
|
||||
explicit referenced_code_blocks_visitor(Visitor visitor_) : visitor(visitor_) {}
|
||||
|
||||
void operator()(relocation_entry rel, cell index, code_block *compiled)
|
||||
{
|
||||
call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
|
||||
parent->iterate_active_frames(call_frame_visitor);
|
||||
}
|
||||
|
||||
void visit_callback_code_blocks()
|
||||
relocation_type type = rel.rel_type();
|
||||
if(type == RT_XT || type == RT_XT_PIC || type == RT_XT_PIC_TAIL)
|
||||
{
|
||||
callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
|
||||
parent->callbacks->iterate(callback_visitor);
|
||||
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
|
||||
cell literal = op.load_value();
|
||||
code_block *compiled = ((code_block *)literal - 1);
|
||||
compiled = visitor(compiled);
|
||||
literal = (cell)compiled->xt();
|
||||
op.store_value(literal);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
void code_block_visitor<Visitor>::visit_referenced_code_blocks(code_block *compiled)
|
||||
{
|
||||
if(!parent->code->needs_fixup_p(compiled))
|
||||
{
|
||||
referenced_code_blocks_visitor<Visitor> visitor(this->visitor);
|
||||
parent->iterate_relocations(compiled,visitor);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
void code_block_visitor<Visitor>::visit_context_code_blocks()
|
||||
{
|
||||
call_frame_code_block_visitor<Visitor> call_frame_visitor(parent,visitor);
|
||||
parent->iterate_active_frames(call_frame_visitor);
|
||||
}
|
||||
|
||||
template<typename Visitor>
|
||||
struct callback_code_block_visitor {
|
||||
callback_heap *callbacks;
|
||||
Visitor visitor;
|
||||
|
||||
explicit callback_code_block_visitor(callback_heap *callbacks_, Visitor visitor_) :
|
||||
callbacks(callbacks_), visitor(visitor_) {}
|
||||
|
||||
void operator()(callback *stub)
|
||||
{
|
||||
stub->compiled = visitor(stub->compiled);
|
||||
callbacks->update(stub);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
void code_block_visitor<Visitor>::visit_callback_code_blocks()
|
||||
{
|
||||
callback_code_block_visitor<Visitor> callback_visitor(parent->callbacks,visitor);
|
||||
parent->callbacks->iterate(callback_visitor);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -161,8 +161,8 @@ void factor_vm::relocate_code_block_step(relocation_entry rel, cell index, code_
|
|||
tagged<byte_array>(compiled->relocation).untag_check(this);
|
||||
#endif
|
||||
|
||||
embedded_pointer ptr(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
|
||||
ptr.store_address(compute_relocation(rel,index,compiled));
|
||||
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)compiled->xt());
|
||||
op.store_value(compute_relocation(rel,index,compiled));
|
||||
}
|
||||
|
||||
struct word_references_updater {
|
||||
|
@ -202,42 +202,6 @@ void factor_vm::update_word_references(code_block *compiled)
|
|||
}
|
||||
}
|
||||
|
||||
/* This runs after a full collection */
|
||||
struct literal_and_word_references_updater {
|
||||
factor_vm *parent;
|
||||
|
||||
explicit literal_and_word_references_updater(factor_vm *parent_) : parent(parent_) {}
|
||||
|
||||
void operator()(relocation_entry rel, cell index, code_block *compiled)
|
||||
{
|
||||
relocation_type type = rel.rel_type();
|
||||
|
||||
switch(type)
|
||||
{
|
||||
case RT_IMMEDIATE:
|
||||
case RT_XT:
|
||||
case RT_XT_PIC:
|
||||
case RT_XT_PIC_TAIL:
|
||||
parent->relocate_code_block_step(rel,index,compiled);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::update_code_block_words_and_literals(code_block *compiled)
|
||||
{
|
||||
if(code->needs_fixup_p(compiled))
|
||||
relocate_code_block(compiled);
|
||||
else
|
||||
{
|
||||
literal_and_word_references_updater updater(this);
|
||||
iterate_relocations(compiled,updater);
|
||||
flush_icache_for(compiled);
|
||||
}
|
||||
}
|
||||
|
||||
void factor_vm::check_code_address(cell address)
|
||||
{
|
||||
#ifdef FACTOR_DEBUG
|
||||
|
@ -277,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));
|
||||
|
||||
embedded_pointer ptr(rel_class,offset + (cell)(compiled + 1));
|
||||
ptr.store_address(target + (cell)(compiled + 1));
|
||||
instruction_operand op(rel_class,offset + (cell)(compiled + 1));
|
||||
op.store_value(target + (cell)(compiled + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -103,25 +103,6 @@ void factor_vm::update_code_heap_words()
|
|||
iterate_code_heap(updater);
|
||||
}
|
||||
|
||||
/* After a full GC that did not grow the heap, we have to update references
|
||||
to literals and other words. */
|
||||
struct word_and_literal_code_heap_updater {
|
||||
factor_vm *parent;
|
||||
|
||||
explicit word_and_literal_code_heap_updater(factor_vm *parent_) : parent(parent_) {}
|
||||
|
||||
void operator()(code_block *block, cell size)
|
||||
{
|
||||
parent->update_code_block_words_and_literals(block);
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::update_code_heap_words_and_literals()
|
||||
{
|
||||
word_and_literal_code_heap_updater updater(this);
|
||||
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 {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
template<typename TargetGeneration, typename Policy> struct collector_workhorse {
|
||||
template<typename TargetGeneration, typename Policy> struct data_workhorse {
|
||||
factor_vm *parent;
|
||||
TargetGeneration *target;
|
||||
Policy policy;
|
||||
|
||||
explicit collector_workhorse(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
|
||||
explicit data_workhorse(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
|
||||
parent(parent_),
|
||||
target(target_),
|
||||
policy(policy_) {}
|
||||
|
@ -61,13 +61,13 @@ template<typename TargetGeneration, typename Policy> struct collector_workhorse
|
|||
};
|
||||
|
||||
template<typename TargetGeneration, typename Policy>
|
||||
inline static slot_visitor<collector_workhorse<TargetGeneration,Policy> > make_collector_workhorse(
|
||||
inline static slot_visitor<data_workhorse<TargetGeneration,Policy> > make_data_visitor(
|
||||
factor_vm *parent,
|
||||
TargetGeneration *target,
|
||||
Policy policy)
|
||||
{
|
||||
return slot_visitor<collector_workhorse<TargetGeneration,Policy> >(parent,
|
||||
collector_workhorse<TargetGeneration,Policy>(parent,target,policy));
|
||||
return slot_visitor<data_workhorse<TargetGeneration,Policy> >(parent,
|
||||
data_workhorse<TargetGeneration,Policy>(parent,target,policy));
|
||||
}
|
||||
|
||||
struct dummy_unmarker {
|
||||
|
@ -85,12 +85,13 @@ struct full_unmarker {
|
|||
void operator()(card *ptr) { *ptr = 0; }
|
||||
};
|
||||
|
||||
template<typename TargetGeneration, typename Policy> struct collector {
|
||||
template<typename TargetGeneration, typename Policy>
|
||||
struct collector {
|
||||
factor_vm *parent;
|
||||
data_heap *data;
|
||||
code_heap *code;
|
||||
TargetGeneration *target;
|
||||
slot_visitor<collector_workhorse<TargetGeneration,Policy> > workhorse;
|
||||
slot_visitor<data_workhorse<TargetGeneration,Policy> > data_visitor;
|
||||
cell cards_scanned;
|
||||
cell decks_scanned;
|
||||
cell code_blocks_scanned;
|
||||
|
@ -100,37 +101,37 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
data(parent_->data),
|
||||
code(parent_->code),
|
||||
target(target_),
|
||||
workhorse(make_collector_workhorse(parent_,target_,policy_)),
|
||||
data_visitor(make_data_visitor(parent_,target_,policy_)),
|
||||
cards_scanned(0),
|
||||
decks_scanned(0),
|
||||
code_blocks_scanned(0) {}
|
||||
|
||||
void trace_handle(cell *handle)
|
||||
{
|
||||
workhorse.visit_handle(handle);
|
||||
data_visitor.visit_handle(handle);
|
||||
}
|
||||
|
||||
void trace_object(object *ptr)
|
||||
{
|
||||
workhorse.visit_slots(ptr);
|
||||
data_visitor.visit_slots(ptr);
|
||||
if(ptr->type() == ALIEN_TYPE)
|
||||
((alien *)ptr)->update_address();
|
||||
}
|
||||
|
||||
void trace_roots()
|
||||
{
|
||||
workhorse.visit_roots();
|
||||
data_visitor.visit_roots();
|
||||
}
|
||||
|
||||
void trace_contexts()
|
||||
{
|
||||
workhorse.visit_contexts();
|
||||
data_visitor.visit_contexts();
|
||||
}
|
||||
|
||||
/* Trace all literals referenced from a code block. Only for aging and nursery collections */
|
||||
void trace_literal_references(code_block *compiled)
|
||||
void trace_referenced_literals(code_block *compiled)
|
||||
{
|
||||
workhorse.visit_literal_references(compiled);
|
||||
data_visitor.visit_referenced_literals(compiled);
|
||||
}
|
||||
|
||||
void trace_code_heap_roots(std::set<code_block *> *remembered_set)
|
||||
|
@ -140,7 +141,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
|
||||
for(; iter != end; iter++)
|
||||
{
|
||||
trace_literal_references(*iter);
|
||||
trace_referenced_literals(*iter);
|
||||
code_blocks_scanned++;
|
||||
}
|
||||
}
|
||||
|
@ -183,7 +184,7 @@ template<typename TargetGeneration, typename Policy> struct collector {
|
|||
cell *end_ptr = (cell *)end;
|
||||
|
||||
for(; slot_ptr < end_ptr; slot_ptr++)
|
||||
workhorse.visit_handle(slot_ptr);
|
||||
data_visitor.visit_handle(slot_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -95,7 +95,7 @@ template<typename SlotForwarder> struct code_block_compaction_updater {
|
|||
void operator()(code_block *old_address, code_block *new_address, cell size)
|
||||
{
|
||||
memmove(new_address,old_address,size);
|
||||
slot_forwarder.visit_literal_references(new_address);
|
||||
slot_forwarder.visit_referenced_literals(new_address);
|
||||
parent->relocate_code_block(new_address);
|
||||
}
|
||||
};
|
||||
|
@ -157,7 +157,7 @@ struct object_code_block_updater {
|
|||
};
|
||||
|
||||
struct dummy_slot_forwarder {
|
||||
void visit_literal_references(code_block *compiled) {}
|
||||
void visit_referenced_literals(code_block *compiled) {}
|
||||
};
|
||||
|
||||
/* Compact just the code heap */
|
||||
|
|
|
@ -217,7 +217,7 @@ data_heap_room factor_vm::data_room()
|
|||
room.tenured_free_block_count = data->tenured->free_block_count();
|
||||
room.cards = data->cards_end - data->cards;
|
||||
room.decks = data->decks_end - data->decks;
|
||||
room.mark_stack = data->tenured->mark_stack.capacity() * sizeof(cell);
|
||||
room.mark_stack = mark_stack.capacity() * sizeof(cell);
|
||||
|
||||
return room;
|
||||
}
|
||||
|
|
|
@ -3,11 +3,38 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
inline static code_block_visitor<code_workhorse> make_code_visitor(factor_vm *parent)
|
||||
{
|
||||
return code_block_visitor<code_workhorse>(parent,code_workhorse(parent));
|
||||
}
|
||||
|
||||
full_collector::full_collector(factor_vm *parent_) :
|
||||
collector<tenured_space,full_policy>(
|
||||
parent_,
|
||||
parent_->data->tenured,
|
||||
full_policy(parent_)) {}
|
||||
full_policy(parent_)),
|
||||
code_visitor(make_code_visitor(parent_)) {}
|
||||
|
||||
void full_collector::trace_code_block(code_block *compiled)
|
||||
{
|
||||
data_visitor.visit_referenced_literals(compiled);
|
||||
code_visitor.visit_referenced_code_blocks(compiled);
|
||||
}
|
||||
|
||||
void full_collector::trace_context_code_blocks()
|
||||
{
|
||||
code_visitor.visit_context_code_blocks();
|
||||
}
|
||||
|
||||
void full_collector::trace_callback_code_blocks()
|
||||
{
|
||||
code_visitor.visit_callback_code_blocks();
|
||||
}
|
||||
|
||||
void full_collector::trace_object_code_block(object *obj)
|
||||
{
|
||||
code_visitor.visit_object_code_block(obj);
|
||||
}
|
||||
|
||||
/* After a sweep, invalidate any code heap roots which are not marked,
|
||||
so that if a block makes a tail call to a generic word, and the PIC
|
||||
|
@ -57,51 +84,39 @@ void factor_vm::update_code_roots_for_compaction()
|
|||
}
|
||||
}
|
||||
|
||||
struct code_block_marker {
|
||||
code_heap *code;
|
||||
full_collector *collector;
|
||||
|
||||
explicit code_block_marker(code_heap *code_, full_collector *collector_) :
|
||||
code(code_), collector(collector_) {}
|
||||
|
||||
code_block *operator()(code_block *compiled)
|
||||
{
|
||||
if(!code->marked_p(compiled))
|
||||
{
|
||||
code->set_marked_p(compiled);
|
||||
collector->trace_literal_references(compiled);
|
||||
}
|
||||
|
||||
return compiled;
|
||||
}
|
||||
};
|
||||
|
||||
void factor_vm::collect_mark_impl(bool trace_contexts_p)
|
||||
{
|
||||
full_collector collector(this);
|
||||
|
||||
mark_stack.clear();
|
||||
|
||||
code->clear_mark_bits();
|
||||
data->tenured->clear_mark_bits();
|
||||
data->tenured->clear_mark_stack();
|
||||
|
||||
code_block_visitor<code_block_marker> code_marker(this,code_block_marker(code,&collector));
|
||||
|
||||
collector.trace_roots();
|
||||
if(trace_contexts_p)
|
||||
{
|
||||
collector.trace_contexts();
|
||||
code_marker.visit_context_code_blocks();
|
||||
code_marker.visit_callback_code_blocks();
|
||||
collector.trace_context_code_blocks();
|
||||
collector.trace_callback_code_blocks();
|
||||
}
|
||||
|
||||
std::vector<object *> *mark_stack = &data->tenured->mark_stack;
|
||||
|
||||
while(!mark_stack->empty())
|
||||
while(!mark_stack.empty())
|
||||
{
|
||||
object *obj = mark_stack->back();
|
||||
mark_stack->pop_back();
|
||||
cell ptr = mark_stack.back();
|
||||
mark_stack.pop_back();
|
||||
|
||||
if(ptr & 1)
|
||||
{
|
||||
code_block *compiled = (code_block *)(ptr - 1);
|
||||
collector.trace_code_block(compiled);
|
||||
}
|
||||
else
|
||||
{
|
||||
object *obj = (object *)ptr;
|
||||
collector.trace_object(obj);
|
||||
code_marker.visit_object_code_block(obj);
|
||||
collector.trace_object_code_block(obj);
|
||||
}
|
||||
}
|
||||
|
||||
data->reset_generation(data->tenured);
|
||||
|
@ -133,8 +148,6 @@ void factor_vm::collect_full(bool trace_contexts_p)
|
|||
current_gc->event->op = collect_compact_op;
|
||||
collect_compact_impl(trace_contexts_p);
|
||||
}
|
||||
else
|
||||
update_code_heap_words_and_literals();
|
||||
}
|
||||
|
||||
void factor_vm::collect_compact(bool trace_contexts_p)
|
||||
|
|
|
@ -14,20 +14,43 @@ struct full_policy {
|
|||
|
||||
void promoted_object(object *obj)
|
||||
{
|
||||
tenured->mark_and_push(obj);
|
||||
tenured->set_marked_p(obj);
|
||||
parent->mark_stack.push_back((cell)obj);
|
||||
}
|
||||
|
||||
void visited_object(object *obj)
|
||||
{
|
||||
if(!tenured->marked_p(obj))
|
||||
tenured->mark_and_push(obj);
|
||||
promoted_object(obj);
|
||||
}
|
||||
};
|
||||
|
||||
struct code_workhorse {
|
||||
factor_vm *parent;
|
||||
code_heap *code;
|
||||
|
||||
explicit code_workhorse(factor_vm *parent_) : parent(parent_), code(parent->code) {}
|
||||
|
||||
code_block *operator()(code_block *compiled)
|
||||
{
|
||||
if(!code->marked_p(compiled))
|
||||
{
|
||||
code->set_marked_p(compiled);
|
||||
parent->mark_stack.push_back((cell)compiled + 1);
|
||||
}
|
||||
|
||||
return compiled;
|
||||
}
|
||||
};
|
||||
|
||||
struct full_collector : collector<tenured_space,full_policy> {
|
||||
bool trace_contexts_p;
|
||||
code_block_visitor<code_workhorse> code_visitor;
|
||||
|
||||
explicit full_collector(factor_vm *parent_);
|
||||
void trace_code_block(code_block *compiled);
|
||||
void trace_context_code_blocks();
|
||||
void trace_callback_code_blocks();
|
||||
void trace_object_code_block(object *obj);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace factor
|
|||
{
|
||||
|
||||
/* Load a 32-bit value from a PowerPC LIS/ORI sequence */
|
||||
fixnum embedded_pointer::load_address_2_2()
|
||||
fixnum instruction_operand::load_value_2_2()
|
||||
{
|
||||
cell *ptr = (cell *)pointer;
|
||||
cell hi = (ptr[-1] & 0xffff);
|
||||
|
@ -13,14 +13,14 @@ fixnum embedded_pointer::load_address_2_2()
|
|||
}
|
||||
|
||||
/* Load a value from a bitfield of a PowerPC instruction */
|
||||
fixnum embedded_pointer::load_address_masked(cell mask, fixnum shift)
|
||||
fixnum instruction_operand::load_value_masked(cell mask, fixnum shift)
|
||||
{
|
||||
cell *ptr = (cell *)pointer;
|
||||
|
||||
return (*ptr & mask) << shift;
|
||||
}
|
||||
|
||||
fixnum embedded_pointer::load_address()
|
||||
fixnum instruction_operand::load_value()
|
||||
{
|
||||
switch(rel_class)
|
||||
{
|
||||
|
@ -29,21 +29,21 @@ fixnum embedded_pointer::load_address()
|
|||
case RC_ABSOLUTE:
|
||||
return *(u32*)pointer;
|
||||
case RC_RELATIVE:
|
||||
return *(u32*)pointer + pointer + sizeof(u32);
|
||||
return *(s32*)pointer + pointer + sizeof(u32);
|
||||
case RC_ABSOLUTE_PPC_2_2:
|
||||
return load_address_2_2();
|
||||
return load_value_2_2();
|
||||
case RC_ABSOLUTE_PPC_2:
|
||||
return load_address_masked(rel_absolute_ppc_2_mask,0);
|
||||
return load_value_masked(rel_absolute_ppc_2_mask,0);
|
||||
case RC_RELATIVE_PPC_2:
|
||||
return load_address_masked(rel_relative_ppc_2_mask,0) + pointer;
|
||||
return load_value_masked(rel_relative_ppc_2_mask,0) + pointer;
|
||||
case RC_RELATIVE_PPC_3:
|
||||
return load_address_masked(rel_relative_ppc_3_mask,0) + pointer;
|
||||
return load_value_masked(rel_relative_ppc_3_mask,0) + pointer;
|
||||
case RC_RELATIVE_ARM_3:
|
||||
return load_address_masked(rel_relative_arm_3_mask,2) + pointer + sizeof(cell) * 2;
|
||||
return load_value_masked(rel_relative_arm_3_mask,2) + pointer + sizeof(cell) * 2;
|
||||
case RC_INDIRECT_ARM:
|
||||
return load_address_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell);
|
||||
return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell);
|
||||
case RC_INDIRECT_ARM_PC:
|
||||
return load_address_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell) * 2;
|
||||
return load_value_masked(rel_indirect_arm_mask,0) + pointer + sizeof(cell) * 2;
|
||||
default:
|
||||
critical_error("Bad rel class",rel_class);
|
||||
return 0;
|
||||
|
@ -51,7 +51,7 @@ fixnum embedded_pointer::load_address()
|
|||
}
|
||||
|
||||
/* Store a 32-bit value into a PowerPC LIS/ORI sequence */
|
||||
void embedded_pointer::store_address_2_2(fixnum value)
|
||||
void instruction_operand::store_value_2_2(fixnum value)
|
||||
{
|
||||
cell *ptr = (cell *)pointer;
|
||||
ptr[-1] = ((ptr[-1] & ~0xffff) | ((value >> 16) & 0xffff));
|
||||
|
@ -59,7 +59,7 @@ void embedded_pointer::store_address_2_2(fixnum value)
|
|||
}
|
||||
|
||||
/* Store a value into a bitfield of a PowerPC instruction */
|
||||
void embedded_pointer::store_address_masked(fixnum value, cell mask, fixnum shift)
|
||||
void instruction_operand::store_value_masked(fixnum value, cell mask, fixnum shift)
|
||||
{
|
||||
cell *ptr = (cell *)pointer;
|
||||
|
||||
|
@ -71,7 +71,7 @@ void embedded_pointer::store_address_masked(fixnum value, cell mask, fixnum shif
|
|||
*ptr = ((*ptr & ~mask) | ((value >> shift) & mask));
|
||||
}
|
||||
|
||||
void embedded_pointer::store_address(fixnum absolute_value)
|
||||
void instruction_operand::store_value(fixnum absolute_value)
|
||||
{
|
||||
fixnum relative_value = absolute_value - pointer;
|
||||
|
||||
|
@ -84,28 +84,28 @@ void embedded_pointer::store_address(fixnum absolute_value)
|
|||
*(u32*)pointer = absolute_value;
|
||||
break;
|
||||
case RC_RELATIVE:
|
||||
*(u32*)pointer = relative_value - sizeof(u32);
|
||||
*(s32*)pointer = relative_value - sizeof(u32);
|
||||
break;
|
||||
case RC_ABSOLUTE_PPC_2_2:
|
||||
store_address_2_2(absolute_value);
|
||||
store_value_2_2(absolute_value);
|
||||
break;
|
||||
case RC_ABSOLUTE_PPC_2:
|
||||
store_address_masked(absolute_value,rel_absolute_ppc_2_mask,0);
|
||||
store_value_masked(absolute_value,rel_absolute_ppc_2_mask,0);
|
||||
break;
|
||||
case RC_RELATIVE_PPC_2:
|
||||
store_address_masked(relative_value,rel_relative_ppc_2_mask,0);
|
||||
store_value_masked(relative_value,rel_relative_ppc_2_mask,0);
|
||||
break;
|
||||
case RC_RELATIVE_PPC_3:
|
||||
store_address_masked(relative_value,rel_relative_ppc_3_mask,0);
|
||||
store_value_masked(relative_value,rel_relative_ppc_3_mask,0);
|
||||
break;
|
||||
case RC_RELATIVE_ARM_3:
|
||||
store_address_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
|
||||
store_value_masked(relative_value - sizeof(cell) * 2,rel_relative_arm_3_mask,2);
|
||||
break;
|
||||
case RC_INDIRECT_ARM:
|
||||
store_address_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
|
||||
store_value_masked(relative_value - sizeof(cell),rel_indirect_arm_mask,0);
|
||||
break;
|
||||
case RC_INDIRECT_ARM_PC:
|
||||
store_address_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
|
||||
store_value_masked(relative_value - sizeof(cell) * 2,rel_indirect_arm_mask,0);
|
||||
break;
|
||||
default:
|
||||
critical_error("Bad rel class",rel_class);
|
|
@ -119,20 +119,20 @@ struct relocation_entry {
|
|||
}
|
||||
};
|
||||
|
||||
struct embedded_pointer {
|
||||
struct instruction_operand {
|
||||
cell rel_class;
|
||||
cell pointer;
|
||||
|
||||
embedded_pointer(cell rel_class_, cell pointer_) :
|
||||
instruction_operand(cell rel_class_, cell pointer_) :
|
||||
rel_class(rel_class_), pointer(pointer_) {}
|
||||
|
||||
fixnum load_address_2_2();
|
||||
fixnum load_address_masked(cell mask, fixnum shift);
|
||||
fixnum load_address();
|
||||
fixnum load_value_2_2();
|
||||
fixnum load_value_masked(cell mask, fixnum shift);
|
||||
fixnum load_value();
|
||||
|
||||
void store_address_2_2(fixnum value);
|
||||
void store_address_masked(fixnum value, cell mask, fixnum shift);
|
||||
void store_address(fixnum value);
|
||||
void store_value_2_2(fixnum value);
|
||||
void store_value_masked(fixnum value, cell mask, fixnum shift);
|
||||
void store_value(fixnum value);
|
||||
};
|
||||
|
||||
}
|
|
@ -49,7 +49,7 @@ namespace factor
|
|||
#include "errors.hpp"
|
||||
#include "bignumint.hpp"
|
||||
#include "bignum.hpp"
|
||||
#include "embedded_pointers.hpp"
|
||||
#include "instruction_operands.hpp"
|
||||
#include "code_blocks.hpp"
|
||||
#include "bump_allocator.hpp"
|
||||
#include "bitwise_hacks.hpp"
|
||||
|
|
|
@ -151,9 +151,7 @@ void factor_vm::primitive_become()
|
|||
by referencing the old quotation unless we recompile all
|
||||
unoptimized words. */
|
||||
compile_all_words();
|
||||
|
||||
/* Update references to old objects in the code heap */
|
||||
update_code_heap_words_and_literals();
|
||||
update_code_heap_words();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ template<typename Visitor> struct slot_visitor {
|
|||
void visit_bignum_roots();
|
||||
void visit_roots();
|
||||
void visit_contexts();
|
||||
void visit_literal_references(code_block *compiled);
|
||||
void visit_referenced_literals(code_block *compiled);
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
|
@ -125,33 +125,34 @@ void slot_visitor<Visitor>::visit_contexts()
|
|||
|
||||
template<typename Visitor>
|
||||
struct literal_references_visitor {
|
||||
factor_vm *parent;
|
||||
slot_visitor<Visitor> *visitor;
|
||||
|
||||
explicit literal_references_visitor(factor_vm *parent_, slot_visitor<Visitor> *visitor_)
|
||||
: parent(parent_), visitor(visitor_) {}
|
||||
explicit literal_references_visitor(slot_visitor<Visitor> *visitor_) : visitor(visitor_) {}
|
||||
|
||||
void operator()(relocation_entry rel, cell index, code_block *compiled)
|
||||
{
|
||||
if(rel.rel_type() == RT_IMMEDIATE)
|
||||
{
|
||||
embedded_pointer ptr(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
|
||||
cell literal = ptr.load_address();
|
||||
instruction_operand op(rel.rel_class(),rel.rel_offset() + (cell)(compiled + 1));
|
||||
cell literal = op.load_address();
|
||||
literal = visitor->visit_pointer(literal);
|
||||
ptr.store_address(literal);
|
||||
op.store_address(literal);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Visitor>
|
||||
void slot_visitor<Visitor>::visit_literal_references(code_block *compiled)
|
||||
void slot_visitor<Visitor>::visit_referenced_literals(code_block *compiled)
|
||||
{
|
||||
visit_handle(&compiled->owner);
|
||||
visit_handle(&compiled->literals);
|
||||
visit_handle(&compiled->relocation);
|
||||
|
||||
literal_references_visitor<Visitor> visitor(parent,this);
|
||||
if(!parent->code->needs_fixup_p(compiled))
|
||||
{
|
||||
literal_references_visitor<Visitor> visitor(this);
|
||||
parent->iterate_relocations(compiled,visitor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,7 +3,6 @@ namespace factor
|
|||
|
||||
struct tenured_space : free_list_allocator<object> {
|
||||
object_start_map starts;
|
||||
std::vector<object *> mark_stack;
|
||||
|
||||
explicit tenured_space(cell size, cell start) :
|
||||
free_list_allocator<object>(size,start), starts(size,start) {}
|
||||
|
@ -37,20 +36,14 @@ struct tenured_space : free_list_allocator<object> {
|
|||
state.clear_mark_bits();
|
||||
}
|
||||
|
||||
void clear_mark_stack()
|
||||
{
|
||||
mark_stack.clear();
|
||||
}
|
||||
|
||||
bool marked_p(object *obj)
|
||||
{
|
||||
return this->state.marked_p(obj);
|
||||
}
|
||||
|
||||
void mark_and_push(object *obj)
|
||||
void set_marked_p(object *obj)
|
||||
{
|
||||
this->state.set_marked_p(obj);
|
||||
this->mark_stack.push_back(obj);
|
||||
}
|
||||
|
||||
void sweep()
|
||||
|
|
|
@ -3,20 +3,20 @@
|
|||
namespace factor
|
||||
{
|
||||
|
||||
to_tenured_collector::to_tenured_collector(factor_vm *myvm_) :
|
||||
to_tenured_collector::to_tenured_collector(factor_vm *parent_) :
|
||||
collector<tenured_space,to_tenured_policy>(
|
||||
myvm_,
|
||||
myvm_->data->tenured,
|
||||
to_tenured_policy(myvm_)) {}
|
||||
parent_,
|
||||
parent_->data->tenured,
|
||||
to_tenured_policy(parent_)) {}
|
||||
|
||||
void to_tenured_collector::tenure_reachable_objects()
|
||||
{
|
||||
std::vector<object *> *mark_stack = &this->target->mark_stack;
|
||||
std::vector<cell> *mark_stack = &parent->mark_stack;
|
||||
while(!mark_stack->empty())
|
||||
{
|
||||
object *obj = mark_stack->back();
|
||||
cell ptr = mark_stack->back();
|
||||
mark_stack->pop_back();
|
||||
this->trace_object(obj);
|
||||
this->trace_object((object *)ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ void factor_vm::collect_to_tenured()
|
|||
/* Copy live objects from aging space to tenured space. */
|
||||
to_tenured_collector collector(this);
|
||||
|
||||
data->tenured->clear_mark_stack();
|
||||
mark_stack.clear();
|
||||
|
||||
collector.trace_roots();
|
||||
collector.trace_contexts();
|
||||
|
|
|
@ -2,10 +2,10 @@ namespace factor
|
|||
{
|
||||
|
||||
struct to_tenured_policy {
|
||||
factor_vm *myvm;
|
||||
factor_vm *parent;
|
||||
tenured_space *tenured;
|
||||
|
||||
explicit to_tenured_policy(factor_vm *myvm_) : myvm(myvm_), tenured(myvm->data->tenured) {}
|
||||
explicit to_tenured_policy(factor_vm *parent_) : parent(parent_), tenured(parent->data->tenured) {}
|
||||
|
||||
bool should_copy_p(object *untagged)
|
||||
{
|
||||
|
@ -14,14 +14,14 @@ struct to_tenured_policy {
|
|||
|
||||
void promoted_object(object *obj)
|
||||
{
|
||||
tenured->mark_stack.push_back(obj);
|
||||
parent->mark_stack.push_back((cell)obj);
|
||||
}
|
||||
|
||||
void visited_object(object *obj) {}
|
||||
};
|
||||
|
||||
struct to_tenured_collector : collector<tenured_space,to_tenured_policy> {
|
||||
explicit to_tenured_collector(factor_vm *myvm_);
|
||||
explicit to_tenured_collector(factor_vm *parent_);
|
||||
void tenure_reachable_objects();
|
||||
};
|
||||
|
||||
|
|
|
@ -55,6 +55,9 @@ struct factor_vm
|
|||
/* Only set if we're performing a GC */
|
||||
gc_state *current_gc;
|
||||
|
||||
/* Mark stack */
|
||||
std::vector<cell> mark_stack;
|
||||
|
||||
/* If not NULL, we push GC events here */
|
||||
std::vector<gc_event> *gc_events;
|
||||
|
||||
|
@ -525,7 +528,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_code_block_words_and_literals(code_block *compiled);
|
||||
void check_code_address(cell address);
|
||||
void relocate_code_block(code_block *compiled);
|
||||
void fixup_labels(array *labels, code_block *compiled);
|
||||
|
@ -544,7 +546,6 @@ struct factor_vm
|
|||
bool in_code_heap_p(cell ptr);
|
||||
void jit_compile_word(cell word_, cell def_, bool relocate);
|
||||
void update_code_heap_words();
|
||||
void update_code_heap_words_and_literals();
|
||||
void primitive_modify_code_heap();
|
||||
code_heap_room code_room();
|
||||
void primitive_code_room();
|
||||
|
|
Loading…
Reference in New Issue