1 /*
  2  * Copyright (c) 2024 Alibaba Group Holding Limited. 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.c2.irTests.scalarReplacement;
 25 
 26 import compiler.lib.ir_framework.*;
 27 
 28 /*
 29  * @test
 30  * @bug 8333334
 31  * @summary Tests that dead barrier control flows do not affect the scalar replacement.
 32  * @library /test/lib /
 33  * @requires vm.compiler2.enabled
 34  * @requires vm.gc.G1
 35  * @run driver compiler.c2.irTests.scalarReplacement.ScalarReplacementWithGCBarrierTests
 36  */
 37 public class ScalarReplacementWithGCBarrierTests {
 38     static class List {
 39         public Node head;
 40 
 41         public void push(int value) {
 42             Node n = new Node();
 43             n.value = value;
 44             n.next = head;
 45             head = n;
 46         }
 47 
 48         @ForceInline
 49         public Iter iter() {
 50             Iter iter = new Iter();
 51             iter.list = this;
 52             iter.n = head;
 53             iter.sum = 0;
 54             return iter;
 55         }
 56     }
 57 
 58     static class Node {
 59         public int value;
 60         public Node next;
 61     }
 62 
 63     static class Iter {
 64         public List list;
 65         public Node n;
 66         public Integer sum;
 67 
 68         @ForceInline
 69         public boolean next() {
 70             int lastSum = sum;
 71             while (sum - lastSum < 1000) {
 72                 while (n != null && n.value < 30) n = n.next;
 73                 if (n == null) return false;
 74                 sum += n.value;
 75                 n = n.next;
 76             }
 77             return true;
 78         }
 79     }
 80 
 81     private static final int SIZE = 1000;
 82 
 83     public static void main(String[] args) {
 84         // Must use G1 GC to ensure there is a pre-barrier
 85         // before the first field write.
 86         TestFramework.runWithFlags("-XX:+UseG1GC");
 87     }
 88 
 89     @Run(test = "testScalarReplacementWithGCBarrier")
 90     private void runner() {
 91         List list = new List();
 92         for (int i = 0; i < SIZE; i++) {
 93             list.push(i);
 94         }
 95         testScalarReplacementWithGCBarrier(list);
 96     }
 97 
 98     // Allocation of `Iter iter` should be eliminated by scalar replacement, and
 99     // the allocation of `Integer sum` can not be eliminated, so there should be
100     // 1 allocation after allocations and locks elimination.
101     //
102     // Before the patch of JDK-8333334, both allocations of `Iter` and `Integer`
103     // could not be eliminated.
104     @Test
105     @IR(phase = { CompilePhase.AFTER_PARSING }, counts = { IRNode.ALLOC, "1" })
106     @IR(phase = { CompilePhase.INCREMENTAL_BOXING_INLINE }, counts = { IRNode.ALLOC, "2" })
107     @IR(phase = { CompilePhase.ITER_GVN_AFTER_ELIMINATION }, counts = { IRNode.ALLOC, "1" })
108     private int testScalarReplacementWithGCBarrier(List list) {
109         Iter iter = list.iter();
110         while (true) {
111             while (iter.next()) {}
112             if (list.head == null) break;
113             list.head = list.head.next;
114             iter.n = list.head;
115         }
116         return iter.sum;
117     }
118 }