< prev index next >

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

Print this page

        

*** 77,694 **** run(ThreeLevelHierarchyAbstractVsDefault.class); run(ThreeLevelDefaultHierarchy.class); run(ThreeLevelDefaultHierarchy1.class); } - public static class ObjectToString extends ATest<ObjectToString.I> { - public ObjectToString() { super(I.class, C.class); } - - interface J { String toString(); } - interface I extends J {} - - static class C implements I {} - - interface K1 extends I {} - interface K2 extends I { String toString(); } // K2.tS() ABSTRACT - // interface K3 extends I { default String toString() { return "K3"; } // K2.tS() DEFAULT - - static class D implements I { public String toString() { return "D"; }} - - static class DJ1 implements J {} - static class DJ2 implements J { public String toString() { return "DJ2"; }} - - @Override - public Object test(I i) { return ObjectToStringHelper.test(i); /* invokeinterface I.toString() */ } - - @TestCase - public void testMono() { - // 0. Trigger compilation of a monomorphic call site - compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.toString() - assertCompiled(); - - // Dependency: none - - call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I - assertCompiled(); - } - - @TestCase - public void testBi() { - // 0. Trigger compilation of a bimorphic call site - compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString() - assertCompiled(); - - // Dependency: none - - call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I - assertCompiled(); - } - - @TestCase - public void testMega() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.toString() - assertCompiled(); - - // Dependency: none - // compiler.cha.StrengthReduceInterfaceCall$ObjectToString::test (5 bytes) - // @ 1 compiler.cha.StrengthReduceInterfaceCall$ObjectToStringHelper::test (7 bytes) inline (hot) - // @ 1 java.lang.Object::toString (36 bytes) virtual call - - // No dependency - no invalidation - repeat(100, () -> call(new C(){})); // Cn <: C <: intf I - assertCompiled(); - - initialize(K1.class, // intf K1 <: intf I <: intf J - K2.class, // intf K2.tS ABSTRACT <: intf I <: intf J - DJ1.class, // DJ1 <: intf J - DJ2.class); // DJ2.tS <: intf J - assertCompiled(); - - initialize(D.class); // D.tS <: intf I <: intf J - assertCompiled(); - - call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I - assertCompiled(); - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface - test(j); - }); - assertCompiled(); - } - } - - public static class ObjectHashCode extends ATest<ObjectHashCode.I> { - public ObjectHashCode() { super(I.class, C.class); } - - interface J {} - interface I extends J {} - - static class C implements I {} - - interface K1 extends I {} - interface K2 extends I { int hashCode(); } // K2.hC() ABSTRACT - // interface K3 extends I { default int hashCode() { return CORRECT; } // K2.hC() DEFAULT - - static class D implements I { public int hashCode() { return super.hashCode(); }} - - static class DJ1 implements J {} - static class DJ2 implements J { public int hashCode() { return super.hashCode(); }} - - @Override - public Object test(I i) { - return ObjectHashCodeHelper.test(i); /* invokeinterface I.hashCode() */ - } - - @TestCase - public void testMono() { - // 0. Trigger compilation of a monomorphic call site - compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.hashCode() - assertCompiled(); - - // Dependency: none - - call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I - assertCompiled(); - } - - @TestCase - public void testBi() { - // 0. Trigger compilation of a bimorphic call site - compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString() - assertCompiled(); - - // Dependency: none - - call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I - assertCompiled(); - } - - @TestCase - public void testMega() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.hashCode() - assertCompiled(); - - // Dependency: none - - // No dependency - no invalidation - repeat(100, () -> call(new C(){})); // Cn <: C <: intf I - assertCompiled(); - - initialize(K1.class, // intf K1 <: intf I <: intf J - K2.class, // intf K2.hC ABSTRACT <: intf I <: intf J - DJ1.class, // DJ1 <: intf J - DJ2.class); // DJ2.hC <: intf J - assertCompiled(); - - initialize(D.class); // D.hC <: intf I <: intf J - assertCompiled(); - - call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I - assertCompiled(); - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface - test(j); - }); - assertCompiled(); - } - } - - public static class TwoLevelHierarchyLinear extends ATest<TwoLevelHierarchyLinear.I> { - public TwoLevelHierarchyLinear() { super(I.class, C.class); } - - interface J { default Object m() { return WRONG; } } - - interface I extends J { Object m(); } - static class C implements I { public Object m() { return CORRECT; }} - - interface K1 extends I {} - interface K2 extends I { Object m(); } - interface K3 extends I { default Object m() { return WRONG; }} - - static class D implements I { public Object m() { return WRONG; }} - - static class DJ1 implements J {} - static class DJ2 implements J { public Object m() { return WRONG; }} - - @DontInline - public Object test(I i) { - return i.m(); - } - - @TestCase - public void testMega1() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m ABSTRACT - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check is preserved - - // 1. No deoptimization/invalidation on not-yet-seen receiver - repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT - assertCompiled(); - - // 2. No dependency invalidation on class loading of unrelated classes: different context - initialize(K1.class, // intf K1 <: intf I.m ABSTRACT <: intf J.m DEFAULT - K2.class, // intf K2.m ABSTRACT <: intf I.m ABSTRACT <: intf J.m DEFAULT - DJ1.class, // DJ1 <: intf J.m DEFAULT - DJ2.class); // DJ2.m <: intf J.m DEFAULT - assertCompiled(); - - // 3. Dependency invalidation on D <: I - initialize(D.class); // D.m <: intf I.m ABSTRACT <: intf J.m DEFAULT - assertNotCompiled(); - - // 4. Recompilation: no inlining, no dependencies - compile(megamorphic()); - call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT - assertCompiled(); - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - } - - @TestCase - public void testMega2() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // 1. Dependency invalidation - initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT - assertNotCompiled(); - - // 2. Recompilation: still inlines - // FIXME: no default method support in CHA yet - compile(megamorphic()); - call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT - assertNotCompiled(); - - // 3. Recompilation: no inlining, no dependencies - compile(megamorphic()); - call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT - assertCompiled(); - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface - test(j); - }); - assertCompiled(); - } - } - - public static class ThreeLevelHierarchyLinear extends ATest<ThreeLevelHierarchyLinear.I> { - public ThreeLevelHierarchyLinear() { super(I.class, C.class); } - - interface J { Object m(); } - interface I extends J {} - - interface K1 extends I {} - interface K2 extends I { Object m(); } - interface K3 extends I { default Object m() { return WRONG; }} - - static class C implements I { public Object m() { return CORRECT; }} - - static class DI implements I { public Object m() { return WRONG; }} - static class DJ implements J { public Object m() { return WRONG; }} - - @DontInline - public Object test(I i) { - return i.m(); // I <: J.m ABSTRACT - } - - @TestCase - public void testMega1() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // 1. No deoptimization/invalidation on not-yet-seen receiver - repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I - assertCompiled(); // No deopt on not-yet-seen receiver - - // 2. No dependency invalidation: different context - initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT - K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT - K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT - assertCompiled(); - - // 3. Dependency invalidation: DI.m <: I - initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT - assertNotCompiled(); - - // 4. Recompilation w/o a dependency - compile(megamorphic()); - call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT - assertCompiled(); // no dependency - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - } - - @TestCase - public void testMega2() { - compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // Dependency invalidation - initialize(K3.class); // intf K3.m DEFAULT <: intf I; - assertNotCompiled(); // FIXME: default methods in sub-interfaces shouldn't be taken into account by CHA - - // Recompilation with a dependency - compile(megamorphic()); - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: K3.m DEFAULT <: intf I <: intf J.m ABSTRACT - assertNotCompiled(); - - // Recompilation w/o a dependency - compile(megamorphic()); - // Dependency: none - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT - assertCompiled(); - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() { public Object m() { return WRONG; }}); // super interface - test(j); - }); - assertCompiled(); - } - } - - public static class ThreeLevelHierarchyAbstractVsDefault extends ATest<ThreeLevelHierarchyAbstractVsDefault.I> { - public ThreeLevelHierarchyAbstractVsDefault() { super(I.class, C.class); } - - interface J1 { default Object m() { return WRONG; } } // intf J1.m DEFAULT - interface J2 extends J1 { Object m(); } // intf J2.m ABSTRACT <: intf J1 - interface I extends J1, J2 {} // intf I.m OVERPASS <: intf J1,J2 - - static class C implements I { public Object m() { return CORRECT; }} - - @DontInline - public Object test(I i) { - return i.m(); // intf I.m OVERPASS - } - - static class DI implements I { public Object m() { return WRONG; }} - - static class DJ11 implements J1 {} - static class DJ12 implements J1 { public Object m() { return WRONG; }} - - static class DJ2 implements J2 { public Object m() { return WRONG; }} - - interface K11 extends J1 {} - interface K12 extends J1 { Object m(); } - interface K13 extends J1 { default Object m() { return WRONG; }} - interface K21 extends J2 {} - interface K22 extends J2 { Object m(); } - interface K23 extends J2 { default Object m() { return WRONG; }} - - - public void testMega1() { - // 0. Trigger compilation of megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // 1. No deopt/invalidation on not-yet-seen receiver - repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT - assertCompiled(); - - // 2. No dependency invalidation: different context - initialize(K11.class, K12.class, K13.class, - K21.class, K22.class, K23.class); - - // 3. Dependency invalidation: Cn.m <: C <: I - call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT - assertNotCompiled(); - - // 4. Recompilation w/o a dependency - compile(megamorphic()); - call(new C() { public Object m() { return CORRECT; }}); - assertCompiled(); // no inlining - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - } - - public void testMega2() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); - assertCompiled(); - - // Dependency: type = unique_concrete_method, context = I, method = C.m - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // 1. No dependency invalidation: different context - initialize(DJ11.class, - DJ12.class, - DJ2.class); - assertCompiled(); - - // 2. Dependency invalidation: DI.m <: I - initialize(DI.class); - assertNotCompiled(); - - // 3. Recompilation w/o a dependency - compile(megamorphic()); - call(new C() { public Object m() { return CORRECT; }}); - assertCompiled(); // no inlining - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() {}); // super interface - test(j); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() { public Object m() { return WRONG; }}); // super interface - test(j); - }); - assertCompiled(); - } - } - - public static class ThreeLevelDefaultHierarchy extends ATest<ThreeLevelDefaultHierarchy.I> { - public ThreeLevelDefaultHierarchy() { super(I.class, C.class); } - - interface J { default Object m() { return WRONG; }} - interface I extends J {} - - static class C implements I { public Object m() { return CORRECT; }} - - interface K1 extends I {} - interface K2 extends I { Object m(); } - interface K3 extends I { default Object m() { return WRONG; }} - - static class DI implements I { public Object m() { return WRONG; }} - static class DJ implements J { public Object m() { return WRONG; }} - - @DontInline - public Object test(I i) { - return i.m(); // no inlining since J.m is a default method - } - - @TestCase - public void testMega() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT - assertCompiled(); - - // Dependency: none - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // 1. No deoptimization/invalidation on not-yet-seen receiver - repeat(100, () -> call(new C() {})); - assertCompiled(); - - // 2. No dependency and no inlining - initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT - DI.class, // DI.m <: intf I <: intf J.m ABSTRACT - K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT - K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT - assertCompiled(); - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface - test(j); - }); - assertCompiled(); - } - } - - public static class ThreeLevelDefaultHierarchy1 extends ATest<ThreeLevelDefaultHierarchy1.I> { - public ThreeLevelDefaultHierarchy1() { super(I.class, C.class); } - - interface J1 { Object m();} - interface J2 extends J1 { default Object m() { return WRONG; } } - interface I extends J1, J2 {} - - static class C implements I { public Object m() { return CORRECT; }} - - interface K1 extends I {} - interface K2 extends I { Object m(); } - interface K3 extends I { default Object m() { return WRONG; }} - - static class DI implements I { public Object m() { return WRONG; }} - static class DJ1 implements J1 { public Object m() { return WRONG; }} - static class DJ2 implements J2 { public Object m() { return WRONG; }} - - @DontInline - public Object test(I i) { - return i.m(); // no inlining since J.m is a default method - } - - @TestCase - public void testMega() { - // 0. Trigger compilation of a megamorphic call site - compile(megamorphic()); - assertCompiled(); - - // Dependency: none - - checkInvalidReceiver(); // ensure proper type check on receiver is preserved - - // 1. No deoptimization/invalidation on not-yet-seen receiver - repeat(100, () -> call(new C() {})); - assertCompiled(); - - // 2. No dependency, no inlining - // CHA doesn't support default methods yet. - initialize(DJ1.class, - DJ2.class, - DI.class, - K1.class, - K2.class, - K3.class); - assertCompiled(); - } - - @Override - public void checkInvalidReceiver() { - shouldThrow(IncompatibleClassChangeError.class, () -> { - I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated - test(o); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() { public Object m() { return WRONG; } }); // super interface - test(j); - }); - assertCompiled(); - - shouldThrow(IncompatibleClassChangeError.class, () -> { - I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() {}); // super interface - test(j); - }); - assertCompiled(); - } - } - /* =========================================================== */ interface Action { int run(); } --- 77,86 ----
< prev index next >