The method HeapRegionRemSet::split_card() looks as follows:
HeapRegion* hr = G1CollectedHeap::heap()->heap_region_containing(from);
card_region = hr->hrm_index();
card_within_region = (uint)(pointer_delta((HeapWord*)from, hr->bottom()) >> (CardTable::card_shift - LogHeapWordSize));
I.e. from a memory POV:
- load of Universe::_heap
- calculating using it (loading heap bottom,) loading heap region size shift)
- look up heap region hr
- indirect loads from heap region hr (index, bottom)
This can be done simpler:
uintptr_t offset = pointer_delta(from, _heap_base_address, 1);
card_region = offset >> _split_card_shift;
card_within_region = (offset & _split_card_mask) >> CardTable::card_shift;
- one load of heap base address
- load and shift by precalculated value
- mask by value plus shift
This change also enables card region virtualization.