DecoratorSet cannot be passed to each MMTk runtime barrier implementation.
OpenJDK uses template DecoratorSet to describe certain memory access. For example, HeapAccess<AS_NO_KEEPALIVE>::oop_store_at where oop_store_at is expected to take AS_NO_KEEPALIVE into consideration in its implementation.
// A decorator is an attribute or property that affects the way a memory access is performed in some way.
// There are different groups of decorators. Some have to do with memory ordering, others to do with,
// e.g. strength of references, strength of GC barriers, or whether compression should be applied or not.
// Some decorators are set at buildtime, such as whether primitives require GC barriers or not, others
// at callsites such as whether an access is in the heap or not, and others are resolved at runtime
// such as GC-specific barriers and encoding/decoding compressed oops.
typedef uint64_t DecoratorSet;
However, we cannot access DecoratorSet in each MMTk barrier implementation (such as MMTkObjectBarrierSetRuntime, or MMTkSATBBarrierSetRuntime).
The reason is that MMTk is registered as a single third-party GC for OpenJDK, and OpenJDK expects one BarrierSet implementation for each GC. Thus MMTk only has one MMTkBarrierSet (and one corresponding AccessBarrier where you can access DecoratorSet). To support multiple MMTk GC plans, the binding creates its own barrier interface, and uses virtual dispatch in MMTkBarrierSet/AccessBarrier to each MMTkBarrierSetRuntime. The template type DecoratorSet cannot be passed to MMTkBarrierSetRuntime via virtual dispatch. And the last place where we can access Decoratorset is in MMTkBarrierSet which is used for all MMTk plans. This is not ideal.
This caused issues when I tried to implement https://github.com/mmtk/mmtk-openjdk/pull/311#issuecomment-3157323190. Also some code introduced with concurrent Immix to MMTkBarrierSet that uses DecoratorSet may only apply to concurrent Immix, but now it is used for all the MMTk plans: https://github.com/tianleq/mmtk-openjdk/blob/0d869df5438f286e4110b26361d09bf82983f3b2/openjdk/mmtkBarrierSet.hpp#L188
I wonder whether we can hack BarrierResolver::resolve_barrier_gc() in openjdk so that is when it is ThirdPartyHeapBarrierSet, we delegate the selection of barrier function to a method of the active ThirdPartyHeap implementation.
However, when making the PR https://github.com/mmtk/mmtk-openjdk/pull/328, I have a feeling that if a part of the runtime is too closely related to the GC (such as reference processing), it is better to re-implement part of them in the mmtk-openjdk binding, using a combination of raw memory access and plan-specific barrier operations, rather than trying to reuse 100% of the code in OpenJDK by implementing HeapAccess<...> that satisfies their use cases. My concerns include:
- If a part is too GC-specific, it is better if the field access is as transparent to us as possible. This gives us control of what exactly happens to a field and/or an object. What MMTk's plans do may not match what OpenJDK's own GCs do. For example, they may have read barriers, color pointers, card-marking barriers which we don't have, and some of the access decorators are designed for those things.
- Current MMTk core does not have the concept of "GC worker barriers", i.e. barrier operations performed by GC workers. Currently all barrier operations (such as remembering objects or remembering fields) assumes there is a
Mutatorstruct and it has all the needed buffers for that operation. But in OpenJDK, the GC (such as the reference processor) sometimes useHeapAccess<...>to access object fields.
it is better to re-implement part of them in the mmtk-openjdk binding, using a combination of raw memory access and plan-specific barrier operations, rather than trying to reuse 100% of the code in OpenJDK by implementing HeapAccess<...> that satisfies their use cases.
That would be good. But I am concerned that those heap access decorators are contracts between the runtime and the GC. It is not like just our MMTk GC talks to the MMTk barrier so we know how it works. The runtime expects the GC/barrier to behave in certain ways with those decorators -- currently we completely ignore these.