-
Notifications
You must be signed in to change notification settings - Fork 79
Description
TL;DR: The Scanning::scan_object API should have an additional argument to tell the VM binding MMTk-core's intended way for handling weak references.
- This is not strictly necessary (although nice to have) for porting the OpenJDK-specific Reference processing code from the
lxrbranch tomaster. We can implement OpenJDK-style reference processing inmmtk-openjdkwithout modifyingmmtk-core. - This is not necessary for implementing the SATB barrier for ConcurrentImmix, either.
- It will be necessary for LXR or RC-based plans.
What does the lxr branch do?
The lxr mimics the way OpenJDK processes weak references. It gradually discovers Reference objects when computing the (strong) transitive closure, and process discovered references afterwards. The discovery is piggy-backed on the object-scanning code, which is Scanning::scan_object in our API. During reference discovery, the referent field of a weak Reference object is ignored, but the Reference is added to a discovered list.
But at the same time, the write barrier function object_probable_write_slow visits both strong and weak fields. When RC promotes an object, it also visits both strong and weak fields.
Such a requirement needs to control whether Scanning::scan_object should visit weak fields and whether it should do "reference discovery".
Conflicts with the goal of being VM-neutral
MMTk core is designed to be VM-neutral. It needs to support VMs that process weak references in different ways. Our Porting Guide mentioned that there are two basic ways to identify weak references:
- Registering them when they are constructed. (e.g. JikesRVM)
- Discover them while computing transitive closure. (e.g. OpenJDK)
So I deem the flags RefScanPolicy::Follow and RefScanPolicy::Discover inappropriate for mmtk-core APIs because "reference discovery" is a concept that OpenJDK uses, but not other JVMs (such as JikesRVM).
Just tell the VM what mmtk-core wants to do
A proper API should communicate the intention of the invocation of Scanning::scan_object. Currently in the master branch, mmtk-core calls Scanning::scan_object for several purposes:
- Computing the transitive closure of strong references (including following further strong references after retaining softly reachable objects and/or finalizable objects). This is for most plans.
- Updating references before compaction. This is for MarkCompact and Compressor.
We can simply encode those two intentions with the following enum:
enum RefScanPolicy {
StrongClosure,
RefUpdate,
}StrongClosure:Scanning::scan_objectshould only visit strong fields. Depending on the VM implementation, the VM may add the reference to "discovered lists" or ignore them if they are already registered.RefUpdate:Scanning::scan_objectshould simply visit all fields.
The key is that we don't mention "discover" in the API. The VM binding decide whether to "discover" in the StrongClosure case.
Other potential intentions
RefScanPolicy may take other values if we have other use cases.
SatbBarrier: We are scanning an object in the slow path of an SATB barrier. It should only visit strong fields because the snapshot should only contain strongly-reachable objects. There are weak-field-loading barriers that handle weak fields by keeping the referent alive.RCBarrier: (Correct me if I am wrong) Coalescing RC barrier. It should count both strong references and weak references because we can't handle weak references when an object suddenly becomes not strongly reachable during RC. We may have to conservatively let weak references contribute reference counts, too.StrongOnly: Force visiting strong fields, only. This implies there is no need to do any special handling for weak fields or Java-styleReferenceobjects.All: Force visiting all fields.
But since barriers are executed in mutators, we need introduce another API function in Scanning. See #1375 for more details.