I don't follow. It puts LoadStore for all constructors that store final fields (as expected), and
StoreStore for everything else (as expected). StoreStore is needed to protect the recently allocated
object metadata from the races. Note that you can see the "default" values of Java fields because
publishing the reference to the object may appear "before" constructor stores are observed. But the
same thing would be catastrophic for "metadata" stores like initial mark and klass words: in the
_best_ case scenario, JVM would just crash.
Graal is not alone in this, see e.g.
https://bugs.openjdk.java.net/browse/JDK-8032481
I vaguely remember this being discussed, but cannot remember the conclusion. It tries to emulate
final fields without declaring them final? It does not work completely without LoadLoad on the
reader side (
https://shipilev.net/blog/2014/all-fields-are-final/#_implementation_support), but it
is safer than not doing the release stores at all.
> The question is: Why all these fences cannot be moved to places which work with concurrency
> immediately: GCs, static field initializers, concurrent data structures and APIs like futures,
> actors, etc.?
I don't follow this suggestion. These fences are about surviving races (this is what finals are
for), and thus every follow-up access to the object is exposed on every path, including those that
do not deal with concurrency "immediately".
-Aleksey