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 public void runArrayStoreTests() {
553 {
554 Object[] a = new Object[10];
555 Object o1 = new Object();
556 testArrayStore(a, 4, o1);
557 Asserts.assertEquals(o1, a[4]);
558 }
559 {
560 Object[] a = new Object[10];
561 testArrayStoreNull(a, 4);
562 Asserts.assertNull(a[4]);
563 }
564 {
565 Object[] a = new Object[10];
566 Object o1 = new Object();
567 testArrayStoreNotNull(a, 4, o1);
568 Asserts.assertEquals(o1, a[4]);
569 }
570 {
571 Object[] a = new Object[10];
572 Object[] b = new Object[10];
573 Object o1 = new Object();
574 testArrayStoreTwice(a, b, 4, o1);
575 Asserts.assertEquals(o1, a[4]);
576 Asserts.assertEquals(o1, b[4]);
577 }
578 {
579 Object o1 = new Object();
580 Object[] a = testStoreOnNewArrayAtKnownIndex(o1);
581 Asserts.assertEquals(o1, a[4]);
582 }
583 {
584 Object o1 = new Object();
585 Object[] a = testStoreOnNewArrayAtUnknownIndex(o1, 5);
586 Asserts.assertEquals(o1, a[5]);
587 }
588 {
589 Object o1 = new Object();
590 Object[] a = testStoreAllOnNewSmallArray(o1);
591 for (int i = 0; i < a.length; i++) {
592 Asserts.assertEquals(o1, a[i]);
593 }
594 }
595 {
596 Object o1 = new Object();
597 Object[] a = testStoreAllOnNewLargeArray(o1);
598 for (int i = 0; i < a.length; i++) {
599 Asserts.assertEquals(o1, a[i]);
600 }
601 }
602 }
603
604 @Test
605 public static Object[] testCloneArrayOfObjects(Object[] a) {
606 Object[] a1 = null;
607 try {
608 a1 = a.clone();
609 } catch (Exception e) {}
610 return a1;
611 }
612
613 @Test
614 @IR(applyIf = {"ReduceInitialCardMarks", "true"},
615 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY,
616 IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY,
617 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY},
618 phase = CompilePhase.FINAL_CODE)
619 @IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "false"},
620 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"},
621 phase = CompilePhase.FINAL_CODE)
622 @IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "true"},
623 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"},
624 phase = CompilePhase.FINAL_CODE)
625 public static OuterWithFewFields testCloneObjectWithFewFields(OuterWithFewFields o) {
626 Object o1 = null;
627 try {
628 o1 = o.clone();
629 } catch (Exception e) {}
630 return (OuterWithFewFields)o1;
631 }
632
633 @Test
634 @IR(applyIf = {"ReduceInitialCardMarks", "true"},
635 counts = {IRNode.CALL_OF, "jlong_disjoint_arraycopy", "1"})
636 @IR(applyIf = {"ReduceInitialCardMarks", "false"},
637 counts = {IRNode.CALL_OF, "G1BarrierSetRuntime::clone", "1"})
638 public static OuterWithManyFields testCloneObjectWithManyFields(OuterWithManyFields o) {
639 Object o1 = null;
640 try {
641 o1 = o.clone();
642 } catch (Exception e) {}
643 return (OuterWithManyFields)o1;
644 }
645
646 @Run(test = {"testCloneArrayOfObjects",
647 "testCloneObjectWithFewFields",
648 "testCloneObjectWithManyFields"})
649 public void runCloneTests() {
650 {
651 Object o1 = new Object();
652 Object[] a = new Object[4];
653 for (int i = 0; i < 4; i++) {
654 a[i] = o1;
655 }
656 Object[] a1 = testCloneArrayOfObjects(a);
657 for (int i = 0; i < 4; i++) {
658 Asserts.assertEquals(o1, a1[i]);
659 }
660 }
661 {
662 Object a = new Object();
663 Object b = new Object();
664 OuterWithFewFields o = new OuterWithFewFields();
665 o.f1 = a;
666 o.f2 = b;
667 OuterWithFewFields o1 = testCloneObjectWithFewFields(o);
668 Asserts.assertEquals(a, o1.f1);
669 Asserts.assertEquals(b, o1.f2);
670 }
671 {
672 Object a = new Object();
673 Object b = new Object();
674 Object c = new Object();
675 Object d = new Object();
676 Object e = new Object();
677 Object f = new Object();
678 Object g = new Object();
679 Object h = new Object();
680 Object i = new Object();
681 Object j = new Object();
682 OuterWithManyFields o = new OuterWithManyFields();
683 o.f1 = a;
684 o.f2 = b;
685 o.f3 = c;
686 o.f4 = d;
687 o.f5 = e;
688 o.f6 = f;
689 o.f7 = g;
690 o.f8 = h;
691 o.f9 = i;
692 o.f10 = j;
693 OuterWithManyFields o1 = testCloneObjectWithManyFields(o);
694 Asserts.assertEquals(a, o1.f1);
695 Asserts.assertEquals(b, o1.f2);
696 Asserts.assertEquals(c, o1.f3);
697 Asserts.assertEquals(d, o1.f4);
698 Asserts.assertEquals(e, o1.f5);
699 Asserts.assertEquals(f, o1.f6);
700 Asserts.assertEquals(g, o1.f7);
701 Asserts.assertEquals(h, o1.f8);
702 Asserts.assertEquals(i, o1.f9);
703 Asserts.assertEquals(j, o1.f10);
704 }
705 }
706
707 @Test
708 @IR(applyIf = {"UseCompressedOops", "false"},
709 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
710 phase = CompilePhase.FINAL_CODE)
711 @IR(applyIf = {"UseCompressedOops", "true"},
712 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
713 phase = CompilePhase.FINAL_CODE)
714 static Object testCompareAndExchange(Outer o, Object oldVal, Object newVal) {
715 return fVarHandle.compareAndExchange(o, oldVal, newVal);
716 }
717
718 @Test
719 @IR(applyIf = {"UseCompressedOops", "false"},
720 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
721 phase = CompilePhase.FINAL_CODE)
722 @IR(applyIf = {"UseCompressedOops", "true"},
723 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
724 phase = CompilePhase.FINAL_CODE)
725 static boolean testCompareAndSwap(Outer o, Object oldVal, Object newVal) {
726 return fVarHandle.compareAndSet(o, oldVal, newVal);
727 }
728
729 @Test
730 @IR(applyIf = {"UseCompressedOops", "false"},
731 counts = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
732 phase = CompilePhase.FINAL_CODE)
733 @IR(applyIf = {"UseCompressedOops", "true"},
734 counts = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
735 phase = CompilePhase.FINAL_CODE)
736 static Object testGetAndSet(Outer o, Object newVal) {
737 return fVarHandle.getAndSet(o, newVal);
738 }
739
740 // IR checks are disabled for s390 because barriers are not elided (to be investigated).
741 @Test
742 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
743 applyIfPlatform = {"s390", "false"},
744 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
745 phase = CompilePhase.FINAL_CODE)
746 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
747 applyIfPlatform = {"s390", "false"},
748 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
749 phase = CompilePhase.FINAL_CODE)
750 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
751 applyIfPlatform = {"s390", "false"},
752 failOn = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, ANY},
753 phase = CompilePhase.FINAL_CODE)
754 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
755 applyIfPlatform = {"s390", "false"},
756 failOn = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, ANY},
757 phase = CompilePhase.FINAL_CODE)
758 static Object testCompareAndExchangeOnNewObject(Object oldVal, Object newVal) {
759 Outer o = new Outer();
760 o.f = oldVal;
761 return fVarHandle.compareAndExchange(o, oldVal, newVal);
762 }
763
764 // IR checks are disabled for s390 when OOPs compression is disabled
765 // because barriers are not elided in this configuration (to be investigated).
766 @Test
767 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
768 applyIfPlatform = {"s390", "false"},
769 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
770 phase = CompilePhase.FINAL_CODE)
771 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
772 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
773 phase = CompilePhase.FINAL_CODE)
774 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
775 applyIfPlatform = {"s390", "false"},
776 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY},
777 phase = CompilePhase.FINAL_CODE)
778 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
779 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY},
780 phase = CompilePhase.FINAL_CODE)
781 static boolean testCompareAndSwapOnNewObject(Object oldVal, Object newVal) {
782 Outer o = new Outer();
783 o.f = oldVal;
784 return fVarHandle.compareAndSet(o, oldVal, newVal);
785 }
786
787 @Test
788 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
789 counts = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
790 phase = CompilePhase.FINAL_CODE)
791 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
792 counts = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
793 phase = CompilePhase.FINAL_CODE)
794 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
795 failOn = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, ANY},
796 phase = CompilePhase.FINAL_CODE)
797 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
798 failOn = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, ANY},
799 phase = CompilePhase.FINAL_CODE)
800 static Object testGetAndSetOnNewObject(Object oldVal, Object newVal) {
801 Outer o = new Outer();
802 o.f = oldVal;
803 return fVarHandle.getAndSet(o, newVal);
804 }
805
806 @Test
807 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
808 counts = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
809 phase = CompilePhase.FINAL_CODE)
810 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
811 counts = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
812 phase = CompilePhase.FINAL_CODE)
813 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
814 failOn = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, ANY},
815 phase = CompilePhase.FINAL_CODE)
816 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
817 failOn = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, ANY},
818 phase = CompilePhase.FINAL_CODE)
819 static Object testGetAndSetConditionallyOnNewObject(Object oldVal, Object newVal, boolean c) {
820 Outer o = new Outer();
821 o.f = oldVal;
822 if (c) {
823 return fVarHandle.getAndSet(o, newVal);
824 }
825 return oldVal;
826 }
827
828 @Test
829 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
830 counts = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
831 phase = CompilePhase.FINAL_CODE)
832 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
833 counts = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
834 phase = CompilePhase.FINAL_CODE)
835 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
836 failOn = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, ANY},
837 phase = CompilePhase.FINAL_CODE)
838 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
839 failOn = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, ANY},
840 phase = CompilePhase.FINAL_CODE)
841 static Object testGetAndSetOnNewObjectAfterException(Object oldVal, Object newVal, boolean c) throws Exception {
842 Outer o = new Outer();
843 if (c) {
844 throw new Exception("");
845 }
846 o.f = oldVal;
847 return fVarHandle.getAndSet(o, newVal);
848 }
849
850 @Test
851 @IR(applyIf = {"UseCompressedOops", "false"},
852 counts = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
853 phase = CompilePhase.FINAL_CODE)
854 @IR(applyIf = {"UseCompressedOops", "true"},
855 counts = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
856 phase = CompilePhase.FINAL_CODE)
857 static Object testGetAndSetOnNewObjectAfterCall(Object oldVal, Object newVal) {
858 Outer o = new Outer();
859 nonInlinedMethod();
860 o.f = oldVal;
861 return fVarHandle.getAndSet(o, newVal);
862 }
863
864 @Run(test = {"testCompareAndExchange",
865 "testCompareAndSwap",
866 "testGetAndSet",
867 "testCompareAndExchangeOnNewObject",
868 "testCompareAndSwapOnNewObject",
869 "testGetAndSetOnNewObject",
870 "testGetAndSetConditionallyOnNewObject",
871 "testGetAndSetOnNewObjectAfterException",
872 "testGetAndSetOnNewObjectAfterCall"})
873 public void runAtomicTests() {
874 {
875 Outer o = new Outer();
876 Object oldVal = new Object();
877 o.f = oldVal;
878 Object newVal = new Object();
879 Object oldVal2 = testCompareAndExchange(o, oldVal, newVal);
880 Asserts.assertEquals(oldVal, oldVal2);
881 Asserts.assertEquals(o.f, newVal);
882 }
883 {
884 Outer o = new Outer();
885 Object oldVal = new Object();
886 o.f = oldVal;
887 Object newVal = new Object();
888 boolean b = testCompareAndSwap(o, oldVal, newVal);
889 Asserts.assertTrue(b);
890 Asserts.assertEquals(o.f, newVal);
891 }
892 {
893 Outer o = new Outer();
894 Object oldVal = new Object();
895 o.f = oldVal;
896 Object newVal = new Object();
897 Object oldVal2 = testGetAndSet(o, newVal);
898 Asserts.assertEquals(oldVal, oldVal2);
899 Asserts.assertEquals(o.f, newVal);
900 }
901 {
902 Object oldVal = new Object();
903 Object newVal = new Object();
904 Object oldVal2 = testCompareAndExchangeOnNewObject(oldVal, newVal);
905 Asserts.assertEquals(oldVal, oldVal2);
906 }
907 {
908 Object oldVal = new Object();
909 Object newVal = new Object();
910 boolean b = testCompareAndSwapOnNewObject(oldVal, newVal);
911 Asserts.assertTrue(b);
912 }
913 {
914 Object oldVal = new Object();
915 Object newVal = new Object();
916 Object oldVal2 = testGetAndSetOnNewObject(oldVal, newVal);
917 Asserts.assertEquals(oldVal, oldVal2);
918 }
919 {
920 Object oldVal = new Object();
921 Object newVal = new Object();
922 boolean c = ThreadLocalRandom.current().nextBoolean();
923 Object oldVal2 = testGetAndSetConditionallyOnNewObject(oldVal, newVal, c);
924 Asserts.assertEquals(oldVal, oldVal2);
925 }
926 {
927 Object oldVal = new Object();
928 Object newVal = new Object();
929 boolean c = ThreadLocalRandom.current().nextBoolean();
930 try {
931 Object oldVal2 = testGetAndSetOnNewObjectAfterException(oldVal, newVal, c);
932 } catch (Exception e) {}
933 }
934 {
935 Object oldVal = new Object();
936 Object newVal = new Object();
937 Object oldVal2 = testGetAndSetOnNewObjectAfterCall(oldVal, newVal);
938 Asserts.assertEquals(oldVal, oldVal2);
939 }
940 }
941
942 @Test
943 @IR(applyIf = {"UseCompressedOops", "false"},
944 counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
945 phase = CompilePhase.FINAL_CODE)
946 @IR(applyIf = {"UseCompressedOops", "true"},
947 counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
948 phase = CompilePhase.FINAL_CODE)
949 static Object testLoadSoftReference(SoftReference<Object> ref) {
950 return ref.get();
951 }
952
953 @Test
954 @IR(applyIf = {"UseCompressedOops", "false"},
955 counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
956 phase = CompilePhase.FINAL_CODE)
957 @IR(applyIf = {"UseCompressedOops", "true"},
958 counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
959 phase = CompilePhase.FINAL_CODE)
960 static Object testLoadWeakReference(WeakReference<Object> ref) {
961 return ref.get();
962 }
963
964 @Run(test = {"testLoadSoftReference",
965 "testLoadWeakReference"})
966 public void runReferenceTests() {
967 {
968 Object o1 = new Object();
969 SoftReference<Object> sref = new SoftReference<Object>(o1);
970 Object o2 = testLoadSoftReference(sref);
971 Asserts.assertTrue(o2 == o1 || o2 == null);
972 }
973 {
974 Object o1 = new Object();
975 WeakReference<Object> wref = new WeakReference<Object>(o1);
976 Object o2 = testLoadWeakReference(wref);
977 Asserts.assertTrue(o2 == o1 || o2 == null);
978 }
979 }
980 }