< prev index next >

test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java

Print this page




  62 import java.lang.invoke.MethodHandles;
  63 import java.lang.reflect.Method;
  64 import java.util.HashMap;
  65 import java.util.concurrent.Callable;
  66 
  67 import static jdk.test.lib.Asserts.*;
  68 import static jdk.internal.org.objectweb.asm.ClassWriter.*;
  69 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  70 
  71 public class StrengthReduceInterfaceCall {
  72     public static void main(String[] args) {
  73         run(ObjectToString.class);
  74         run(ObjectHashCode.class);
  75         run(TwoLevelHierarchyLinear.class);
  76         run(ThreeLevelHierarchyLinear.class);
  77         run(ThreeLevelHierarchyAbstractVsDefault.class);
  78         run(ThreeLevelDefaultHierarchy.class);
  79         run(ThreeLevelDefaultHierarchy1.class);
  80     }
  81 
  82     public static class ObjectToString extends ATest<ObjectToString.I> {
  83         public ObjectToString() { super(I.class, C.class); }
  84 
  85         interface J           { String toString(); }
  86         interface I extends J {}
  87 
  88         static class C implements I {}
  89 
  90         interface K1 extends I {}
  91         interface K2 extends I { String toString(); } // K2.tS() ABSTRACT
  92         // interface K3 extends I { default String toString() { return "K3"; } // K2.tS() DEFAULT
  93 
  94         static class D implements I { public String toString() { return "D"; }}
  95 
  96         static class DJ1 implements J {}
  97         static class DJ2 implements J { public String toString() { return "DJ2"; }}
  98 
  99         @Override
 100         public Object test(I i) { return ObjectToStringHelper.test(i); /* invokeinterface I.toString() */ }
 101 
 102         @TestCase
 103         public void testMono() {
 104             // 0. Trigger compilation of a monomorphic call site
 105             compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.toString()
 106             assertCompiled();
 107 
 108             // Dependency: none
 109 
 110             call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
 111             assertCompiled();
 112         }
 113 
 114         @TestCase
 115         public void testBi() {
 116             // 0. Trigger compilation of a bimorphic call site
 117             compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()
 118             assertCompiled();
 119 
 120             // Dependency: none
 121 
 122             call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
 123             assertCompiled();
 124         }
 125 
 126         @TestCase
 127         public void testMega() {
 128             // 0. Trigger compilation of a megamorphic call site
 129             compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.toString()
 130             assertCompiled();
 131 
 132             // Dependency: none
 133             // compiler.cha.StrengthReduceInterfaceCall$ObjectToString::test (5 bytes)
 134             //     @ 1   compiler.cha.StrengthReduceInterfaceCall$ObjectToStringHelper::test (7 bytes)   inline (hot)
 135             //       @ 1   java.lang.Object::toString (36 bytes)   virtual call
 136 
 137             // No dependency - no invalidation
 138             repeat(100, () -> call(new C(){})); // Cn <: C <: intf I
 139             assertCompiled();
 140 
 141             initialize(K1.class,   // intf  K1             <: intf I <: intf J
 142                        K2.class,   // intf  K2.tS ABSTRACT <: intf I <: intf J
 143                        DJ1.class,  //      DJ1                       <: intf J
 144                        DJ2.class); //      DJ2.tS                    <: intf J
 145             assertCompiled();
 146 
 147             initialize(D.class); // D.tS <: intf I <: intf J
 148             assertCompiled();
 149 
 150             call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
 151             assertCompiled();
 152         }
 153 
 154         @Override
 155         public void checkInvalidReceiver() {
 156             shouldThrow(IncompatibleClassChangeError.class, () -> {
 157                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 158                 test(o);
 159             });
 160             assertCompiled();
 161 
 162             shouldThrow(IncompatibleClassChangeError.class, () -> {
 163                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
 164                 test(j);
 165             });
 166             assertCompiled();
 167         }
 168     }
 169 
 170     public static class ObjectHashCode extends ATest<ObjectHashCode.I> {
 171         public ObjectHashCode() { super(I.class, C.class); }
 172 
 173         interface J {}
 174         interface I extends J {}
 175 
 176         static class C implements I {}
 177 
 178         interface K1 extends I {}
 179         interface K2 extends I { int hashCode(); } // K2.hC() ABSTRACT
 180         // interface K3 extends I { default int hashCode() { return CORRECT; } // K2.hC() DEFAULT
 181 
 182         static class D implements I { public int hashCode() { return super.hashCode(); }}
 183 
 184         static class DJ1 implements J {}
 185         static class DJ2 implements J { public int hashCode() { return super.hashCode(); }}
 186 
 187         @Override
 188         public Object test(I i) {
 189             return ObjectHashCodeHelper.test(i); /* invokeinterface I.hashCode() */
 190         }
 191 
 192         @TestCase
 193         public void testMono() {
 194             // 0. Trigger compilation of a monomorphic call site
 195             compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.hashCode()
 196             assertCompiled();
 197 
 198             // Dependency: none
 199 
 200             call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
 201             assertCompiled();
 202         }
 203 
 204         @TestCase
 205         public void testBi() {
 206             // 0. Trigger compilation of a bimorphic call site
 207             compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()
 208             assertCompiled();
 209 
 210             // Dependency: none
 211 
 212             call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
 213             assertCompiled();
 214         }
 215 
 216         @TestCase
 217         public void testMega() {
 218             // 0. Trigger compilation of a megamorphic call site
 219             compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.hashCode()
 220             assertCompiled();
 221 
 222             // Dependency: none
 223 
 224             // No dependency - no invalidation
 225             repeat(100, () -> call(new C(){})); // Cn <: C <: intf I
 226             assertCompiled();
 227 
 228             initialize(K1.class,   // intf  K1             <: intf I <: intf J
 229                        K2.class,   // intf  K2.hC ABSTRACT <: intf I <: intf J
 230                        DJ1.class,  //      DJ1                       <: intf J
 231                        DJ2.class); //      DJ2.hC                    <: intf J
 232             assertCompiled();
 233 
 234             initialize(D.class); // D.hC <: intf I <: intf J
 235             assertCompiled();
 236 
 237             call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
 238             assertCompiled();
 239         }
 240 
 241         @Override
 242         public void checkInvalidReceiver() {
 243             shouldThrow(IncompatibleClassChangeError.class, () -> {
 244                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 245                 test(o);
 246             });
 247             assertCompiled();
 248 
 249             shouldThrow(IncompatibleClassChangeError.class, () -> {
 250                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
 251                 test(j);
 252             });
 253             assertCompiled();
 254         }
 255     }
 256 
 257     public static class TwoLevelHierarchyLinear extends ATest<TwoLevelHierarchyLinear.I> {
 258         public TwoLevelHierarchyLinear() { super(I.class, C.class); }
 259 
 260         interface J { default Object m() { return WRONG; } }
 261 
 262         interface I extends J { Object m(); }
 263         static class C implements I { public Object m() { return CORRECT; }}
 264 
 265         interface K1 extends I {}
 266         interface K2 extends I { Object m(); }
 267         interface K3 extends I { default Object m() { return WRONG; }}
 268 
 269         static class D implements I { public Object m() { return WRONG;   }}
 270 
 271         static class DJ1 implements J {}
 272         static class DJ2 implements J { public Object m() { return WRONG; }}
 273 
 274         @DontInline
 275         public Object test(I i) {
 276             return i.m();
 277         }
 278 
 279         @TestCase
 280         public void testMega1() {
 281             // 0. Trigger compilation of a megamorphic call site
 282             compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m ABSTRACT
 283             assertCompiled();
 284 
 285             // Dependency: type = unique_concrete_method, context = I, method = C.m
 286 
 287             checkInvalidReceiver(); // ensure proper type check is preserved
 288 
 289             // 1. No deoptimization/invalidation on not-yet-seen receiver
 290             repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
 291             assertCompiled();
 292 
 293             // 2. No dependency invalidation on class loading of unrelated classes: different context
 294             initialize(K1.class,   // intf  K1            <: intf I.m ABSTRACT <: intf J.m DEFAULT
 295                        K2.class,   // intf  K2.m ABSTRACT <: intf I.m ABSTRACT <: intf J.m DEFAULT
 296                        DJ1.class,  //      DJ1                                 <: intf J.m DEFAULT
 297                        DJ2.class); //      DJ2.m                               <: intf J.m DEFAULT
 298             assertCompiled();
 299 
 300             // 3. Dependency invalidation on D <: I
 301             initialize(D.class); // D.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
 302             assertNotCompiled();
 303 
 304             // 4. Recompilation: no inlining, no dependencies
 305             compile(megamorphic());
 306             call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
 307             assertCompiled();
 308 
 309             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 310         }
 311 
 312         @TestCase
 313         public void testMega2() {
 314             // 0. Trigger compilation of a megamorphic call site
 315             compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
 316             assertCompiled();
 317 
 318             // Dependency: type = unique_concrete_method, context = I, method = C.m
 319 
 320             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 321 
 322             // 1. Dependency invalidation
 323             initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
 324             assertNotCompiled();
 325 
 326             // 2. Recompilation: still inlines
 327             // FIXME: no default method support in CHA yet
 328             compile(megamorphic());
 329             call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT
 330             assertNotCompiled();
 331 
 332             // 3. Recompilation: no inlining, no dependencies
 333             compile(megamorphic());
 334             call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: intf K3.m DEFAULT  <: intf I.m ABSTRACT <: intf J.m DEFAULT
 335             assertCompiled();
 336 
 337             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 338         }
 339 
 340         @Override
 341         public void checkInvalidReceiver() {
 342             shouldThrow(IncompatibleClassChangeError.class, () -> {
 343                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 344                 test(o);
 345             });
 346             assertCompiled();
 347 
 348             shouldThrow(IncompatibleClassChangeError.class, () -> {
 349                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
 350                 test(j);
 351             });
 352             assertCompiled();
 353         }
 354     }
 355 
 356     public static class ThreeLevelHierarchyLinear extends ATest<ThreeLevelHierarchyLinear.I> {
 357         public ThreeLevelHierarchyLinear() { super(I.class, C.class); }
 358 
 359         interface J           { Object m(); }
 360         interface I extends J {}
 361 
 362         interface K1 extends I {}
 363         interface K2 extends I { Object m(); }
 364         interface K3 extends I { default Object m() { return WRONG; }}
 365 
 366         static class C  implements I { public Object m() { return CORRECT; }}
 367 
 368         static class DI implements I { public Object m() { return WRONG;   }}
 369         static class DJ implements J { public Object m() { return WRONG;   }}
 370 
 371         @DontInline
 372         public Object test(I i) {
 373             return i.m(); // I <: J.m ABSTRACT
 374         }
 375 
 376         @TestCase
 377         public void testMega1() {
 378             // 0. Trigger compilation of a megamorphic call site
 379             compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
 380             assertCompiled();
 381 
 382             // Dependency: type = unique_concrete_method, context = I, method = C.m
 383 
 384             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 385 
 386             // 1. No deoptimization/invalidation on not-yet-seen receiver
 387             repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I
 388             assertCompiled(); // No deopt on not-yet-seen receiver
 389 
 390             // 2. No dependency invalidation: different context
 391             initialize(DJ.class,  //      DJ.m                    <: intf J.m ABSTRACT
 392                        K1.class,  // intf K1            <: intf I <: intf J.m ABSTRACT
 393                        K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT
 394             assertCompiled();
 395 
 396             // 3. Dependency invalidation: DI.m <: I
 397             initialize(DI.class); //      DI.m          <: intf I <: intf J.m ABSTRACT
 398             assertNotCompiled();
 399 
 400             // 4. Recompilation w/o a dependency
 401             compile(megamorphic());
 402             call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
 403             assertCompiled(); // no dependency
 404 
 405             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 406         }
 407 
 408         @TestCase
 409         public void testMega2() {
 410             compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
 411             assertCompiled();
 412 
 413             // Dependency: type = unique_concrete_method, context = I, method = C.m
 414 
 415             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 416 
 417             // Dependency invalidation
 418             initialize(K3.class); // intf K3.m DEFAULT <: intf I;
 419             assertNotCompiled(); // FIXME: default methods in sub-interfaces shouldn't be taken into account by CHA
 420 
 421             // Recompilation with a dependency
 422             compile(megamorphic());
 423             assertCompiled();
 424 
 425             // Dependency: type = unique_concrete_method, context = I, method = C.m
 426 
 427             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 428 
 429             call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: K3.m DEFAULT <: intf I <: intf J.m ABSTRACT
 430             assertNotCompiled();
 431 
 432             // Recompilation w/o a dependency
 433             compile(megamorphic());
 434             // Dependency: none
 435             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 436             call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
 437             assertCompiled();
 438         }
 439 
 440         @Override
 441         public void checkInvalidReceiver() {
 442             shouldThrow(IncompatibleClassChangeError.class, () -> {
 443                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 444                 test(o);
 445             });
 446             assertCompiled();
 447 
 448             shouldThrow(IncompatibleClassChangeError.class, () -> {
 449                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() { public Object m() { return WRONG; }}); // super interface
 450                 test(j);
 451             });
 452             assertCompiled();
 453         }
 454     }
 455 
 456     public static class ThreeLevelHierarchyAbstractVsDefault extends ATest<ThreeLevelHierarchyAbstractVsDefault.I> {
 457         public ThreeLevelHierarchyAbstractVsDefault() { super(I.class, C.class); }
 458 
 459         interface J1                { default Object m() { return WRONG; } } // intf J1.m DEFAULT
 460         interface J2 extends J1     { Object m(); }                          // intf J2.m ABSTRACT <: intf J1
 461         interface I  extends J1, J2 {}                                       // intf  I.m OVERPASS <: intf J1,J2
 462 
 463         static class C  implements I { public Object m() { return CORRECT; }}
 464 
 465         @DontInline
 466         public Object test(I i) {
 467             return i.m(); // intf I.m OVERPASS
 468         }
 469 
 470         static class DI implements I { public Object m() { return WRONG;   }}
 471 
 472         static class DJ11 implements J1 {}
 473         static class DJ12 implements J1 { public Object m() { return WRONG; }}
 474 
 475         static class DJ2 implements J2 { public Object m() { return WRONG;   }}
 476 
 477         interface K11 extends J1 {}
 478         interface K12 extends J1 { Object m(); }
 479         interface K13 extends J1 { default Object m() { return WRONG; }}
 480         interface K21 extends J2 {}
 481         interface K22 extends J2 { Object m(); }
 482         interface K23 extends J2 { default Object m() { return WRONG; }}
 483 
 484 
 485         public void testMega1() {
 486             // 0. Trigger compilation of megamorphic call site
 487             compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
 488             assertCompiled();
 489 
 490             // Dependency: type = unique_concrete_method, context = I, method = C.m
 491 
 492             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 493 
 494             // 1. No deopt/invalidation on not-yet-seen receiver
 495             repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
 496             assertCompiled();
 497 
 498             // 2. No dependency invalidation: different context
 499             initialize(K11.class, K12.class, K13.class,
 500                        K21.class, K22.class, K23.class);
 501 
 502             // 3. Dependency invalidation: Cn.m <: C <: I
 503             call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
 504             assertNotCompiled();
 505 
 506             // 4. Recompilation w/o a dependency
 507             compile(megamorphic());
 508             call(new C() { public Object m() { return CORRECT; }});
 509             assertCompiled(); // no inlining
 510 
 511             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 512         }
 513 
 514         public void testMega2() {
 515             // 0. Trigger compilation of a megamorphic call site
 516             compile(megamorphic());
 517             assertCompiled();
 518 
 519             // Dependency: type = unique_concrete_method, context = I, method = C.m
 520 
 521             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 522 
 523             // 1. No dependency invalidation: different context
 524             initialize(DJ11.class,
 525                        DJ12.class,
 526                        DJ2.class);
 527             assertCompiled();
 528 
 529             // 2. Dependency invalidation: DI.m <: I
 530             initialize(DI.class);
 531             assertNotCompiled();
 532 
 533             // 3. Recompilation w/o a dependency
 534             compile(megamorphic());
 535             call(new C() { public Object m() { return CORRECT; }});
 536             assertCompiled(); // no inlining
 537 
 538             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 539         }
 540 
 541         @Override
 542         public void checkInvalidReceiver() {
 543             shouldThrow(IncompatibleClassChangeError.class, () -> {
 544                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 545                 test(o);
 546             });
 547             assertCompiled();
 548 
 549             shouldThrow(IncompatibleClassChangeError.class, () -> {
 550                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() {}); // super interface
 551                 test(j);
 552             });
 553             assertCompiled();
 554 
 555             shouldThrow(IncompatibleClassChangeError.class, () -> {
 556                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() { public Object m() { return WRONG; }}); // super interface
 557                 test(j);
 558             });
 559             assertCompiled();
 560         }
 561     }
 562 
 563     public static class ThreeLevelDefaultHierarchy extends ATest<ThreeLevelDefaultHierarchy.I> {
 564         public ThreeLevelDefaultHierarchy() { super(I.class, C.class); }
 565 
 566         interface J           { default Object m() { return WRONG; }}
 567         interface I extends J {}
 568 
 569         static class C  implements I { public Object m() { return CORRECT; }}
 570 
 571         interface K1 extends I {}
 572         interface K2 extends I { Object m(); }
 573         interface K3 extends I { default Object m() { return WRONG; }}
 574 
 575         static class DI implements I { public Object m() { return WRONG; }}
 576         static class DJ implements J { public Object m() { return WRONG; }}
 577 
 578         @DontInline
 579         public Object test(I i) {
 580             return i.m(); // no inlining since J.m is a default method
 581         }
 582 
 583         @TestCase
 584         public void testMega() {
 585             // 0. Trigger compilation of a megamorphic call site
 586             compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
 587             assertCompiled();
 588 
 589             // Dependency: none
 590 
 591             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 592 
 593             // 1. No deoptimization/invalidation on not-yet-seen receiver
 594             repeat(100, () -> call(new C() {}));
 595             assertCompiled();
 596 
 597             // 2. No dependency and no inlining
 598             initialize(DJ.class,  //      DJ.m                    <: intf J.m ABSTRACT
 599                        DI.class,  //      DI.m          <: intf I <: intf J.m ABSTRACT
 600                        K1.class,  // intf K1            <: intf I <: intf J.m ABSTRACT
 601                        K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT
 602             assertCompiled();
 603         }
 604 
 605         @Override
 606         public void checkInvalidReceiver() {
 607             shouldThrow(IncompatibleClassChangeError.class, () -> {
 608                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 609                 test(o);
 610             });
 611             assertCompiled();
 612 
 613             shouldThrow(IncompatibleClassChangeError.class, () -> {
 614                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
 615                 test(j);
 616             });
 617             assertCompiled();
 618         }
 619     }
 620 
 621     public static class ThreeLevelDefaultHierarchy1 extends ATest<ThreeLevelDefaultHierarchy1.I> {
 622         public ThreeLevelDefaultHierarchy1() { super(I.class, C.class); }
 623 
 624         interface J1                { Object m();}
 625         interface J2 extends J1     { default Object m() { return WRONG; }  }
 626         interface I  extends J1, J2 {}
 627 
 628         static class C  implements I { public Object m() { return CORRECT; }}
 629 
 630         interface K1 extends I {}
 631         interface K2 extends I { Object m(); }
 632         interface K3 extends I { default Object m() { return WRONG; }}
 633 
 634         static class DI implements I { public Object m() { return WRONG; }}
 635         static class DJ1 implements J1 { public Object m() { return WRONG; }}
 636         static class DJ2 implements J2 { public Object m() { return WRONG; }}
 637 
 638         @DontInline
 639         public Object test(I i) {
 640             return i.m(); // no inlining since J.m is a default method
 641         }
 642 
 643         @TestCase
 644         public void testMega() {
 645             // 0. Trigger compilation of a megamorphic call site
 646             compile(megamorphic());
 647             assertCompiled();
 648 
 649             // Dependency: none
 650 
 651             checkInvalidReceiver(); // ensure proper type check on receiver is preserved
 652 
 653             // 1. No deoptimization/invalidation on not-yet-seen receiver
 654             repeat(100, () -> call(new C() {}));
 655             assertCompiled();
 656 
 657             // 2. No dependency, no inlining
 658             // CHA doesn't support default methods yet.
 659             initialize(DJ1.class,
 660                        DJ2.class,
 661                        DI.class,
 662                        K1.class,
 663                        K2.class,
 664                        K3.class);
 665             assertCompiled();
 666         }
 667 
 668         @Override
 669         public void checkInvalidReceiver() {
 670             shouldThrow(IncompatibleClassChangeError.class, () -> {
 671                 I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
 672                 test(o);
 673             });
 674             assertCompiled();
 675 
 676             shouldThrow(IncompatibleClassChangeError.class, () -> {
 677                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() { public Object m() { return WRONG; } }); // super interface
 678                 test(j);
 679             });
 680             assertCompiled();
 681 
 682             shouldThrow(IncompatibleClassChangeError.class, () -> {
 683                 I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() {}); // super interface
 684                 test(j);
 685             });
 686             assertCompiled();
 687         }
 688     }
 689 
 690     /* =========================================================== */
 691 
 692     interface Action {
 693         int run();
 694     }
 695 
 696     public static final Unsafe U = Unsafe.getUnsafe();
 697 
 698     interface Test<T> {
 699         void call(T o);
 700         T receiver(int id);
 701 
 702         default Runnable monomophic() {
 703             return () -> {
 704                 call(receiver(0)); // 100%
 705             };
 706         }
 707 
 708         default Runnable bimorphic() {
 709             return () -> {




  62 import java.lang.invoke.MethodHandles;
  63 import java.lang.reflect.Method;
  64 import java.util.HashMap;
  65 import java.util.concurrent.Callable;
  66 
  67 import static jdk.test.lib.Asserts.*;
  68 import static jdk.internal.org.objectweb.asm.ClassWriter.*;
  69 import static jdk.internal.org.objectweb.asm.Opcodes.*;
  70 
  71 public class StrengthReduceInterfaceCall {
  72     public static void main(String[] args) {
  73         run(ObjectToString.class);
  74         run(ObjectHashCode.class);
  75         run(TwoLevelHierarchyLinear.class);
  76         run(ThreeLevelHierarchyLinear.class);
  77         run(ThreeLevelHierarchyAbstractVsDefault.class);
  78         run(ThreeLevelDefaultHierarchy.class);
  79         run(ThreeLevelDefaultHierarchy1.class);
  80     }
  81 
































































































































































































































































































































































































































































































































































































































  82     /* =========================================================== */
  83 
  84     interface Action {
  85         int run();
  86     }
  87 
  88     public static final Unsafe U = Unsafe.getUnsafe();
  89 
  90     interface Test<T> {
  91         void call(T o);
  92         T receiver(int id);
  93 
  94         default Runnable monomophic() {
  95             return () -> {
  96                 call(receiver(0)); // 100%
  97             };
  98         }
  99 
 100         default Runnable bimorphic() {
 101             return () -> {


< prev index next >