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 sun.hotspot.WhiteBox; 27 import jdk.test.lib.Asserts; 28 29 /* 30 * @test 31 * @summary Test calls from {C1} to {C2, Interpreter}, and vice versa. 32 * @library /testlibrary /test/lib /compiler/whitebox / 33 * @requires os.simpleArch == "x64" 34 * @compile TestCallingConventionC1.java 35 * @run driver ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.Platform 36 * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions 37 * -XX:+UnlockExperimentalVMOptions -XX:+WhiteBoxAPI 38 * compiler.valhalla.valuetypes.ValueTypeTest 39 * compiler.valhalla.valuetypes.TestCallingConventionC1 40 */ 41 public class TestCallingConventionC1 extends ValueTypeTest { 42 public static final int C1 = COMP_LEVEL_SIMPLE; 43 public static final int C2 = COMP_LEVEL_FULL_OPTIMIZATION; 44 45 @Override 46 public int getNumScenarios() { 47 return 2; 48 } 49 50 @Override 51 public String[] getVMParameters(int scenario) { 52 switch (scenario) { 53 54 // Default: both C1 and C2 are enabled, tierd compilation enabled 55 case 0: return new String[] {"-XX:+EnableValhallaC1", "-XX:CICompilerCount=2" 56 // , "-XX:-CheckCompressedOops", "-XX:CompileCommand=print,*::test78*" 57 //, "-XX:CompileCommand=print,*::func_c1" 58 }; 59 // Only C1. Tierd compilation disabled. 60 case 1: return new String[] {"-XX:+EnableValhallaC1", "-XX:TieredStopAtLevel=1" 61 // , "-XX:-CheckCompressedOops", "-XX:CompileCommand=print,*::test76*" 62 }; 63 } 64 return null; 65 } 66 67 public static void main(String[] args) throws Throwable { 68 System.gc(); // Resolve this call, to avoid C1 code patching in the test cases. 69 TestCallingConventionC1 test = new TestCallingConventionC1(); 70 test.run(args, 71 Point.class, 72 Functor.class, 73 Functor1.class, 74 Functor2.class, 75 Functor3.class, 76 Functor4.class, 77 MyImplPojo0.class, 78 MyImplPojo1.class, 79 MyImplPojo2.class, 80 MyImplVal1.class, 81 MyImplVal2.class, 82 FixedPoints.class, 83 FloatPoint.class, 84 RefPoint.class); 85 } 86 87 static inline class Point { 88 final int x; 89 final int y; 90 public Point(int x, int y) { 91 this.x = x; 92 this.y = y; 93 } 94 95 @DontCompile 96 @DontInline 97 public int func() { 98 return x + y; 99 } 100 101 @ForceCompile(compLevel = C1) 102 @DontInline 103 public int func_c1(Point p) { 104 return x + y + p.x + p.y; 105 } 106 } 107 108 static interface FunctorInterface { 109 public int apply_interp(Point p); 110 } 111 112 static class Functor implements FunctorInterface { 113 @DontCompile 114 @DontInline 115 public int apply_interp(Point p) { 116 return p.func() + 0; 117 } 118 } 119 static class Functor1 extends Functor { 120 @DontCompile 121 @DontInline 122 public int apply_interp(Point p) { 123 return p.func() + 10000; 124 } 125 } 126 static class Functor2 extends Functor { 127 @DontCompile 128 @DontInline 129 public int apply_interp(Point p) { 130 return p.func() + 20000; 131 } 132 } 133 static class Functor3 extends Functor { 134 @DontCompile 135 @DontInline 136 public int apply_interp(Point p) { 137 return p.func() + 30000; 138 } 139 } 140 static class Functor4 extends Functor { 141 @DontCompile 142 @DontInline 143 public int apply_interp(Point p) { 144 return p.func() + 40000; 145 } 146 } 147 148 static Functor functors[] = { 149 new Functor(), 150 new Functor1(), 151 new Functor2(), 152 new Functor3(), 153 new Functor4() 154 }; 155 static int functorCounter = 0; 156 static Functor getFunctor() { 157 int n = (++ functorCounter) % functors.length; 158 return functors[n]; 159 } 160 161 static Point pointField = new Point(123, 456); 162 static Point pointField1 = new Point(1123, 1456); 163 static Point pointField2 = new Point(2123, 2456); 164 165 static interface Intf { 166 public int func1(int a, int b); 167 public int func2(int a, int b, Point p); 168 } 169 170 static class MyImplPojo0 implements Intf { 171 int field = 0; 172 @DontInline @DontCompile 173 public int func1(int a, int b) { return field + a + b + 1; } 174 @DontInline @DontCompile 175 public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 1; } 176 } 177 178 static class MyImplPojo1 implements Intf { 179 int field = 1000; 180 181 @DontInline @ForceCompile(compLevel = C1) 182 public int func1(int a, int b) { return field + a + b + 20; } 183 @DontInline @ForceCompile(compLevel = C1) 184 public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 20; } 185 } 186 187 static class MyImplPojo2 implements Intf { 188 int field = 2000; 189 190 @DontInline @ForceCompile(compLevel = C2) 191 public int func1(int a, int b) { return field + a + b + 20; } 192 @DontInline @ForceCompile(compLevel = C2) 193 public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 20; } 194 } 195 196 static inline class MyImplVal1 implements Intf { 197 final int field; 198 MyImplVal1() { 199 field = 11000; 200 } 201 202 @DontInline @ForceCompile(compLevel = C1) 203 public int func1(int a, int b) { return field + a + b + 300; } 204 205 @DontInline @ForceCompile(compLevel = C1) 206 public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; } 207 } 208 209 static inline class MyImplVal2 implements Intf { 210 final int field; 211 MyImplVal2() { 212 field = 12000; 213 } 214 215 @DontInline @ForceCompile(compLevel = C2) 216 public int func1(int a, int b) { return field + a + b + 300; } 217 218 @DontInline @ForceCompile(compLevel = C2) 219 public int func2(int a, int b, Point p) { return field + a + b + p.x + p.y + 300; } 220 } 221 222 static Intf intfs[] = { 223 new MyImplPojo0(), // methods not compiled 224 new MyImplPojo1(), // methods compiled by C1 225 new MyImplPojo2(), // methods compiled by C2 226 new MyImplVal1(), // methods compiled by C1 227 new MyImplVal2() // methods compiled by C2 228 }; 229 static Intf getIntf(int i) { 230 int n = i % intfs.length; 231 return intfs[n]; 232 } 233 234 static inline class FixedPoints { 235 final boolean Z0 = false; 236 final boolean Z1 = true; 237 final byte B = (byte)2; 238 final char C = (char)34; 239 final short S = (short)456; 240 final int I = 5678; 241 final long J = 0x1234567800abcdefL; 242 } 243 static FixedPoints fixedPointsField = new FixedPoints(); 244 245 static inline class FloatPoint { 246 final float x; 247 final float y; 248 public FloatPoint(float x, float y) { 249 this.x = x; 250 this.y = y; 251 } 252 } 253 static inline class DoublePoint { 254 final double x; 255 final double y; 256 public DoublePoint(double x, double y) { 257 this.x = x; 258 this.y = y; 259 } 260 } 261 static FloatPoint floatPointField = new FloatPoint(123.456f, 789.012f); 262 static DoublePoint doublePointField = new DoublePoint(123.456, 789.012); 263 264 static inline class EightFloats { 265 float f1, f2, f3, f4, f5, f6, f7, f8; 266 public EightFloats() { 267 f1 = 1.1f; 268 f2 = 2.2f; 269 f3 = 3.3f; 270 f4 = 4.4f; 271 f5 = 5.5f; 272 f6 = 6.6f; 273 f7 = 7.7f; 274 f8 = 8.8f; 275 } 276 } 277 static EightFloats eightFloatsField = new EightFloats(); 278 279 static class Number { 280 int n; 281 Number(int v) { 282 n = v; 283 } 284 void set(int v) { 285 n = v; 286 } 287 } 288 289 static interface RefPoint_Access { 290 public int func1(RefPoint rp2); 291 public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2); 292 } 293 294 static inline class RefPoint implements RefPoint_Access { 295 final Number x; 296 final Number y; 297 public RefPoint(int x, int y) { 298 this.x = new Number(x); 299 this.y = new Number(y); 300 } 301 public RefPoint(Number x, Number y) { 302 this.x = x; 303 this.y = y; 304 } 305 306 @DontInline 307 @ForceCompile(compLevel = C1) 308 public final int final_func(RefPoint rp2) { // opt_virtual_call 309 return this.x.n + this.y.n + rp2.x.n + rp2.y.n; 310 } 311 312 @DontInline 313 @ForceCompile(compLevel = C1) 314 public int func1(RefPoint rp2) { 315 return this.x.n + this.y.n + rp2.x.n + rp2.y.n; 316 } 317 318 @DontInline 319 @ForceCompile(compLevel = C1) 320 public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) { 321 return x.n + y.n + 322 rp1.x.n + rp1.y.n + 323 rp2.x.n + rp2.y.n + 324 n1.n + 325 rp3.x.n + rp3.y.n + 326 rp4.x.n + rp4.y.n + 327 n2.n; 328 } 329 } 330 331 static class RefPoint_Access_Impl1 implements RefPoint_Access { 332 @DontInline @DontCompile 333 public int func1(RefPoint rp2) { 334 return rp2.x.n + rp2.y.n + 1111111; 335 } 336 @DontInline @DontCompile 337 public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) { 338 return 111111 + 339 rp1.x.n + rp1.y.n + 340 rp2.x.n + rp2.y.n + 341 n1.n + 342 rp3.x.n + rp3.y.n + 343 rp4.x.n + rp4.y.n + 344 n2.n; 345 } 346 } 347 static class RefPoint_Access_Impl2 implements RefPoint_Access { 348 @DontInline @DontCompile 349 public int func1(RefPoint rp2) { 350 return rp2.x.n + rp2.y.n + 2222222; 351 } 352 @DontInline @DontCompile 353 public int func2(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) { 354 return 222222 + 355 rp1.x.n + rp1.y.n + 356 rp2.x.n + rp2.y.n + 357 n1.n + 358 rp3.x.n + rp3.y.n + 359 rp4.x.n + rp4.y.n + 360 n2.n; 361 } 362 } 363 364 static RefPoint_Access refPoint_Access_impls[] = { 365 new RefPoint_Access_Impl1(), 366 new RefPoint_Access_Impl2(), 367 new RefPoint(0x12345, 0x6789a) 368 }; 369 370 static int next_RefPoint_Access = 0; 371 static RefPoint_Access get_RefPoint_Access() { 372 int i = next_RefPoint_Access ++; 373 return refPoint_Access_impls[i % refPoint_Access_impls.length]; 374 } 375 376 static RefPoint refPointField1 = new RefPoint(12, 34); 377 static RefPoint refPointField2 = new RefPoint(56789, 0x12345678); 378 379 // This inline class has too many fields to fit in registers on x64 for 380 // ValueTypeReturnedAsFields. 381 static inline class TooBigToReturnAsFields { 382 int a0 = 0; 383 int a1 = 1; 384 int a2 = 2; 385 int a3 = 3; 386 int a4 = 4; 387 int a5 = 5; 388 int a6 = 6; 389 int a7 = 7; 390 int a8 = 8; 391 int a9 = 9; 392 } 393 394 static TooBigToReturnAsFields tooBig = new TooBigToReturnAsFields(); 395 396 //********************************************************************** 397 // PART 1 - C1 calls interpreted code 398 //********************************************************************** 399 400 401 //** C1 passes value to interpreter (static) 402 @Test(compLevel = C1) 403 public int test1() { 404 return test1_helper(pointField); 405 } 406 407 @DontInline 408 @DontCompile 409 private static int test1_helper(Point p) { 410 return p.func(); 411 } 412 413 @DontCompile 414 public void test1_verifier(boolean warmup) { 415 int count = warmup ? 1 : 10; 416 for (int i=0; i<count; i++) { // need a loop to test inline cache 417 int result = test1() + i; 418 Asserts.assertEQ(result, pointField.func() + i); 419 } 420 } 421 422 423 //** C1 passes value to interpreter (monomorphic) 424 @Test(compLevel = C1) 425 public int test2() { 426 return test2_helper(pointField); 427 } 428 429 @DontInline 430 @DontCompile 431 private int test2_helper(Point p) { 432 return p.func(); 433 } 434 435 @DontCompile 436 public void test2_verifier(boolean warmup) { 437 int count = warmup ? 1 : 10; 438 for (int i=0; i<count; i++) { // need a loop to test inline cache 439 int result = test2() + i; 440 Asserts.assertEQ(result, pointField.func() + i); 441 } 442 } 443 444 // C1 passes value to interpreter (megamorphic: vtable) 445 @Test(compLevel = C1) 446 public int test3(Functor functor) { 447 return functor.apply_interp(pointField); 448 } 449 450 @DontCompile 451 public void test3_verifier(boolean warmup) { 452 int count = warmup ? 1 : 100; 453 for (int i=0; i<count; i++) { // need a loop to test inline cache and vtable indexing 454 Functor functor = warmup ? functors[0] : getFunctor(); 455 int result = test3(functor) + i; 456 Asserts.assertEQ(result, functor.apply_interp(pointField) + i); 457 } 458 } 459 460 // Same as test3, but compiled with C2. Test the hastable of VtableStubs 461 @Test(compLevel = C2) 462 public int test3b(Functor functor) { 463 return functor.apply_interp(pointField); 464 } 465 466 @DontCompile 467 public void test3b_verifier(boolean warmup) { 468 int count = warmup ? 1 : 100; 469 for (int i=0; i<count; i++) { // need a loop to test inline cache and vtable indexing 470 Functor functor = warmup ? functors[0] : getFunctor(); 471 int result = test3b(functor) + i; 472 Asserts.assertEQ(result, functor.apply_interp(pointField) + i); 473 } 474 } 475 476 // C1 passes value to interpreter (megamorphic: itable) 477 @Test(compLevel = C1) 478 public int test4(FunctorInterface fi) { 479 return fi.apply_interp(pointField); 480 } 481 482 @DontCompile 483 public void test4_verifier(boolean warmup) { 484 int count = warmup ? 1 : 100; 485 for (int i=0; i<count; i++) { // need a loop to test inline cache and itable indexing 486 Functor functor = warmup ? functors[0] : getFunctor(); 487 int result = test4(functor) + i; 488 Asserts.assertEQ(result, functor.apply_interp(pointField) + i); 489 } 490 } 491 492 //********************************************************************** 493 // PART 2 - interpreter calls C1 494 //********************************************************************** 495 496 // Interpreter passes value to C1 (static) 497 @Test(compLevel = C1) 498 static public int test20(Point p1, long l, Point p2) { 499 return p1.x + p2.y; 500 } 501 502 @DontCompile 503 public void test20_verifier(boolean warmup) { 504 int result = test20(pointField1, 0, pointField2); 505 int n = pointField1.x + pointField2.y; 506 Asserts.assertEQ(result, n); 507 } 508 509 // Interpreter passes value to C1 (instance method in inline class) 510 @Test 511 public int test21(Point p) { 512 return test21_helper(p); 513 } 514 515 @DontCompile 516 @DontInline 517 int test21_helper(Point p) { 518 return p.func_c1(p); 519 } 520 521 @DontCompile 522 public void test21_verifier(boolean warmup) { 523 int result = test21(pointField); 524 int n = 2 * (pointField.x + pointField.y); 525 Asserts.assertEQ(result, n); 526 } 527 528 529 //********************************************************************** 530 // PART 3 - C2 calls C1 531 //********************************************************************** 532 533 // C2->C1 invokestatic, single value arg 534 @Test(compLevel = C2) 535 public int test30() { 536 return test30_helper(pointField); 537 } 538 539 @DontInline 540 @ForceCompile(compLevel = C1) 541 private static int test30_helper(Point p) { 542 return p.x + p.y; 543 } 544 545 @DontCompile 546 public void test30_verifier(boolean warmup) { 547 int count = warmup ? 1 : 2; 548 for (int i=0; i<count; i++) { // need a loop to test inline cache 549 int result = test30(); 550 int n = pointField.x + pointField.y; 551 Asserts.assertEQ(result, n); 552 } 553 } 554 555 // C2->C1 invokestatic, two single value args 556 @Test(compLevel = C2) 557 public int test31() { 558 return test31_helper(pointField1, pointField2); 559 } 560 561 @DontInline 562 @ForceCompile(compLevel = C1) 563 private static int test31_helper(Point p1, Point p2) { 564 return p1.x + p2.y; 565 } 566 567 @DontCompile 568 public void test31_verifier(boolean warmup) { 569 int count = warmup ? 1 : 2; 570 for (int i=0; i<count; i++) { // need a loop to test inline cache 571 int result = test31(); 572 int n = pointField1.x + pointField2.y; 573 Asserts.assertEQ(result, n); 574 } 575 } 576 577 // C2->C1 invokestatic, two single value args and interleaving ints (all passed in registers on x64) 578 @Test(compLevel = C2) 579 public int test32() { 580 return test32_helper(0, pointField1, 1, pointField2); 581 } 582 583 @DontInline 584 @ForceCompile(compLevel = C1) 585 private static int test32_helper(int x, Point p1, int y, Point p2) { 586 return p1.x + p2.y + x + y; 587 } 588 589 @DontCompile 590 public void test32_verifier(boolean warmup) { 591 int count = warmup ? 1 : 2; 592 for (int i=0; i<count; i++) { // need a loop to test inline cache 593 int result = test32(); 594 int n = pointField1.x + pointField2.y + 0 + 1; 595 Asserts.assertEQ(result, n); 596 } 597 } 598 599 // C2->C1 invokeinterface -- no verified_ro_entry (no value args except for receiver) 600 @Test(compLevel = C2) 601 public int test33(Intf intf, int a, int b) { 602 return intf.func1(a, b); 603 } 604 605 @DontCompile 606 public void test33_verifier(boolean warmup) { 607 int count = warmup ? 1 : 20; 608 for (int i=0; i<count; i++) { 609 Intf intf = warmup ? intfs[0] : getIntf(i+1); 610 int result = test33(intf, 123, 456) + i; 611 Asserts.assertEQ(result, intf.func1(123, 456) + i); 612 } 613 } 614 615 // C2->C1 invokeinterface -- use verified_ro_entry (has value args other than receiver) 616 @Test(compLevel = C2) 617 public int test34(Intf intf, int a, int b) { 618 return intf.func2(a, b, pointField); 619 } 620 621 @DontCompile 622 public void test34_verifier(boolean warmup) { 623 int count = warmup ? 1 : 20; 624 for (int i=0; i<count; i++) { 625 Intf intf = warmup ? intfs[0] : getIntf(i+1); 626 int result = test34(intf, 123, 456) + i; 627 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 628 } 629 } 630 631 // C2->C1 invokestatic, Point.y is on stack (x64) 632 @Test(compLevel = C2) 633 public int test35() { 634 return test35_helper(1, 2, 3, 4, 5, pointField); 635 } 636 637 @DontInline 638 @ForceCompile(compLevel = C1) 639 private static int test35_helper(int a1, int a2, int a3, int a4, int a5, Point p) { 640 return a1 + a2 + a3 + a4 + a5 + p.x + p.y; 641 } 642 643 @DontCompile 644 public void test35_verifier(boolean warmup) { 645 int count = warmup ? 1 : 2; 646 for (int i=0; i<count; i++) { // need a loop to test inline cache 647 int result = test35(); 648 int n = 1 + 2 + 3 + 4 + 5 + pointField.x + pointField.y; 649 Asserts.assertEQ(result, n); 650 } 651 } 652 653 // C2->C1 invokestatic, shuffling arguments that are passed on stack 654 @Test(compLevel = C2) 655 public int test36() { 656 return test36_helper(pointField, 1, 2, 3, 4, 5, 6, 7, 8); 657 } 658 659 @DontInline 660 @ForceCompile(compLevel = C1) 661 private static int test36_helper(Point p, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8) { 662 return a6 + a8; 663 } 664 665 @DontCompile 666 public void test36_verifier(boolean warmup) { 667 int count = warmup ? 1 : 2; 668 for (int i=0; i<count; i++) { // need a loop to test inline cache 669 int result = test36(); 670 int n = 6 + 8; 671 Asserts.assertEQ(result, n); 672 } 673 } 674 675 // C2->C1 invokestatic, shuffling long arguments 676 @Test(compLevel = C2) 677 public int test37() { 678 return test37_helper(pointField, 1, 2, 3, 4, 5, 6, 7, 8); 679 } 680 681 @DontInline 682 @ForceCompile(compLevel = C1) 683 private static int test37_helper(Point p, long a1, long a2, long a3, long a4, long a5, long a6, long a7, long a8) { 684 return (int)(a6 + a8); 685 } 686 687 @DontCompile 688 public void test37_verifier(boolean warmup) { 689 int count = warmup ? 1 : 2; 690 for (int i=0; i<count; i++) { // need a loop to test inline cache 691 int result = test37(); 692 int n = 6 + 8; 693 Asserts.assertEQ(result, n); 694 } 695 } 696 697 // C2->C1 invokestatic, shuffling boolean, byte, char, short, int, long arguments 698 @Test(compLevel = C2) 699 public int test38() { 700 return test38_helper(pointField, true, (byte)1, (char)2, (short)3, 4, 5, (byte)6, (short)7, 8); 701 } 702 703 @DontInline 704 @ForceCompile(compLevel = C1) 705 private static int test38_helper(Point p, boolean a0, byte a1, char a2, short a3, int a4, long a5, byte a6, short a7, int a8) { 706 if (a0) { 707 return (int)(a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8); 708 } else { 709 return -1; 710 } 711 } 712 713 @DontCompile 714 public void test38_verifier(boolean warmup) { 715 int count = warmup ? 1 : 2; 716 for (int i=0; i<count; i++) { // need a loop to test inline cache 717 int result = test38(); 718 int n = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8; 719 Asserts.assertEQ(result, n); 720 } 721 } 722 723 // C2->C1 invokestatic, packing a value object with all types of fixed point primitive fields. 724 @Test(compLevel = C2) 725 public long test39() { 726 return test39_helper(1, fixedPointsField, 2, fixedPointsField); 727 } 728 729 @DontInline 730 @ForceCompile(compLevel = C1) 731 private static long test39_helper(int a1, FixedPoints f1, int a2, FixedPoints f2) { 732 if (f1.Z0 == false && f1.Z1 == true && f2.Z0 == false && f2.Z1 == true) { 733 return f1.B + f2.C + f1.S + f2.I + f1.J; 734 } else { 735 return -1; 736 } 737 } 738 739 @DontCompile 740 public void test39_verifier(boolean warmup) { 741 int count = warmup ? 1 : 2; 742 for (int i=0; i<count; i++) { // need a loop to test inline cache 743 long result = test39(); 744 long n = test39_helper(1, fixedPointsField, 2, fixedPointsField); 745 Asserts.assertEQ(result, n); 746 } 747 } 748 749 // C2->C1 invokestatic, shuffling floating point args 750 @Test(compLevel = C2) 751 public double test40() { 752 return test40_helper(1.1f, 1.2, floatPointField, doublePointField, 1.3f, 1.4, 1.5f, 1.7, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12); 753 } 754 755 @DontInline 756 @ForceCompile(compLevel = C1) 757 private static double test40_helper(float a1, double a2, FloatPoint fp, DoublePoint dp, float a3, double a4, float a5, double a6, double a7, double a8, double a9, double a10, double a11, double a12) { 758 return a1 + a2 + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12 + fp.x + fp.y - dp.x - dp.y; 759 } 760 761 @DontCompile 762 public void test40_verifier(boolean warmup) { 763 int count = warmup ? 1 : 2; 764 for (int i=0; i<count; i++) { // need a loop to test inline cache 765 double result = test40(); 766 double n = test40_helper(1.1f, 1.2, floatPointField, doublePointField, 1.3f, 1.4, 1.5f, 1.7, 1.7, 1.8, 1.9, 1.10, 1.11, 1.12); 767 Asserts.assertEQ(result, n); 768 } 769 } 770 771 // C2->C1 invokestatic, mixing floats and ints 772 @Test(compLevel = C2) 773 public double test41() { 774 return test41_helper(1, 1.2, pointField, floatPointField, doublePointField, 1.3f, 4, 1.5f, 1.7, 1.7, 1.8, 9, 1.10, 1.11, 1.12); 775 } 776 777 @DontInline 778 @ForceCompile(compLevel = C1) 779 private static double test41_helper(int a1, double a2, Point p, FloatPoint fp, DoublePoint dp, float a3, int a4, float a5, double a6, double a7, double a8, long a9, double a10, double a11, double a12) { 780 return a1 + a2 + fp.x + fp.y - dp.x - dp.y + a3 + a4 + a5 + a6 + a7 + a8 + a9 + a10 + a11 + a12; 781 } 782 783 @DontCompile 784 public void test41_verifier(boolean warmup) { 785 int count = warmup ? 1 : 2; 786 for (int i=0; i<count; i++) { // need a loop to test inline cache 787 double result = test41(); 788 double n = test41_helper(1, 1.2, pointField, floatPointField, doublePointField, 1.3f, 4, 1.5f, 1.7, 1.7, 1.8, 9, 1.10, 1.11, 1.12); 789 Asserts.assertEQ(result, n); 790 } 791 } 792 793 // C2->C1 invokestatic, circular dependency (between rdi and first stack slot on x64) 794 @Test(compLevel = C2) 795 public float test42() { 796 return test42_helper(eightFloatsField, pointField, 3, 4, 5, floatPointField, 7); 797 } 798 799 @DontInline 800 @ForceCompile(compLevel = C1) 801 private static float test42_helper(EightFloats ep1, // (xmm0 ... xmm7) -> rsi 802 Point p2, // (rsi, rdx) -> rdx 803 int i3, // rcx -> rcx 804 int i4, // r8 -> r8 805 int i5, // r9 -> r9 806 FloatPoint fp6, // (stk[0], stk[1]) -> rdi ** circ depend 807 int i7) // rdi -> stk[0] ** circ depend 808 { 809 return ep1.f1 + ep1.f2 + ep1.f3 + ep1.f4 + ep1.f5 + ep1.f6 + ep1.f7 + ep1.f8 + 810 p2.x + p2.y + i3 + i4 + i5 + fp6.x + fp6.y + i7; 811 } 812 813 @DontCompile 814 public void test42_verifier(boolean warmup) { 815 int count = warmup ? 1 : 2; 816 for (int i=0; i<count; i++) { // need a loop to test inline cache 817 float result = test42(); 818 float n = test42_helper(eightFloatsField, pointField, 3, 4, 5, floatPointField, 7); 819 Asserts.assertEQ(result, n); 820 } 821 } 822 823 // C2->C1 invokestatic, packing causes stack growth (1 extra stack word) 824 @Test(compLevel = C2) 825 public float test43() { 826 return test43_helper(floatPointField, 1, 2, 3, 4, 5, 6); 827 } 828 829 @DontInline 830 @ForceCompile(compLevel = C1) 831 private static float test43_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5, int a6) { 832 // On x64: 833 // Scalarized entry -- all parameters are passed in registers 834 // Non-scalarized entry -- a6 is passed on stack[0] 835 return fp.x + fp.y + a1 + a2 + a3 + a4 + a5 + a6; 836 } 837 838 @DontCompile 839 public void test43_verifier(boolean warmup) { 840 int count = warmup ? 1 : 2; 841 for (int i=0; i<count; i++) { // need a loop to test inline cache 842 float result = test43(); 843 float n = test43_helper(floatPointField, 1, 2, 3, 4, 5, 6); 844 Asserts.assertEQ(result, n); 845 } 846 } 847 848 // C2->C1 invokestatic, packing causes stack growth (2 extra stack words) 849 @Test(compLevel = C2) 850 public float test44() { 851 return test44_helper(floatPointField, floatPointField, 1, 2, 3, 4, 5, 6); 852 } 853 854 @DontInline 855 @ForceCompile(compLevel = C1) 856 private static float test44_helper(FloatPoint fp1, FloatPoint fp2, int a1, int a2, int a3, int a4, int a5, int a6) { 857 // On x64: 858 // Scalarized entry -- all parameters are passed in registers 859 // Non-scalarized entry -- a5 is passed on stack[0] 860 // Non-scalarized entry -- a6 is passed on stack[1] 861 return fp1.x + fp1.y + 862 fp2.x + fp2.y + 863 a1 + a2 + a3 + a4 + a5 + a6; 864 } 865 866 @DontCompile 867 public void test44_verifier(boolean warmup) { 868 int count = warmup ? 1 : 2; 869 for (int i=0; i<count; i++) { // need a loop to test inline cache 870 float result = test44(); 871 float n = test44_helper(floatPointField, floatPointField, 1, 2, 3, 4, 5, 6); 872 Asserts.assertEQ(result, n); 873 } 874 } 875 876 // C2->C1 invokestatic, packing causes stack growth (5 extra stack words) 877 @Test(compLevel = C2) 878 public float test45() { 879 return test45_helper(floatPointField, floatPointField, floatPointField, floatPointField, floatPointField, 1, 2, 3, 4, 5, 6, 7); 880 } 881 882 @DontInline 883 @ForceCompile(compLevel = C1) 884 private static float test45_helper(FloatPoint fp1, FloatPoint fp2, FloatPoint fp3, FloatPoint fp4, FloatPoint fp5, int a1, int a2, int a3, int a4, int a5, int a6, int a7) { 885 return fp1.x + fp1.y + 886 fp2.x + fp2.y + 887 fp3.x + fp3.y + 888 fp4.x + fp4.y + 889 fp5.x + fp5.y + 890 a1 + a2 + a3 + a4 + a5 + a6 + a7; 891 } 892 893 @DontCompile 894 public void test45_verifier(boolean warmup) { 895 int count = warmup ? 1 : 2; 896 for (int i=0; i<count; i++) { // need a loop to test inline cache 897 float result = test45(); 898 float n = test45_helper(floatPointField, floatPointField, floatPointField, floatPointField, floatPointField, 1, 2, 3, 4, 5, 6, 7); 899 Asserts.assertEQ(result, n); 900 } 901 } 902 903 // C2->C1 invokestatic, packing causes stack growth (1 extra stack word -- mixing Point and FloatPoint) 904 @Test(compLevel = C2) 905 public float test46() { 906 return test46_helper(floatPointField, floatPointField, pointField, floatPointField, floatPointField, pointField, floatPointField, 1, 2, 3, 4, 5, 6, 7); 907 } 908 909 @DontInline 910 @ForceCompile(compLevel = C1) 911 private static float test46_helper(FloatPoint fp1, FloatPoint fp2, Point p1, FloatPoint fp3, FloatPoint fp4, Point p2, FloatPoint fp5, int a1, int a2, int a3, int a4, int a5, int a6, int a7) { 912 return p1.x + p1.y + 913 p2.x + p2.y + 914 fp1.x + fp1.y + 915 fp2.x + fp2.y + 916 fp3.x + fp3.y + 917 fp4.x + fp4.y + 918 fp5.x + fp5.y + 919 a1 + a2 + a3 + a4 + a5 + a6 + a7; 920 } 921 922 @DontCompile 923 public void test46_verifier(boolean warmup) { 924 int count = warmup ? 1 : 2; 925 for (int i=0; i<count; i++) { // need a loop to test inline cache 926 float result = test46(); 927 float n = test46_helper(floatPointField, floatPointField, pointField, floatPointField, floatPointField, pointField, floatPointField, 1, 2, 3, 4, 5, 6, 7); 928 Asserts.assertEQ(result, n); 929 } 930 } 931 932 static class MyRuntimeException extends RuntimeException { 933 MyRuntimeException(String s) { 934 super(s); 935 } 936 } 937 938 static void checkStackTrace(Throwable t, String... methodNames) { 939 StackTraceElement[] trace = t.getStackTrace(); 940 for (int i=0; i<methodNames.length; i++) { 941 if (!methodNames[i].equals(trace[i].getMethodName())) { 942 String error = "Unexpected stack trace: level " + i + " should be " + methodNames[i]; 943 System.out.println(error); 944 t.printStackTrace(System.out); 945 throw new RuntimeException(error, t); 946 } 947 } 948 } 949 //* 950 951 // C2->C1 invokestatic, make sure stack walking works (with static variable) 952 @Test(compLevel = C2) 953 public void test47(int n) { 954 try { 955 test47_helper(floatPointField, 1, 2, 3, 4, 5); 956 test47_value = 666; 957 } catch (MyRuntimeException e) { 958 // expected; 959 } 960 test47_value = n; 961 } 962 963 @DontInline 964 @ForceCompile(compLevel = C1) 965 private static float test47_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5) { 966 test47_thrower(); 967 return 0.0f; 968 } 969 970 @DontInline @DontCompile 971 private static void test47_thrower() { 972 MyRuntimeException e = new MyRuntimeException("This exception should have been caught!"); 973 checkStackTrace(e, "test47_thrower", "test47_helper", "test47", "test47_verifier"); 974 throw e; 975 } 976 977 static int test47_value = 999; 978 979 @DontCompile 980 public void test47_verifier(boolean warmup) { 981 int count = warmup ? 1 : 5; 982 for (int i=0; i<count; i++) { // need a loop to test inline cache 983 test47_value = 777 + i; 984 test47(i); 985 Asserts.assertEQ(test47_value, i); 986 } 987 } 988 989 // C2->C1 invokestatic, make sure stack walking works (with returned value) 990 @Test(compLevel = C2) 991 public int test48(int n) { 992 try { 993 test48_helper(floatPointField, 1, 2, 3, 4, 5); 994 return 666; 995 } catch (MyRuntimeException e) { 996 // expected; 997 } 998 return n; 999 } 1000 1001 @DontInline 1002 @ForceCompile(compLevel = C1) 1003 private static float test48_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5) { 1004 test48_thrower(); 1005 return 0.0f; 1006 } 1007 1008 @DontInline @DontCompile 1009 private static void test48_thrower() { 1010 MyRuntimeException e = new MyRuntimeException("This exception should have been caught!"); 1011 checkStackTrace(e, "test48_thrower", "test48_helper", "test48", "test48_verifier"); 1012 throw e; 1013 } 1014 1015 @DontCompile 1016 public void test48_verifier(boolean warmup) { 1017 int count = warmup ? 1 : 5; 1018 for (int i=0; i<count; i++) { // need a loop to test inline cache 1019 int n = test48(i); 1020 Asserts.assertEQ(n, i); 1021 } 1022 } 1023 1024 // C2->interpreter invokestatic, make sure stack walking works (same as test 48, but with stack extension/repair) 1025 // (this is the baseline for test50 -- 1026 // the only difference is: test49_helper is interpreted but test50_helper is compiled by C1). 1027 @Test(compLevel = C2) 1028 public int test49(int n) { 1029 try { 1030 test49_helper(floatPointField, 1, 2, 3, 4, 5, 6); 1031 return 666; 1032 } catch (MyRuntimeException e) { 1033 // expected; 1034 } 1035 return n; 1036 } 1037 1038 @DontInline @DontCompile 1039 private static float test49_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5, int a6) { 1040 test49_thrower(); 1041 return 0.0f; 1042 } 1043 1044 @DontInline @DontCompile 1045 private static void test49_thrower() { 1046 MyRuntimeException e = new MyRuntimeException("This exception should have been caught!"); 1047 checkStackTrace(e, "test49_thrower", "test49_helper", "test49", "test49_verifier"); 1048 throw e; 1049 } 1050 1051 @DontCompile 1052 public void test49_verifier(boolean warmup) { 1053 int count = warmup ? 1 : 5; 1054 for (int i=0; i<count; i++) { // need a loop to test inline cache 1055 int n = test49(i); 1056 Asserts.assertEQ(n, i); 1057 } 1058 } 1059 1060 // C2->C1 invokestatic, make sure stack walking works (same as test 48, but with stack extension/repair) 1061 @Test(compLevel = C2) 1062 public int test50(int n) { 1063 try { 1064 test50_helper(floatPointField, 1, 2, 3, 4, 5, 6); 1065 return 666; 1066 } catch (MyRuntimeException e) { 1067 // expected; 1068 } 1069 return n; 1070 } 1071 1072 @DontInline 1073 @ForceCompile(compLevel = C1) 1074 private static float test50_helper(FloatPoint fp, int a1, int a2, int a3, int a4, int a5, int a6) { 1075 test50_thrower(); 1076 return 0.0f; 1077 } 1078 1079 @DontInline @DontCompile 1080 private static void test50_thrower() { 1081 MyRuntimeException e = new MyRuntimeException("This exception should have been caught!"); 1082 checkStackTrace(e, "test50_thrower", "test50_helper", "test50", "test50_verifier"); 1083 throw e; 1084 } 1085 1086 @DontCompile 1087 public void test50_verifier(boolean warmup) { 1088 int count = warmup ? 1 : 5; 1089 for (int i=0; i<count; i++) { // need a loop to test inline cache 1090 int n = test50(i); 1091 Asserts.assertEQ(n, i); 1092 } 1093 } 1094 1095 1096 // C2->C1 invokestatic, inline class with ref fields (RefPoint) 1097 @Test(compLevel = C2) 1098 public int test51() { 1099 return test51_helper(refPointField1); 1100 } 1101 1102 @DontInline 1103 @ForceCompile(compLevel = C1) 1104 private static int test51_helper(RefPoint rp1) { 1105 return rp1.x.n + rp1.y.n; 1106 } 1107 1108 @DontCompile 1109 public void test51_verifier(boolean warmup) { 1110 int count = warmup ? 1 : 5; 1111 for (int i=0; i<count; i++) { // need a loop to test inline cache 1112 int result = test51(); 1113 int n = test51_helper(refPointField1); 1114 Asserts.assertEQ(result, n); 1115 } 1116 } 1117 1118 // C2->C1 invokestatic, inline class with ref fields (Point, RefPoint) 1119 @Test(compLevel = C2) 1120 public int test52() { 1121 return test52_helper(pointField, refPointField1); 1122 } 1123 1124 @DontInline 1125 @ForceCompile(compLevel = C1) 1126 private static int test52_helper(Point p1, RefPoint rp1) { 1127 return p1.x + p1.y + rp1.x.n + rp1.y.n; 1128 } 1129 1130 @DontCompile 1131 public void test52_verifier(boolean warmup) { 1132 int count = warmup ? 1 : 5; 1133 for (int i=0; i<count; i++) { // need a loop to test inline cache 1134 int result = test52(); 1135 int n = test52_helper(pointField, refPointField1); 1136 Asserts.assertEQ(result, n); 1137 } 1138 } 1139 1140 // C2->C1 invokestatic, inline class with ref fields (RefPoint, RefPoint, RefPoint, RefPoint) 1141 @Test(compLevel = C2) 1142 public int test53() { 1143 return test53_helper(refPointField1, refPointField2, refPointField1, refPointField2); 1144 } 1145 1146 @DontInline 1147 @ForceCompile(compLevel = C1) 1148 private static int test53_helper(RefPoint rp1, RefPoint rp2, RefPoint rp3, RefPoint rp4) { 1149 return rp1.x.n + rp1.y.n + 1150 rp2.x.n + rp2.y.n + 1151 rp3.x.n + rp3.y.n + 1152 rp4.x.n + rp4.y.n; 1153 } 1154 1155 @DontCompile 1156 public void test53_verifier(boolean warmup) { 1157 int count = warmup ? 1 : 5; 1158 for (int i=0; i<count; i++) { // need a loop to test inline cache 1159 int result = test53(); 1160 int n = test53_helper(refPointField1, refPointField2, refPointField1, refPointField2); 1161 Asserts.assertEQ(result, n); 1162 } 1163 } 1164 1165 // C2->C1 invokestatic, inline class with ref fields (RefPoint, RefPoint, float, int, RefPoint, RefPoint) 1166 @Test(compLevel = C2) 1167 public int test54() { 1168 return test54_helper(refPointField1, refPointField2, 1.0f, 2, refPointField1, refPointField2); 1169 } 1170 1171 @DontInline 1172 @ForceCompile(compLevel = C1) 1173 private static int test54_helper(RefPoint rp1, RefPoint rp2, float f, int i, RefPoint rp3, RefPoint rp4) { 1174 return rp1.x.n + rp1.y.n + 1175 rp2.x.n + rp2.y.n + 1176 (int)(f) + i + 1177 rp3.x.n + rp3.y.n + 1178 rp4.x.n + rp4.y.n; 1179 } 1180 1181 @DontCompile 1182 public void test54_verifier(boolean warmup) { 1183 int count = warmup ? 1 : 5; 1184 for (int i=0; i<count; i++) { // need a loop to test inline cache 1185 int result = test54(); 1186 int n = test54_helper(refPointField1, refPointField2, 1.0f, 2, refPointField1, refPointField2); 1187 Asserts.assertEQ(result, n); 1188 } 1189 } 1190 1191 static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 1192 static final String ScavengeALot = "ScavengeALot"; 1193 1194 1195 /** 1196 * Each allocation with a "try" block like this will cause a GC 1197 * 1198 * try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1199 * result = test55(p1); 1200 * } 1201 */ 1202 static class ForceGCMarker implements java.io.Closeable { 1203 static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); 1204 1205 ForceGCMarker() { 1206 WHITE_BOX.setBooleanVMFlag(ScavengeALot, true); 1207 } 1208 public void close() { 1209 WHITE_BOX.setBooleanVMFlag(ScavengeALot, false); 1210 } 1211 1212 static ForceGCMarker mark(boolean warmup) { 1213 return warmup ? null : new ForceGCMarker(); 1214 } 1215 } 1216 1217 // C2->C1 invokestatic, force GC for every allocation when entering a C1 VEP (Point) 1218 @Test(compLevel = C2) 1219 public int test55(Point p1) { 1220 return test55_helper(p1); 1221 } 1222 1223 @DontInline 1224 @ForceCompile(compLevel = C1) 1225 private static int test55_helper(Point p1) { 1226 return p1.x + p1.y; 1227 } 1228 1229 @DontCompile 1230 public void test55_verifier(boolean warmup) { 1231 int count = warmup ? 1 : 5; 1232 for (int i=0; i<count; i++) { // need a loop to test inline cache 1233 Point p1 = new Point(1, 2); 1234 int result; 1235 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1236 result = test55(p1); 1237 } 1238 int n = test55_helper(p1); 1239 Asserts.assertEQ(result, n); 1240 } 1241 } 1242 1243 // C2->C1 invokestatic, force GC for every allocation when entering a C1 VEP (RefPoint) 1244 @Test(compLevel = C2) 1245 public int test56(RefPoint rp1) { 1246 return test56_helper(rp1); 1247 } 1248 1249 @DontInline 1250 @ForceCompile(compLevel = C1) 1251 private static int test56_helper(RefPoint rp1) { 1252 return rp1.x.n + rp1.y.n; 1253 } 1254 1255 @DontCompile 1256 public void test56_verifier(boolean warmup) { 1257 int count = warmup ? 1 : 5; 1258 for (int i=0; i<count; i++) { // need a loop to test inline cache 1259 RefPoint rp1 = new RefPoint(1, 2); 1260 int result; 1261 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1262 result = test56(rp1); 1263 } 1264 int n = test56_helper(rp1); 1265 Asserts.assertEQ(result, n); 1266 } 1267 } 1268 1269 // C2->Interpreter (same as test56, but test c2i entry instead of C1) 1270 @Test(compLevel = C2) 1271 public int test57(RefPoint rp1) { 1272 return test57_helper(rp1); 1273 } 1274 1275 @DontInline @DontCompile 1276 private static int test57_helper(RefPoint rp1) { 1277 return rp1.x.n + rp1.y.n; 1278 } 1279 1280 @DontCompile 1281 public void test57_verifier(boolean warmup) { 1282 int count = warmup ? 1 : 5; 1283 for (int i=0; i<count; i++) { // need a loop to test inline cache 1284 RefPoint rp1 = new RefPoint(1, 2); 1285 int result; 1286 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1287 result = test57(rp1); 1288 } 1289 int n = test57_helper(rp1); 1290 Asserts.assertEQ(result, n); 1291 } 1292 } 1293 1294 // C2->C1 invokestatic, force GC for every allocation when entering a C1 VEP (a bunch of RefPoints and Numbers); 1295 @Test(compLevel = C2) 1296 public int test58(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) { 1297 return test58_helper(rp1, rp2, n1, rp3, rp4, n2); 1298 } 1299 1300 @DontInline 1301 @ForceCompile(compLevel = C1) 1302 private static int test58_helper(RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) { 1303 return rp1.x.n + rp1.y.n + 1304 rp2.x.n + rp2.y.n + 1305 n1.n + 1306 rp3.x.n + rp3.y.n + 1307 rp4.x.n + rp4.y.n + 1308 n2.n; 1309 } 1310 1311 @DontCompile 1312 public void test58_verifier(boolean warmup) { 1313 int count = warmup ? 1 : 5; 1314 for (int i=0; i<count; i++) { // need a loop to test inline cache 1315 RefPoint rp1 = new RefPoint(1, 2); 1316 RefPoint rp2 = refPointField1; 1317 RefPoint rp3 = new RefPoint(222, 777); 1318 RefPoint rp4 = refPointField2; 1319 Number n1 = new Number(5878); 1320 Number n2 = new Number(1234); 1321 int result; 1322 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1323 result = test58(rp1, rp2, n1, rp3, rp4, n2); 1324 } 1325 int n = test58_helper(rp1, rp2, n1, rp3, rp4, n2); 1326 Asserts.assertEQ(result, n); 1327 } 1328 } 1329 1330 // C2->C1 invokestatic, GC inside main body of C1-compiled method (caller's args should not be GC'ed). 1331 @Test(compLevel = C2) 1332 public int test59(RefPoint rp1, boolean doGC) { 1333 return test59_helper(rp1, 11, 222, 3333, 4444, doGC); 1334 } 1335 1336 @DontInline 1337 @ForceCompile(compLevel = C1) 1338 private static int test59_helper(RefPoint rp1, int a1, int a2, int a3, int a4, boolean doGC) { 1339 if (doGC) { 1340 System.gc(); 1341 } 1342 return rp1.x.n + rp1.y.n + a1 + a2 + a3 + a4; 1343 } 1344 1345 @DontCompile 1346 public void test59_verifier(boolean warmup) { 1347 int count = warmup ? 1 : 5; 1348 boolean doGC = !warmup; 1349 for (int i=0; i<count; i++) { // need a loop to test inline cache 1350 RefPoint rp1 = new RefPoint(1, 2); 1351 int result = test59(rp1, doGC); 1352 int n = test59_helper(rp1, 11, 222, 3333, 4444, doGC); 1353 Asserts.assertEQ(result, n); 1354 } 1355 } 1356 1357 // C2->C1 invokestatic, GC inside main body of C1-compiled method (caller's args should not be GC'ed). 1358 // same as test59, but the incoming (scalarized) oops are passed in both registers and stack. 1359 @Test(compLevel = C2) 1360 public int test60(RefPoint rp1, RefPoint rp2, boolean doGC) { 1361 return test60_helper(555, 6666, 77777, rp1, rp2, 11, 222, 3333, 4444, doGC); 1362 } 1363 1364 @DontInline 1365 @ForceCompile(compLevel = C1) 1366 private static int test60_helper(int x0, int x1, int x2, RefPoint rp1, RefPoint rp2,int a1, int a2, int a3, int a4, boolean doGC) { 1367 // On x64, C2 passes: reg0=x1, reg1=x1, reg2=x2, reg3=rp1.x, reg4=rp1.y, reg5=rp2.x stack0=rp2.y .... 1368 // C1 expects: reg0=x1, reg1=x1, reg2=x2, reg3=rp1, reg4=rp2, reg5=a1 stack0=a2 ... 1369 // When GC happens, make sure it does not treat reg5 and stack0 as oops! 1370 if (doGC) { 1371 System.gc(); 1372 } 1373 return x0 + x1 + x2 + rp1.x.n + rp1.y.n + rp2.x.n + rp2.y.n + a1 + a2 + a3 + a4; 1374 } 1375 1376 @DontCompile 1377 public void test60_verifier(boolean warmup) { 1378 int count = warmup ? 1 : 5; 1379 boolean doGC = !warmup; 1380 for (int i=0; i<count; i++) { // need a loop to test inline cache 1381 RefPoint rp1 = new RefPoint(1, 2); 1382 RefPoint rp2 = new RefPoint(33, 44); 1383 int result = test60(rp1, rp2, doGC); 1384 int n = test60_helper(555, 6666, 77777, rp1, rp2, 11, 222, 3333, 4444, doGC); 1385 Asserts.assertEQ(result, n); 1386 } 1387 } 1388 1389 // C2->C1 invokeinterface via VVEP(RO) 1390 @Test(compLevel = C2) 1391 public int test61(RefPoint_Access rpa, RefPoint rp2) { 1392 return rpa.func1(rp2); 1393 } 1394 1395 @DontCompile 1396 public void test61_verifier(boolean warmup) { 1397 int count = warmup ? 1 : 20; 1398 for (int i=0; i<count; i++) { // need a loop to test inline cache 1399 RefPoint_Access rpa = get_RefPoint_Access(); 1400 RefPoint rp2 = refPointField2; 1401 int result = test61(rpa, rp2); 1402 int n = rpa.func1(rp2); 1403 Asserts.assertEQ(result, n); 1404 } 1405 } 1406 1407 // C2->C1 invokeinterface via VVEP(RO) -- force GC for every allocation when entering a C1 VVEP(RO) (RefPoint) 1408 @Test(compLevel = C2) 1409 public int test62(RefPoint_Access rpa, RefPoint rp2) { 1410 return rpa.func1(rp2); 1411 } 1412 1413 @DontCompile 1414 public void test62_verifier(boolean warmup) { 1415 int count = warmup ? 1 : 20; 1416 for (int i=0; i<count; i++) { // need a loop to test inline cache 1417 RefPoint_Access rpa = get_RefPoint_Access(); 1418 RefPoint rp2 = new RefPoint(111, 2222); 1419 int result; 1420 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1421 result = test62(rpa, rp2); 1422 } 1423 int n = rpa.func1(rp2); 1424 Asserts.assertEQ(result, n); 1425 } 1426 } 1427 1428 /* disabled due to bug JDK-8224944 [lworld] TestCallingConventionC1::test63 fails with -Xcomp 1429 1430 1431 // C2->C1 invokeinterface via VVEP(RO) -- force GC for every allocation when entering a C1 VVEP(RO) (a bunch of RefPoints and Numbers) 1432 @Test(compLevel = C2) 1433 public int test63(RefPoint_Access rpa, RefPoint rp1, RefPoint rp2, Number n1, RefPoint rp3, RefPoint rp4, Number n2) { 1434 return rpa.func2(rp1, rp2, n1, rp3, rp4, n2); 1435 } 1436 1437 @DontCompile 1438 public void test63_verifier(boolean warmup) { 1439 int count = warmup ? 1 : 20; 1440 for (int i=0; i<count; i++) { // need a loop to test inline cache 1441 RefPoint_Access rpa = get_RefPoint_Access(); 1442 RefPoint rp1 = new RefPoint(1, 2); 1443 RefPoint rp2 = refPointField1; 1444 RefPoint rp3 = new RefPoint(222, 777); 1445 RefPoint rp4 = refPointField2; 1446 Number n1 = new Number(5878); 1447 Number n2 = new Number(1234); 1448 int result; 1449 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1450 result = test63(rpa, rp1, rp2, n1, rp3, rp4, n2); 1451 } 1452 int n = rpa.func2(rp1, rp2, n1, rp3, rp4, n2); 1453 Asserts.assertEQ(result, n); 1454 } 1455 } 1456 /**/ 1457 1458 // C2->C1 invokevirtual via VVEP(RO) (opt_virtual_call) 1459 @Test(compLevel = C2) 1460 public int test76(RefPoint rp1, RefPoint rp2) { 1461 return rp1.final_func(rp2); 1462 } 1463 1464 @DontCompile 1465 public void test76_verifier(boolean warmup) { 1466 int count = warmup ? 1 : 5; 1467 for (int i=0; i<count; i++) { // need a loop to test inline cache 1468 RefPoint rp1 = refPointField1; 1469 RefPoint rp2 = refPointField2; 1470 int result = test76(rp1, rp2); 1471 int n = rp1.final_func(rp2); 1472 Asserts.assertEQ(result, n); 1473 } 1474 } 1475 1476 // C2->C1 invokevirtual, force GC for every allocation when entering a C1 VEP (RefPoint) 1477 // Same as test56, except we call the VVEP(RO) instead of VEP. 1478 @Test(compLevel = C2) 1479 public int test77(RefPoint rp1, RefPoint rp2) { 1480 return rp1.final_func(rp2); 1481 } 1482 1483 @DontCompile 1484 public void test77_verifier(boolean warmup) { 1485 int count = warmup ? 1 : 5; 1486 for (int i=0; i<count; i++) { // need a loop to test inline cache 1487 RefPoint rp1 = new RefPoint(1, 2); 1488 RefPoint rp2 = new RefPoint(22, 33); 1489 int result; 1490 try (ForceGCMarker m = ForceGCMarker.mark(warmup)) { 1491 result = test77(rp1, rp2); 1492 } 1493 int n = rp1.final_func(rp2); 1494 Asserts.assertEQ(result, n); 1495 } 1496 } 1497 1498 //------------------------------------------------------------------------------- 1499 // Tests for how C1 handles ValueTypeReturnedAsFields in both calls and returns 1500 //------------------------------------------------------------------------------- 1501 // C2->C1 invokestatic with ValueTypeReturnedAsFields (Point) 1502 @Test(compLevel = C2) 1503 public int test78(Point p) { 1504 Point np = test78_helper(p); 1505 return np.x + np.y; 1506 } 1507 1508 @DontInline 1509 @ForceCompile(compLevel = C1) 1510 private static Point test78_helper(Point p) { 1511 return p; 1512 } 1513 1514 @DontCompile 1515 public void test78_verifier(boolean warmup) { 1516 int result = test78(pointField1); 1517 int n = pointField1.x + pointField1.y; 1518 Asserts.assertEQ(result, n); 1519 } 1520 1521 // C2->C1 invokestatic with ValueTypeReturnedAsFields (RefPoint) 1522 @Test(compLevel = C2) 1523 public int test79(RefPoint p) { 1524 RefPoint np = test79_helper(p); 1525 return np.x.n + np.y.n; 1526 } 1527 1528 @DontInline 1529 @ForceCompile(compLevel = C1) 1530 private static RefPoint test79_helper(RefPoint p) { 1531 return p; 1532 } 1533 1534 @DontCompile 1535 public void test79_verifier(boolean warmup) { 1536 int result = test79(refPointField1); 1537 int n = refPointField1.x.n + refPointField1.y.n; 1538 Asserts.assertEQ(result, n); 1539 } 1540 1541 // C1->C2 invokestatic with ValueTypeReturnedAsFields (RefPoint) 1542 @Test(compLevel = C1) 1543 public int test80(RefPoint p) { 1544 RefPoint np = test80_helper(p); 1545 return np.x.n + np.y.n; 1546 } 1547 1548 @DontInline 1549 @ForceCompile(compLevel = C2) 1550 private static RefPoint test80_helper(RefPoint p) { 1551 return p; 1552 } 1553 1554 @DontCompile 1555 public void test80_verifier(boolean warmup) { 1556 int result = test80(refPointField1); 1557 int n = refPointField1.x.n + refPointField1.y.n; 1558 Asserts.assertEQ(result, n); 1559 } 1560 1561 // Interpreter->C1 invokestatic with ValueTypeReturnedAsFields (Point) 1562 @Test(compLevel = C1) 1563 public Point test81(Point p) { 1564 return p; 1565 } 1566 1567 @DontCompile 1568 public void test81_verifier(boolean warmup) { 1569 Point p = test81(pointField1); 1570 Asserts.assertEQ(p.x, pointField1.x); 1571 Asserts.assertEQ(p.y, pointField1.y); 1572 p = test81(pointField2); 1573 Asserts.assertEQ(p.x, pointField2.x); 1574 Asserts.assertEQ(p.y, pointField2.y); 1575 } 1576 1577 // C1->Interpreter invokestatic with ValueTypeReturnedAsFields (RefPoint) 1578 @Test(compLevel = C1) 1579 public int test82(RefPoint p) { 1580 RefPoint np = test82_helper(p); 1581 return np.x.n + np.y.n; 1582 } 1583 1584 @DontInline @DontCompile 1585 private static RefPoint test82_helper(RefPoint p) { 1586 return p; 1587 } 1588 1589 @DontCompile 1590 public void test82_verifier(boolean warmup) { 1591 int result = test82(refPointField1); 1592 int n = refPointField1.x.n + refPointField1.y.n; 1593 Asserts.assertEQ(result, n); 1594 } 1595 1596 //------------------------------------------------------------------------------- 1597 // Tests for ValueTypeReturnedAsFields vs the inline class TooBigToReturnAsFields 1598 //------------------------------------------------------------------------------- 1599 1600 // C2->C1 invokestatic with ValueTypeReturnedAsFields (TooBigToReturnAsFields) 1601 @Test(compLevel = C2) 1602 public int test83(TooBigToReturnAsFields p) { 1603 TooBigToReturnAsFields np = test83_helper(p); 1604 return p.a0 + p.a5; 1605 } 1606 1607 @DontInline 1608 @ForceCompile(compLevel = C1) 1609 private static TooBigToReturnAsFields test83_helper(TooBigToReturnAsFields p) { 1610 return p; 1611 } 1612 1613 @DontCompile 1614 public void test83_verifier(boolean warmup) { 1615 int result = test83(tooBig); 1616 int n = tooBig.a0 + tooBig.a5; 1617 Asserts.assertEQ(result, n); 1618 } 1619 1620 // C1->C2 invokestatic with ValueTypeReturnedAsFields (TooBigToReturnAsFields) 1621 @Test(compLevel = C1) 1622 public int test84(TooBigToReturnAsFields p) { 1623 TooBigToReturnAsFields np = test84_helper(p); 1624 return p.a0 + p.a5; 1625 } 1626 1627 @DontInline 1628 @ForceCompile(compLevel = C2) 1629 private static TooBigToReturnAsFields test84_helper(TooBigToReturnAsFields p) { 1630 return p; 1631 } 1632 1633 @DontCompile 1634 public void test84_verifier(boolean warmup) { 1635 int result = test84(tooBig); 1636 int n = tooBig.a0 + tooBig.a5; 1637 Asserts.assertEQ(result, n); 1638 } 1639 1640 // Interpreter->C1 invokestatic with ValueTypeReturnedAsFields (TooBigToReturnAsFields) 1641 @Test(compLevel = C1) 1642 public TooBigToReturnAsFields test85(TooBigToReturnAsFields p) { 1643 return p; 1644 } 1645 1646 @DontCompile 1647 public void test85_verifier(boolean warmup) { 1648 TooBigToReturnAsFields p = test85(tooBig); 1649 Asserts.assertEQ(p.a0, tooBig.a0); 1650 Asserts.assertEQ(p.a2, tooBig.a2); 1651 } 1652 1653 // C1->Interpreter invokestatic with ValueTypeReturnedAsFields (TooBigToReturnAsFields) 1654 @Test(compLevel = C1) 1655 public int test86(TooBigToReturnAsFields p) { 1656 TooBigToReturnAsFields np = test86_helper(p); 1657 return p.a0 + p.a5; 1658 } 1659 1660 @DontInline @DontCompile 1661 private static TooBigToReturnAsFields test86_helper(TooBigToReturnAsFields p) { 1662 return p; 1663 } 1664 1665 @DontCompile 1666 public void test86_verifier(boolean warmup) { 1667 int result = test86(tooBig); 1668 int n = tooBig.a0 + tooBig.a5; 1669 Asserts.assertEQ(result, n); 1670 } 1671 1672 //------------------------------------------------------------------------------- 1673 // Tests for how C1 handles ValueTypeReturnedAsFields in both calls and returns (RefPoint?) 1674 //------------------------------------------------------------------------------- 1675 1676 // C2->C1 invokestatic with ValueTypeReturnedAsFields (RefPoint?) 1677 @Test(compLevel = C2) 1678 public RefPoint? test87(RefPoint? p) { 1679 return test87_helper(p); 1680 } 1681 1682 @DontInline 1683 @ForceCompile(compLevel = C1) 1684 private static RefPoint? test87_helper(RefPoint? p) { 1685 return p; 1686 } 1687 1688 @DontCompile 1689 public void test87_verifier(boolean warmup) { 1690 Object result = test87(null); 1691 Asserts.assertEQ(result, null); 1692 } 1693 1694 // C2->C1 invokestatic with ValueTypeReturnedAsFields (RefPoint? with constant null) 1695 @Test(compLevel = C2) 1696 public RefPoint? test88() { 1697 return test88_helper(); 1698 } 1699 1700 @DontInline 1701 @ForceCompile(compLevel = C1) 1702 private static RefPoint? test88_helper() { 1703 return null; 1704 } 1705 1706 @DontCompile 1707 public void test88_verifier(boolean warmup) { 1708 Object result = test88(); 1709 Asserts.assertEQ(result, null); 1710 } 1711 1712 // C1->C2 invokestatic with ValueTypeReturnedAsFields (RefPoint?) 1713 @Test(compLevel = C1) 1714 public RefPoint? test89(RefPoint? p) { 1715 return test89_helper(p); 1716 } 1717 1718 @DontInline 1719 @ForceCompile(compLevel = C2) 1720 private static RefPoint? test89_helper(RefPoint? p) { 1721 return p; 1722 } 1723 1724 @DontCompile 1725 public void test89_verifier(boolean warmup) { 1726 Object result = test89(null); 1727 Asserts.assertEQ(result, null); 1728 } 1729 1730 //---------------------------------------------------------------------------------- 1731 // Tests for unverified entries: there are 6 cases: 1732 // C1 -> Unverified Value Entry compiled by C1 1733 // C1 -> Unverified Value Entry compiled by C2 1734 // C2 -> Unverified Entry compiled by C1 (target is NOT a value type) 1735 // C2 -> Unverified Entry compiled by C2 (target is NOT a value type) 1736 // C2 -> Unverified Entry compiled by C1 (target IS a value type, i.e., has VVEP_RO) 1737 // C2 -> Unverified Entry compiled by C2 (target IS a value type, i.e., has VVEP_RO) 1738 //---------------------------------------------------------------------------------- 1739 1740 // C1->C1 invokeinterface -- call Unverified Value Entry of MyImplPojo1.func2 (compiled by C1) 1741 @Test(compLevel = C1) 1742 public int test90(Intf intf, int a, int b) { 1743 return intf.func2(a, b, pointField); 1744 } 1745 1746 static Intf test90_intfs[] = { 1747 new MyImplPojo1(), 1748 new MyImplPojo2(), 1749 }; 1750 1751 @DontCompile 1752 public void test90_verifier(boolean warmup) { 1753 int count = warmup ? 1 : 20; 1754 for (int i=0; i<count; i++) { 1755 Intf intf = test90_intfs[i % test90_intfs.length]; 1756 int result = test90(intf, 123, 456) + i; 1757 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 1758 } 1759 } 1760 1761 // C1->C2 invokeinterface -- call Unverified Value Entry of MyImplPojo2.func2 (compiled by C2) 1762 @Test(compLevel = C1) 1763 public int test91(Intf intf, int a, int b) { 1764 return intf.func2(a, b, pointField); 1765 } 1766 1767 static Intf test91_intfs[] = { 1768 new MyImplPojo2(), 1769 new MyImplPojo1(), 1770 }; 1771 1772 @DontCompile 1773 public void test91_verifier(boolean warmup) { 1774 int count = warmup ? 1 : 20; 1775 for (int i=0; i<count; i++) { 1776 Intf intf = test91_intfs[i % test91_intfs.length]; 1777 int result = test91(intf, 123, 456) + i; 1778 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 1779 } 1780 } 1781 1782 // C2->C1 invokeinterface -- call Unverified Entry of MyImplPojo1.func2 (compiled by C1) 1783 @Test(compLevel = C2) 1784 public int test92(Intf intf, int a, int b) { 1785 return intf.func2(a, b, pointField); 1786 } 1787 1788 static Intf test92_intfs[] = { 1789 new MyImplPojo1(), 1790 new MyImplPojo2(), 1791 }; 1792 1793 @DontCompile 1794 public void test92_verifier(boolean warmup) { 1795 int count = warmup ? 1 : 20; 1796 for (int i=0; i<count; i++) { 1797 Intf intf = test92_intfs[i % test92_intfs.length]; 1798 int result = test92(intf, 123, 456) + i; 1799 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 1800 } 1801 } 1802 1803 // C2->C2 invokeinterface -- call Unverified Entry of MyImplPojo2.func2 (compiled by C2) 1804 @Test(compLevel = C2) 1805 public int test93(Intf intf, int a, int b) { 1806 return intf.func2(a, b, pointField); 1807 } 1808 1809 static Intf test93_intfs[] = { 1810 new MyImplPojo2(), 1811 new MyImplPojo1(), 1812 }; 1813 1814 @DontCompile 1815 public void test93_verifier(boolean warmup) { 1816 int count = warmup ? 1 : 20; 1817 for (int i=0; i<count; i++) { 1818 Intf intf = test93_intfs[i % test93_intfs.length]; 1819 int result = test93(intf, 123, 456) + i; 1820 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 1821 } 1822 } 1823 1824 // C2->C1 invokeinterface -- call Unverified Entry of MyImplVal1.func2 (compiled by C1 - has VVEP_RO) 1825 @Test(compLevel = C2) 1826 public int test94(Intf intf, int a, int b) { 1827 return intf.func2(a, b, pointField); 1828 } 1829 1830 static Intf test94_intfs[] = { 1831 new MyImplVal1(), 1832 new MyImplVal2(), 1833 }; 1834 1835 @DontCompile 1836 public void test94_verifier(boolean warmup) { 1837 int count = warmup ? 1 : 20; 1838 for (int i=0; i<count; i++) { 1839 Intf intf = test94_intfs[i % test94_intfs.length]; 1840 int result = test94(intf, 123, 456) + i; 1841 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 1842 } 1843 } 1844 1845 // C2->C2 invokeinterface -- call Unverified Entry of MyImplVal2.func2 (compiled by C2 - has VVEP_RO) 1846 @Test(compLevel = C2) 1847 public int test95(Intf intf, int a, int b) { 1848 return intf.func2(a, b, pointField); 1849 } 1850 1851 static Intf test95_intfs[] = { 1852 new MyImplVal2(), 1853 new MyImplVal1(), 1854 }; 1855 1856 @DontCompile 1857 public void test95_verifier(boolean warmup) { 1858 int count = warmup ? 1 : 20; 1859 for (int i=0; i<count; i++) { 1860 Intf intf = test95_intfs[i % test95_intfs.length]; 1861 int result = test95(intf, 123, 456) + i; 1862 Asserts.assertEQ(result, intf.func2(123, 456, pointField) + i); 1863 } 1864 } 1865 1866 // C1->C2 GC handling in StubRoutines::store_value_type_fields_to_buf() 1867 @Test(compLevel = C1) 1868 public RefPoint test96(RefPoint rp, boolean b) { 1869 RefPoint p = test96_helper(rp); 1870 if (b) { 1871 return rp; 1872 } 1873 return p; 1874 } 1875 1876 @DontInline @ForceCompile(compLevel = C2) 1877 public RefPoint test96_helper(RefPoint rp) { 1878 return rp; 1879 } 1880 1881 @DontCompile 1882 public void test96_verifier(boolean warmup) { 1883 int count = warmup ? 1 : 20000; // Do enough iteration to cause GC inside StubRoutines::store_value_type_fields_to_buf 1884 Number x = new Number(10); // old object 1885 for (int i=0; i<count; i++) { 1886 Number y = new Number(i); // new object for each iteraton 1887 RefPoint rp1 = new RefPoint(x, y); 1888 RefPoint rp2 = test96(rp1, warmup); 1889 1890 Asserts.assertEQ(rp1.x, x); 1891 Asserts.assertEQ(rp1.y, y); 1892 Asserts.assertEQ(rp1.y.n, i); 1893 } 1894 } 1895 }