1 /*
2 * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 package compiler.gcbarriers;
25
26 import compiler.lib.ir_framework.*;
27 import java.lang.invoke.VarHandle;
28 import java.lang.invoke.MethodHandles;
29 import java.lang.ref.Reference;
30 import java.lang.ref.ReferenceQueue;
31 import java.lang.ref.SoftReference;
32 import java.lang.ref.WeakReference;
33 import java.util.concurrent.ThreadLocalRandom;
34 import jdk.test.lib.Asserts;
35
36 /**
37 * @test
38 * @summary Test that G1 barriers are generated and optimized as expected.
39 * @library /test/lib /
40 * @requires vm.gc.G1
41 * @run driver compiler.gcbarriers.TestG1BarrierGeneration
42 */
43
44 public class TestG1BarrierGeneration {
45 static final String PRE_ONLY = "pre";
46 static final String POST_ONLY = "post";
47 static final String POST_ONLY_NOT_NULL = "post notnull";
48 static final String PRE_AND_POST = "pre post";
49 static final String PRE_AND_POST_NOT_NULL = "pre post notnull";
50 static final String ANY = ".*";
51
52 static class Outer {
53 Object f;
54 }
55
56 static class OuterWithVolatileField {
57 volatile Object f;
58 }
59
60 static class OuterWithFewFields implements Cloneable {
61 Object f1;
62 Object f2;
63 public Object clone() throws CloneNotSupportedException {
64 return super.clone();
65 }
66 }
67
68 static class OuterWithManyFields implements Cloneable {
69 Object f1;
70 Object f2;
71 Object f3;
72 Object f4;
73 Object f5;
74 Object f6;
75 Object f7;
76 Object f8;
77 Object f9;
78 Object f10;
79 public Object clone() throws CloneNotSupportedException {
80 return super.clone();
81 }
82 }
83
84 static final VarHandle fVarHandle;
85 static {
86 MethodHandles.Lookup l = MethodHandles.lookup();
87 try {
88 fVarHandle = l.findVarHandle(Outer.class, "f", Object.class);
89 } catch (Exception e) {
90 throw new Error(e);
91 }
92 }
93
94 @DontInline
95 static void nonInlinedMethod() {}
96
97 public static void main(String[] args) {
98 TestFramework framework = new TestFramework();
99 Scenario[] scenarios = new Scenario[2*2];
100 int scenarioIndex = 0;
101 for (int i = 0; i < 2; i++) {
102 for (int j = 0; j < 2; j++) {
103 scenarios[scenarioIndex] =
104 new Scenario(scenarioIndex,
105 "-XX:CompileCommand=inline,java.lang.ref.*::*",
106 "-XX:" + (i == 0 ? "-" : "+") + "UseCompressedOops",
107 "-XX:" + (j == 0 ? "-" : "+") + "ReduceInitialCardMarks");
108 scenarioIndex++;
109 }
110 }
111 framework.addScenarios(scenarios);
112 framework.start();
113 }
114
115 @Test
116 @IR(applyIf = {"UseCompressedOops", "false"},
117 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
118 phase = CompilePhase.FINAL_CODE)
119 @IR(applyIf = {"UseCompressedOops", "true"},
120 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
121 phase = CompilePhase.FINAL_CODE)
122 public static void testStore(Outer o, Object o1) {
123 o.f = o1;
124 }
125
126 @Test
127 @IR(applyIf = {"UseCompressedOops", "false"},
128 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
129 phase = CompilePhase.FINAL_CODE)
130 @IR(applyIf = {"UseCompressedOops", "true"},
131 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
132 phase = CompilePhase.FINAL_CODE)
133 public static void testStoreNull(Outer o) {
134 o.f = null;
135 }
136
137 @Test
138 @IR(applyIf = {"UseCompressedOops", "false"},
139 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
140 phase = CompilePhase.FINAL_CODE)
141 @IR(applyIf = {"UseCompressedOops", "true"},
142 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
143 phase = CompilePhase.FINAL_CODE)
144 public static void testStoreObfuscatedNull(Outer o, Object o1) {
145 Object o2 = o1;
146 for (int i = 0; i < 4; i++) {
147 if ((i % 2) == 0) {
148 o2 = null;
149 }
150 }
151 // o2 is null here, but this is only known to C2 after applying some
152 // optimizations (loop unrolling, IGVN).
153 o.f = o2;
154 }
155
156 @Test
157 @IR(applyIf = {"UseCompressedOops", "false"},
158 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
159 phase = CompilePhase.FINAL_CODE)
160 @IR(applyIf = {"UseCompressedOops", "true"},
161 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
162 phase = CompilePhase.FINAL_CODE)
163 public static void testStoreNotNull(Outer o, Object o1) {
164 if (o1.hashCode() == 42) {
165 return;
166 }
167 o.f = o1;
168 }
169
170 @Test
171 @IR(applyIf = {"UseCompressedOops", "false"},
172 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
173 phase = CompilePhase.FINAL_CODE)
174 @IR(applyIf = {"UseCompressedOops", "true"},
175 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
176 phase = CompilePhase.FINAL_CODE)
177 public static void testStoreTwice(Outer o, Outer p, Object o1) {
178 o.f = o1;
179 p.f = o1;
180 }
181
182 @Test
183 @IR(applyIf = {"UseCompressedOops", "false"},
184 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
185 phase = CompilePhase.FINAL_CODE)
186 @IR(applyIf = {"UseCompressedOops", "true"},
187 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
188 phase = CompilePhase.FINAL_CODE)
189 public static void testStoreVolatile(OuterWithVolatileField o, Object o1) {
190 o.f = o1;
191 }
192
193 @Test
194 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
195 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
196 phase = CompilePhase.FINAL_CODE)
197 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
198 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
199 phase = CompilePhase.FINAL_CODE)
200 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
201 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
202 phase = CompilePhase.FINAL_CODE)
203 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
204 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
205 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
206 phase = CompilePhase.FINAL_CODE)
207 public static Outer testStoreOnNewObject(Object o1) {
208 Outer o = new Outer();
209 o.f = o1;
210 return o;
211 }
212
213 @Test
214 @IR(failOn = {IRNode.STORE_P, IRNode.STORE_N},
215 phase = CompilePhase.BEFORE_MACRO_EXPANSION)
216 public static Outer testStoreNullOnNewObject() {
217 Outer o = new Outer();
218 o.f = null;
219 return o;
220 }
221
222 @Test
223 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
224 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY_NOT_NULL, "1"},
225 phase = CompilePhase.FINAL_CODE)
226 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
227 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY_NOT_NULL, "1"},
228 phase = CompilePhase.FINAL_CODE)
229 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
230 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
231 phase = CompilePhase.FINAL_CODE)
232 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
233 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
234 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
235 phase = CompilePhase.FINAL_CODE)
236 public static Outer testStoreNotNullOnNewObject(Object o1) {
237 if (o1.hashCode() == 42) {
238 return null;
239 }
240 Outer o = new Outer();
241 o.f = o1;
242 return o;
243 }
244
245 @Test
246 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
247 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"},
248 phase = CompilePhase.FINAL_CODE)
249 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
250 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"},
251 phase = CompilePhase.FINAL_CODE)
252 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
253 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
254 phase = CompilePhase.FINAL_CODE)
255 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
256 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
257 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
258 phase = CompilePhase.FINAL_CODE)
259 public static Outer testStoreOnNewObjectInTwoPaths(Object o1, boolean c) {
260 Outer o;
261 if (c) {
262 o = new Outer();
263 o.f = o1;
264 } else {
265 o = new Outer();
266 o.f = o1;
267 }
268 return o;
269 }
270
271 @Test
272 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
273 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
274 phase = CompilePhase.FINAL_CODE)
275 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
276 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
277 phase = CompilePhase.FINAL_CODE)
278 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
279 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
280 phase = CompilePhase.FINAL_CODE)
281 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
282 failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
283 phase = CompilePhase.FINAL_CODE)
284 public static Outer testStoreConditionallyOnNewObject(Object o1, boolean c) {
285 Outer o = new Outer();
286 if (c) {
287 o.f = o1;
288 }
289 return o;
290 }
291
292 @Test
293 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
294 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
295 phase = CompilePhase.FINAL_CODE)
296 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
297 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
298 phase = CompilePhase.FINAL_CODE)
299 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
300 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
301 phase = CompilePhase.FINAL_CODE)
302 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
303 failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
304 phase = CompilePhase.FINAL_CODE)
305 public static Outer testStoreOnNewObjectAfterException(Object o1, boolean c) throws Exception {
306 Outer o = new Outer();
307 if (c) {
308 throw new Exception("");
309 }
310 o.f = o1;
311 return o;
312 }
313
314 @Test
315 @IR(applyIf = {"UseCompressedOops", "false"},
316 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
317 phase = CompilePhase.FINAL_CODE)
318 @IR(applyIf = {"UseCompressedOops", "true"},
319 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
320 phase = CompilePhase.FINAL_CODE)
321 public static Outer testStoreOnNewObjectAfterCall(Object o1) {
322 Outer o = new Outer();
323 nonInlinedMethod();
324 o.f = o1;
325 return o;
326 }
327
328 @Run(test = {"testStore",
329 "testStoreNull",
330 "testStoreObfuscatedNull",
331 "testStoreNotNull",
332 "testStoreTwice",
333 "testStoreVolatile",
334 "testStoreOnNewObject",
335 "testStoreNullOnNewObject",
336 "testStoreNotNullOnNewObject",
337 "testStoreOnNewObjectInTwoPaths",
338 "testStoreConditionallyOnNewObject",
339 "testStoreOnNewObjectAfterException",
340 "testStoreOnNewObjectAfterCall"})
341 public void runStoreTests() {
342 {
343 Outer o = new Outer();
344 Object o1 = new Object();
345 testStore(o, o1);
346 Asserts.assertEquals(o1, o.f);
347 }
348 {
349 Outer o = new Outer();
350 testStoreNull(o);
351 Asserts.assertNull(o.f);
352 }
353 {
354 Outer o = new Outer();
355 Object o1 = new Object();
356 testStoreObfuscatedNull(o, o1);
357 Asserts.assertNull(o.f);
358 }
359 {
360 Outer o = new Outer();
361 Object o1 = new Object();
362 testStoreNotNull(o, o1);
363 Asserts.assertEquals(o1, o.f);
364 }
365 {
366 Outer o = new Outer();
367 Outer p = new Outer();
368 Object o1 = new Object();
369 testStoreTwice(o, p, o1);
370 Asserts.assertEquals(o1, o.f);
371 Asserts.assertEquals(o1, p.f);
372 }
373 {
374 OuterWithVolatileField o = new OuterWithVolatileField();
375 Object o1 = new Object();
376 testStoreVolatile(o, o1);
377 Asserts.assertEquals(o1, o.f);
378 }
379 {
380 Object o1 = new Object();
381 Outer o = testStoreOnNewObject(o1);
382 Asserts.assertEquals(o1, o.f);
383 }
384 {
385 Outer o = testStoreNullOnNewObject();
386 Asserts.assertNull(o.f);
387 }
388 {
389 Object o1 = new Object();
390 Outer o = testStoreNotNullOnNewObject(o1);
391 Asserts.assertEquals(o1, o.f);
392 }
393 {
394 Object o1 = new Object();
395 Outer o = testStoreOnNewObjectInTwoPaths(o1, ThreadLocalRandom.current().nextBoolean());
396 Asserts.assertEquals(o1, o.f);
397 }
398 {
399 Object o1 = new Object();
400 boolean c = ThreadLocalRandom.current().nextBoolean();
401 Outer o = testStoreConditionallyOnNewObject(o1, c);
402 Asserts.assertTrue(o.f == (c ? o1 : null));
403 }
404 {
405 Object o1 = new Object();
406 boolean c = ThreadLocalRandom.current().nextBoolean();
407 try {
408 Outer o = testStoreOnNewObjectAfterException(o1, c);
409 } catch (Exception e) {}
410 }
411 {
412 Object o1 = new Object();
413 Outer o = testStoreOnNewObjectAfterCall(o1);
414 Asserts.assertEquals(o1, o.f);
415 }
416 }
417
418 @Test
419 @IR(applyIf = {"UseCompressedOops", "false"},
420 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
421 phase = CompilePhase.FINAL_CODE)
422 @IR(applyIf = {"UseCompressedOops", "true"},
423 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
424 phase = CompilePhase.FINAL_CODE)
425 public static void testArrayStore(Object[] a, int index, Object o1) {
426 a[index] = o1;
427 }
428
429 @Test
430 @IR(applyIf = {"UseCompressedOops", "false"},
431 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
432 phase = CompilePhase.FINAL_CODE)
433 @IR(applyIf = {"UseCompressedOops", "true"},
434 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
435 phase = CompilePhase.FINAL_CODE)
436 public static void testArrayStoreNull(Object[] a, int index) {
437 a[index] = null;
438 }
439
440 @Test
441 @IR(applyIf = {"UseCompressedOops", "false"},
442 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
443 phase = CompilePhase.FINAL_CODE)
444 @IR(applyIf = {"UseCompressedOops", "true"},
445 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
446 phase = CompilePhase.FINAL_CODE)
447 public static void testArrayStoreNotNull(Object[] a, int index, Object o1) {
448 if (o1.hashCode() == 42) {
449 return;
450 }
451 a[index] = o1;
452 }
453
454 @Test
455 @IR(applyIf = {"UseCompressedOops", "false"},
456 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
457 phase = CompilePhase.FINAL_CODE)
458 @IR(applyIf = {"UseCompressedOops", "true"},
459 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
460 phase = CompilePhase.FINAL_CODE)
461 public static void testArrayStoreTwice(Object[] a, Object[] b, int index, Object o1) {
462 a[index] = o1;
463 b[index] = o1;
464 }
465
466 @Test
467 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
468 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
469 phase = CompilePhase.FINAL_CODE)
470 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
471 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
472 phase = CompilePhase.FINAL_CODE)
473 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
474 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
475 phase = CompilePhase.FINAL_CODE)
476 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
477 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
478 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
479 phase = CompilePhase.FINAL_CODE)
480 public static Object[] testStoreOnNewArrayAtKnownIndex(Object o1) {
481 Object[] a = new Object[10];
482 a[4] = o1;
483 return a;
484 }
485
486 @Test
487 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
488 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
489 phase = CompilePhase.FINAL_CODE)
490 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
491 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
492 phase = CompilePhase.FINAL_CODE)
493 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
494 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
495 phase = CompilePhase.FINAL_CODE)
496 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
497 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
498 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
499 phase = CompilePhase.FINAL_CODE)
500 public static Object[] testStoreOnNewArrayAtUnknownIndex(Object o1, int index) {
501 Object[] a = new Object[10];
502 a[index] = o1;
503 return a;
504 }
505
506 @Test
507 @IR(failOn = IRNode.SAFEPOINT)
508 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
509 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, ">1"},
510 phase = CompilePhase.FINAL_CODE)
511 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
512 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, ">1"},
513 phase = CompilePhase.FINAL_CODE)
514 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
515 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY},
516 phase = CompilePhase.FINAL_CODE)
517 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
518 failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
519 phase = CompilePhase.FINAL_CODE)
520 public static Object[] testStoreAllOnNewSmallArray(Object o1) {
521 Object[] a = new Object[64];
522 for (int i = 0; i < a.length; i++) {
523 a[i] = o1;
524 }
525 return a;
526 }
527
528 @Test
529 @IR(counts = {IRNode.SAFEPOINT, "1"})
530 @IR(applyIf = {"UseCompressedOops", "false"},
531 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
532 phase = CompilePhase.FINAL_CODE)
533 @IR(applyIf = {"UseCompressedOops", "true"},
534 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
535 phase = CompilePhase.FINAL_CODE)
536 public static Object[] testStoreAllOnNewLargeArray(Object o1) {
537 Object[] a = new Object[1024];
538 for (int i = 0; i < a.length; i++) {
539 a[i] = o1;
540 }
541 return a;
542 }
543
544 @Run(test = {"testArrayStore",
545 "testArrayStoreNull",
546 "testArrayStoreNotNull",
547 "testArrayStoreTwice",
548 "testStoreOnNewArrayAtKnownIndex",
549 "testStoreOnNewArrayAtUnknownIndex",
550 "testStoreAllOnNewSmallArray",
551 "testStoreAllOnNewLargeArray"})
552 @Warmup(5000)
553 public void runArrayStoreTests() {
554 {
555 Object[] a = new Object[10];
556 Object o1 = new Object();
557 testArrayStore(a, 4, o1);
558 Asserts.assertEquals(o1, a[4]);
559 }
560 {
561 Object[] a = new Object[10];
562 testArrayStoreNull(a, 4);
563 Asserts.assertNull(a[4]);
564 }
565 {
566 Object[] a = new Object[10];
567 Object o1 = new Object();
568 testArrayStoreNotNull(a, 4, o1);
569 Asserts.assertEquals(o1, a[4]);
570 }
571 {
572 Object[] a = new Object[10];
573 Object[] b = new Object[10];
574 Object o1 = new Object();
575 testArrayStoreTwice(a, b, 4, o1);
576 Asserts.assertEquals(o1, a[4]);
577 Asserts.assertEquals(o1, b[4]);
578 }
579 {
580 Object o1 = new Object();
581 Object[] a = testStoreOnNewArrayAtKnownIndex(o1);
582 Asserts.assertEquals(o1, a[4]);
583 }
584 {
585 Object o1 = new Object();
586 Object[] a = testStoreOnNewArrayAtUnknownIndex(o1, 5);
587 Asserts.assertEquals(o1, a[5]);
588 }
589 {
590 Object o1 = new Object();
591 Object[] a = testStoreAllOnNewSmallArray(o1);
592 for (int i = 0; i < a.length; i++) {
593 Asserts.assertEquals(o1, a[i]);
594 }
595 }
596 {
597 Object o1 = new Object();
598 Object[] a = testStoreAllOnNewLargeArray(o1);
599 for (int i = 0; i < a.length; i++) {
600 Asserts.assertEquals(o1, a[i]);
601 }
602 }
603 }
604
605 @Test
606 public static Object[] testCloneArrayOfObjects(Object[] a) {
607 Object[] a1 = null;
608 try {
609 a1 = a.clone();
610 } catch (Exception e) {}
611 return a1;
612 }
613
614 @Test
615 @IR(applyIf = {"ReduceInitialCardMarks", "true"},
616 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY,
617 IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
618 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
619 phase = CompilePhase.FINAL_CODE)
620 @IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "false"},
621 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"},
622 phase = CompilePhase.FINAL_CODE)
623 @IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "true"},
624 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"},
625 phase = CompilePhase.FINAL_CODE)
626 public static OuterWithFewFields testCloneObjectWithFewFields(OuterWithFewFields o) {
627 Object o1 = null;
628 try {
629 o1 = o.clone();
630 } catch (Exception e) {}
631 return (OuterWithFewFields)o1;
632 }
633
634 @Test
635 @IR(applyIf = {"ReduceInitialCardMarks", "true"},
636 counts = {IRNode.CALL_OF, "jlong_disjoint_arraycopy", "1"})
637 @IR(applyIf = {"ReduceInitialCardMarks", "false"},
638 counts = {IRNode.CALL_OF, "G1BarrierSetRuntime::clone", "1"})
639 public static OuterWithManyFields testCloneObjectWithManyFields(OuterWithManyFields o) {
640 Object o1 = null;
641 try {
642 o1 = o.clone();
643 } catch (Exception e) {}
644 return (OuterWithManyFields)o1;
645 }
646
647 @Run(test = {"testCloneArrayOfObjects",
648 "testCloneObjectWithFewFields",
649 "testCloneObjectWithManyFields"})
650 public void runCloneTests() {
651 {
652 Object o1 = new Object();
653 Object[] a = new Object[4];
654 for (int i = 0; i < 4; i++) {
655 a[i] = o1;
656 }
657 Object[] a1 = testCloneArrayOfObjects(a);
658 for (int i = 0; i < 4; i++) {
659 Asserts.assertEquals(o1, a1[i]);
660 }
661 }
662 {
663 Object a = new Object();
664 Object b = new Object();
665 OuterWithFewFields o = new OuterWithFewFields();
666 o.f1 = a;
667 o.f2 = b;
668 OuterWithFewFields o1 = testCloneObjectWithFewFields(o);
669 Asserts.assertEquals(a, o1.f1);
670 Asserts.assertEquals(b, o1.f2);
671 }
672 {
673 Object a = new Object();
674 Object b = new Object();
675 Object c = new Object();
676 Object d = new Object();
677 Object e = new Object();
678 Object f = new Object();
679 Object g = new Object();
680 Object h = new Object();
681 Object i = new Object();
682 Object j = new Object();
683 OuterWithManyFields o = new OuterWithManyFields();
684 o.f1 = a;
685 o.f2 = b;
686 o.f3 = c;
687 o.f4 = d;
688 o.f5 = e;
689 o.f6 = f;
690 o.f7 = g;
691 o.f8 = h;
692 o.f9 = i;
693 o.f10 = j;
694 OuterWithManyFields o1 = testCloneObjectWithManyFields(o);
695 Asserts.assertEquals(a, o1.f1);
696 Asserts.assertEquals(b, o1.f2);
697 Asserts.assertEquals(c, o1.f3);
698 Asserts.assertEquals(d, o1.f4);
699 Asserts.assertEquals(e, o1.f5);
700 Asserts.assertEquals(f, o1.f6);
701 Asserts.assertEquals(g, o1.f7);
702 Asserts.assertEquals(h, o1.f8);
703 Asserts.assertEquals(i, o1.f9);
704 Asserts.assertEquals(j, o1.f10);
705 }
706 }
707
708 @Test
709 @IR(applyIf = {"UseCompressedOops", "false"},
710 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
711 phase = CompilePhase.FINAL_CODE)
712 @IR(applyIf = {"UseCompressedOops", "true"},
713 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
714 phase = CompilePhase.FINAL_CODE)
715 static Object testCompareAndExchange(Outer o, Object oldVal, Object newVal) {
716 return fVarHandle.compareAndExchange(o, oldVal, newVal);
717 }
718
719 @Test
720 @IR(applyIf = {"UseCompressedOops", "false"},
721 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
722 phase = CompilePhase.FINAL_CODE)
723 @IR(applyIf = {"UseCompressedOops", "true"},
724 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
725 phase = CompilePhase.FINAL_CODE)
726 static boolean testCompareAndSwap(Outer o, Object oldVal, Object newVal) {
727 return fVarHandle.compareAndSet(o, oldVal, newVal);
728 }
729
730 @Test
731 @IR(applyIf = {"UseCompressedOops", "false"},
732 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
733 phase = CompilePhase.FINAL_CODE)
734 @IR(applyIf = {"UseCompressedOops", "true"},
735 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
736 phase = CompilePhase.FINAL_CODE)
737 static Object testGetAndSet(Outer o, Object newVal) {
738 return fVarHandle.getAndSet(o, newVal);
739 }
740
741 // IR checks are disabled for s390 because barriers are not elided (to be investigated).
742 @Test
743 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
744 applyIfPlatform = {"s390", "false"},
745 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
746 phase = CompilePhase.FINAL_CODE)
747 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
748 applyIfPlatform = {"s390", "false"},
749 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
750 phase = CompilePhase.FINAL_CODE)
751 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
752 applyIfPlatform = {"s390", "false"},
753 failOn = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, ANY},
754 phase = CompilePhase.FINAL_CODE)
755 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
756 applyIfPlatform = {"s390", "false"},
757 failOn = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, ANY},
758 phase = CompilePhase.FINAL_CODE)
759 static Object testCompareAndExchangeOnNewObject(Object oldVal, Object newVal) {
760 Outer o = new Outer();
761 o.f = oldVal;
762 return fVarHandle.compareAndExchange(o, oldVal, newVal);
763 }
764
765 // IR checks are disabled for s390 when OOPs compression is disabled
766 // because barriers are not elided in this configuration (to be investigated).
767 @Test
768 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
769 applyIfPlatform = {"s390", "false"},
770 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
771 phase = CompilePhase.FINAL_CODE)
772 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
773 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
774 phase = CompilePhase.FINAL_CODE)
775 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
776 applyIfPlatform = {"s390", "false"},
777 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY},
778 phase = CompilePhase.FINAL_CODE)
779 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
780 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY},
781 phase = CompilePhase.FINAL_CODE)
782 static boolean testCompareAndSwapOnNewObject(Object oldVal, Object newVal) {
783 Outer o = new Outer();
784 o.f = oldVal;
785 return fVarHandle.compareAndSet(o, oldVal, newVal);
786 }
787
788 @Test
789 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
790 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
791 phase = CompilePhase.FINAL_CODE)
792 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
793 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
794 phase = CompilePhase.FINAL_CODE)
795 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
796 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY},
797 phase = CompilePhase.FINAL_CODE)
798 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
799 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY},
800 phase = CompilePhase.FINAL_CODE)
801 static Object testGetAndSetOnNewObject(Object oldVal, Object newVal) {
802 Outer o = new Outer();
803 o.f = oldVal;
804 return fVarHandle.getAndSet(o, newVal);
805 }
806
807 @Test
808 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
809 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
810 phase = CompilePhase.FINAL_CODE)
811 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
812 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
813 phase = CompilePhase.FINAL_CODE)
814 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
815 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY},
816 phase = CompilePhase.FINAL_CODE)
817 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
818 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY},
819 phase = CompilePhase.FINAL_CODE)
820 static Object testGetAndSetConditionallyOnNewObject(Object oldVal, Object newVal, boolean c) {
821 Outer o = new Outer();
822 o.f = oldVal;
823 if (c) {
824 return fVarHandle.getAndSet(o, newVal);
825 }
826 return oldVal;
827 }
828
829 @Test
830 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
831 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
832 phase = CompilePhase.FINAL_CODE)
833 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
834 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
835 phase = CompilePhase.FINAL_CODE)
836 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
837 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY},
838 phase = CompilePhase.FINAL_CODE)
839 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
840 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY},
841 phase = CompilePhase.FINAL_CODE)
842 static Object testGetAndSetOnNewObjectAfterException(Object oldVal, Object newVal, boolean c) throws Exception {
843 Outer o = new Outer();
844 if (c) {
845 throw new Exception("");
846 }
847 o.f = oldVal;
848 return fVarHandle.getAndSet(o, newVal);
849 }
850
851 @Test
852 @IR(applyIf = {"UseCompressedOops", "false"},
853 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
854 phase = CompilePhase.FINAL_CODE)
855 @IR(applyIf = {"UseCompressedOops", "true"},
856 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
857 phase = CompilePhase.FINAL_CODE)
858 static Object testGetAndSetOnNewObjectAfterCall(Object oldVal, Object newVal) {
859 Outer o = new Outer();
860 nonInlinedMethod();
861 o.f = oldVal;
862 return fVarHandle.getAndSet(o, newVal);
863 }
864
865 @Run(test = {"testCompareAndExchange",
866 "testCompareAndSwap",
867 "testGetAndSet",
868 "testCompareAndExchangeOnNewObject",
869 "testCompareAndSwapOnNewObject",
870 "testGetAndSetOnNewObject",
871 "testGetAndSetConditionallyOnNewObject",
872 "testGetAndSetOnNewObjectAfterException",
873 "testGetAndSetOnNewObjectAfterCall"})
874 public void runAtomicTests() {
875 {
876 Outer o = new Outer();
877 Object oldVal = new Object();
878 o.f = oldVal;
879 Object newVal = new Object();
880 Object oldVal2 = testCompareAndExchange(o, oldVal, newVal);
881 Asserts.assertEquals(oldVal, oldVal2);
882 Asserts.assertEquals(o.f, newVal);
883 }
884 {
885 Outer o = new Outer();
886 Object oldVal = new Object();
887 o.f = oldVal;
888 Object newVal = new Object();
889 boolean b = testCompareAndSwap(o, oldVal, newVal);
890 Asserts.assertTrue(b);
891 Asserts.assertEquals(o.f, newVal);
892 }
893 {
894 Outer o = new Outer();
895 Object oldVal = new Object();
896 o.f = oldVal;
897 Object newVal = new Object();
898 Object oldVal2 = testGetAndSet(o, newVal);
899 Asserts.assertEquals(oldVal, oldVal2);
900 Asserts.assertEquals(o.f, newVal);
901 }
902 {
903 Object oldVal = new Object();
904 Object newVal = new Object();
905 Object oldVal2 = testCompareAndExchangeOnNewObject(oldVal, newVal);
906 Asserts.assertEquals(oldVal, oldVal2);
907 }
908 {
909 Object oldVal = new Object();
910 Object newVal = new Object();
911 boolean b = testCompareAndSwapOnNewObject(oldVal, newVal);
912 Asserts.assertTrue(b);
913 }
914 {
915 Object oldVal = new Object();
916 Object newVal = new Object();
917 Object oldVal2 = testGetAndSetOnNewObject(oldVal, newVal);
918 Asserts.assertEquals(oldVal, oldVal2);
919 }
920 {
921 Object oldVal = new Object();
922 Object newVal = new Object();
923 boolean c = ThreadLocalRandom.current().nextBoolean();
924 Object oldVal2 = testGetAndSetConditionallyOnNewObject(oldVal, newVal, c);
925 Asserts.assertEquals(oldVal, oldVal2);
926 }
927 {
928 Object oldVal = new Object();
929 Object newVal = new Object();
930 boolean c = ThreadLocalRandom.current().nextBoolean();
931 try {
932 Object oldVal2 = testGetAndSetOnNewObjectAfterException(oldVal, newVal, c);
933 } catch (Exception e) {}
934 }
935 {
936 Object oldVal = new Object();
937 Object newVal = new Object();
938 Object oldVal2 = testGetAndSetOnNewObjectAfterCall(oldVal, newVal);
939 Asserts.assertEquals(oldVal, oldVal2);
940 }
941 }
942
943 @Test
944 @IR(applyIf = {"UseCompressedOops", "false"},
945 counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
946 phase = CompilePhase.FINAL_CODE)
947 @IR(applyIf = {"UseCompressedOops", "true"},
948 counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
949 phase = CompilePhase.FINAL_CODE)
950 static Object testLoadSoftReference(SoftReference<Object> ref) {
951 return ref.get();
952 }
953
954 @Test
955 @IR(applyIf = {"UseCompressedOops", "false"},
956 counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
957 phase = CompilePhase.FINAL_CODE)
958 @IR(applyIf = {"UseCompressedOops", "true"},
959 counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
960 phase = CompilePhase.FINAL_CODE)
961 static Object testLoadWeakReference(WeakReference<Object> ref) {
962 return ref.get();
963 }
964
965 @Run(test = {"testLoadSoftReference",
966 "testLoadWeakReference"})
967 public void runReferenceTests() {
968 {
969 Object o1 = new Object();
970 SoftReference<Object> sref = new SoftReference<Object>(o1);
971 Object o2 = testLoadSoftReference(sref);
972 Asserts.assertTrue(o2 == o1 || o2 == null);
973 }
974 {
975 Object o1 = new Object();
976 WeakReference<Object> wref = new WeakReference<Object>(o1);
977 Object o2 = testLoadWeakReference(wref);
978 Asserts.assertTrue(o2 == o1 || o2 == null);
979 }
980 }
981 }