Path: blob/master/test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java
41149 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @requires !vm.graal.enabled & vm.opt.final.UseVtableBasedCHA == true26* @modules java.base/jdk.internal.org.objectweb.asm27* java.base/jdk.internal.misc28* java.base/jdk.internal.vm.annotation29* @library /test/lib /30* @compile Utils.java31* @build sun.hotspot.WhiteBox32* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox33*34* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions35* -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet36* -XX:CompileCommand=compileonly,*::m37* -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test38* -XX:CompileCommand=compileonly,*::testHelper -XX:CompileCommand=inline,*::testHelper39* -Xbatch -Xmixed -XX:+WhiteBoxAPI40* -XX:-TieredCompilation41* compiler.cha.StrengthReduceInterfaceCall42*43* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions44* -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet45* -XX:CompileCommand=compileonly,*::m46* -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test47* -XX:CompileCommand=compileonly,*::testHelper -XX:CompileCommand=inline,*::testHelper48* -Xbatch -Xmixed -XX:+WhiteBoxAPI49* -XX:+TieredCompilation -XX:TieredStopAtLevel=150* compiler.cha.StrengthReduceInterfaceCall51*/52package compiler.cha;5354import jdk.internal.vm.annotation.DontInline;5556import static compiler.cha.Utils.*;5758public class StrengthReduceInterfaceCall {59public static void main(String[] args) {60run(ObjectToString.class);61run(ObjectHashCode.class);62run(TwoLevelHierarchyLinear.class);63run(ThreeLevelHierarchyLinear.class);64run(ThreeLevelHierarchyAbstractVsDefault.class);65run(ThreeLevelDefaultHierarchy.class);66run(ThreeLevelDefaultHierarchy1.class);67System.out.println("TEST PASSED");68}6970public static class ObjectToString extends ATest<ObjectToString.I> {71public ObjectToString() { super(I.class, C.class); }7273interface J { String toString(); }74interface I extends J {}7576static class C implements I {}7778interface K1 extends I {}79interface K2 extends I { String toString(); } // K2.tS() ABSTRACT80// interface K3 extends I { default String toString() { return "K3"; } // K2.tS() DEFAULT8182static class D implements I { public String toString() { return "D"; }}8384static class DJ1 implements J {}85static class DJ2 implements J { public String toString() { return "DJ2"; }}8687@Override88public Object test(I i) { return ObjectToStringHelper.testHelper(i); /* invokeinterface I.toString() */ }8990@TestCase91public void testMono() {92// 0. Trigger compilation of a monomorphic call site93compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.toString()94assertCompiled();9596// Dependency: none9798call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I99assertCompiled();100}101102@TestCase103public void testBi() {104// 0. Trigger compilation of a bimorphic call site105compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()106assertCompiled();107108// Dependency: none109110call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I111assertCompiled();112}113114@TestCase115public void testMega() {116// 0. Trigger compilation of a megamorphic call site117compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.toString()118assertCompiled();119120// Dependency: none121// compiler.cha.StrengthReduceInterfaceCall$ObjectToString::test (5 bytes)122// @ 1 compiler.cha.StrengthReduceInterfaceCall$ObjectToStringHelper::test (7 bytes) inline (hot)123// @ 1 java.lang.Object::toString (36 bytes) virtual call124125// No dependency - no invalidation126repeat(100, () -> call(new C(){})); // Cn <: C <: intf I127assertCompiled();128129initialize(K1.class, // intf K1 <: intf I <: intf J130K2.class, // intf K2.tS ABSTRACT <: intf I <: intf J131DJ1.class, // DJ1 <: intf J132DJ2.class); // DJ2.tS <: intf J133assertCompiled();134135initialize(D.class); // D.tS <: intf I <: intf J136assertCompiled();137138call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I139assertCompiled();140}141142@Override143public void checkInvalidReceiver() {144shouldThrow(IncompatibleClassChangeError.class, () -> {145I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated146test(o);147});148assertCompiled();149150shouldThrow(IncompatibleClassChangeError.class, () -> {151I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface152test(j);153});154assertCompiled();155}156}157158public static class ObjectHashCode extends ATest<ObjectHashCode.I> {159public ObjectHashCode() { super(I.class, C.class); }160161interface J {}162interface I extends J {}163164static class C implements I {}165166interface K1 extends I {}167interface K2 extends I { int hashCode(); } // K2.hC() ABSTRACT168// interface K3 extends I { default int hashCode() { return CORRECT; } // K2.hC() DEFAULT169170static class D implements I { public int hashCode() { return super.hashCode(); }}171172static class DJ1 implements J {}173static class DJ2 implements J { public int hashCode() { return super.hashCode(); }}174175@Override176public Object test(I i) {177return ObjectHashCodeHelper.testHelper(i); /* invokeinterface I.hashCode() */178}179180@TestCase181public void testMono() {182// 0. Trigger compilation of a monomorphic call site183compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.hashCode()184assertCompiled();185186// Dependency: none187188call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I189assertCompiled();190}191192@TestCase193public void testBi() {194// 0. Trigger compilation of a bimorphic call site195compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()196assertCompiled();197198// Dependency: none199200call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I201assertCompiled();202}203204@TestCase205public void testMega() {206// 0. Trigger compilation of a megamorphic call site207compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.hashCode()208assertCompiled();209210// Dependency: none211212// No dependency - no invalidation213repeat(100, () -> call(new C(){})); // Cn <: C <: intf I214assertCompiled();215216initialize(K1.class, // intf K1 <: intf I <: intf J217K2.class, // intf K2.hC ABSTRACT <: intf I <: intf J218DJ1.class, // DJ1 <: intf J219DJ2.class); // DJ2.hC <: intf J220assertCompiled();221222initialize(D.class); // D.hC <: intf I <: intf J223assertCompiled();224225call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I226assertCompiled();227}228229@Override230public void checkInvalidReceiver() {231shouldThrow(IncompatibleClassChangeError.class, () -> {232I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated233test(o);234});235assertCompiled();236237shouldThrow(IncompatibleClassChangeError.class, () -> {238I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface239test(j);240});241assertCompiled();242}243}244245public static class TwoLevelHierarchyLinear extends ATest<TwoLevelHierarchyLinear.I> {246public TwoLevelHierarchyLinear() { super(I.class, C.class); }247248interface J { default Object m() { return WRONG; } }249250interface I extends J { Object m(); }251static class C implements I { public Object m() { return CORRECT; }}252253interface K1 extends I {}254interface K2 extends I { Object m(); }255interface K3 extends I { default Object m() { return WRONG; }}256interface K4 extends I { default Object m() { return CORRECT; }}257258static class D implements I { public Object m() { return WRONG; }}259260static class DJ1 implements J {}261static class DJ2 implements J { public Object m() { return WRONG; }}262263@DontInline264public Object test(I i) {265return i.m();266}267268@TestCase269public void testMega1() {270// 0. Trigger compilation of a megamorphic call site271compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m ABSTRACT272assertCompiled();273274// Dependency: type = unique_concrete_method, context = I, method = C.m275276checkInvalidReceiver(); // ensure proper type check is preserved277278// 1. No deoptimization/invalidation on not-yet-seen receiver279repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT280assertCompiled();281282// 2. No dependency invalidation on class loading of unrelated classes: different context283initialize(K1.class, // intf K1 <: intf I.m ABSTRACT <: intf J.m DEFAULT284K2.class, // intf K2.m ABSTRACT <: intf I.m ABSTRACT <: intf J.m DEFAULT285DJ1.class, // DJ1 <: intf J.m DEFAULT286DJ2.class); // DJ2.m <: intf J.m DEFAULT287assertCompiled();288289// 3. Dependency invalidation on D <: I290initialize(D.class); // D.m <: intf I.m ABSTRACT <: intf J.m DEFAULT291assertNotCompiled();292293// 4. Recompilation: no inlining, no dependencies294compile(megamorphic());295call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT296assertCompiled();297298checkInvalidReceiver(); // ensure proper type check on receiver is preserved299}300301@TestCase302public void testMega2() {303// 0. Trigger compilation of a megamorphic call site304compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT305assertCompiled();306307// Dependency: type = unique_concrete_method, context = I, method = C.m308309checkInvalidReceiver(); // ensure proper type check on receiver is preserved310311// 1. No invalidation: interfaces don't participate in CHA.312initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT313assertCompiled();314315// 2. Dependency invalidation on K3n <: I with concrete method.316call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT317assertNotCompiled();318319// 3. Recompilation: no inlining, no dependencies320compile(megamorphic());321call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT322assertCompiled();323324checkInvalidReceiver(); // ensure proper type check on receiver is preserved325}326327@TestCase328public void testMega3() {329// 0. Trigger compilation of a megamorphic call site330compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT331assertCompiled();332333// Dependency: type = unique_concrete_method, context = I, method = C.m334335checkInvalidReceiver(); // ensure proper type check on receiver is preserved336337// 1. No invalidation: interfaces don't participate in CHA.338initialize(K4.class); // intf K4.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT339assertCompiled();340341// 2. Dependency invalidation on K4n <: I with default method.342call(new K4() { /* default method K4.m */ }); // K4n <: intf K4.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT343assertNotCompiled();344345// 3. Recompilation: no inlining, no dependencies346compile(megamorphic());347call(new K4() { /* default method K4.m */ }); // K4n <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT348assertCompiled();349350checkInvalidReceiver(); // ensure proper type check on receiver is preserved351}352353@Override354public void checkInvalidReceiver() {355shouldThrow(IncompatibleClassChangeError.class, () -> {356I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated357test(o);358});359assertCompiled();360361shouldThrow(IncompatibleClassChangeError.class, () -> {362I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface363test(j);364});365assertCompiled();366}367}368369public static class ThreeLevelHierarchyLinear extends ATest<ThreeLevelHierarchyLinear.I> {370public ThreeLevelHierarchyLinear() { super(I.class, C.class); }371372interface J { Object m(); }373interface I extends J {}374375interface K1 extends I {}376interface K2 extends I { Object m(); }377interface K3 extends I { default Object m() { return WRONG; }}378interface K4 extends I { default Object m() { return CORRECT; }}379380static class C implements I { public Object m() { return CORRECT; }}381382static class DI implements I { public Object m() { return WRONG; }}383static class DJ implements J { public Object m() { return WRONG; }}384385@DontInline386public Object test(I i) {387return i.m(); // I <: J.m ABSTRACT388}389390@TestCase391public void testMega1() {392// 0. Trigger compilation of a megamorphic call site393compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT394assertCompiled();395396// Dependency: type = unique_concrete_method, context = I, method = C.m397398checkInvalidReceiver(); // ensure proper type check on receiver is preserved399400// 1. No deoptimization/invalidation on not-yet-seen receiver401repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I402assertCompiled(); // No deopt on not-yet-seen receiver403404// 2. No dependency invalidation: different context405initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT406K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT407K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT408assertCompiled();409410// 3. Dependency invalidation: DI.m <: I411initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT412assertNotCompiled();413414// 4. Recompilation w/o a dependency415compile(megamorphic());416call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT417assertCompiled(); // no dependency418419checkInvalidReceiver(); // ensure proper type check on receiver is preserved420}421422@TestCase423public void testMega2() {424compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT425assertCompiled();426427// Dependency: type = unique_concrete_method, context = I, method = C.m428429checkInvalidReceiver(); // ensure proper type check on receiver is preserved430431// No invalidation: interfaces don't participate in CHA.432initialize(K3.class); // intf K3.m DEFAULT <: intf I;433assertCompiled();434435// Dependency: type = unique_concrete_method, context = I, method = C.m436437checkInvalidReceiver(); // ensure proper type check on receiver is preserved438439call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: K3.m DEFAULT <: intf I <: intf J.m ABSTRACT440assertNotCompiled();441442// Recompilation w/o a dependency443compile(megamorphic());444// Dependency: none445checkInvalidReceiver(); // ensure proper type check on receiver is preserved446call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT447assertCompiled();448}449450@TestCase451public void testMega3() {452compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT453assertCompiled();454455// Dependency: type = unique_concrete_method, context = I, method = C.m456457checkInvalidReceiver(); // ensure proper type check on receiver is preserved458459// No invalidation: interfaces don't participate in CHA.460initialize(K4.class); // intf K3.m DEFAULT <: intf I;461assertCompiled();462463// Dependency: type = unique_concrete_method, context = I, method = C.m464465checkInvalidReceiver(); // ensure proper type check on receiver is preserved466467call(new K4() { /* default method K4.m */ }); // K4n <: K4.m DEFAULT <: intf I <: intf J.m ABSTRACT468assertNotCompiled();469470// Recompilation w/o a dependency471compile(megamorphic());472// Dependency: none473checkInvalidReceiver(); // ensure proper type check on receiver is preserved474call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT475assertCompiled();476}477478@Override479public void checkInvalidReceiver() {480shouldThrow(IncompatibleClassChangeError.class, () -> {481I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated482test(o);483});484assertCompiled();485486shouldThrow(IncompatibleClassChangeError.class, () -> {487I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() { public Object m() { return WRONG; }}); // super interface488test(j);489});490assertCompiled();491}492}493494public static class ThreeLevelHierarchyAbstractVsDefault extends ATest<ThreeLevelHierarchyAbstractVsDefault.I> {495public ThreeLevelHierarchyAbstractVsDefault() { super(I.class, C.class); }496497interface J1 { default Object m() { return WRONG; } } // intf J1.m DEFAULT498interface J2 extends J1 { Object m(); } // intf J2.m ABSTRACT <: intf J1499interface I extends J1, J2 {} // intf I.m OVERPASS <: intf J1,J2500501static class C implements I { public Object m() { return CORRECT; }}502503@DontInline504public Object test(I i) {505return i.m(); // intf I.m OVERPASS506}507508static class DI implements I { public Object m() { return WRONG; }}509510static class DJ11 implements J1 {}511static class DJ12 implements J1 { public Object m() { return WRONG; }}512513static class DJ2 implements J2 { public Object m() { return WRONG; }}514515interface K11 extends J1 {}516interface K12 extends J1 { Object m(); }517interface K13 extends J1 { default Object m() { return WRONG; }}518interface K21 extends J2 {}519interface K22 extends J2 { Object m(); }520interface K23 extends J2 { default Object m() { return WRONG; }}521522523public void testMega1() {524// 0. Trigger compilation of megamorphic call site525compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT526assertCompiled();527528// Dependency: type = unique_concrete_method, context = I, method = C.m529530checkInvalidReceiver(); // ensure proper type check on receiver is preserved531532// 1. No deopt/invalidation on not-yet-seen receiver533repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT534assertCompiled();535536// 2. No dependency invalidation: different context537initialize(K11.class, K12.class, K13.class,538K21.class, K22.class, K23.class);539540// 3. Dependency invalidation: Cn.m <: C <: I541call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT542assertNotCompiled();543544// 4. Recompilation w/o a dependency545compile(megamorphic());546call(new C() { public Object m() { return CORRECT; }});547assertCompiled(); // no inlining548549checkInvalidReceiver(); // ensure proper type check on receiver is preserved550}551552public void testMega2() {553// 0. Trigger compilation of a megamorphic call site554compile(megamorphic());555assertCompiled();556557// Dependency: type = unique_concrete_method, context = I, method = C.m558559checkInvalidReceiver(); // ensure proper type check on receiver is preserved560561// 1. No dependency invalidation: different context562initialize(DJ11.class,563DJ12.class,564DJ2.class);565assertCompiled();566567// 2. Dependency invalidation: DI.m <: I568initialize(DI.class);569assertNotCompiled();570571// 3. Recompilation w/o a dependency572compile(megamorphic());573call(new C() { public Object m() { return CORRECT; }});574assertCompiled(); // no inlining575576checkInvalidReceiver(); // ensure proper type check on receiver is preserved577}578579@Override580public void checkInvalidReceiver() {581shouldThrow(IncompatibleClassChangeError.class, () -> {582I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated583test(o);584});585assertCompiled();586587shouldThrow(IncompatibleClassChangeError.class, () -> {588I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() {}); // super interface589test(j);590});591assertCompiled();592593shouldThrow(IncompatibleClassChangeError.class, () -> {594I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() { public Object m() { return WRONG; }}); // super interface595test(j);596});597assertCompiled();598}599}600601public static class ThreeLevelDefaultHierarchy extends ATest<ThreeLevelDefaultHierarchy.I> {602public ThreeLevelDefaultHierarchy() { super(I.class, C.class); }603604interface J { default Object m() { return WRONG; }}605interface I extends J {}606607static class C implements I { public Object m() { return CORRECT; }}608609interface K1 extends I {}610interface K2 extends I { Object m(); }611interface K3 extends J { default Object m() { return WRONG; }}612613static class DI implements I { public Object m() { return WRONG; }}614static class DJ implements J { public Object m() { return WRONG; }}615static class DK3 implements K3 {}616617@DontInline618public Object test(I i) {619return i.m();620}621622@TestCase623public void testMega() {624// 0. Trigger compilation of a megamorphic call site625compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT626assertCompiled();627628// Dependency: type = unique_concrete_method, context = I, method = C.m629630checkInvalidReceiver(); // ensure proper type check on receiver is preserved631632// 1. No deoptimization/invalidation on not-yet-seen receiver633repeat(100, () -> call(new C() {}));634assertCompiled();635636// 2. No dependency invalidation637initialize(DJ.class, // DJ.m <: intf J.m ABSTRACT638K1.class, // intf K1 <: intf I <: intf J.m ABSTRACT639K2.class, // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT640DK3.class); // DK3.m <: intf K3.m DEFAULT <: intf J.m ABSTRACT641assertCompiled();642643// 3. Dependency invalidation644initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT645assertNotCompiled();646647// 4. Recompilation w/o a dependency648compile(megamorphic());649call(new C() { public Object m() { return CORRECT; }});650assertCompiled(); // no inlining651}652653@Override654public void checkInvalidReceiver() {655shouldThrow(IncompatibleClassChangeError.class, () -> {656I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated657test(o);658});659assertCompiled();660661shouldThrow(IncompatibleClassChangeError.class, () -> {662I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface663test(j);664});665assertCompiled();666}667}668669public static class ThreeLevelDefaultHierarchy1 extends ATest<ThreeLevelDefaultHierarchy1.I> {670public ThreeLevelDefaultHierarchy1() { super(I.class, C.class); }671672interface J1 { Object m();}673interface J2 extends J1 { default Object m() { return WRONG; } }674interface I extends J1, J2 {}675676static class C implements I { public Object m() { return CORRECT; }}677678interface K1 extends I {}679interface K2 extends I { Object m(); }680interface K3 extends I { default Object m() { return WRONG; }}681682static class DI implements I { public Object m() { return WRONG; }}683static class DJ1 implements J1 { public Object m() { return WRONG; }}684static class DJ2 implements J2 { public Object m() { return WRONG; }}685686@DontInline687public Object test(I i) {688return i.m();689}690691@TestCase692public void testMega() {693// 0. Trigger compilation of a megamorphic call site694compile(megamorphic());695assertCompiled();696697// Dependency: type = unique_concrete_method, context = I, method = C.m698699checkInvalidReceiver(); // ensure proper type check on receiver is preserved700701// 1. No deoptimization/invalidation on not-yet-seen receiver702repeat(100, () -> call(new C() {}));703assertCompiled();704705// 2. No dependency invalidation706initialize(DJ1.class,707DJ2.class,708K1.class,709K2.class,710K3.class);711assertCompiled();712713// 3. Dependency invalidation714initialize(DI.class); // DI.m <: intf I <: intf J.m ABSTRACT715assertNotCompiled();716717// 4. Recompilation w/o a dependency718compile(megamorphic());719call(new C() { public Object m() { return CORRECT; }});720assertCompiled(); // no inlining721}722723@Override724public void checkInvalidReceiver() {725shouldThrow(IncompatibleClassChangeError.class, () -> {726I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated727test(o);728});729assertCompiled();730731shouldThrow(IncompatibleClassChangeError.class, () -> {732I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() { public Object m() { return WRONG; } }); // super interface733test(j);734});735assertCompiled();736737shouldThrow(IncompatibleClassChangeError.class, () -> {738I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() {}); // super interface739test(j);740});741assertCompiled();742}743}744}745746747