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