bool trace_partial_object(cell start, cell end, cell card_start, cell card_end) { if(card_start >= end) return false; if(end >= card_end) end = card_end; cell *slot_ptr = (cell *)start; cell *end_ptr = (cell *)end; bool copied = false; if(slot_ptr != end_ptr) { slot++; for(; slot_ptr < end_ptr; slot++) copied |= trace_handle(slot_ptr); } return copied; } template void trace_cards(SourceGeneration *gen, card mask, Unmarker unmarker) { u64 start = current_micros(); card_deck *decks = this->data->decks; card_deck *cards = this->data->cards; cell first_deck = card_deck_index(gen->start); cell last_deck = card_deck_index(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 = card_index(deck_index); cell last_card = card_index(deck_index + 1); bool deck_dirty = false; for(cell card_index = first_card; card_index < last_card; card_index++) { if(cards[card_index] & mask) { if(card_start >= end) { start = find_card_containing_header(card_index); binary_start = start + myvm->binary_payload_start((object *)start); end = start + myvm->untagged_object_size((object *)start); } bool card_dirty = false; while(start < card_end_offset(card_index)) { card_dirty |= trace_partial_object( start, binary_start, card_start_offset(card_index), card_end_offset(card_index)); start = gen->next_object_after(start); binary_start = start + myvm->binary_payload_start((object *)start); end = start + myvm->untagged_object_size((object *)start); } unmarker(copied,&cards[card_index]); this->myvm->gc_stats.cards_scanned++; deck_dirty |= card_dirty; } } unmarker(copied,&decks[deck_index]); } } this->myvm->gc_stats.card_scan_time += (current_micros() - start); }