Skip to content

Commit 9ec8d5d

Browse files
committed
Ephemeron
1 parent b9c4086 commit 9ec8d5d

File tree

1 file changed

+46
-8
lines changed

1 file changed

+46
-8
lines changed

docs/userguide/src/portingguide/topics/weakref.md

+46-8
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,15 @@ objects. When using MMTk, there are two ways to implement this semantics.
219219
The easiest way is **treating `SoftReference` as strong references in non-emergency GCs, and
220220
treating them as weak references in emergency GCs**.
221221

222-
- During non-emergency GC, we let `Scanning::scan_objects` scan the weak reference field inside a
223-
`SoftReference` instance as if it were an ordinary strong reference field. In this way, the
224-
(strong) transitive closure after the `Closure` stage will also include softly reachable
225-
objects, and they will be kept alive just like strongly reachable objects.
226-
- During emergency GC, however, skip this field in `Scanning::scan_objects`, and clear
227-
`SoftReference` just like `WeakReference` in `Scanning::process_weak_refs`. In this way, softly
228-
reachable objects will be dead unless they are subject to finalization.
222+
- During non-emergency GC, we let `Scanning::scan_object` and
223+
`Scanning::scan_object_and_trace_edges` scan the weak reference field inside a `SoftReference`
224+
instance as if it were an ordinary strong reference field. In this way, the (strong) transitive
225+
closure after the `Closure` stage will also include softly reachable objects, and they will be
226+
kept alive just like strongly reachable objects.
227+
- During emergency GC, however, skip this field in `Scanning::scan_object` or
228+
`Scanning::scan_object_and_trace_edges` , and clear `SoftReference` just like `WeakReference` in
229+
`Scanning::process_weak_refs`. In this way, softly reachable objects will be dead unless they
230+
are subject to finalization.
229231

230232
The other way is **resurrecting referents of `SoftReference` after the strong closure**. This
231233
involves supporting multiple levels of reference strengths, which will be introduced in the next
@@ -328,7 +330,43 @@ fn process_weak_ref(...) -> bool {
328330

329331
### Ephemerons
330332

331-
TODO
333+
An [Ephemeron] has a *key* and a *value*, both of which are object references. The key is a weak
334+
reference, while the value keeps the referent alive only if both the ephemeron itself and the key
335+
are reachable.
336+
337+
[Ephemeron]: https://dl.acm.org/doi/10.1145/263700.263733
338+
339+
To support ephemerons, the VM binding needs to identify ephemerons. This includes ephemerons as
340+
individual objects, objects that contain ephemerons, and, equivalently, objects that contain
341+
key/value fields that have semantics similar to ephemerons.
342+
343+
The following is the algorithm for processing ephemerons. It gradually discovers ephemerons as we
344+
do the tracing. We maintain a queue of ephemerons which is empty before the `Closure` stage.
345+
346+
1. In `Scanning::scan_object` and `Scanning::scan_object_and_trace_edges`, we enqueue ephemerons as
347+
we scan them, but do not trace either the key or the value fields.
348+
2. In `Scanning::process_weak_refs`, we iterate through all ephemerons in the queue. If the key of
349+
an ephemeron is reached, but its value has not yet been reached, then resurrect its value, and
350+
remove the ephemeron from the queue. Otherwise, keep the object in the queue.
351+
3. If any value is resurrected, return `true` from `Scanning::process_weak_refs` so that it will be
352+
called again after the transitive closure from retained values are computed. Then go back to
353+
Step 2.
354+
4. If no value is resurrected, the algorithm completes. The queue contains reachable ephemerons
355+
that have unreachable keys.
356+
357+
This algorithm can be modified if we have a list of all ephemerons before GC starts. We no longer
358+
need to maintain the queue.
359+
360+
- In Step 1, we don't need to enqueue ephemerons.
361+
- In Step 2, we iterate through all ephemerons, and we resurrect the value if both the ephemeron
362+
itself and the key are reached, and the value is not reached yet. We don't need to remove any
363+
ephemeron from the list.
364+
- When the algorithm completes, we can identify both reachable and unreachable ephemerons that
365+
have unreachable keys. But we need to remove unreachable (dead) ephemerons from the list
366+
because they will be recycled in the `Release` stage.
367+
368+
And we can go through ephemerons with unreachable keys and do necessary clean-up operations, either
369+
immediately or postponed to mutator time.
332370

333371

334372
## Optimizations

0 commit comments

Comments
 (0)