1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 class Circle { Circle(double radius)18 Circle(double radius) { 19 this.radius = radius; 20 } getArea()21 public double getArea() { 22 return radius * radius * Math.PI; 23 } 24 private double radius; 25 } 26 27 class TestClass { 28 static { 29 sTestClassObj = new TestClass(-1, -2); 30 } TestClass()31 TestClass() { 32 } TestClass(int i, int j)33 TestClass(int i, int j) { 34 this.i = i; 35 this.j = j; 36 } 37 int i; 38 int j; 39 volatile int k; 40 TestClass next; 41 String str; 42 static int si; 43 static TestClass sTestClassObj; 44 } 45 46 class SubTestClass extends TestClass { 47 int k; 48 } 49 50 class TestClass2 { 51 int i; 52 int j; 53 } 54 55 class TestClass3 { 56 float floatField = 8.0f; 57 boolean test1 = true; 58 } 59 60 class Finalizable { 61 static boolean sVisited = false; 62 static final int VALUE = 0xbeef; 63 int i; 64 finalize()65 protected void finalize() { 66 if (i != VALUE) { 67 System.out.println("Where is the beef?"); 68 } 69 sVisited = true; 70 } 71 } 72 73 public class Main { 74 75 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (before) 76 /// CHECK: NewInstance 77 /// CHECK: InstanceFieldSet 78 /// CHECK: InstanceFieldGet 79 80 /// CHECK-START: double Main.calcCircleArea(double) load_store_elimination (after) 81 /// CHECK: NewInstance 82 /// CHECK-NOT: InstanceFieldSet 83 /// CHECK-NOT: InstanceFieldGet 84 calcCircleArea(double radius)85 static double calcCircleArea(double radius) { 86 return new Circle(radius).getArea(); 87 } 88 89 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (before) 90 /// CHECK: InstanceFieldSet 91 /// CHECK: InstanceFieldSet 92 /// CHECK: InstanceFieldGet 93 /// CHECK: InstanceFieldGet 94 95 /// CHECK-START: int Main.test1(TestClass, TestClass) load_store_elimination (after) 96 /// CHECK: InstanceFieldSet 97 /// CHECK: InstanceFieldSet 98 /// CHECK-NOT: NullCheck 99 /// CHECK-NOT: InstanceFieldGet 100 101 // Different fields shouldn't alias. test1(TestClass obj1, TestClass obj2)102 static int test1(TestClass obj1, TestClass obj2) { 103 obj1.i = 1; 104 obj2.j = 2; 105 return obj1.i + obj2.j; 106 } 107 108 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (before) 109 /// CHECK: InstanceFieldSet 110 /// CHECK: InstanceFieldSet 111 /// CHECK: InstanceFieldGet 112 113 /// CHECK-START: int Main.test2(TestClass) load_store_elimination (after) 114 /// CHECK: InstanceFieldSet 115 /// CHECK-NOT: NullCheck 116 /// CHECK-NOT: InstanceFieldSet 117 /// CHECK-NOT: InstanceFieldGet 118 119 // Redundant store of the same value. test2(TestClass obj)120 static int test2(TestClass obj) { 121 obj.j = 1; 122 obj.j = 1; 123 return obj.j; 124 } 125 126 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (before) 127 /// CHECK: NewInstance 128 /// CHECK: StaticFieldGet 129 /// CHECK: NewInstance 130 /// CHECK: InstanceFieldSet 131 /// CHECK: InstanceFieldSet 132 /// CHECK: InstanceFieldSet 133 /// CHECK: InstanceFieldSet 134 /// CHECK: InstanceFieldGet 135 /// CHECK: InstanceFieldGet 136 /// CHECK: InstanceFieldGet 137 /// CHECK: InstanceFieldGet 138 139 /// CHECK-START: int Main.test3(TestClass) load_store_elimination (after) 140 /// CHECK: NewInstance 141 /// CHECK: StaticFieldGet 142 /// CHECK: NewInstance 143 /// CHECK: InstanceFieldSet 144 /// CHECK: InstanceFieldSet 145 /// CHECK: InstanceFieldSet 146 /// CHECK: InstanceFieldSet 147 /// CHECK-NOT: InstanceFieldGet 148 /// CHECK-NOT: StaticFieldGet 149 150 // A new allocation (even non-singleton) shouldn't alias with pre-existing values. test3(TestClass obj)151 static int test3(TestClass obj) { 152 // Do an allocation here to avoid the HLoadClass and HClinitCheck 153 // at the second allocation. 154 new TestClass(); 155 TestClass obj1 = TestClass.sTestClassObj; 156 TestClass obj2 = new TestClass(); // Cannot alias with obj or obj1 which pre-exist. 157 obj.next = obj2; // Make obj2 a non-singleton. 158 // All stores below need to stay since obj/obj1/obj2 are not singletons. 159 obj.i = 1; 160 obj1.j = 2; 161 // Following stores won't kill values of obj.i and obj1.j. 162 obj2.i = 3; 163 obj2.j = 4; 164 return obj.i + obj1.j + obj2.i + obj2.j; 165 } 166 167 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (before) 168 /// CHECK: InstanceFieldSet 169 /// CHECK: InstanceFieldGet 170 /// CHECK: Return 171 /// CHECK: InstanceFieldSet 172 173 /// CHECK-START: int Main.test4(TestClass, boolean) load_store_elimination (after) 174 /// CHECK: InstanceFieldSet 175 /// CHECK-NOT: NullCheck 176 /// CHECK-NOT: InstanceFieldGet 177 /// CHECK: Return 178 /// CHECK: InstanceFieldSet 179 180 // Set and merge the same value in two branches. test4(TestClass obj, boolean b)181 static int test4(TestClass obj, boolean b) { 182 if (b) { 183 obj.i = 1; 184 } else { 185 obj.i = 1; 186 } 187 return obj.i; 188 } 189 190 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (before) 191 /// CHECK: InstanceFieldSet 192 /// CHECK: InstanceFieldGet 193 /// CHECK: Return 194 /// CHECK: InstanceFieldSet 195 196 /// CHECK-START: int Main.test5(TestClass, boolean) load_store_elimination (after) 197 /// CHECK: InstanceFieldSet 198 /// CHECK: InstanceFieldGet 199 /// CHECK: Return 200 /// CHECK: InstanceFieldSet 201 202 // Set and merge different values in two branches. test5(TestClass obj, boolean b)203 static int test5(TestClass obj, boolean b) { 204 if (b) { 205 obj.i = 1; 206 } else { 207 obj.i = 2; 208 } 209 return obj.i; 210 } 211 212 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (before) 213 /// CHECK: InstanceFieldSet 214 /// CHECK: InstanceFieldSet 215 /// CHECK: InstanceFieldSet 216 /// CHECK: InstanceFieldGet 217 /// CHECK: InstanceFieldGet 218 219 /// CHECK-START: int Main.test6(TestClass, TestClass, boolean) load_store_elimination (after) 220 /// CHECK: InstanceFieldSet 221 /// CHECK: InstanceFieldSet 222 /// CHECK: InstanceFieldSet 223 /// CHECK: InstanceFieldGet 224 /// CHECK-NOT: NullCheck 225 /// CHECK-NOT: InstanceFieldGet 226 227 // Setting the same value doesn't clear the value for aliased locations. test6(TestClass obj1, TestClass obj2, boolean b)228 static int test6(TestClass obj1, TestClass obj2, boolean b) { 229 obj1.i = 1; 230 obj1.j = 2; 231 if (b) { 232 obj2.j = 2; 233 } 234 return obj1.j + obj2.j; 235 } 236 237 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (before) 238 /// CHECK: InstanceFieldSet 239 /// CHECK: InstanceFieldGet 240 241 /// CHECK-START: int Main.test7(TestClass) load_store_elimination (after) 242 /// CHECK: InstanceFieldSet 243 /// CHECK: InstanceFieldGet 244 245 // Invocation should kill values in non-singleton heap locations. test7(TestClass obj)246 static int test7(TestClass obj) { 247 obj.i = 1; 248 System.out.print(""); 249 return obj.i; 250 } 251 252 /// CHECK-START: int Main.test8() load_store_elimination (before) 253 /// CHECK: NewInstance 254 /// CHECK: InstanceFieldSet 255 /// CHECK: InvokeVirtual 256 /// CHECK: InstanceFieldGet 257 258 /// CHECK-START: int Main.test8() load_store_elimination (after) 259 /// CHECK: NewInstance 260 /// CHECK-NOT: InstanceFieldSet 261 /// CHECK: InvokeVirtual 262 /// CHECK-NOT: NullCheck 263 /// CHECK-NOT: InstanceFieldGet 264 265 // Invocation should not kill values in singleton heap locations. test8()266 static int test8() { 267 TestClass obj = new TestClass(); 268 obj.i = 1; 269 System.out.print(""); 270 return obj.i; 271 } 272 273 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (before) 274 /// CHECK: NewInstance 275 /// CHECK: InstanceFieldSet 276 /// CHECK: InstanceFieldSet 277 /// CHECK: InstanceFieldGet 278 279 /// CHECK-START: int Main.test9(TestClass) load_store_elimination (after) 280 /// CHECK: NewInstance 281 /// CHECK: InstanceFieldSet 282 /// CHECK: InstanceFieldSet 283 /// CHECK: InstanceFieldGet 284 285 // Invocation should kill values in non-singleton heap locations. test9(TestClass obj)286 static int test9(TestClass obj) { 287 TestClass obj2 = new TestClass(); 288 obj2.i = 1; 289 obj.next = obj2; 290 System.out.print(""); 291 return obj2.i; 292 } 293 294 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (before) 295 /// CHECK: StaticFieldGet 296 /// CHECK: InstanceFieldGet 297 /// CHECK: StaticFieldSet 298 /// CHECK: InstanceFieldGet 299 300 /// CHECK-START: int Main.test10(TestClass) load_store_elimination (after) 301 /// CHECK: StaticFieldGet 302 /// CHECK: InstanceFieldGet 303 /// CHECK: StaticFieldSet 304 /// CHECK-NOT: NullCheck 305 /// CHECK-NOT: InstanceFieldGet 306 307 // Static fields shouldn't alias with instance fields. test10(TestClass obj)308 static int test10(TestClass obj) { 309 TestClass.si += obj.i; 310 return obj.i; 311 } 312 313 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (before) 314 /// CHECK: InstanceFieldSet 315 /// CHECK: InstanceFieldGet 316 317 /// CHECK-START: int Main.test11(TestClass) load_store_elimination (after) 318 /// CHECK: InstanceFieldSet 319 /// CHECK-NOT: NullCheck 320 /// CHECK-NOT: InstanceFieldGet 321 322 // Loop without heap writes. 323 // obj.i is actually hoisted to the loop pre-header by licm already. test11(TestClass obj)324 static int test11(TestClass obj) { 325 obj.i = 1; 326 int sum = 0; 327 for (int i = 0; i < 10; i++) { 328 sum += obj.i; 329 } 330 return sum; 331 } 332 333 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (before) 334 /// CHECK: InstanceFieldSet 335 /// CHECK: InstanceFieldGet 336 /// CHECK: InstanceFieldSet 337 338 /// CHECK-START: int Main.test12(TestClass, TestClass) load_store_elimination (after) 339 /// CHECK: InstanceFieldSet 340 /// CHECK: InstanceFieldGet 341 /// CHECK: InstanceFieldSet 342 343 // Loop with heap writes. test12(TestClass obj1, TestClass obj2)344 static int test12(TestClass obj1, TestClass obj2) { 345 obj1.i = 1; 346 int sum = 0; 347 for (int i = 0; i < 10; i++) { 348 sum += obj1.i; 349 obj2.i = sum; 350 } 351 return sum; 352 } 353 354 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (before) 355 /// CHECK: InstanceFieldSet 356 /// CHECK: InstanceFieldSet 357 /// CHECK: InstanceFieldGet 358 /// CHECK: InstanceFieldGet 359 360 /// CHECK-START: int Main.test13(TestClass, TestClass2) load_store_elimination (after) 361 /// CHECK: InstanceFieldSet 362 /// CHECK: InstanceFieldSet 363 /// CHECK-NOT: NullCheck 364 /// CHECK-NOT: InstanceFieldGet 365 366 // Different classes shouldn't alias. test13(TestClass obj1, TestClass2 obj2)367 static int test13(TestClass obj1, TestClass2 obj2) { 368 obj1.i = 1; 369 obj2.i = 2; 370 return obj1.i + obj2.i; 371 } 372 373 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (before) 374 /// CHECK: InstanceFieldSet 375 /// CHECK: InstanceFieldSet 376 /// CHECK: InstanceFieldGet 377 378 /// CHECK-START: int Main.test14(TestClass, SubTestClass) load_store_elimination (after) 379 /// CHECK: InstanceFieldSet 380 /// CHECK: InstanceFieldSet 381 /// CHECK: InstanceFieldGet 382 383 // Subclass may alias with super class. test14(TestClass obj1, SubTestClass obj2)384 static int test14(TestClass obj1, SubTestClass obj2) { 385 obj1.i = 1; 386 obj2.i = 2; 387 return obj1.i; 388 } 389 390 /// CHECK-START: int Main.test15() load_store_elimination (before) 391 /// CHECK: StaticFieldSet 392 /// CHECK: StaticFieldSet 393 /// CHECK: StaticFieldGet 394 395 /// CHECK-START: int Main.test15() load_store_elimination (after) 396 /// CHECK: <<Const2:i\d+>> IntConstant 2 397 /// CHECK: StaticFieldSet 398 /// CHECK: StaticFieldSet 399 /// CHECK-NOT: StaticFieldGet 400 /// CHECK: Return [<<Const2>>] 401 402 // Static field access from subclass's name. test15()403 static int test15() { 404 TestClass.si = 1; 405 SubTestClass.si = 2; 406 return TestClass.si; 407 } 408 409 /// CHECK-START: int Main.test16() load_store_elimination (before) 410 /// CHECK: NewInstance 411 /// CHECK: InstanceFieldSet 412 /// CHECK: InstanceFieldSet 413 /// CHECK: InstanceFieldGet 414 /// CHECK: InstanceFieldGet 415 416 /// CHECK-START: int Main.test16() load_store_elimination (after) 417 /// CHECK: NewInstance 418 /// CHECK-NOT: InstanceFieldSet 419 /// CHECK-NOT: InstanceFieldGet 420 421 // Test inlined constructor. test16()422 static int test16() { 423 TestClass obj = new TestClass(1, 2); 424 return obj.i + obj.j; 425 } 426 427 /// CHECK-START: int Main.test17() load_store_elimination (before) 428 /// CHECK: NewInstance 429 /// CHECK: InstanceFieldSet 430 /// CHECK: InstanceFieldGet 431 432 /// CHECK-START: int Main.test17() load_store_elimination (after) 433 /// CHECK: <<Const0:i\d+>> IntConstant 0 434 /// CHECK: NewInstance 435 /// CHECK-NOT: InstanceFieldSet 436 /// CHECK-NOT: InstanceFieldGet 437 /// CHECK: Return [<<Const0>>] 438 439 // Test getting default value. test17()440 static int test17() { 441 TestClass obj = new TestClass(); 442 obj.j = 1; 443 return obj.i; 444 } 445 446 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (before) 447 /// CHECK: InstanceFieldSet 448 /// CHECK: InstanceFieldGet 449 450 /// CHECK-START: int Main.test18(TestClass) load_store_elimination (after) 451 /// CHECK: InstanceFieldSet 452 /// CHECK: InstanceFieldGet 453 454 // Volatile field load/store shouldn't be eliminated. test18(TestClass obj)455 static int test18(TestClass obj) { 456 obj.k = 1; 457 return obj.k; 458 } 459 460 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (before) 461 /// CHECK: {{f\d+}} ArrayGet 462 /// CHECK: {{f\d+}} ArrayGet 463 464 /// CHECK-START: float Main.test19(float[], float[]) load_store_elimination (after) 465 /// CHECK: {{f\d+}} ArrayGet 466 /// CHECK-NOT: {{f\d+}} ArrayGet 467 468 // I/F, J/D aliasing should not happen any more and LSE should eliminate the load. test19(float[] fa1, float[] fa2)469 static float test19(float[] fa1, float[] fa2) { 470 fa1[0] = fa2[0]; 471 return fa1[0]; 472 } 473 474 /// CHECK-START: TestClass Main.test20() load_store_elimination (before) 475 /// CHECK: NewInstance 476 /// CHECK: InstanceFieldSet 477 478 /// CHECK-START: TestClass Main.test20() load_store_elimination (after) 479 /// CHECK: NewInstance 480 /// CHECK-NOT: InstanceFieldSet 481 482 // Storing default heap value is redundant if the heap location has the 483 // default heap value. test20()484 static TestClass test20() { 485 TestClass obj = new TestClass(); 486 obj.i = 0; 487 return obj; 488 } 489 490 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (before) 491 /// CHECK: NewInstance 492 /// CHECK: InstanceFieldSet 493 /// CHECK: InstanceFieldSet 494 /// CHECK: InstanceFieldSet 495 /// CHECK: InstanceFieldGet 496 /// CHECK: InstanceFieldGet 497 498 /// CHECK-START: void Main.test21(TestClass) load_store_elimination (after) 499 /// CHECK: NewInstance 500 /// CHECK: InstanceFieldSet 501 /// CHECK: InstanceFieldSet 502 /// CHECK: InstanceFieldSet 503 /// CHECK: InstanceFieldGet 504 /// CHECK: InstanceFieldGet 505 506 // Loop side effects can kill heap values, stores need to be kept in that case. test21(TestClass obj0)507 static void test21(TestClass obj0) { 508 TestClass obj = new TestClass(); 509 obj0.str = "abc"; 510 obj.str = "abc"; 511 for (int i = 0; i < 2; i++) { 512 // Generate some loop side effect that writes into obj. 513 obj.str = "def"; 514 } 515 System.out.print(obj0.str.substring(0, 0) + obj.str.substring(0, 0)); 516 } 517 518 /// CHECK-START: int Main.test22() load_store_elimination (before) 519 /// CHECK: NewInstance 520 /// CHECK: InstanceFieldSet 521 /// CHECK: NewInstance 522 /// CHECK: InstanceFieldSet 523 /// CHECK: InstanceFieldGet 524 /// CHECK: NewInstance 525 /// CHECK: InstanceFieldSet 526 /// CHECK: InstanceFieldGet 527 /// CHECK: InstanceFieldGet 528 529 /// CHECK-START: int Main.test22() load_store_elimination (after) 530 /// CHECK: NewInstance 531 /// CHECK-NOT: InstanceFieldSet 532 /// CHECK: NewInstance 533 /// CHECK-NOT: InstanceFieldSet 534 /// CHECK-NOT: InstanceFieldGet 535 /// CHECK: NewInstance 536 /// CHECK-NOT: InstanceFieldSet 537 /// CHECK-NOT: InstanceFieldGet 538 /// CHECK-NOT: InstanceFieldGet 539 540 // For a singleton, loop side effects can kill its field values only if: 541 // (1) it dominiates the loop header, and 542 // (2) its fields are stored into inside a loop. test22()543 static int test22() { 544 int sum = 0; 545 TestClass obj1 = new TestClass(); 546 obj1.i = 2; // This store can be eliminated since obj1 is never stored into inside a loop. 547 for (int i = 0; i < 2; i++) { 548 TestClass obj2 = new TestClass(); 549 obj2.i = 3; // This store can be eliminated since the singleton is inside the loop. 550 sum += obj2.i; 551 } 552 TestClass obj3 = new TestClass(); 553 obj3.i = 5; // This store can be eliminated since the singleton is created after the loop. 554 sum += obj1.i + obj3.i; 555 return sum; 556 } 557 558 /// CHECK-START: int Main.test23(boolean) load_store_elimination (before) 559 /// CHECK: NewInstance 560 /// CHECK: InstanceFieldSet 561 /// CHECK: InstanceFieldGet 562 /// CHECK: InstanceFieldSet 563 /// CHECK: InstanceFieldGet 564 /// CHECK: Return 565 /// CHECK: InstanceFieldGet 566 /// CHECK: InstanceFieldSet 567 568 /// CHECK-START: int Main.test23(boolean) load_store_elimination (after) 569 /// CHECK: NewInstance 570 /// CHECK-NOT: InstanceFieldSet 571 /// CHECK-NOT: InstanceFieldGet 572 /// CHECK: InstanceFieldSet 573 /// CHECK: InstanceFieldGet 574 /// CHECK: Return 575 /// CHECK-NOT: InstanceFieldGet 576 /// CHECK: InstanceFieldSet 577 578 // Test store elimination on merging. test23(boolean b)579 static int test23(boolean b) { 580 TestClass obj = new TestClass(); 581 obj.i = 3; // This store can be eliminated since the value flows into each branch. 582 if (b) { 583 obj.i += 1; // This store cannot be eliminated due to the merge later. 584 } else { 585 obj.i += 2; // This store cannot be eliminated due to the merge later. 586 } 587 return obj.i; 588 } 589 590 /// CHECK-START: float Main.test24() load_store_elimination (before) 591 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 592 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 593 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 594 /// CHECK-DAG: <<Obj:l\d+>> NewInstance 595 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<True>>] 596 /// CHECK-DAG: InstanceFieldSet [<<Obj>>,<<Float8>>] 597 /// CHECK-DAG: <<GetTest:z\d+>> InstanceFieldGet [<<Obj>>] 598 /// CHECK-DAG: <<GetField:f\d+>> InstanceFieldGet [<<Obj>>] 599 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<GetField>>,<<GetTest>>] 600 /// CHECK-DAG: Return [<<Select>>] 601 602 /// CHECK-START: float Main.test24() load_store_elimination (after) 603 /// CHECK-DAG: <<True:i\d+>> IntConstant 1 604 /// CHECK-DAG: <<Float8:f\d+>> FloatConstant 8 605 /// CHECK-DAG: <<Float42:f\d+>> FloatConstant 42 606 /// CHECK-DAG: <<Select:f\d+>> Select [<<Float42>>,<<Float8>>,<<True>>] 607 /// CHECK-DAG: Return [<<Select>>] 608 test24()609 static float test24() { 610 float a = 42.0f; 611 TestClass3 obj = new TestClass3(); 612 if (obj.test1) { 613 a = obj.floatField; 614 } 615 return a; 616 } 617 618 /// CHECK-START: void Main.testFinalizable() load_store_elimination (before) 619 /// CHECK: NewInstance 620 /// CHECK: InstanceFieldSet 621 622 /// CHECK-START: void Main.testFinalizable() load_store_elimination (after) 623 /// CHECK: NewInstance 624 /// CHECK: InstanceFieldSet 625 626 // Allocations and stores into finalizable objects cannot be eliminated. testFinalizable()627 static void testFinalizable() { 628 Finalizable finalizable = new Finalizable(); 629 finalizable.i = Finalizable.VALUE; 630 } 631 getWeakReference()632 static java.lang.ref.WeakReference<Object> getWeakReference() { 633 return new java.lang.ref.WeakReference<>(new Object()); 634 } 635 testFinalizableByForcingGc()636 static void testFinalizableByForcingGc() { 637 testFinalizable(); 638 java.lang.ref.WeakReference<Object> reference = getWeakReference(); 639 640 Runtime runtime = Runtime.getRuntime(); 641 for (int i = 0; i < 20; ++i) { 642 runtime.gc(); 643 System.runFinalization(); 644 try { 645 Thread.sleep(1); 646 } catch (InterruptedException e) { 647 throw new AssertionError(e); 648 } 649 650 // Check to see if the weak reference has been garbage collected. 651 if (reference.get() == null) { 652 // A little bit more sleep time to make sure. 653 try { 654 Thread.sleep(100); 655 } catch (InterruptedException e) { 656 throw new AssertionError(e); 657 } 658 if (!Finalizable.sVisited) { 659 System.out.println("finalize() not called."); 660 } 661 return; 662 } 663 } 664 System.out.println("testFinalizableByForcingGc() failed to force gc."); 665 } 666 667 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (before) 668 /// CHECK: InstanceFieldSet 669 /// CHECK: Select 670 671 /// CHECK-START: int Main.$noinline$testHSelect(boolean) load_store_elimination (after) 672 /// CHECK: InstanceFieldSet 673 /// CHECK: Select 674 675 // Test that HSelect creates alias. $noinline$testHSelect(boolean b)676 public static int $noinline$testHSelect(boolean b) { 677 if (sFlag) { 678 throw new Error(); 679 } 680 TestClass obj = new TestClass(); 681 TestClass obj2 = null; 682 obj.i = 0xdead; 683 if (b) { 684 obj2 = obj; 685 } 686 return obj2.i; 687 } 688 assertIntEquals(int result, int expected)689 public static void assertIntEquals(int result, int expected) { 690 if (expected != result) { 691 throw new Error("Expected: " + expected + ", found: " + result); 692 } 693 } 694 assertFloatEquals(float result, float expected)695 public static void assertFloatEquals(float result, float expected) { 696 if (expected != result) { 697 throw new Error("Expected: " + expected + ", found: " + result); 698 } 699 } 700 assertDoubleEquals(double result, double expected)701 public static void assertDoubleEquals(double result, double expected) { 702 if (expected != result) { 703 throw new Error("Expected: " + expected + ", found: " + result); 704 } 705 } 706 main(String[] args)707 public static void main(String[] args) { 708 assertDoubleEquals(Math.PI * Math.PI * Math.PI, calcCircleArea(Math.PI)); 709 assertIntEquals(test1(new TestClass(), new TestClass()), 3); 710 assertIntEquals(test2(new TestClass()), 1); 711 TestClass obj1 = new TestClass(); 712 TestClass obj2 = new TestClass(); 713 obj1.next = obj2; 714 assertIntEquals(test3(obj1), 10); 715 assertIntEquals(test4(new TestClass(), true), 1); 716 assertIntEquals(test4(new TestClass(), false), 1); 717 assertIntEquals(test5(new TestClass(), true), 1); 718 assertIntEquals(test5(new TestClass(), false), 2); 719 assertIntEquals(test6(new TestClass(), new TestClass(), true), 4); 720 assertIntEquals(test6(new TestClass(), new TestClass(), false), 2); 721 assertIntEquals(test7(new TestClass()), 1); 722 assertIntEquals(test8(), 1); 723 obj1 = new TestClass(); 724 obj2 = new TestClass(); 725 obj1.next = obj2; 726 assertIntEquals(test9(new TestClass()), 1); 727 assertIntEquals(test10(new TestClass(3, 4)), 3); 728 assertIntEquals(TestClass.si, 3); 729 assertIntEquals(test11(new TestClass()), 10); 730 assertIntEquals(test12(new TestClass(), new TestClass()), 10); 731 assertIntEquals(test13(new TestClass(), new TestClass2()), 3); 732 SubTestClass obj3 = new SubTestClass(); 733 assertIntEquals(test14(obj3, obj3), 2); 734 assertIntEquals(test15(), 2); 735 assertIntEquals(test16(), 3); 736 assertIntEquals(test17(), 0); 737 assertIntEquals(test18(new TestClass()), 1); 738 float[] fa1 = { 0.8f }; 739 float[] fa2 = { 1.8f }; 740 assertFloatEquals(test19(fa1, fa2), 1.8f); 741 assertFloatEquals(test20().i, 0); 742 test21(new TestClass()); 743 assertIntEquals(test22(), 13); 744 assertIntEquals(test23(true), 4); 745 assertIntEquals(test23(false), 5); 746 assertFloatEquals(test24(), 8.0f); 747 testFinalizableByForcingGc(); 748 assertIntEquals($noinline$testHSelect(true), 0xdead); 749 } 750 751 static boolean sFlag; 752 } 753