23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 /* |
26 /* |
27 * @test |
27 * @test |
28 * @summary tests on constant folding of unsafe get operations |
28 * @summary tests on constant folding of unsafe get operations from stable arrays |
29 * @library /testlibrary /test/lib |
29 * @library /testlibrary /test/lib |
|
30 * |
|
31 * @requires vm.flavor != "client" |
30 * |
32 * |
31 * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions |
33 * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions |
32 * -Xbatch -XX:-TieredCompilation |
34 * -Xbatch -XX:-TieredCompilation |
33 * -XX:+FoldStableValues |
35 * -XX:+FoldStableValues |
34 * UnsafeGetStableArrayElement |
36 * -XX:CompileCommand=dontinline,*Test::test* |
35 * |
|
36 * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions |
|
37 * -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 |
|
38 * -XX:+FoldStableValues |
|
39 * UnsafeGetStableArrayElement |
37 * UnsafeGetStableArrayElement |
40 */ |
38 */ |
41 import jdk.internal.misc.Unsafe; |
39 import jdk.internal.misc.Unsafe; |
42 import jdk.internal.vm.annotation.Stable; |
40 import jdk.internal.vm.annotation.Stable; |
43 import java.util.concurrent.Callable; |
41 import java.util.concurrent.Callable; |
44 |
42 |
45 import static jdk.internal.misc.Unsafe.*; |
43 import static jdk.internal.misc.Unsafe.*; |
46 import static jdk.test.lib.Asserts.*; |
44 import static jdk.test.lib.Asserts.*; |
47 |
45 |
48 public class UnsafeGetStableArrayElement { |
46 public class UnsafeGetStableArrayElement { |
49 @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[] { 0, 1, -128, 127}; |
47 @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16]; |
50 |
48 @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[16]; |
|
49 @Stable static final short[] STABLE_SHORT_ARRAY = new short[8]; |
|
50 @Stable static final char[] STABLE_CHAR_ARRAY = new char[8]; |
|
51 @Stable static final int[] STABLE_INT_ARRAY = new int[4]; |
|
52 @Stable static final long[] STABLE_LONG_ARRAY = new long[2]; |
|
53 @Stable static final float[] STABLE_FLOAT_ARRAY = new float[4]; |
|
54 @Stable static final double[] STABLE_DOUBLE_ARRAY = new double[2]; |
|
55 @Stable static final Object[] STABLE_OBJECT_ARRAY = new Object[4]; |
|
56 |
|
57 static { |
|
58 Setter.reset(); |
|
59 } |
51 static final Unsafe U = Unsafe.getUnsafe(); |
60 static final Unsafe U = Unsafe.getUnsafe(); |
52 |
61 |
53 static int testChar() { |
62 static class Setter { |
54 return U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 0 * ARRAY_CHAR_INDEX_SCALE) + |
63 private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false : true; } |
55 U.getChar(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET + 1 * ARRAY_CHAR_INDEX_SCALE); |
64 private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0] = defaultVal ? 0 : Byte.MAX_VALUE; } |
56 } |
65 private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0] = defaultVal ? 0 : Short.MAX_VALUE; } |
57 |
66 private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0] = defaultVal ? 0 : Character.MAX_VALUE; } |
58 static void run(Callable c) throws Exception { |
67 private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0] = defaultVal ? 0 : Integer.MAX_VALUE; } |
|
68 private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0] = defaultVal ? 0 : Long.MAX_VALUE; } |
|
69 private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0] = defaultVal ? 0 : Float.MAX_VALUE; } |
|
70 private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0] = defaultVal ? 0 : Double.MAX_VALUE; } |
|
71 private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0] = defaultVal ? null : new Object(); } |
|
72 |
|
73 static void reset() { |
|
74 setZ(false); |
|
75 setB(false); |
|
76 setS(false); |
|
77 setC(false); |
|
78 setI(false); |
|
79 setJ(false); |
|
80 setF(false); |
|
81 setD(false); |
|
82 setL(false); |
|
83 } |
|
84 } |
|
85 |
|
86 static class Test { |
|
87 static void changeZ() { Setter.setZ(true); } |
|
88 static void changeB() { Setter.setB(true); } |
|
89 static void changeS() { Setter.setS(true); } |
|
90 static void changeC() { Setter.setC(true); } |
|
91 static void changeI() { Setter.setI(true); } |
|
92 static void changeJ() { Setter.setJ(true); } |
|
93 static void changeF() { Setter.setF(true); } |
|
94 static void changeD() { Setter.setD(true); } |
|
95 static void changeL() { Setter.setL(true); } |
|
96 |
|
97 static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
98 static byte testZ_B() { return U.getByte( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
99 static short testZ_S() { return U.getShort( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
100 static char testZ_C() { return U.getChar( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
101 static int testZ_I() { return U.getInt( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
102 static long testZ_J() { return U.getLong( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
103 static float testZ_F() { return U.getFloat( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
104 static double testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } |
|
105 |
|
106 static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
107 static byte testB_B() { return U.getByte( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
108 static short testB_S() { return U.getShort( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
109 static char testB_C() { return U.getChar( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
110 static int testB_I() { return U.getInt( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
111 static long testB_J() { return U.getLong( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
112 static float testB_F() { return U.getFloat( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
113 static double testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } |
|
114 |
|
115 static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
116 static byte testS_B() { return U.getByte( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
117 static short testS_S() { return U.getShort( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
118 static char testS_C() { return U.getChar( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
119 static int testS_I() { return U.getInt( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
120 static long testS_J() { return U.getLong( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
121 static float testS_F() { return U.getFloat( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
122 static double testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } |
|
123 |
|
124 static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
125 static byte testC_B() { return U.getByte( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
126 static short testC_S() { return U.getShort( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
127 static char testC_C() { return U.getChar( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
128 static int testC_I() { return U.getInt( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
129 static long testC_J() { return U.getLong( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
130 static float testC_F() { return U.getFloat( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
131 static double testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } |
|
132 |
|
133 static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
134 static byte testI_B() { return U.getByte( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
135 static short testI_S() { return U.getShort( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
136 static char testI_C() { return U.getChar( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
137 static int testI_I() { return U.getInt( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
138 static long testI_J() { return U.getLong( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
139 static float testI_F() { return U.getFloat( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
140 static double testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } |
|
141 |
|
142 static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
143 static byte testJ_B() { return U.getByte( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
144 static short testJ_S() { return U.getShort( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
145 static char testJ_C() { return U.getChar( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
146 static int testJ_I() { return U.getInt( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
147 static long testJ_J() { return U.getLong( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
148 static float testJ_F() { return U.getFloat( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
149 static double testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } |
|
150 |
|
151 static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
152 static byte testF_B() { return U.getByte( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
153 static short testF_S() { return U.getShort( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
154 static char testF_C() { return U.getChar( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
155 static int testF_I() { return U.getInt( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
156 static long testF_J() { return U.getLong( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
157 static float testF_F() { return U.getFloat( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
158 static double testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } |
|
159 |
|
160 static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
161 static byte testD_B() { return U.getByte( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
162 static short testD_S() { return U.getShort( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
163 static char testD_C() { return U.getChar( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
164 static int testD_I() { return U.getInt( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
165 static long testD_J() { return U.getLong( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
166 static float testD_F() { return U.getFloat( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
167 static double testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } |
|
168 |
|
169 static Object testL_L() { return U.getObject( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
170 static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
171 static byte testL_B() { return U.getByte( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
172 static short testL_S() { return U.getShort( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
173 static char testL_C() { return U.getChar( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
174 static int testL_I() { return U.getInt( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
175 static long testL_J() { return U.getLong( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
176 static float testL_F() { return U.getFloat( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
177 static double testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } |
|
178 |
|
179 static short testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); } |
|
180 static char testC_U() { return U.getCharUnaligned( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET + 1); } |
|
181 static int testI_U() { return U.getIntUnaligned( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET + 1); } |
|
182 static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); } |
|
183 } |
|
184 |
|
185 static void run(Callable<?> c, Runnable sameResultAction, Runnable changeResultAction) throws Exception { |
59 Object first = c.call(); |
186 Object first = c.call(); |
|
187 |
|
188 // Trigger compilation. |
60 for (int i = 0; i < 20_000; i++) { |
189 for (int i = 0; i < 20_000; i++) { |
|
190 // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC). |
|
191 c.call(); |
|
192 } |
|
193 |
|
194 if (sameResultAction != null) { |
|
195 sameResultAction.run(); |
61 assertEQ(first, c.call()); |
196 assertEQ(first, c.call()); |
62 } |
197 } |
|
198 |
|
199 if (changeResultAction != null) { |
|
200 changeResultAction.run(); |
|
201 assertNE(first, c.call()); |
|
202 assertEQ(c.call(), c.call()); |
|
203 } |
|
204 } |
|
205 |
|
206 static void testMatched(Callable<?> c, Runnable setDefaultAction) throws Exception { |
|
207 run(c, setDefaultAction, null); |
|
208 Setter.reset(); |
|
209 } |
|
210 |
|
211 static void testMismatched(Callable<?> c, Runnable setDefaultAction) throws Exception { |
|
212 run(c, null, setDefaultAction); |
|
213 Setter.reset(); |
63 } |
214 } |
64 |
215 |
65 public static void main(String[] args) throws Exception { |
216 public static void main(String[] args) throws Exception { |
66 run(UnsafeGetStableArrayElement::testChar); |
217 // boolean[], aligned accesses |
|
218 testMatched( Test::testZ_Z, Test::changeZ); |
|
219 testMismatched(Test::testZ_B, Test::changeZ); |
|
220 testMismatched(Test::testZ_S, Test::changeZ); |
|
221 testMismatched(Test::testZ_C, Test::changeZ); |
|
222 testMismatched(Test::testZ_I, Test::changeZ); |
|
223 testMismatched(Test::testZ_J, Test::changeZ); |
|
224 testMismatched(Test::testZ_F, Test::changeZ); |
|
225 testMismatched(Test::testZ_D, Test::changeZ); |
|
226 |
|
227 // byte[], aligned accesses |
|
228 testMismatched(Test::testB_Z, Test::changeB); |
|
229 testMatched( Test::testB_B, Test::changeB); |
|
230 testMismatched(Test::testB_S, Test::changeB); |
|
231 testMismatched(Test::testB_C, Test::changeB); |
|
232 testMismatched(Test::testB_I, Test::changeB); |
|
233 testMismatched(Test::testB_J, Test::changeB); |
|
234 testMismatched(Test::testB_F, Test::changeB); |
|
235 testMismatched(Test::testB_D, Test::changeB); |
|
236 |
|
237 // short[], aligned accesses |
|
238 testMismatched(Test::testS_Z, Test::changeS); |
|
239 testMismatched(Test::testS_B, Test::changeS); |
|
240 testMatched( Test::testS_S, Test::changeS); |
|
241 testMismatched(Test::testS_C, Test::changeS); |
|
242 testMismatched(Test::testS_I, Test::changeS); |
|
243 testMismatched(Test::testS_J, Test::changeS); |
|
244 testMismatched(Test::testS_F, Test::changeS); |
|
245 testMismatched(Test::testS_D, Test::changeS); |
|
246 |
|
247 // char[], aligned accesses |
|
248 testMismatched(Test::testC_Z, Test::changeC); |
|
249 testMismatched(Test::testC_B, Test::changeC); |
|
250 testMismatched(Test::testC_S, Test::changeC); |
|
251 testMatched( Test::testC_C, Test::changeC); |
|
252 testMismatched(Test::testC_I, Test::changeC); |
|
253 testMismatched(Test::testC_J, Test::changeC); |
|
254 testMismatched(Test::testC_F, Test::changeC); |
|
255 testMismatched(Test::testC_D, Test::changeC); |
|
256 |
|
257 // int[], aligned accesses |
|
258 testMismatched(Test::testI_Z, Test::changeI); |
|
259 testMismatched(Test::testI_B, Test::changeI); |
|
260 testMismatched(Test::testI_S, Test::changeI); |
|
261 testMismatched(Test::testI_C, Test::changeI); |
|
262 testMatched( Test::testI_I, Test::changeI); |
|
263 testMismatched(Test::testI_J, Test::changeI); |
|
264 testMismatched(Test::testI_F, Test::changeI); |
|
265 testMismatched(Test::testI_D, Test::changeI); |
|
266 |
|
267 // long[], aligned accesses |
|
268 testMismatched(Test::testJ_Z, Test::changeJ); |
|
269 testMismatched(Test::testJ_B, Test::changeJ); |
|
270 testMismatched(Test::testJ_S, Test::changeJ); |
|
271 testMismatched(Test::testJ_C, Test::changeJ); |
|
272 testMismatched(Test::testJ_I, Test::changeJ); |
|
273 testMatched( Test::testJ_J, Test::changeJ); |
|
274 testMismatched(Test::testJ_F, Test::changeJ); |
|
275 testMismatched(Test::testJ_D, Test::changeJ); |
|
276 |
|
277 // float[], aligned accesses |
|
278 testMismatched(Test::testF_Z, Test::changeF); |
|
279 testMismatched(Test::testF_B, Test::changeF); |
|
280 testMismatched(Test::testF_S, Test::changeF); |
|
281 testMismatched(Test::testF_C, Test::changeF); |
|
282 testMismatched(Test::testF_I, Test::changeF); |
|
283 testMismatched(Test::testF_J, Test::changeF); |
|
284 testMatched( Test::testF_F, Test::changeF); |
|
285 testMismatched(Test::testF_D, Test::changeF); |
|
286 |
|
287 // double[], aligned accesses |
|
288 testMismatched(Test::testD_Z, Test::changeD); |
|
289 testMismatched(Test::testD_B, Test::changeD); |
|
290 testMismatched(Test::testD_S, Test::changeD); |
|
291 testMismatched(Test::testD_C, Test::changeD); |
|
292 testMismatched(Test::testD_I, Test::changeD); |
|
293 testMismatched(Test::testD_J, Test::changeD); |
|
294 testMismatched(Test::testD_F, Test::changeD); |
|
295 testMatched( Test::testD_D, Test::changeD); |
|
296 |
|
297 // Object[], aligned accesses |
|
298 testMismatched(Test::testL_Z, Test::changeL); |
|
299 testMismatched(Test::testL_B, Test::changeL); |
|
300 testMismatched(Test::testL_S, Test::changeL); |
|
301 testMismatched(Test::testL_C, Test::changeL); |
|
302 testMismatched(Test::testL_I, Test::changeL); |
|
303 testMismatched(Test::testL_J, Test::changeL); |
|
304 testMismatched(Test::testL_F, Test::changeL); |
|
305 testMismatched(Test::testL_D, Test::changeL); |
|
306 testMatched( Test::testL_L, Test::changeL); |
|
307 |
|
308 // Unaligned accesses |
|
309 testMismatched(Test::testS_U, Test::changeS); |
|
310 testMismatched(Test::testC_U, Test::changeC); |
|
311 testMismatched(Test::testI_U, Test::changeI); |
|
312 testMismatched(Test::testJ_U, Test::changeJ); |
67 } |
313 } |
68 } |
314 } |