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.testInvokeSimpleRemove() instruction_simplifier (before) 467 /// CHECK: CheckCast 468 469 /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (after) 470 /// CHECK-NOT: CheckCast testInvokeSimpleRemove()471 public void testInvokeSimpleRemove() { 472 Super b = $noinline$getSubclass(); 473 ((SubclassA)b).$noinline$g(); 474 } 475 /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (before) 476 /// CHECK: CheckCast 477 478 /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (after) 479 /// CHECK-NOT: CheckCast testArrayGetSimpleRemove()480 public void testArrayGetSimpleRemove() { 481 Super[] a = new SubclassA[10]; 482 ((SubclassA)a[0]).$noinline$g(); 483 } 484 485 /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after) 486 /// CHECK: LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false testLoadExceptionInCatchNonExact(int x, int y)487 public int testLoadExceptionInCatchNonExact(int x, int y) { 488 try { 489 return x / y; 490 } catch (ArithmeticException ex) { 491 return ex.hashCode(); 492 } 493 } 494 495 /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after) 496 /// CHECK: LoadException klass:FinalException can_be_null:false exact:true testLoadExceptionInCatchExact(int x)497 public int testLoadExceptionInCatchExact(int x) { 498 try { 499 if (x == 42) { 500 throw new FinalException(); 501 } else { 502 return x; 503 } 504 } catch (FinalException ex) { 505 return ex.hashCode(); 506 } 507 } 508 509 /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after) 510 /// CHECK: LoadException klass:java.lang.Throwable can_be_null:false exact:false testLoadExceptionInCatchAll(int x, int y)511 public int testLoadExceptionInCatchAll(int x, int y) { 512 try { 513 x = x / y; 514 } finally { 515 return x; 516 } 517 } 518 519 private Generic<SubclassC> genericC = new Generic<SubclassC>(); 520 private Generic<Final> genericFinal = new Generic<Final>(); 521 get()522 private SubclassC get() { 523 return genericC.get(); 524 } 525 getFinal()526 private Final getFinal() { 527 return genericFinal.get(); 528 } 529 530 /// CHECK-START: SubclassC Main.inlineGenerics() builder (after) 531 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SubclassC exact:false 532 /// CHECK-NEXT: Return [<<Invoke>>] 533 534 /// CHECK-START: SubclassC Main.inlineGenerics() inliner (after) 535 /// CHECK: <<BoundType:l\d+>> BoundType klass:SubclassC exact:false 536 /// CHECK: Return [<<BoundType>>] inlineGenerics()537 private SubclassC inlineGenerics() { 538 SubclassC c = get(); 539 return c; 540 } 541 542 /// CHECK-START: Final Main.inlineGenericsFinal() builder (after) 543 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Final exact:true 544 /// CHECK-NEXT: Return [<<Invoke>>] 545 546 /// CHECK-START: Final Main.inlineGenericsFinal() inliner (after) 547 /// CHECK: <<BoundType:l\d+>> BoundType klass:Final exact:true 548 /// CHECK: Return [<<BoundType>>] inlineGenericsFinal()549 private Final inlineGenericsFinal() { 550 Final f = getFinal(); 551 return f; 552 } 553 554 /// CHECK-START: void Main.boundOnlyOnceIfNotNull(java.lang.Object) inliner (after) 555 /// CHECK: BoundType 556 /// CHECK-NOT: BoundType boundOnlyOnceIfNotNull(Object o)557 private void boundOnlyOnceIfNotNull(Object o) { 558 if (o != null) { 559 o.toString(); 560 } 561 } 562 563 /// CHECK-START: void Main.boundOnlyOnceIfInstanceOf(java.lang.Object) inliner (after) 564 /// CHECK: BoundType 565 /// CHECK-NOT: BoundType boundOnlyOnceIfInstanceOf(Object o)566 private void boundOnlyOnceIfInstanceOf(Object o) { 567 if (o instanceof Main) { 568 o.toString(); 569 } 570 } 571 572 /// CHECK-START: Final Main.boundOnlyOnceCheckCast(Generic) inliner (after) 573 /// CHECK: BoundType 574 /// CHECK-NOT: BoundType boundOnlyOnceCheckCast(Generic<Final> o)575 private Final boundOnlyOnceCheckCast(Generic<Final> o) { 576 Final f = o.get(); 577 return f; 578 } 579 getSuper()580 private Super getSuper() { 581 return new SubclassA(); 582 } 583 584 /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after) 585 /// CHECK: <<Phi:l\d+>> Phi klass:Super 586 /// CHECK: NullCheck [<<Phi>>] klass:Super 587 588 /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) inliner (after) 589 /// CHECK: <<Phi:l\d+>> Phi klass:SubclassA 590 /// CHECK: NullCheck [<<Phi>>] klass:SubclassA updateNodesInTheSameBlockAsPhi(boolean cond)591 private void updateNodesInTheSameBlockAsPhi(boolean cond) { 592 Super s = getSuper(); 593 if (cond) { 594 s = new SubclassA(); 595 } 596 s.$noinline$f(); 597 } 598 599 /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) inliner (after) 600 /// CHECK: <<This:l\d+>> ParameterValue 601 /// CHECK: <<Param:l\d+>> ParameterValue 602 /// CHECK: <<Clazz:l\d+>> LoadClass 603 /// CHECK: CheckCast [<<Param>>,<<Clazz>>] 604 /// CHECK: BoundType [<<Param>>] can_be_null:true 605 606 /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) instruction_simplifier (after) 607 /// CHECK: <<This:l\d+>> ParameterValue 608 /// CHECK: <<Param:l\d+>> ParameterValue 609 /// CHECK: <<Clazz:l\d+>> LoadClass 610 /// CHECK: CheckCast [<<Param>>,<<Clazz>>] 611 /// CHECK: <<Bound:l\d+>> BoundType [<<Param>>] 612 /// CHECK: NullCheck [<<Bound>>] checkcastPreserveNullCheck(Object a)613 public String checkcastPreserveNullCheck(Object a) { 614 return ((SubclassA)a).toString(); 615 } 616 617 618 /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after) 619 /// CHECK: ParameterValue klass:Main can_be_null:false exact:false 620 /// CHECK: ParameterValue klass:Super can_be_null:true exact:false 621 /// CHECK: ParameterValue 622 /// CHECK: ParameterValue klass:SubclassA can_be_null:true exact:false 623 /// CHECK: ParameterValue klass:Final can_be_null:true exact:true 624 /// CHECK-NOT: ParameterValue argumentCheck(Super s, double d, SubclassA a, Final f)625 private void argumentCheck(Super s, double d, SubclassA a, Final f) { 626 } 627 getNull()628 private Main getNull() { 629 return null; 630 } 631 632 private int mainField = 0; 633 634 /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after) 635 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object 636 /// CHECK: Return [<<Phi>>] getWiderType(boolean cond, Interface a, OtherInterface b)637 private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) { 638 return cond ? a : b; 639 } 640 641 /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (before) 642 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SuperInterface 643 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:SuperInterface exact:false 644 /// CHECK: InvokeInterface [<<NullCheck>>] 645 646 /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (after) 647 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object 648 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:SuperInterface exact:false 649 /// CHECK: InvokeInterface [<<NullCheck>>] testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b)650 private void testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b) { 651 getWiderType(cond, a, b).superInterfaceMethod(); 652 } 653 654 /// CHECK-START: void Main.testInlinerReturnsNull() inliner (before) 655 /// CHECK: <<Int:i\d+>> IntConstant 0 656 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Main 657 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Main exact:false 658 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] 659 660 /// CHECK-START: void Main.testInlinerReturnsNull() inliner (after) 661 /// CHECK: <<Int:i\d+>> IntConstant 0 662 /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object 663 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Null>>] klass:Main exact:false 664 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] testInlinerReturnsNull()665 private void testInlinerReturnsNull() { 666 Main o = getNull(); 667 o.mainField = 0; 668 } 669 670 /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before) 671 /// CHECK-DAG: <<Arg:l\d+>> NewInstance 672 /// CHECK-DAG: InvokeVirtual [<<Arg>>,{{z\d+}}] method_name:Super.$inline$h 673 674 /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after) 675 /// CHECK-DAG: <<Arg:l\d+>> NewInstance 676 /// CHECK-DAG: <<Null:l\d+>> NullConstant 677 /// CHECK-DAG: <<Phi:l\d+>> Phi [<<Arg>>,<<Null>>] klass:SubclassA 678 /// CHECK-DAG: <<NCPhi:l\d+>> NullCheck [<<Phi>>] 679 /// CHECK-DAG: InvokeVirtual [<<NCPhi>>] method_name:java.lang.Object.hashCode 680 testThisArgumentMoreSpecific(boolean cond)681 public void testThisArgumentMoreSpecific(boolean cond) { 682 // Inlining method from Super will build it with `this` typed as Super. 683 // Running RTP will sharpen it to SubclassA. 684 SubclassA obj = new SubclassA(); 685 ((Super) obj).$inline$h(cond); 686 } 687 $inline$hashCode(Super obj)688 public static int $inline$hashCode(Super obj) { 689 return obj.hashCode(); 690 } 691 692 /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before) 693 /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA 694 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 695 /// CHECK-DAG: InvokeStaticOrDirect [<<Arg>>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode 696 697 /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after) 698 /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA 699 /// CHECK-DAG: <<NCArg:l\d+>> NullCheck [<<Arg>>] klass:SubclassA 700 /// CHECK-DAG: InvokeVirtual [<<NCArg>>] method_name:java.lang.Object.hashCode 701 testExplicitArgumentMoreSpecific(SubclassA obj)702 public static void testExplicitArgumentMoreSpecific(SubclassA obj) { 703 // Inlining a method will build it with reference types from its signature, 704 // here the callee graph is built with Super as the type of its only argument. 705 // Running RTP after its ParameterValue instructions are replaced with actual 706 // arguments will type the inner graph more precisely. 707 $inline$hashCode(obj); 708 } 709 710 /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before) 711 /// CHECK: <<Int:i\d+>> IntConstant 0 712 /// CHECK: <<Phi:l\d+>> Phi klass:Main exact:false 713 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false 714 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] 715 716 /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after) 717 /// CHECK: <<Int:i\d+>> IntConstant 0 718 /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object 719 /// CHECK: <<Phi:l\d+>> Phi [<<Null>>,<<Null>>] klass:java.lang.Object exact:false 720 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:java.lang.Object exact:false 721 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] testPhiHasOnlyNullInputs(boolean cond)722 private void testPhiHasOnlyNullInputs(boolean cond) { 723 Main o = cond ? null : getNull(); 724 o.mainField = 0; 725 // getSuper() will force a type propagation after inlining 726 // because returns a more precise type. 727 getSuper(); 728 } 729 730 /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after) 731 /// CHECK-DAG: <<Null:l\d+>> NullConstant 732 /// CHECK-DAG: <<Main:l\d+>> NewInstance klass:Main exact:true 733 /// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<LoopPhi>>,<<Main>>] klass:Main exact:true testLoopPhiWithNullFirstInput(boolean cond)734 private void testLoopPhiWithNullFirstInput(boolean cond) { 735 Main a = null; 736 while (a == null) { 737 if (cond) { 738 a = new Main(); 739 } 740 } 741 } 742 743 /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after) 744 /// CHECK-DAG: <<Null:l\d+>> NullConstant 745 /// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<Phi:l\d+>>] klass:java.lang.Object[] exact:true 746 /// CHECK-DAG: <<Array:l\d+>> NewArray klass:java.lang.Object[] exact:true 747 /// CHECK-DAG: <<Phi>> Phi [<<Array>>,<<LoopPhi>>] klass:java.lang.Object[] exact:true 748 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<LoopPhi>>] klass:java.lang.Object[] exact:true 749 /// CHECK-DAG: ArrayGet [<<NC>>,{{i\d+}}] klass:java.lang.Object exact:false testInstructionsWithUntypedParent()750 private Object[] testInstructionsWithUntypedParent() { 751 Object[] array = null; 752 boolean cond = true; 753 for (int i = 0; i < 10; ++i) { 754 if (cond) { 755 array = new Object[10]; 756 array[0] = new Object(); 757 cond = false; 758 } else { 759 array[i] = array[0]; 760 } 761 } 762 return array; 763 } 764 main(String[] args)765 public static void main(String[] args) { 766 } 767 } 768