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
W
will 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) == true
asw->key
is in the non-moving generation andisAlive
necessarily conservatively considers any objects in the non-moving generation as alive - We call
scavengeLiveWeak
onw
, which will evacuate&w->key
. Asw->key
is 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.