We could scan the survivors as we're copying them, however this will require more work during the initial-mark GCs (and in particular: special-case code in the fast path).
A better approach is to let the concurrent marking threads scan the survivors and mark everything reachable from them a) before any more concurrent marking work is done (so that we can just mark the objects, without needing to push them on a stack, and let the "finger" algorithm discover them) and b) before the next GC starts (since, if we copy them, we won't know which of the new survivors are the ones we need to scan).
This approach has the advantage that it does not require any extra work during the initial-mark GCs and all the work is done by the concurrent marking threads. However, it has the disadvantage that the survivor scanning might hold up the next GC. In most cases this should not be an issue as GCs take place at a reasonably low rate. If it does become a problem we could consider the following:
- like when the GC locker is active, try to extend the eden to give a bit more time to the marking threads to finish scanning the survivors
- instead of waiting for the marking threads, a GC can take over and finish up scanning the remaining survivors (typically, we have more GC threads than marking threads, so the overhead will be reduced)
- if we supported region pinning, we could pin all the regions that were not scanned by the time the GC started so that the marking threads can resume scanning them after the GC completes
But, let's do the simple implementation as a first cut.