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 interface SuperInterface { superInterfaceMethod()18 void superInterfaceMethod(); 19 } 20 21 interface OtherInterface extends SuperInterface { 22 } 23 24 interface Interface extends SuperInterface { $noinline$f()25 void $noinline$f(); 26 } 27 28 class Super implements Interface { superInterfaceMethod()29 public void superInterfaceMethod() {} $noinline$f()30 public void $noinline$f() { 31 throw new RuntimeException(); 32 } 33 $inline$h(boolean cond)34 public int $inline$h(boolean cond) { 35 Super obj = (cond ? this : null); 36 return obj.$noinline$hashCode(); 37 } $noinline$hashCode()38 public int $noinline$hashCode() { 39 return hashCode(); 40 } 41 } 42 43 class SubclassA extends Super { $noinline$f()44 public void $noinline$f() { 45 throw new RuntimeException(); 46 } 47 $noinline$h()48 public String $noinline$h() { 49 throw new RuntimeException(); 50 } 51 $noinline$g()52 void $noinline$g() { 53 throw new RuntimeException(); 54 } 55 } 56 57 class SubclassC extends SubclassA { 58 } 59 60 class SubclassB extends Super { $noinline$f()61 public void $noinline$f() { 62 throw new RuntimeException(); 63 } 64 $noinline$g()65 void $noinline$g() { 66 throw new RuntimeException(); 67 } 68 } 69 70 class Generic<A> { 71 private A a = null; get()72 public A get() { 73 return a; 74 } 75 } 76 77 final class Final {} 78 79 final class FinalException extends Exception {} 80 81 public class Main { 82 83 /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (before) 84 /// CHECK: CheckCast 85 86 /// CHECK-START: void Main.testSimpleRemove() instruction_simplifier (after) 87 /// CHECK-NOT: CheckCast testSimpleRemove()88 public void testSimpleRemove() { 89 Super s = new SubclassA(); 90 ((SubclassA)s).$noinline$g(); 91 } 92 93 /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (before) 94 /// CHECK: CheckCast 95 96 /// CHECK-START: void Main.testSimpleKeep(Super) instruction_simplifier (after) 97 /// CHECK: CheckCast testSimpleKeep(Super s)98 public void testSimpleKeep(Super s) { 99 ((SubclassA)s).$noinline$f(); 100 } 101 102 /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (before) 103 /// CHECK: CheckCast 104 105 /// CHECK-START: java.lang.String Main.testClassRemove() instruction_simplifier (after) 106 /// CHECK-NOT: CheckCast testClassRemove()107 public String testClassRemove() { 108 Object s = SubclassA.class; 109 return ((Class<?>)s).getName(); 110 } 111 112 /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (before) 113 /// CHECK: CheckCast 114 115 /// CHECK-START: java.lang.String Main.testClassKeep() instruction_simplifier (after) 116 /// CHECK: CheckCast testClassKeep()117 public String testClassKeep() { 118 Object s = SubclassA.class; 119 return ((SubclassA)s).$noinline$h(); 120 } 121 122 /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (before) 123 /// CHECK: CheckCast 124 125 /// CHECK-START: void Main.testIfRemove(int) instruction_simplifier (after) 126 /// CHECK-NOT: CheckCast testIfRemove(int x)127 public void testIfRemove(int x) { 128 Super s; 129 if (x % 2 == 0) { 130 s = new SubclassA(); 131 } else { 132 s = new SubclassC(); 133 } 134 ((SubclassA)s).$noinline$g(); 135 } 136 137 /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (before) 138 /// CHECK: CheckCast 139 140 /// CHECK-START: void Main.testIfKeep(int) instruction_simplifier (after) 141 /// CHECK: CheckCast testIfKeep(int x)142 public void testIfKeep(int x) { 143 Super s; 144 if (x % 2 == 0) { 145 s = new SubclassA(); 146 } else { 147 s = new SubclassB(); 148 } 149 ((SubclassA)s).$noinline$g(); 150 } 151 152 /// CHECK-START: void Main.testForRemove(int) instruction_simplifier (before) 153 /// CHECK: CheckCast 154 155 /// CHECK-START: void Main.testForRemove(int) instruction_simplifier (after) 156 /// CHECK-NOT: CheckCast testForRemove(int x)157 public void testForRemove(int x) { 158 Super s = new SubclassA(); 159 for (int i = 0 ; i < x; i++) { 160 if (x % 2 == 0) { 161 s = new SubclassC(); 162 } 163 } 164 ((SubclassA)s).$noinline$g(); 165 } 166 167 /// CHECK-START: void Main.testForKeep(int) instruction_simplifier (before) 168 /// CHECK: CheckCast 169 170 /// CHECK-START: void Main.testForKeep(int) instruction_simplifier (after) 171 /// CHECK: CheckCast testForKeep(int x)172 public void testForKeep(int x) { 173 Super s = new SubclassA(); 174 for (int i = 0 ; i < x; i++) { 175 if (x % 2 == 0) { 176 s = new SubclassC(); 177 } 178 } 179 ((SubclassC)s).$noinline$g(); 180 } 181 182 /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (before) 183 /// CHECK: CheckCast 184 185 /// CHECK-START: void Main.testPhiFromCall(int) instruction_simplifier (after) 186 /// CHECK: CheckCast testPhiFromCall(int i)187 public void testPhiFromCall(int i) { 188 Object x; 189 if (i % 2 == 0) { 190 x = new SubclassC(); 191 } else { 192 x = newObject(); // this one will have an unknown type. 193 } 194 ((SubclassC)x).$noinline$g(); 195 } 196 197 /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (before) 198 /// CHECK: CheckCast 199 /// CHECK: CheckCast 200 /// CHECK-NOT: CheckCast 201 202 /// CHECK-START: void Main.testInstanceOf(java.lang.Object) instruction_simplifier (after) 203 /// CHECK-NOT: CheckCast testInstanceOf(Object o)204 public void testInstanceOf(Object o) { 205 if (o instanceof SubclassC) { 206 ((SubclassC)o).$noinline$g(); 207 } 208 if (o instanceof SubclassB) { 209 ((SubclassB)o).$noinline$g(); 210 } 211 } 212 $inline$InstanceofSubclassB(Object o)213 public static boolean $inline$InstanceofSubclassB(Object o) { return o instanceof SubclassB; } $inline$InstanceofSubclassC(Object o)214 public static boolean $inline$InstanceofSubclassC(Object o) { return o instanceof SubclassC; } 215 216 /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) builder (after) 217 /// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0 218 /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 219 /// CHECK-DAG: <<IOf1:z\d+>> InstanceOf 220 /// CHECK-DAG: NotEqual [<<IOf1>>,<<Cst1>>] 221 /// CHECK-DAG: <<IOf2:z\d+>> InstanceOf 222 /// CHECK-DAG: Equal [<<IOf2>>,<<Cst0>>] 223 224 /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before) 225 /// CHECK: CheckCast 226 /// CHECK: CheckCast 227 /// CHECK-NOT: CheckCast 228 229 /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after) 230 /// CHECK-NOT: CheckCast testInstanceOf_NotInlined(Object o)231 public void testInstanceOf_NotInlined(Object o) { 232 if ((o instanceof SubclassC) == true) { 233 ((SubclassC)o).$noinline$g(); 234 } 235 if ((o instanceof SubclassB) != false) { 236 ((SubclassB)o).$noinline$g(); 237 } 238 } 239 240 /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) builder (after) 241 /// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0 242 /// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1 243 /// CHECK-DAG: <<IOf1:z\d+>> InstanceOf 244 /// CHECK-DAG: Equal [<<IOf1>>,<<Cst1>>] 245 /// CHECK-DAG: <<IOf2:z\d+>> InstanceOf 246 /// CHECK-DAG: NotEqual [<<IOf2>>,<<Cst0>>] 247 248 /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (before) 249 /// CHECK: CheckCast 250 /// CHECK: CheckCast 251 /// CHECK-NOT: CheckCast 252 253 /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) instruction_simplifier (after) 254 /// CHECK-NOT: CheckCast testNotInstanceOf_NotInlined(Object o)255 public void testNotInstanceOf_NotInlined(Object o) { 256 if ((o instanceof SubclassC) != true) { 257 // Empty branch to flip the condition. 258 } else { 259 ((SubclassC)o).$noinline$g(); 260 } 261 if ((o instanceof SubclassB) == false) { 262 // Empty branch to flip the condition. 263 } else { 264 ((SubclassB)o).$noinline$g(); 265 } 266 } 267 268 /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) inliner (after) 269 /// CHECK-DAG: <<IOf:z\d+>> InstanceOf 270 /// CHECK-DAG: If [<<IOf>>] 271 272 /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (before) 273 /// CHECK: CheckCast 274 /// CHECK-NOT: CheckCast 275 276 /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (after) 277 /// CHECK-NOT: CheckCast testInstanceOf_Inlined(Object o)278 public void testInstanceOf_Inlined(Object o) { 279 if (!$inline$InstanceofSubclassC(o)) { 280 // Empty branch to flip the condition. 281 } else { 282 ((SubclassC)o).$noinline$g(); 283 } 284 } 285 286 /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (before) 287 /// CHECK: CheckCast 288 /// CHECK: CheckCast 289 290 /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (after) 291 /// CHECK: CheckCast 292 /// CHECK: CheckCast testInstanceOfKeep(Object o)293 public void testInstanceOfKeep(Object o) { 294 if (o instanceof SubclassC) { 295 ((SubclassB)o).$noinline$g(); 296 } 297 if (o instanceof SubclassB) { 298 ((SubclassA)o).$noinline$g(); 299 } 300 } 301 302 /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (before) 303 /// CHECK: CheckCast 304 /// CHECK: CheckCast 305 306 /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (after) 307 /// CHECK-NOT: CheckCast testInstanceOfNested(Object o)308 public void testInstanceOfNested(Object o) { 309 if (o instanceof SubclassC) { 310 if (o instanceof SubclassB) { 311 ((SubclassB)o).$noinline$g(); 312 } else { 313 ((SubclassC)o).$noinline$g(); 314 } 315 } 316 } 317 318 /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (before) 319 /// CHECK: CheckCast 320 321 /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (after) 322 /// CHECK-NOT: CheckCast testInstanceOfWithPhi(int i)323 public void testInstanceOfWithPhi(int i) { 324 Object o; 325 if (i == 0) { 326 o = new SubclassA(); 327 } else { 328 o = new SubclassB(); 329 } 330 331 if (o instanceof SubclassB) { 332 ((SubclassB)o).$noinline$g(); 333 } 334 } 335 336 /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (before) 337 /// CHECK: CheckCast 338 339 /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (after) 340 /// CHECK-NOT: CheckCast testInstanceOfInFor(int n)341 public void testInstanceOfInFor(int n) { 342 Object o = new SubclassA(); 343 for (int i = 0; i < n; i++) { 344 if (i / 2 == 0) { 345 o = new SubclassB(); 346 } 347 if (o instanceof SubclassB) { 348 ((SubclassB)o).$noinline$g(); 349 } 350 } 351 } 352 353 /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (before) 354 /// CHECK: CheckCast 355 356 /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (after) 357 /// CHECK-NOT: CheckCast testInstanceOfSubclass()358 public void testInstanceOfSubclass() { 359 Object o = new SubclassA(); 360 if (o instanceof Super) { 361 ((SubclassA)o).$noinline$g(); 362 } 363 } 364 365 /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (before) 366 /// CHECK: CheckCast 367 368 /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (after) 369 /// CHECK-NOT: CheckCast testInstanceOfWithPhiSubclass(int i)370 public void testInstanceOfWithPhiSubclass(int i) { 371 Object o; 372 if (i == 0) { 373 o = new SubclassA(); 374 } else { 375 o = new SubclassC(); 376 } 377 378 if (o instanceof Super) { 379 ((SubclassA)o).$noinline$g(); 380 } 381 } 382 383 /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (before) 384 /// CHECK: CheckCast 385 386 /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (after) 387 /// CHECK-NOT: CheckCast testInstanceOfWithPhiTop(int i)388 public void testInstanceOfWithPhiTop(int i) { 389 Object o; 390 if (i == 0) { 391 o = new Object(); 392 } else { 393 o = new SubclassC(); 394 } 395 396 if (o instanceof Super) { 397 ((Super)o).$noinline$f(); 398 } 399 } 400 401 /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (before) 402 /// CHECK: CheckCast 403 404 /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (after) 405 /// CHECK-NOT: CheckCast testInstanceOfSubclassInFor(int n)406 public void testInstanceOfSubclassInFor(int n) { 407 Object o = new SubclassA(); 408 for (int i = 0; i < n; i++) { 409 if (o instanceof Super) { 410 ((SubclassA)o).$noinline$g(); 411 } 412 if (i / 2 == 0) { 413 o = new SubclassC(); 414 } 415 } 416 } 417 418 /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (before) 419 /// CHECK: CheckCast 420 421 /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (after) 422 /// CHECK-NOT: CheckCast testInstanceOfTopInFor(int n)423 public void testInstanceOfTopInFor(int n) { 424 Object o = new SubclassA(); 425 for (int i = 0; i < n; i++) { 426 if (o instanceof Super) { 427 ((Super)o).$noinline$f(); 428 } 429 if (i / 2 == 0) { 430 o = new Object(); 431 } 432 } 433 } 434 newObject()435 public Object newObject() { 436 try { 437 return Object.class.newInstance(); 438 } catch (Exception e) { 439 return null; 440 } 441 } 442 443 public SubclassA a = new SubclassA(); 444 public static SubclassA b = new SubclassA(); 445 446 /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (before) 447 /// CHECK: CheckCast 448 449 /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (after) 450 /// CHECK-NOT: CheckCast testInstanceFieldGetSimpleRemove()451 public void testInstanceFieldGetSimpleRemove() { 452 Main m = new Main(); 453 Super a = m.a; 454 ((SubclassA)a).$noinline$g(); 455 } 456 457 /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (before) 458 /// CHECK: CheckCast 459 460 /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (after) 461 /// CHECK-NOT: CheckCast testStaticFieldGetSimpleRemove()462 public void testStaticFieldGetSimpleRemove() { 463 Super b = Main.b; 464 ((SubclassA)b).$noinline$g(); 465 } 466 $noinline$getSubclass()467 public SubclassA $noinline$getSubclass() { throw new RuntimeException(); } 468 469 /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (before) 470 /// CHECK: CheckCast 471 472 /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (after) 473 /// CHECK-NOT: CheckCast testArraySimpleRemove()474 public void testArraySimpleRemove() { 475 Super[] b = new SubclassA[10]; 476 SubclassA[] c = (SubclassA[])b; 477 } 478 479 /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (before) 480 /// CHECK: CheckCast 481 482 /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (after) 483 /// CHECK-NOT: CheckCast testInvokeSimpleRemove()484 public void testInvokeSimpleRemove() { 485 Super b = $noinline$getSubclass(); 486 ((SubclassA)b).$noinline$g(); 487 } 488 /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (before) 489 /// CHECK: CheckCast 490 491 /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (after) 492 /// CHECK-NOT: CheckCast testArrayGetSimpleRemove()493 public void testArrayGetSimpleRemove() { 494 Super[] a = new SubclassA[10]; 495 ((SubclassA)a[0]).$noinline$g(); 496 } 497 498 /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after) 499 /// CHECK: LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false testLoadExceptionInCatchNonExact(int x, int y)500 public int testLoadExceptionInCatchNonExact(int x, int y) { 501 try { 502 return x / y; 503 } catch (ArithmeticException ex) { 504 return ex.hashCode(); 505 } 506 } 507 508 /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after) 509 /// CHECK: LoadException klass:FinalException can_be_null:false exact:true testLoadExceptionInCatchExact(int x)510 public int testLoadExceptionInCatchExact(int x) { 511 try { 512 if (x == 42) { 513 throw new FinalException(); 514 } else { 515 return x; 516 } 517 } catch (FinalException ex) { 518 return ex.hashCode(); 519 } 520 } 521 522 /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after) 523 /// CHECK: LoadException klass:java.lang.Throwable can_be_null:false exact:false testLoadExceptionInCatchAll(int x, int y)524 public int testLoadExceptionInCatchAll(int x, int y) { 525 try { 526 x = x / y; 527 } finally { 528 return x; 529 } 530 } 531 532 private Generic<SubclassC> genericC = new Generic<SubclassC>(); 533 private Generic<Final> genericFinal = new Generic<Final>(); 534 get()535 private SubclassC get() { 536 return genericC.get(); 537 } 538 getFinal()539 private Final getFinal() { 540 return genericFinal.get(); 541 } 542 543 /// CHECK-START: SubclassC Main.inlineGenerics() builder (after) 544 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SubclassC exact:false 545 /// CHECK-NEXT: Return [<<Invoke>>] 546 547 /// CHECK-START: SubclassC Main.inlineGenerics() inliner (after) 548 /// CHECK: <<BoundType:l\d+>> BoundType klass:SubclassC exact:false 549 /// CHECK: Return [<<BoundType>>] inlineGenerics()550 private SubclassC inlineGenerics() { 551 SubclassC c = get(); 552 return c; 553 } 554 555 /// CHECK-START: Final Main.inlineGenericsFinal() builder (after) 556 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Final exact:true 557 /// CHECK-NEXT: Return [<<Invoke>>] 558 559 /// CHECK-START: Final Main.inlineGenericsFinal() inliner (after) 560 /// CHECK: <<BoundType:l\d+>> BoundType klass:Final exact:true 561 /// CHECK: Return [<<BoundType>>] inlineGenericsFinal()562 private Final inlineGenericsFinal() { 563 Final f = getFinal(); 564 return f; 565 } 566 567 /// CHECK-START: void Main.boundOnlyOnceIfNotNull(java.lang.Object) inliner (after) 568 /// CHECK: BoundType 569 /// CHECK-NOT: BoundType boundOnlyOnceIfNotNull(Object o)570 private void boundOnlyOnceIfNotNull(Object o) { 571 if (o != null) { 572 o.toString(); 573 } 574 } 575 576 /// CHECK-START: void Main.boundOnlyOnceIfInstanceOf(java.lang.Object) inliner (after) 577 /// CHECK: BoundType 578 /// CHECK-NOT: BoundType boundOnlyOnceIfInstanceOf(Object o)579 private void boundOnlyOnceIfInstanceOf(Object o) { 580 if (o instanceof Main) { 581 o.toString(); 582 } 583 } 584 585 /// CHECK-START: Final Main.boundOnlyOnceCheckCast(Generic) inliner (after) 586 /// CHECK: BoundType 587 /// CHECK-NOT: BoundType boundOnlyOnceCheckCast(Generic<Final> o)588 private Final boundOnlyOnceCheckCast(Generic<Final> o) { 589 Final f = o.get(); 590 return f; 591 } 592 getSuper()593 private Super getSuper() { 594 return new SubclassA(); 595 } 596 597 /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after) 598 /// CHECK: <<Phi:l\d+>> Phi klass:Super 599 /// CHECK: NullCheck [<<Phi>>] klass:Super 600 601 /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) inliner (after) 602 /// CHECK: <<Phi:l\d+>> Phi klass:SubclassA 603 /// CHECK: NullCheck [<<Phi>>] klass:SubclassA updateNodesInTheSameBlockAsPhi(boolean cond)604 private void updateNodesInTheSameBlockAsPhi(boolean cond) { 605 Super s = getSuper(); 606 if (cond) { 607 s = new SubclassA(); 608 } 609 s.$noinline$f(); 610 } 611 612 /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) inliner (after) 613 /// CHECK: <<This:l\d+>> ParameterValue 614 /// CHECK: <<Param:l\d+>> ParameterValue 615 /// CHECK: <<Clazz:l\d+>> LoadClass 616 /// CHECK: CheckCast [<<Param>>,<<Clazz>>] 617 /// CHECK: BoundType [<<Param>>] can_be_null:true 618 619 /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) instruction_simplifier (after) 620 /// CHECK: <<This:l\d+>> ParameterValue 621 /// CHECK: <<Param:l\d+>> ParameterValue 622 /// CHECK: <<Clazz:l\d+>> LoadClass 623 /// CHECK: CheckCast [<<Param>>,<<Clazz>>] 624 /// CHECK: <<Bound:l\d+>> BoundType [<<Param>>] 625 /// CHECK: NullCheck [<<Bound>>] checkcastPreserveNullCheck(Object a)626 public String checkcastPreserveNullCheck(Object a) { 627 return ((SubclassA)a).toString(); 628 } 629 630 631 /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after) 632 /// CHECK: ParameterValue klass:Main can_be_null:false exact:false 633 /// CHECK: ParameterValue klass:Super can_be_null:true exact:false 634 /// CHECK: ParameterValue 635 /// CHECK: ParameterValue klass:SubclassA can_be_null:true exact:false 636 /// CHECK: ParameterValue klass:Final can_be_null:true exact:true 637 /// CHECK-NOT: ParameterValue argumentCheck(Super s, double d, SubclassA a, Final f)638 private void argumentCheck(Super s, double d, SubclassA a, Final f) { 639 } 640 getNull()641 private Main getNull() { 642 return null; 643 } 644 645 private int mainField = 0; 646 647 /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after) 648 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object 649 /// CHECK: Return [<<Phi>>] getWiderType(boolean cond, Interface a, OtherInterface b)650 private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) { 651 return cond ? a : b; 652 } 653 654 /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (before) 655 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SuperInterface 656 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:SuperInterface exact:false 657 /// CHECK: InvokeInterface [<<NullCheck>>] 658 659 /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (after) 660 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object 661 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:SuperInterface exact:false 662 /// CHECK: InvokeInterface [<<NullCheck>>] testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b)663 private void testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b) { 664 getWiderType(cond, a, b).superInterfaceMethod(); 665 } 666 667 /// CHECK-START: void Main.testInlinerReturnsNull() inliner (before) 668 /// CHECK: <<Int:i\d+>> IntConstant 0 669 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Main 670 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Main exact:false 671 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] 672 673 /// CHECK-START: void Main.testInlinerReturnsNull() inliner (after) 674 /// CHECK: <<Int:i\d+>> IntConstant 0 675 /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object 676 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Null>>] klass:Main exact:false 677 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] testInlinerReturnsNull()678 private void testInlinerReturnsNull() { 679 Main o = getNull(); 680 o.mainField = 0; 681 } 682 683 /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before) 684 /// CHECK-DAG: <<Arg:l\d+>> NewInstance 685 /// CHECK-DAG: InvokeVirtual [<<Arg>>,{{z\d+}}] method_name:Super.$inline$h 686 687 /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after) 688 /// CHECK-DAG: <<Arg:l\d+>> NewInstance 689 /// CHECK-DAG: <<Null:l\d+>> NullConstant 690 /// CHECK-DAG: <<Phi:l\d+>> Phi [<<Arg>>,<<Null>>] klass:SubclassA 691 /// CHECK-DAG: <<NCPhi:l\d+>> NullCheck [<<Phi>>] 692 /// CHECK-DAG: InvokeVirtual [<<NCPhi>>] method_name:Super.$noinline$hashCode 693 testThisArgumentMoreSpecific(boolean cond)694 public void testThisArgumentMoreSpecific(boolean cond) { 695 // Inlining method from Super will build it with `this` typed as Super. 696 // Running RTP will sharpen it to SubclassA. 697 SubclassA obj = new SubclassA(); 698 ((Super) obj).$inline$h(cond); 699 } 700 $inline$hashCode(Super obj)701 public static int $inline$hashCode(Super obj) { 702 return obj.hashCode(); 703 } 704 705 /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before) 706 /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA 707 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 708 /// CHECK-DAG: InvokeStaticOrDirect [<<Arg>>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode 709 710 /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after) 711 /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA 712 /// CHECK-DAG: <<NCArg:l\d+>> NullCheck [<<Arg>>] klass:SubclassA 713 /// CHECK-DAG: InvokeVirtual [<<NCArg>>] method_name:java.lang.Object.hashCode 714 testExplicitArgumentMoreSpecific(SubclassA obj)715 public static void testExplicitArgumentMoreSpecific(SubclassA obj) { 716 // Inlining a method will build it with reference types from its signature, 717 // here the callee graph is built with Super as the type of its only argument. 718 // Running RTP after its ParameterValue instructions are replaced with actual 719 // arguments will type the inner graph more precisely. 720 $inline$hashCode(obj); 721 } 722 723 /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before) 724 /// CHECK: <<Int:i\d+>> IntConstant 0 725 /// CHECK: <<Phi:l\d+>> Phi klass:Main exact:false 726 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false 727 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] 728 729 /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after) 730 /// CHECK: <<Int:i\d+>> IntConstant 0 731 /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object 732 /// CHECK: <<Phi:l\d+>> Phi [<<Null>>,<<Null>>] klass:java.lang.Object exact:false 733 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:java.lang.Object exact:false 734 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] testPhiHasOnlyNullInputs(boolean cond)735 private void testPhiHasOnlyNullInputs(boolean cond) { 736 Main o = cond ? null : getNull(); 737 o.mainField = 0; 738 // getSuper() will force a type propagation after inlining 739 // because returns a more precise type. 740 getSuper(); 741 } 742 743 /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after) 744 /// CHECK-DAG: <<Null:l\d+>> NullConstant 745 /// CHECK-DAG: <<Main:l\d+>> NewInstance klass:Main exact:true 746 /// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<LoopPhi>>,<<Main>>] klass:Main exact:true testLoopPhiWithNullFirstInput(boolean cond)747 private void testLoopPhiWithNullFirstInput(boolean cond) { 748 Main a = null; 749 while (a == null) { 750 if (cond) { 751 a = new Main(); 752 } 753 } 754 } 755 756 /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after) 757 /// CHECK-DAG: <<Null:l\d+>> NullConstant 758 /// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<Phi:l\d+>>] klass:java.lang.Object[] exact:true 759 /// CHECK-DAG: <<Array:l\d+>> NewArray klass:java.lang.Object[] exact:true 760 /// CHECK-DAG: <<Phi>> Phi [<<Array>>,<<LoopPhi>>] klass:java.lang.Object[] exact:true 761 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<LoopPhi>>] klass:java.lang.Object[] exact:true 762 /// CHECK-DAG: ArrayGet [<<NC>>,{{i\d+}}] klass:java.lang.Object exact:false testInstructionsWithUntypedParent()763 private Object[] testInstructionsWithUntypedParent() { 764 Object[] array = null; 765 boolean cond = true; 766 for (int i = 0; i < 10; ++i) { 767 if (cond) { 768 array = new Object[10]; 769 array[0] = new Object(); 770 cond = false; 771 } else { 772 array[i] = array[0]; 773 } 774 } 775 return array; 776 } 777 main(String[] args)778 public static void main(String[] args) { 779 } 780 } 781