Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

275 lines (222 sloc) 6.183 kb
namespace factor
{
struct must_start_gc_again {};
template<typename TargetGeneration, typename Policy> struct gc_workhorse : no_fixup {
static const bool translated_code_block_map = false;
factor_vm *parent;
TargetGeneration *target;
Policy policy;
code_heap *code;
explicit gc_workhorse(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
parent(parent_),
target(target_),
policy(policy_),
code(parent->code) {}
object *resolve_forwarding(object *untagged)
{
parent->check_data_pointer(untagged);
/* is there another forwarding pointer? */
while(untagged->forwarding_pointer_p())
untagged = untagged->forwarding_pointer();
/* we've found the destination */
return untagged;
}
object *promote_object(object *untagged)
{
cell size = untagged->size();
object *newpointer = target->allot(size);
if(!newpointer) throw must_start_gc_again();
memcpy(newpointer,untagged,size);
untagged->forward_to(newpointer);
policy.promoted_object(newpointer);
return newpointer;
}
object *fixup_data(object *obj)
{
parent->check_data_pointer(obj);
if(!policy.should_copy_p(obj))
{
policy.visited_object(obj);
return obj;
}
object *forwarding = resolve_forwarding(obj);
if(forwarding == obj)
return promote_object(obj);
else if(policy.should_copy_p(forwarding))
return promote_object(forwarding);
else
{
policy.visited_object(forwarding);
return forwarding;
}
}
code_block *fixup_code(code_block *compiled)
{
if(!code->marked_p(compiled))
{
code->set_marked_p(compiled);
parent->mark_stack.push_back((cell)compiled + 1);
}
return compiled;
}
};
struct dummy_unmarker {
void operator()(card *ptr) {}
};
struct simple_unmarker {
card unmask;
explicit simple_unmarker(card unmask_) : unmask(unmask_) {}
void operator()(card *ptr) { *ptr &= ~unmask; }
};
struct full_unmarker {
explicit full_unmarker() {}
void operator()(card *ptr) { *ptr = 0; }
};
template<typename TargetGeneration, typename Policy>
struct collector {
factor_vm *parent;
data_heap *data;
code_heap *code;
TargetGeneration *target;
gc_workhorse<TargetGeneration,Policy> workhorse;
slot_visitor<gc_workhorse<TargetGeneration,Policy> > data_visitor;
cell cards_scanned;
cell decks_scanned;
cell code_blocks_scanned;
explicit collector(factor_vm *parent_, TargetGeneration *target_, Policy policy_) :
parent(parent_),
data(parent_->data),
code(parent_->code),
target(target_),
workhorse(parent,target,policy_),
data_visitor(parent,workhorse),
cards_scanned(0),
decks_scanned(0),
code_blocks_scanned(0) {}
void trace_handle(cell *handle)
{
data_visitor.visit_handle(handle);
}
void trace_object(object *ptr)
{
data_visitor.visit_slots(ptr);
if(ptr->type() == ALIEN_TYPE)
((alien *)ptr)->update_address();
}
void trace_roots()
{
data_visitor.visit_roots();
}
void trace_contexts()
{
data_visitor.visit_contexts();
}
void trace_code_block_objects(code_block *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)
{
std::set<code_block *>::const_iterator iter = remembered_set->begin();
std::set<code_block *>::const_iterator end = remembered_set->end();
for(; iter != end; iter++)
{
code_block *compiled = *iter;
trace_code_block_objects(compiled);
trace_embedded_literals(compiled);
compiled->flush_icache();
code_blocks_scanned++;
}
}
inline cell first_card_in_deck(cell deck)
{
return deck << (deck_bits - card_bits);
}
inline cell last_card_in_deck(cell deck)
{
return first_card_in_deck(deck + 1);
}
inline cell card_deck_for_address(cell a)
{
return addr_to_deck(a - data->start);
}
inline cell card_start_address(cell card)
{
return (card << card_bits) + data->start;
}
inline cell card_end_address(cell card)
{
return ((card + 1) << card_bits) + data->start;
}
void trace_partial_objects(cell start, cell end, cell card_start, cell card_end)
{
if(card_start < end)
{
start += sizeof(cell);
if(start < card_start) start = card_start;
if(end > card_end) end = card_end;
cell *slot_ptr = (cell *)start;
cell *end_ptr = (cell *)end;
for(; slot_ptr < end_ptr; slot_ptr++)
data_visitor.visit_handle(slot_ptr);
}
}
template<typename SourceGeneration, typename Unmarker>
void trace_cards(SourceGeneration *gen, card mask, Unmarker unmarker)
{
card_deck *decks = data->decks;
card_deck *cards = data->cards;
cell gen_start_card = addr_to_card(gen->start - data->start);
cell first_deck = card_deck_for_address(gen->start);
cell last_deck = card_deck_for_address(gen->end);
cell start = 0, binary_start = 0, end = 0;
for(cell deck_index = first_deck; deck_index < last_deck; deck_index++)
{
if(decks[deck_index] & mask)
{
decks_scanned++;
cell first_card = first_card_in_deck(deck_index);
cell last_card = last_card_in_deck(deck_index);
for(cell card_index = first_card; card_index < last_card; card_index++)
{
if(cards[card_index] & mask)
{
cards_scanned++;
if(end < card_start_address(card_index))
{
start = gen->starts.find_object_containing_card(card_index - gen_start_card);
binary_start = start + ((object *)start)->binary_payload_start();
end = start + ((object *)start)->size();
}
scan_next_object: if(start < card_end_address(card_index))
{
trace_partial_objects(
start,
binary_start,
card_start_address(card_index),
card_end_address(card_index));
if(end < card_end_address(card_index))
{
start = gen->next_object_after(start);
if(start)
{
binary_start = start + ((object *)start)->binary_payload_start();
end = start + ((object *)start)->size();
goto scan_next_object;
}
}
}
unmarker(&cards[card_index]);
if(!start) return;
}
}
unmarker(&decks[deck_index]);
}
}
}
};
}
Jump to Line
Something went wrong with that request. Please try again.