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_Inlined(java.lang.Object) inliner (after) 214 /// CHECK-DAG: <<IOf:z\d+>> InstanceOf 215 /// CHECK-DAG: If [<<IOf>>] 216 217 /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (before) 218 /// CHECK: CheckCast 219 /// CHECK-NOT: CheckCast 220 221 /// CHECK-START: void Main.testInstanceOf_Inlined(java.lang.Object) instruction_simplifier$after_inlining (after) 222 /// CHECK-NOT: CheckCast testInstanceOf_Inlined(Object o)223 public void testInstanceOf_Inlined(Object o) { 224 if (!$inline$InstanceofSubclassC(o)) { 225 // Empty branch to flip the condition. 226 } else { 227 ((SubclassC)o).$noinline$g(); 228 } 229 } 230 231 /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (before) 232 /// CHECK: CheckCast 233 /// CHECK: CheckCast 234 235 /// CHECK-START: void Main.testInstanceOfKeep(java.lang.Object) instruction_simplifier (after) 236 /// CHECK: CheckCast 237 /// CHECK: CheckCast testInstanceOfKeep(Object o)238 public void testInstanceOfKeep(Object o) { 239 if (o instanceof SubclassC) { 240 ((SubclassB)o).$noinline$g(); 241 } 242 if (o instanceof SubclassB) { 243 ((SubclassA)o).$noinline$g(); 244 } 245 } 246 247 /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (before) 248 /// CHECK: CheckCast 249 /// CHECK: CheckCast 250 251 /// CHECK-START: void Main.testInstanceOfNested(java.lang.Object) instruction_simplifier (after) 252 /// CHECK-NOT: CheckCast testInstanceOfNested(Object o)253 public void testInstanceOfNested(Object o) { 254 if (o instanceof SubclassC) { 255 if (o instanceof SubclassB) { 256 ((SubclassB)o).$noinline$g(); 257 } else { 258 ((SubclassC)o).$noinline$g(); 259 } 260 } 261 } 262 263 /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (before) 264 /// CHECK: CheckCast 265 266 /// CHECK-START: void Main.testInstanceOfWithPhi(int) instruction_simplifier (after) 267 /// CHECK-NOT: CheckCast testInstanceOfWithPhi(int i)268 public void testInstanceOfWithPhi(int i) { 269 Object o; 270 if (i == 0) { 271 o = new SubclassA(); 272 } else { 273 o = new SubclassB(); 274 } 275 276 if (o instanceof SubclassB) { 277 ((SubclassB)o).$noinline$g(); 278 } 279 } 280 281 /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (before) 282 /// CHECK: CheckCast 283 284 /// CHECK-START: void Main.testInstanceOfInFor(int) instruction_simplifier (after) 285 /// CHECK-NOT: CheckCast testInstanceOfInFor(int n)286 public void testInstanceOfInFor(int n) { 287 Object o = new SubclassA(); 288 for (int i = 0; i < n; i++) { 289 if (i / 2 == 0) { 290 o = new SubclassB(); 291 } 292 if (o instanceof SubclassB) { 293 ((SubclassB)o).$noinline$g(); 294 } 295 } 296 } 297 298 /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (before) 299 /// CHECK: CheckCast 300 301 /// CHECK-START: void Main.testInstanceOfSubclass() instruction_simplifier (after) 302 /// CHECK-NOT: CheckCast testInstanceOfSubclass()303 public void testInstanceOfSubclass() { 304 Object o = new SubclassA(); 305 if (o instanceof Super) { 306 ((SubclassA)o).$noinline$g(); 307 } 308 } 309 310 /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (before) 311 /// CHECK: CheckCast 312 313 /// CHECK-START: void Main.testInstanceOfWithPhiSubclass(int) instruction_simplifier (after) 314 /// CHECK-NOT: CheckCast testInstanceOfWithPhiSubclass(int i)315 public void testInstanceOfWithPhiSubclass(int i) { 316 Object o; 317 if (i == 0) { 318 o = new SubclassA(); 319 } else { 320 o = new SubclassC(); 321 } 322 323 if (o instanceof Super) { 324 ((SubclassA)o).$noinline$g(); 325 } 326 } 327 328 /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (before) 329 /// CHECK: CheckCast 330 331 /// CHECK-START: void Main.testInstanceOfWithPhiTop(int) instruction_simplifier (after) 332 /// CHECK-NOT: CheckCast testInstanceOfWithPhiTop(int i)333 public void testInstanceOfWithPhiTop(int i) { 334 Object o; 335 if (i == 0) { 336 o = new Object(); 337 } else { 338 o = new SubclassC(); 339 } 340 341 if (o instanceof Super) { 342 ((Super)o).$noinline$f(); 343 } 344 } 345 346 /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (before) 347 /// CHECK: CheckCast 348 349 /// CHECK-START: void Main.testInstanceOfSubclassInFor(int) instruction_simplifier (after) 350 /// CHECK-NOT: CheckCast testInstanceOfSubclassInFor(int n)351 public void testInstanceOfSubclassInFor(int n) { 352 Object o = new SubclassA(); 353 for (int i = 0; i < n; i++) { 354 if (o instanceof Super) { 355 ((SubclassA)o).$noinline$g(); 356 } 357 if (i / 2 == 0) { 358 o = new SubclassC(); 359 } 360 } 361 } 362 363 /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (before) 364 /// CHECK: CheckCast 365 366 /// CHECK-START: void Main.testInstanceOfTopInFor(int) instruction_simplifier (after) 367 /// CHECK-NOT: CheckCast testInstanceOfTopInFor(int n)368 public void testInstanceOfTopInFor(int n) { 369 Object o = new SubclassA(); 370 for (int i = 0; i < n; i++) { 371 if (o instanceof Super) { 372 ((Super)o).$noinline$f(); 373 } 374 if (i / 2 == 0) { 375 o = new Object(); 376 } 377 } 378 } 379 newObject()380 public Object newObject() { 381 try { 382 return Object.class.newInstance(); 383 } catch (Exception e) { 384 return null; 385 } 386 } 387 388 public SubclassA a = new SubclassA(); 389 public static SubclassA b = new SubclassA(); 390 391 /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (before) 392 /// CHECK: CheckCast 393 394 /// CHECK-START: void Main.testInstanceFieldGetSimpleRemove() instruction_simplifier (after) 395 /// CHECK-NOT: CheckCast testInstanceFieldGetSimpleRemove()396 public void testInstanceFieldGetSimpleRemove() { 397 Main m = new Main(); 398 Super a = m.a; 399 ((SubclassA)a).$noinline$g(); 400 } 401 402 /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (before) 403 /// CHECK: CheckCast 404 405 /// CHECK-START: void Main.testStaticFieldGetSimpleRemove() instruction_simplifier (after) 406 /// CHECK-NOT: CheckCast testStaticFieldGetSimpleRemove()407 public void testStaticFieldGetSimpleRemove() { 408 Super b = Main.b; 409 ((SubclassA)b).$noinline$g(); 410 } 411 $noinline$getSubclass()412 public SubclassA $noinline$getSubclass() { throw new RuntimeException(); } 413 414 /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (before) 415 /// CHECK: CheckCast 416 417 /// CHECK-START: void Main.testArraySimpleRemove() instruction_simplifier (after) 418 /// CHECK-NOT: CheckCast testArraySimpleRemove()419 public void testArraySimpleRemove() { 420 Super[] b = new SubclassA[10]; 421 SubclassA[] c = (SubclassA[])b; 422 } 423 424 /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (before) 425 /// CHECK: CheckCast 426 427 /// CHECK-START: void Main.testInvokeSimpleRemove() instruction_simplifier (after) 428 /// CHECK-NOT: CheckCast testInvokeSimpleRemove()429 public void testInvokeSimpleRemove() { 430 Super b = $noinline$getSubclass(); 431 ((SubclassA)b).$noinline$g(); 432 } 433 /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (before) 434 /// CHECK: CheckCast 435 436 /// CHECK-START: void Main.testArrayGetSimpleRemove() instruction_simplifier (after) 437 /// CHECK-NOT: CheckCast testArrayGetSimpleRemove()438 public void testArrayGetSimpleRemove() { 439 Super[] a = new SubclassA[10]; 440 ((SubclassA)a[0]).$noinline$g(); 441 } 442 443 /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after) 444 /// CHECK: LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false testLoadExceptionInCatchNonExact(int x, int y)445 public int testLoadExceptionInCatchNonExact(int x, int y) { 446 try { 447 return x / y; 448 } catch (ArithmeticException ex) { 449 return ex.hashCode(); 450 } 451 } 452 453 /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after) 454 /// CHECK: LoadException klass:FinalException can_be_null:false exact:true testLoadExceptionInCatchExact(int x)455 public int testLoadExceptionInCatchExact(int x) { 456 try { 457 if (x == 42) { 458 throw new FinalException(); 459 } else { 460 return x; 461 } 462 } catch (FinalException ex) { 463 return ex.hashCode(); 464 } 465 } 466 467 /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after) 468 /// CHECK: LoadException klass:java.lang.Throwable can_be_null:false exact:false testLoadExceptionInCatchAll(int x, int y)469 public int testLoadExceptionInCatchAll(int x, int y) { 470 try { 471 x = x / y; 472 } finally { 473 return x; 474 } 475 } 476 477 private Generic<SubclassC> genericC = new Generic<SubclassC>(); 478 private Generic<Final> genericFinal = new Generic<Final>(); 479 get()480 private SubclassC get() { 481 return genericC.get(); 482 } 483 getFinal()484 private Final getFinal() { 485 return genericFinal.get(); 486 } 487 488 /// CHECK-START: SubclassC Main.inlineGenerics() builder (after) 489 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SubclassC exact:false 490 /// CHECK-NEXT: Return [<<Invoke>>] 491 492 /// CHECK-START: SubclassC Main.inlineGenerics() inliner (after) 493 /// CHECK: <<BoundType:l\d+>> BoundType klass:SubclassC exact:false 494 /// CHECK: Return [<<BoundType>>] inlineGenerics()495 private SubclassC inlineGenerics() { 496 SubclassC c = get(); 497 return c; 498 } 499 500 /// CHECK-START: Final Main.inlineGenericsFinal() builder (after) 501 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Final exact:true 502 /// CHECK-NEXT: Return [<<Invoke>>] 503 504 /// CHECK-START: Final Main.inlineGenericsFinal() inliner (after) 505 /// CHECK: <<BoundType:l\d+>> BoundType klass:Final exact:true 506 /// CHECK: Return [<<BoundType>>] inlineGenericsFinal()507 private Final inlineGenericsFinal() { 508 Final f = getFinal(); 509 return f; 510 } 511 512 /// CHECK-START: void Main.boundOnlyOnceIfNotNull(java.lang.Object) inliner (after) 513 /// CHECK: BoundType 514 /// CHECK-NOT: BoundType boundOnlyOnceIfNotNull(Object o)515 private void boundOnlyOnceIfNotNull(Object o) { 516 if (o != null) { 517 o.toString(); 518 } 519 } 520 521 /// CHECK-START: void Main.boundOnlyOnceIfInstanceOf(java.lang.Object) inliner (after) 522 /// CHECK: BoundType 523 /// CHECK-NOT: BoundType boundOnlyOnceIfInstanceOf(Object o)524 private void boundOnlyOnceIfInstanceOf(Object o) { 525 if (o instanceof Main) { 526 o.toString(); 527 } 528 } 529 530 /// CHECK-START: Final Main.boundOnlyOnceCheckCast(Generic) inliner (after) 531 /// CHECK: BoundType 532 /// CHECK-NOT: BoundType boundOnlyOnceCheckCast(Generic<Final> o)533 private Final boundOnlyOnceCheckCast(Generic<Final> o) { 534 Final f = o.get(); 535 return f; 536 } 537 getSuper()538 private Super getSuper() { 539 return new SubclassA(); 540 } 541 542 /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after) 543 /// CHECK: <<Phi:l\d+>> Phi klass:Super 544 /// CHECK: NullCheck [<<Phi>>] klass:Super 545 546 /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) inliner (after) 547 /// CHECK: <<Phi:l\d+>> Phi klass:SubclassA 548 /// CHECK: NullCheck [<<Phi>>] klass:SubclassA updateNodesInTheSameBlockAsPhi(boolean cond)549 private void updateNodesInTheSameBlockAsPhi(boolean cond) { 550 Super s = getSuper(); 551 if (cond) { 552 s = new SubclassA(); 553 } 554 s.$noinline$f(); 555 } 556 557 /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) inliner (after) 558 /// CHECK: <<This:l\d+>> ParameterValue 559 /// CHECK: <<Param:l\d+>> ParameterValue 560 /// CHECK: <<Clazz:l\d+>> LoadClass 561 /// CHECK: CheckCast [<<Param>>,<<Clazz>>] 562 /// CHECK: BoundType [<<Param>>] can_be_null:true 563 564 /// CHECK-START: java.lang.String Main.checkcastPreserveNullCheck(java.lang.Object) instruction_simplifier (after) 565 /// CHECK: <<This:l\d+>> ParameterValue 566 /// CHECK: <<Param:l\d+>> ParameterValue 567 /// CHECK: <<Clazz:l\d+>> LoadClass 568 /// CHECK: CheckCast [<<Param>>,<<Clazz>>] 569 /// CHECK: <<Bound:l\d+>> BoundType [<<Param>>] 570 /// CHECK: NullCheck [<<Bound>>] checkcastPreserveNullCheck(Object a)571 public String checkcastPreserveNullCheck(Object a) { 572 return ((SubclassA)a).toString(); 573 } 574 575 576 /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after) 577 /// CHECK: ParameterValue klass:Main can_be_null:false exact:false 578 /// CHECK: ParameterValue klass:Super can_be_null:true exact:false 579 /// CHECK: ParameterValue 580 /// CHECK: ParameterValue klass:SubclassA can_be_null:true exact:false 581 /// CHECK: ParameterValue klass:Final can_be_null:true exact:true 582 /// CHECK-NOT: ParameterValue argumentCheck(Super s, double d, SubclassA a, Final f)583 private void argumentCheck(Super s, double d, SubclassA a, Final f) { 584 } 585 getNull()586 private Main getNull() { 587 return null; 588 } 589 590 private int mainField = 0; 591 592 /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after) 593 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object 594 /// CHECK: Return [<<Phi>>] getWiderType(boolean cond, Interface a, OtherInterface b)595 private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) { 596 return cond ? a : b; 597 } 598 599 /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (before) 600 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SuperInterface 601 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:SuperInterface exact:false 602 /// CHECK: InvokeInterface [<<NullCheck>>] 603 604 /// CHECK-START: void Main.testInlinerWidensReturnType(boolean, Interface, OtherInterface) inliner (after) 605 /// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object 606 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:SuperInterface exact:false 607 /// CHECK: InvokeInterface [<<NullCheck>>] testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b)608 private void testInlinerWidensReturnType(boolean cond, Interface a, OtherInterface b) { 609 getWiderType(cond, a, b).superInterfaceMethod(); 610 } 611 612 /// CHECK-START: void Main.testInlinerReturnsNull() inliner (before) 613 /// CHECK: <<Int:i\d+>> IntConstant 0 614 /// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Main 615 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Invoke>>] klass:Main exact:false 616 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] 617 618 /// CHECK-START: void Main.testInlinerReturnsNull() inliner (after) 619 /// CHECK: <<Int:i\d+>> IntConstant 0 620 /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object 621 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Null>>] klass:Main exact:false 622 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] testInlinerReturnsNull()623 private void testInlinerReturnsNull() { 624 Main o = getNull(); 625 o.mainField = 0; 626 } 627 628 /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (before) 629 /// CHECK-DAG: <<Arg:l\d+>> NewInstance 630 /// CHECK-DAG: InvokeVirtual [<<Arg>>,{{z\d+}}] method_name:Super.$inline$h 631 632 /// CHECK-START: void Main.testThisArgumentMoreSpecific(boolean) inliner (after) 633 /// CHECK-DAG: <<Arg:l\d+>> NewInstance 634 /// CHECK-DAG: <<Null:l\d+>> NullConstant 635 /// CHECK-DAG: <<Phi:l\d+>> Phi [<<Arg>>,<<Null>>] klass:SubclassA 636 /// CHECK-DAG: <<NCPhi:l\d+>> NullCheck [<<Phi>>] 637 /// CHECK-DAG: InvokeVirtual [<<NCPhi>>] method_name:Super.hashCode 638 testThisArgumentMoreSpecific(boolean cond)639 public void testThisArgumentMoreSpecific(boolean cond) { 640 // Inlining method from Super will build it with `this` typed as Super. 641 // Running RTP will sharpen it to SubclassA. 642 SubclassA obj = new SubclassA(); 643 ((Super) obj).$inline$h(cond); 644 } 645 $inline$hashCode(Super obj)646 public static int $inline$hashCode(Super obj) { 647 return obj.hashCode(); 648 } 649 650 /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (before) 651 /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA 652 // Note: The ArtMethod* (typed as int or long) is optional after sharpening. 653 /// CHECK-DAG: InvokeStaticOrDirect [<<Arg>>{{(,[ij]\d+)?}}] method_name:Main.$inline$hashCode 654 655 /// CHECK-START: void Main.testExplicitArgumentMoreSpecific(SubclassA) inliner (after) 656 /// CHECK-DAG: <<Arg:l\d+>> ParameterValue klass:SubclassA 657 /// CHECK-DAG: <<NCArg:l\d+>> NullCheck [<<Arg>>] klass:SubclassA 658 /// CHECK-DAG: InvokeVirtual [<<NCArg>>] method_name:Super.hashCode 659 testExplicitArgumentMoreSpecific(SubclassA obj)660 public void testExplicitArgumentMoreSpecific(SubclassA obj) { 661 // Inlining a method will build it with reference types from its signature, 662 // here the callee graph is built with Super as the type of its only argument. 663 // Running RTP after its ParameterValue instructions are replaced with actual 664 // arguments will type the inner graph more precisely. 665 $inline$hashCode(obj); 666 } 667 668 /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (before) 669 /// CHECK: <<Int:i\d+>> IntConstant 0 670 /// CHECK: <<Phi:l\d+>> Phi klass:Main exact:false 671 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:Main exact:false 672 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] 673 674 /// CHECK-START: void Main.testPhiHasOnlyNullInputs(boolean) inliner (after) 675 /// CHECK: <<Int:i\d+>> IntConstant 0 676 /// CHECK: <<Null:l\d+>> NullConstant klass:java.lang.Object 677 /// CHECK: <<Phi:l\d+>> Phi [<<Null>>,<<Null>>] klass:java.lang.Object exact:false 678 /// CHECK: <<NullCheck:l\d+>> NullCheck [<<Phi>>] klass:java.lang.Object exact:false 679 /// CHECK: InstanceFieldSet [<<NullCheck>>,<<Int>>] testPhiHasOnlyNullInputs(boolean cond)680 private void testPhiHasOnlyNullInputs(boolean cond) { 681 Main o = cond ? null : getNull(); 682 o.mainField = 0; 683 // getSuper() will force a type propagation after inlining 684 // because returns a more precise type. 685 getSuper(); 686 } 687 688 /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after) 689 /// CHECK-DAG: <<Null:l\d+>> NullConstant 690 /// CHECK-DAG: <<Main:l\d+>> NewInstance klass:Main exact:true 691 /// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<LoopPhi>>,<<Main>>] klass:Main exact:true testLoopPhiWithNullFirstInput(boolean cond)692 private void testLoopPhiWithNullFirstInput(boolean cond) { 693 Main a = null; 694 while (a == null) { 695 if (cond) { 696 a = new Main(); 697 } 698 } 699 } 700 701 /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after) 702 /// CHECK-DAG: <<Null:l\d+>> NullConstant 703 /// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<Phi:l\d+>>] klass:java.lang.Object[] exact:true 704 /// CHECK-DAG: <<Array:l\d+>> NewArray klass:java.lang.Object[] exact:true 705 /// CHECK-DAG: <<Phi>> Phi [<<Array>>,<<LoopPhi>>] klass:java.lang.Object[] exact:true 706 /// CHECK-DAG: <<NC:l\d+>> NullCheck [<<LoopPhi>>] klass:java.lang.Object[] exact:true 707 /// CHECK-DAG: ArrayGet [<<NC>>,{{i\d+}}] klass:java.lang.Object exact:false testInstructionsWithUntypedParent()708 private Object[] testInstructionsWithUntypedParent() { 709 Object[] array = null; 710 boolean cond = true; 711 for (int i = 0; i < 10; ++i) { 712 if (cond) { 713 array = new Object[10]; 714 array[0] = new Object(); 715 cond = false; 716 } else { 717 array[i] = array[0]; 718 } 719 } 720 return array; 721 } 722 main(String[] args)723 public static void main(String[] args) { 724 } 725 } 726