3737import com .oracle .svm .core .annotate .TargetClass ;
3838import com .oracle .svm .core .snippets .KnownIntrinsics ;
3939
40- import jdk .internal .misc .Unsafe ;
41-
4240@ TargetClass (className = "jdk.internal.misc.VM" )
4341public final class Target_jdk_internal_misc_VM {
4442 /** Ensure that we do not leak the full set of properties from the image generator. */
@@ -72,11 +70,14 @@ public static ClassLoader latestUserDefinedLoader0() {
7270}
7371
7472final class DirectMemoryAccessors {
75- /*
76- * Not volatile to avoid a memory barrier when reading the values. Instead, an explicit barrier
77- * is inserted when writing the values.
73+ /**
74+ * This field needs to be volatile to ensure that reads emit a LOAD-LOAD barrier. Without this
75+ * barrier, subsequent reads could be reordered before the read of {@link #initialized},
76+ * allowing threads to observe an uninitialized value for {@link #directMemory}. We could
77+ * directly emit a LOAD-LOAD barrier instead, but it doesn't make any difference in terms of the
78+ * used instructions on any of the relevant CPU architectures.
7879 */
79- private static boolean initialized ;
80+ private static volatile boolean initialized ;
8081 private static long directMemory ;
8182
8283 static long getDirectMemory () {
@@ -102,27 +103,16 @@ private static long tryInitialize() {
102103 newDirectMemory = Runtime .getRuntime ().maxMemory ();
103104 }
104105
105- /*
106- * The initialization is not synchronized, so multiple threads can race. Usually this will
107- * lead to the same value, unless the runtime options are modified concurrently - which is
108- * possible but not a case we care about.
109- */
110106 directMemory = newDirectMemory ;
111-
112- /* Ensure values are published to other threads before marking fields as initialized. */
113- Unsafe .getUnsafe ().storeFence ();
107+ /* STORE_STORE barrier is executed as part of the volatile write. */
114108 initialized = true ;
115-
116109 return newDirectMemory ;
117110 }
118111}
119112
120113final class PageAlignDirectMemoryAccessors {
121- /*
122- * Not volatile to avoid a memory barrier when reading the values. Instead, an explicit barrier
123- * is inserted when writing the values.
124- */
125- private static boolean initialized ;
114+ /** See {@link DirectMemoryAccessors#initialized} on why this needs to be volatile. */
115+ private static volatile boolean initialized ;
126116 private static boolean pageAlignDirectMemory ;
127117
128118 static Boolean getPageAlignDirectMemory () {
@@ -134,9 +124,7 @@ static Boolean getPageAlignDirectMemory() {
134124
135125 private static void initialize () {
136126 pageAlignDirectMemory = Boolean .getBoolean ("sun.nio.PageAlignDirectMemory" );
137-
138- /* Ensure values are published to other threads before marking fields as initialized. */
139- Unsafe .getUnsafe ().storeFence ();
127+ /* STORE_STORE barrier is executed as part of the volatile write. */
140128 initialized = true ;
141129 }
142130}
0 commit comments