Paste: card scanning
Author: | slava |
Mode: | c++ |
Date: | Wed, 14 Oct 2009 07:29:46 |
Plain Text |
template<typename SourceGeneration, typename Unmarker>
void trace_cards(SourceGeneration *gen, card mask, Unmarker unmarker)
{
u64 start_time = current_micros();
card_deck *decks = this->data->decks;
card_deck *cards = this->data->cards;
cell gen_start_card = addr_to_card(gen->start - this->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)
{
cell first_card = first_card_in_deck(deck_index);
cell last_card = last_card_in_deck(deck_index);
bool deck_dirty = false;
for(cell card_index = first_card; card_index < last_card; card_index++)
{
if(cards[card_index] & mask)
{
if(end < card_start_address(card_index))
{
start = gen->find_object_containing_card(card_index - gen_start_card);
binary_start = start + this->myvm->binary_payload_start((object *)start);
end = start + this->myvm->untagged_object_size((object *)start);
}
bool card_dirty = false;
#ifdef FACTOR_DEBUG
assert(addr_to_card(start - this->data->start) <= card_index);
assert(start < card_end_address(card_index));
#endif
scan_next_object: {
card_dirty |= 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(this->myvm,start);
if(start)
{
binary_start = start + this->myvm->binary_payload_start((object *)start);
end = start + this->myvm->untagged_object_size((object *)start);
goto scan_next_object;
}
}
}
unmarker(card_dirty,&cards[card_index]);
this->myvm->gc_stats.cards_scanned++;
deck_dirty |= card_dirty;
if(!start) goto end;
}
}
unmarker(deck_dirty,&decks[deck_index]);
}
}
end: this->myvm->gc_stats.card_scan_time += (current_micros() - start_time);
}
New Annotation