Relates :
|
|
Relates :
|
|
Relates :
|
In HeapRegion::oops_on_card_seq_iterate_careful() there is the following code that actually iterates over the card contents (stripped of non-essential stuff): (1) if (!g1h->is_obj_dead(obj)) { obj->oop_iterate(cl, mr); } while (cur < end) { obj = oop(cur); if (obj->klass_or_null() == NULL) { return cur; }; // Otherwise: next = cur + block_size(cur); (2) if (!g1h->is_obj_dead(obj)) { if (next < end || !obj->is_objArray()) { // This object either does not span the MemRegion // boundary, or if it does it's not an array. // Apply closure to whole object. obj->oop_iterate(cl); } else { // This obj is an array that spans the boundary. // Stop at the boundary. obj->oop_iterate(cl, mr); } } cur = next; } I.e. at (1) the code iterates over the first object reaching into the card, always limiting itself to the card area. Then, without advancing the "cur" pointer, it immediately iterates over the same object either limited to the card or without limit. This is because non-object arrays may be marked imprecise, i.e. only at the object header. So you need to always iterate over regular objects reaching into or out of the area in full. The side effect is, that the first object will always be iterated for references twice. This is bad because particularly for parts of object arrays G1 does duplicate work, lengthening the update rs phase for no reason. Particularly loads with many reference arrays benefit from a fix. By rearranging the code, transforming the if-while construct into a do-while loop this can be avoided completely. (And being more compact and more easily understood). Fix this. A follow-up might want to investigate what benefit this imprecise marking actually gives.
|