template 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); }