WebAssembly / WebAssembly/shared-everything-threads
Using FinalizationRegistry for ThreadBoundData
Nobody has claimed this yet.
- Dominant language
- WebAssembly
- Stars
- 97
- Forks
- 6
- PR merge metrics
- No merged PRs in 30d
Description
One idea that came up in verbal discussions of ThreadBoundData was the alternative of allowing shared objects as keys in a FinalizationRegistry, but not as keys in WeakMap. Opening this issue to continue this discussion.
With this, a shared object could hold an index to an unshared object stored in a thread specific table (instead of holding a ref to a ThreadBoundData). Then the toolchain could add the shared object into a finalization registry that would deallocate the unshared objects from the table when the shared object expires.
This would give languages 'strong' lifetimes for their shared-to-unshared references, while avoiding the need for engines to support marking all heaps together.
This would work because the unshared finalization registry only keeps alive an unshared callback, so there's no shared-to-unshared references for the engine to manage. The lifetime of the callback doesn't depend on the lifetime of the shared key. There is some coordination in the GC to notify finalization registries that a shared reference they contain has expired, but this could be done asynchronously with a notification or message from the shared GC.
WeakMap and ThreadBoundData (with strong behavior) are different because the lifetime of the unshared values depend on the lifetime of the shared keys. Liveness is transitive, so we'd have to be able to trace through all heaps to support this.
The downside of using finalization registry for ThreadBoundData would be that it could not collect arbitrary shared/unshared cycles. A cycle passing through shared and unshared objects using indices/finalization registry would not be visible to the GC and therefore not able to be broken.
I personally think that would be an acceptable tradeoff to deliver enough value with an MVP.
The only relevant note on this all that I found in the overview was:
An intermediate behavior would be the strong behavior but without cross-heap cycle collection. This is as expressive as the weak behavior if we were to hypothetically augment it by allowing shared objects to be keys in FinalizationRegistry but not WeakMap (which would be too inconsistent for us to actually ship). The FinalizationRegistry would be able to automatically manage the lifetimes of rooted unshared objects as long as they do not cyclically keep the shared objects that refer to them alive.
I would argue this is not necessarily inconsistent behavior. As noted above, FR and WM have different implementation characteristics, it seems reasonable for them to have different restrictions. I be curious to hear why they must accept the same set of values as keys.
cc @lukewagner who originally brought up this idea.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the overview note quoted in the issue, then review the discussion of FinalizationRegistry, WeakMap, and ThreadBoundData. The issue names no files, tests, or entry points; done would require a documented decision on whether shared FinalizationRegistry keys are acceptable for the proposed MVP.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- wasm
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100