1 /* 2 * Copyright (c) 2019, 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.valuetypes; 25 26 import jdk.test.lib.Asserts; 27 28 /* 29 * @test 30 * @summary Test calls from {C1} to {C2, Interpreter}, and vice versa. 31 * @library /testlibrary /test/lib /compiler/whitebox / 32 * @requires os.simpleArch == "x64" 33 * @compile -XDallowWithFieldOperator TestCallingConventionC1.java 34 * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform 35 * @run main/othervm/timeout=120 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 36 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI -XX:+EnableValhalla 37 * compiler.valhalla.valuetypes.ValueTypeTest 38 * compiler.valhalla.valuetypes.TestCallingConventionC1 39 */ 40 public class TestCallingConventionC1 extends ValueTypeTest { 41 public static final int C1 = COMP_LEVEL_SIMPLE; 42 public static final int C2 = COMP_LEVEL_FULL_OPTIMIZATION; 43 44 @Override 45 public int getNumScenarios() { 46 return 2; 47 } 48 49 @Override 50 public String[] getVMParameters(int scenario) { 51 switch (scenario) { 52 53 // Default: both C1 and C2 are enabled, tierd compilation enabled 54 case 0: return new String[] {"-XX:+EnableValhallaC1", "-XX:CICompilerCount=2" 55 , "-XX:-CheckCompressedOops", "-XX:CompileCommand=print,*::test3*" 56 }; 57 // Only C1. Tierd compilation disabled. 58 case 1: return new String[] {"-XX:+EnableValhallaC1", "-XX:TieredStopAtLevel=1"}; 59 } 60 return null; 61 } 62 63 public static void main(String[] args) throws Throwable { 64 TestCallingConventionC1 test = new TestCallingConventionC1(); 65 test.run(args, 66 Point.class, 67 Functor.class, 68 Functor1.class, 69 Functor2.class, 70 Functor3.class, 71 Functor4.class); 72 } 73 74 static value class Point { 75 final int x; 76 final int y; 77 public Point(int x, int y) { 78 this.x = x; 79 this.y = y; 80 } 81 82 @DontCompile // FIXME -- C1 can't handle incoming values yet 83 public int func() { 84 return x + y; 85 } 86 } 87 88 static interface FunctorInterface { 89 public int apply(Point p); 90 } 91 92 static class Functor implements FunctorInterface { 93 @DontCompile // FIXME -- C1 can't handle incoming values yet 94 @DontInline 95 public int apply(Point p) { 96 return p.func() + 0; 97 } 98 } 99 static class Functor1 extends Functor { 100 @DontCompile // FIXME -- C1 can't handle incoming values yet 101 @DontInline 102 public int apply(Point p) { 103 return p.func() + 10000; 104 } 105 } 106 static class Functor2 extends Functor { 107 @DontCompile // FIXME -- C1 can't handle incoming values yet 108 @DontInline 109 public int apply(Point p) { 110 return p.func() + 20000; 111 } 112 } 113 static class Functor3 extends Functor { 114 @DontCompile // FIXME -- C1 can't handle incoming values yet 115 @DontInline 116 public int apply(Point p) { 117 return p.func() + 30000; 118 } 119 } 120 static class Functor4 extends Functor { 121 @DontCompile // FIXME -- C1 can't handle incoming values yet 122 @DontInline 123 public int apply(Point p) { 124 return p.func() + 40000; 125 } 126 } 127 128 static Functor functors[] = { 129 new Functor(), 130 new Functor1(), 131 new Functor2(), 132 new Functor3(), 133 new Functor4() 134 }; 135 static int counter = 0; 136 static Functor getFunctor() { 137 int n = (++ counter) % functors.length; 138 return functors[n]; 139 } 140 141 static Point pointField = new Point(123, 456); 142 143 //********************************************************************** 144 // PART 1 - C1 calls interpreted code 145 //********************************************************************** 146 147 148 //** C1 passes value to interpreter (static) 149 @Test(compLevel = C1) 150 public int test1() { 151 return test1_helper(pointField); 152 } 153 154 @DontInline 155 @DontCompile 156 private static int test1_helper(Point p) { 157 return p.func(); 158 } 159 160 @DontCompile 161 public void test1_verifier(boolean warmup) { 162 int count = warmup ? 1 : 10; 163 for (int i=0; i<count; i++) { 164 int result = test1() + i; 165 Asserts.assertEQ(result, pointField.func() + i); 166 } 167 } 168 169 170 //** C1 passes value to interpreter (monomorphic) 171 @Test(compLevel = C1) 172 public int test2() { 173 return test2_helper(pointField); 174 } 175 176 @DontInline 177 @DontCompile 178 private int test2_helper(Point p) { 179 return p.func(); 180 } 181 182 @DontCompile 183 public void test2_verifier(boolean warmup) { 184 int count = warmup ? 1 : 10; 185 for (int i=0; i<count; i++) { 186 int result = test2() + i; 187 Asserts.assertEQ(result, pointField.func() + i); 188 } 189 } 190 191 // C1 passes value to interpreter (megamorphic: vtable) 192 @Test(compLevel = C1) 193 public int test3(Functor functor) { 194 return functor.apply(pointField); 195 } 196 197 @DontCompile 198 public void test3_verifier(boolean warmup) { 199 int count = warmup ? 1 : 100; 200 for (int i=0; i<count; i++) { 201 Functor functor = warmup ? functors[0] : getFunctor(); 202 int result = test3(functor) + i; 203 Asserts.assertEQ(result, functor.apply(pointField) + i); 204 } 205 } 206 207 // Same as test3, but compiled with C2. Test the hastable of VtableStubs 208 @Test(compLevel = C2) 209 public int test3b(Functor functor) { 210 return functor.apply(pointField); 211 } 212 213 @DontCompile 214 public void test3b_verifier(boolean warmup) { 215 int count = warmup ? 1 : 100; 216 for (int i=0; i<count; i++) { 217 Functor functor = warmup ? functors[0] : getFunctor(); 218 int result = test3b(functor) + i; 219 Asserts.assertEQ(result, functor.apply(pointField) + i); 220 } 221 } 222 223 // C1 passes value to interpreter (megamorphic: itable) 224 @Test(compLevel = C1) 225 public int test4(FunctorInterface fi) { 226 return fi.apply(pointField); 227 } 228 229 @DontCompile 230 public void test4_verifier(boolean warmup) { 231 int count = warmup ? 1 : 100; 232 for (int i=0; i<count; i++) { 233 Functor functor = warmup ? functors[0] : getFunctor(); 234 int result = test4(functor) + i; 235 Asserts.assertEQ(result, functor.apply(pointField) + i); 236 } 237 } 238 239 /* not working 240 241 // Interpreter passes value to C1 242 @Test(compLevel = C2) 243 public int test2(Point p) { 244 return p.x + p.y; 245 } 246 247 @DontCompile 248 public void test2_verifier(boolean warmup) { 249 int result = test2(pointField); 250 int n = pointField.x + pointField.y; 251 Asserts.assertEQ(result, n); 252 } 253 254 */ 255 256 257 /* 258 259 // C1 passes value to C2 260 @Test(compLevel = C1) 261 public int test3() { 262 return test3_helper(pointField); 263 } 264 265 @DontInline 266 @ForceCompile(compLevel = C2) 267 private static int test3_helper(Point p) { 268 return p.x + p.y; 269 } 270 271 @DontCompile 272 public void test3_verifier(boolean warmup) { 273 int result = test3(); 274 int n = pointField.x + pointField.y; 275 Asserts.assertEQ(result, n); 276 } 277 278 */ 279 }