Non-moving collector is unable to finalize weak pointers
Currently, the non-moving collector is unable to finalize weak pointers under some circumstances due to an interaction between the moving and non-moving collectors' weak pointer marking logic. Specifically, consider a case such as:
nursery ┆ non-moving gen.
┆
┆
┆ K
┌───┆────► ┌───────┐
│ ┆ │ │
│ ┆ │ │
│ ┆ │ │
W │ ┆ └───────┘
┌────────────┐ │ ┆
│WEAK │ │ ┆
│ key ├──┘ ┆
│ value ├──────┆──────► ...
│ finalizer │──────┆──────► ...
└────────────┘ ┆
┆
┆
- At some point the weak will be promoted into the non-moving generation.
- At some point later, we will initiate a major collection and
Wwill be moved tooldest_gen->old_weak_ptr_list(byinitWeakForGC) - We proceed with scavenging and eventually call
traverseWeakPtrList, which will eventually calltidyWeakList(oldest_gen) - We find that
isAlive(w->key) == trueasw->keyis in the non-moving generation andisAlivenecessarily conservatively considers any objects in the non-moving generation as alive - We call
scavengeLiveWeakonw, which will evacuate&w->key. Asw->keyis a non-moving object, it is pushed to the update-remembered set (seeNote [Aging under the non-moving collector]).
At this point we are in a situation where w cannot be tombstoned by the nonmoving GC as w->key is reachable via the update-remembered set.