Closed Bug 1652962 Opened 2 months ago Closed 2 months ago

Simplify FinalizationRegistry implementation by separating JS interface from implementation of callback queue


(Core :: JavaScript: GC, enhancement, P3)




Tracking Status
firefox80 --- fixed


(Reporter: jonco, Assigned: jonco)



(3 files)

Bug 1615362 introduced a lot of complexity in the FinalizationRegistry implementation by introducing weak edges from FinalizationRecordObjects to FinalizationRegistryObjects. These edges need to be swept, but also they are sometimes traced at unusual times. This approach has resulted in bug 1643913 and as a factor in bug 1646708.

In hindsight I should have known this was a bad idea when I wrote the following comment:

  // Perform a manual read barrier. This is the only place where the GC itself
  // needs to perform a read barrier so we must work around our assertions that
  // this doesn't happen.

Another approach is to split the FinalizationRegistryObject into two pieces: the user-facing JS interface and an internal implementation object that is not exposed. These can have different lifetimes, leading to a much more natural implementation.

This splits the FinalizationRegistryObject into two separate objects but doesn't change any behaviour. The objects both have strong edges to each other.

Assignee: nobody → jcoppeard

This rearranges things so that edge from FinalizationQueueObject to FinalizationRegistryObject is weak, and hence the latter can outlive the former. The weak edge from FinalizationRecordObject to FinalizationRegistryObject is replaced with a strong edge to FinalizationQueueObject.

This removes the requirement to trace anything during sweeping. The FinalizationQueueObject is kept alive by the strong edges from FinalizationRecordObjects. As a result, they may live for an extra GC cycle more than they would otherwise (as the record objects did before), but this is not visible to users. This means we can remove GC support for doing extra marking work pushed during sweeping that was needed for this one case.

This also means we can remove the set of active records that needs to be maintained.

Depends on D83759

Pushed by
Split off FinalizationQueueObject from FinalizationRegistryObject r=sfink
Allow FinalizationQueueObject to outlive FinalizationRegistry object r=sfink
Update FinalizationRegistry documentation r=sfink
Closed: 2 months ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla80
You need to log in before you can comment on or make changes to this bug.