1 /*
  2  * Copyright (c) 2020, 2021, 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.valhalla.inlinetypes;
 25 
 26 import compiler.lib.ir_framework.CompLevel;
 27 import compiler.lib.ir_framework.Run;
 28 import compiler.lib.ir_framework.Scenario;
 29 import compiler.lib.ir_framework.Test;
 30 import jdk.test.lib.Asserts;
 31 
 32 
 33 /*
 34  * @test
 35  * @key randomness
 36  * @summary Verify that chains of getfields on flattened fields are correctly optimized
 37  * @library /test/lib /
 38  * @requires (os.simpleArch == "x64" | os.simpleArch == "aarch64")
 39  * @compile GetfieldChains.jcod
 40  * @run driver/timeout=300 compiler.valhalla.inlinetypes.TestGetfieldChains
 41  */
 42 
 43 public class TestGetfieldChains {
 44 
 45     public static void main(String[] args) {
 46 
 47         final Scenario[] scenarios = {
 48                 new Scenario(0,
 49                         // C1 only
 50                         "-XX:TieredStopAtLevel=1",
 51                         "-XX:+TieredCompilation"),
 52                 new Scenario(1,
 53                         // C2 only. (Make sure the tests are correctly written)
 54                         "-XX:TieredStopAtLevel=4",
 55                         "-XX:-TieredCompilation",
 56                         "-XX:-OmitStackTraceInFastThrow"),
 57                 new Scenario(2,
 58                         // interpreter only
 59                         "-Xint"),
 60                 new Scenario(3,
 61                         // Xcomp Only C1.
 62                         "-XX:TieredStopAtLevel=1",
 63                         "-XX:+TieredCompilation",
 64                         "-Xcomp"),
 65                 new Scenario(4,
 66                         // Xcomp Only C2.
 67                         "-XX:TieredStopAtLevel=4",
 68                         "-XX:-TieredCompilation",
 69                         "-XX:-OmitStackTraceInFastThrow",
 70                         "-Xcomp")
 71         };
 72 
 73         InlineTypes.getFramework()
 74                    .addScenarios(scenarios)
 75                    .start();
 76     }
 77 
 78 
 79     // Simple chain of getfields ending with primitive field
 80     @Test(compLevel = CompLevel.C1_SIMPLE)
 81     public int test1() {
 82         return NamedRectangle.getP1X(new NamedRectangle());
 83     }
 84 
 85     @Run(test = "test1")
 86     public void test1_verifier() {
 87         int res = test1();
 88         Asserts.assertEQ(res, 4);
 89     }
 90 
 91     // Simple chain of getfields ending with a flattened field
 92     @Test(compLevel = CompLevel.C1_SIMPLE)
 93     public Point test2() {
 94         return NamedRectangle.getP1(new NamedRectangle());
 95     }
 96 
 97     @Run(test = "test2")
 98     public void test2_verifier() {
 99         Point p = test2();
100         Asserts.assertEQ(p.x, 4);
101         Asserts.assertEQ(p.y, 7);
102     }
103 
104     // Chain of getfields but the initial receiver is null
105     @Test(compLevel = CompLevel.C1_SIMPLE)
106     public NullPointerException test3() {
107         NullPointerException npe = null;
108         try {
109             NamedRectangle.getP1X(null);
110         } catch(NullPointerException e) {
111             npe = e;
112         }
113         return npe;
114     }
115 
116     @Run(test = "test3")
117     public void test3_verifier() {
118         NullPointerException npe = test3();
119         Asserts.assertNE(npe, null);
120         StackTraceElement st = npe.getStackTrace()[0];
121         Asserts.assertEQ(st.getMethodName(), "getP1X");
122         Asserts.assertEQ(st.getLineNumber(), 31);       // line number depends on file NamedRectangle.java
123     }
124 
125     // Chain of getfields but one getfield in the middle of the chain trigger an illegal access
126     @Test(compLevel = CompLevel.C1_SIMPLE)
127     public IllegalAccessError test4() {
128         IllegalAccessError iae = null;
129         try {
130             int i = NamedRectangleP.getP1X(new NamedRectangleP());
131         } catch(IllegalAccessError e) {
132             iae = e;
133         }
134         return iae;
135     }
136 
137     @Run(test = "test4")
138     public void test4_verifier() {
139         IllegalAccessError iae = test4();
140         Asserts.assertNE(iae, null);
141         StackTraceElement st = iae.getStackTrace()[0];
142         Asserts.assertEQ(st.getMethodName(), "getP1X");
143         Asserts.assertEQ(st.getLineNumber(), 31);       // line number depends on jcod file generated from NamedRectangle.java
144         Asserts.assertTrue(iae.getMessage().contains("class compiler.valhalla.inlinetypes.NamedRectangleP tried to access private field compiler.valhalla.inlinetypes.RectangleP.p1"));
145     }
146 
147     // Chain of getfields but the last getfield trigger a NoSuchFieldError
148     @Test(compLevel = CompLevel.C1_SIMPLE)
149     public NoSuchFieldError test5() {
150         NoSuchFieldError nsfe = null;
151         try {
152             int i = NamedRectangleN.getP1X(new NamedRectangleN());
153         } catch(NoSuchFieldError e) {
154             nsfe = e;
155         }
156         return nsfe;
157     }
158 
159     @Run(test = "test5")
160     public void test5_verifier() {
161         NoSuchFieldError nsfe = test5();
162         Asserts.assertNE(nsfe, null);
163         StackTraceElement st = nsfe.getStackTrace()[0];
164         Asserts.assertEQ(st.getMethodName(), "getP1X");
165         Asserts.assertEQ(st.getLineNumber(), 31);       // line number depends on jcod file generated from NamedRectangle.java
166         Asserts.assertEQ(nsfe.getMessage(), "x");
167     }
168 
169     static primitive class EmptyType { }
170     static primitive class EmptyContainer {
171         int i = 0;
172         EmptyType et = new EmptyType();
173     }
174     static primitive class Container {
175         EmptyContainer container0 = new EmptyContainer();
176         EmptyContainer container1 = new EmptyContainer();
177     }
178 
179     @Test(compLevel = CompLevel.C1_SIMPLE)
180     public EmptyType test6() {
181         Container c = new Container();
182         return c.container1.et;
183     }
184 
185     @Run(test = "test6")
186     public void test6_verifier() {
187         EmptyType et = test6();
188         Asserts.assertEQ(et, EmptyType.default);
189     }
190 
191     @Test(compLevel = CompLevel.C1_SIMPLE)
192     public EmptyType test7() {
193         Container[] ca = new Container[10];
194         return ca[3].container0.et;
195     }
196 
197     @Run(test = "test7")
198     public void test7_verifier() {
199         EmptyType et = test7();
200         Asserts.assertEQ(et, EmptyType.default);
201     }
202 }