VM: splits out the little ugly scan_next-object + goto-loop into a function trace_card()

db4
Björn Lindqvist 2015-02-23 13:40:48 +00:00 committed by John Benediktsson
parent 8e91ca3e31
commit ab75e3b05d
1 changed files with 32 additions and 36 deletions

View File

@ -111,14 +111,6 @@ template <typename TargetGeneration, typename Policy> struct collector {
return addr_to_deck(a - data->start); return addr_to_deck(a - data->start);
} }
cell card_start_address(cell card) {
return (card << card_bits) + data->start;
}
cell card_end_address(cell card) {
return ((card + 1) << card_bits) + data->start;
}
void trace_partial_objects(cell start, cell card_start, cell card_end) { void trace_partial_objects(cell start, cell card_start, cell card_end) {
object* obj = (object*)start; object* obj = (object*)start;
cell end = start + obj->binary_payload_start(); cell end = start + obj->binary_payload_start();
@ -136,21 +128,47 @@ template <typename TargetGeneration, typename Policy> struct collector {
} }
} }
template <typename SourceGeneration>
cell trace_card(SourceGeneration* gen, cell index, cell start) {
cell start_addr = data->start + index * card_size;
cell end_addr = start_addr + card_size;
if (!start || (start + ((object*)start)->size()) < start_addr) {
/* Optimization because finding the objects in a memory range is
expensive. It helps a lot when tracing consecutive cards. */
cell gen_start_card = (gen->start - data->start) / card_size;
start = gen->starts
.find_object_containing_card(index - gen_start_card);
}
while (start && start < end_addr) {
trace_partial_objects(start, start_addr, end_addr);
if ((start + ((object*)start)->size()) >= end_addr) {
/* The object can overlap the card boundary, then the
remainder of it will be handled in the next card
tracing if that card is marked. */
break;
}
start = gen->next_object_after(start);
}
return start;
}
template <typename SourceGeneration> template <typename SourceGeneration>
void trace_cards(SourceGeneration* gen, card mask, card unmask) { void trace_cards(SourceGeneration* gen, card mask, card unmask) {
card_deck* decks = data->decks; card_deck* decks = data->decks;
card_deck* cards = data->cards; 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 first_deck = card_deck_for_address(gen->start);
cell last_deck = card_deck_for_address(gen->end); cell last_deck = card_deck_for_address(gen->end);
/* Address of last traced object. */
cell start = 0; cell start = 0;
cell end = 0;
for (cell deck_index = first_deck; deck_index < last_deck; deck_index++) { for (cell deck_index = first_deck; deck_index < last_deck; deck_index++) {
if (decks[deck_index] & mask) { if (decks[deck_index] & mask) {
decks[deck_index] &= ~unmask;
decks_scanned++; decks_scanned++;
cell first_card = first_card_in_deck(deck_index); cell first_card = first_card_in_deck(deck_index);
@ -159,38 +177,16 @@ template <typename TargetGeneration, typename Policy> struct collector {
for (cell card_index = first_card; card_index < last_card; for (cell card_index = first_card; card_index < last_card;
card_index++) { card_index++) {
if (cards[card_index] & mask) { if (cards[card_index] & mask) {
cards[card_index] &= ~unmask;
cards_scanned++; cards_scanned++;
cell start_addr = card_start_address(card_index); start = trace_card(gen, card_index, start);
cell end_addr = card_end_address(card_index);
if (end < start_addr) {
factor_print_p = true;
start = gen->starts
.find_object_containing_card(card_index - gen_start_card);
end = start + ((object*)start)->size();
}
scan_next_object:
if (start < end_addr) {
trace_partial_objects(start, start_addr, end_addr);
if (end < end_addr) {
start = gen->next_object_after(start);
if (start) {
end = start + ((object*)start)->size();
goto scan_next_object;
}
}
}
if (!start) { if (!start) {
/* At end of generation, no need to scan more cards. */
return; return;
} }
} }
cards[card_index] &= ~unmask;
} }
decks[deck_index] &= ~unmask;
} }
} }
} }