@@ -219,13 +219,15 @@ objects. When using MMTk, there are two ways to implement this semantics.
219
219
The easiest way is ** treating ` SoftReference ` as strong references in non-emergency GCs, and
220
220
treating them as weak references in emergency GCs** .
221
221
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.
229
231
230
232
The other way is ** resurrecting referents of ` SoftReference ` after the strong closure** . This
231
233
involves supporting multiple levels of reference strengths, which will be introduced in the next
@@ -328,7 +330,43 @@ fn process_weak_ref(...) -> bool {
328
330
329
331
### Ephemerons
330
332
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.
332
370
333
371
334
372
## Optimizations
0 commit comments