37
37
import com .oracle .svm .core .annotate .TargetClass ;
38
38
import com .oracle .svm .core .snippets .KnownIntrinsics ;
39
39
40
- import jdk .internal .misc .Unsafe ;
41
-
42
40
@ TargetClass (className = "jdk.internal.misc.VM" )
43
41
public final class Target_jdk_internal_misc_VM {
44
42
/** Ensure that we do not leak the full set of properties from the image generator. */
@@ -72,11 +70,14 @@ public static ClassLoader latestUserDefinedLoader0() {
72
70
}
73
71
74
72
final 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.
78
79
*/
79
- private static boolean initialized ;
80
+ private static volatile boolean initialized ;
80
81
private static long directMemory ;
81
82
82
83
static long getDirectMemory () {
@@ -102,27 +103,16 @@ private static long tryInitialize() {
102
103
newDirectMemory = Runtime .getRuntime ().maxMemory ();
103
104
}
104
105
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
- */
110
106
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. */
114
108
initialized = true ;
115
-
116
109
return newDirectMemory ;
117
110
}
118
111
}
119
112
120
113
final 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 ;
126
116
private static boolean pageAlignDirectMemory ;
127
117
128
118
static Boolean getPageAlignDirectMemory () {
@@ -134,9 +124,7 @@ static Boolean getPageAlignDirectMemory() {
134
124
135
125
private static void initialize () {
136
126
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. */
140
128
initialized = true ;
141
129
}
142
130
}
0 commit comments