VM: Fix WeakProperty processing during parallel marking.
Previously if one marker marked the weak property and another marker marked its key then the first marker might stop marking before it sees that the key was marked.
Here is a possible concurrent execution, assuming P is a WeakProperty and K is P.key:
(Marker A) (Marker B)
[ mark property P ] |
[ drain marking stack ] |
[ no more work to do ] |
| [ mark K ]
| [ draing marking stack ]
| [ no more work to do ]
In this execution we end up clearing P even though P.key is marked.
To fix this issue without reintroducing central WeakProperty processing
we change the marking phase loop in such a way that markers consider the
marking done only if all of them agree that they have no more weak properties
with marked keys.
Essentially the marking loop now has a separate phase where all markers check
their pending weak properties. The decision to proceed to the next marking phase
(weak handles processing) is done in lock step using barrier - either all threads
advance to the next stage or one of the threads finds a weak property
with marked key and unmarked value and all threads resume marking.