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 }