/*
 * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

/*
 * @test
 * @requires !vm.graal.enabled & vm.opt.final.UseVtableBasedCHA == true
 * @modules java.base/jdk.internal.org.objectweb.asm
 *          java.base/jdk.internal.misc
 *          java.base/jdk.internal.vm.annotation
 * @library /test/lib /
 * @compile Utils.java
 * @build jdk.test.whitebox.WhiteBox
 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 *
 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
 *                   -XX:+PrintCompilation -XX:+PrintInlining -Xlog:dependencies=debug -verbose:class -XX:CompileCommand=quiet
 *                   -XX:CompileCommand=compileonly,*::m
 *                   -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test
 *                   -XX:CompileCommand=compileonly,*::testHelper -XX:CompileCommand=inline,*::testHelper
 *                   -Xbatch -Xmixed -XX:+WhiteBoxAPI
 *                   -XX:-TieredCompilation
 *                      compiler.cha.StrengthReduceInterfaceCall
 *
 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
 *                   -XX:+PrintCompilation -XX:+PrintInlining -Xlog:dependencies=debug -verbose:class -XX:CompileCommand=quiet
 *                   -XX:CompileCommand=compileonly,*::m
 *                   -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=dontinline,*::test
 *                   -XX:CompileCommand=compileonly,*::testHelper -XX:CompileCommand=inline,*::testHelper
 *                   -Xbatch -Xmixed -XX:+WhiteBoxAPI
 *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
 *                      compiler.cha.StrengthReduceInterfaceCall
 */
package compiler.cha;

import jdk.internal.vm.annotation.DontInline;

import static compiler.cha.Utils.*;

public class StrengthReduceInterfaceCall {
    public static void main(String[] args) {
        run(ObjectToString.class);
        run(ObjectHashCode.class);
        run(TwoLevelHierarchyLinear.class);
        run(ThreeLevelHierarchyLinear.class);
        run(ThreeLevelHierarchyAbstractVsDefault.class);
        run(ThreeLevelDefaultHierarchy.class);
        run(ThreeLevelDefaultHierarchy1.class);
        System.out.println("TEST PASSED");
    }

    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.testHelper(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.testHelper(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;   }}
        interface K4 extends I { default Object m() { return CORRECT; }}

        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. No invalidation: interfaces don't participate in CHA.
            initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
            assertCompiled();

            // 2. Dependency invalidation on K3n <: I with concrete method.
            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; }}); // K3n.m <: intf K3.m DEFAULT  <: intf I.m ABSTRACT <: intf J.m DEFAULT
            assertCompiled();

            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
        }

        @TestCase
        public void testMega3() {
            // 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. No invalidation: interfaces don't participate in CHA.
            initialize(K4.class); // intf K4.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
            assertCompiled();

            // 2. Dependency invalidation on K4n <: I with default method.
            call(new K4() { /* default method K4.m */ }); // K4n <: intf K4.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT
            assertNotCompiled();

            // 3. Recompilation: no inlining, no dependencies
            compile(megamorphic());
            call(new K4() { /* default method K4.m */  }); // K4n <: 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;   }}
        interface K4 extends I { default Object m() { return CORRECT; }}

        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

            // No invalidation: interfaces don't participate in CHA.
            initialize(K3.class); // intf K3.m DEFAULT <: intf I;
            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();
        }

        @TestCase
        public void testMega3() {
            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

            // No invalidation: interfaces don't participate in CHA.
            initialize(K4.class); // intf K3.m DEFAULT <: intf I;
            assertCompiled();

            // Dependency: type = unique_concrete_method, context = I, method = C.m

            checkInvalidReceiver(); // ensure proper type check on receiver is preserved

            call(new K4() { /* default method K4.m */ }); // K4n <: K4.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 J { 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; }}
        static class DK3 implements K3 {}

        @DontInline
        public Object test(I i) {
            return i.m();
        }

        @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: 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() {}));
            assertCompiled();

            // 2. No dependency invalidation
            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
                       DK3.class); //      DK3.m          <: intf K3.m DEFAULT <: intf J.m ABSTRACT
            assertCompiled();

            // 3. Dependency invalidation
            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; }});
            assertCompiled(); // no inlining
        }

        @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();
        }

        @TestCase
        public void testMega() {
            // 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 deoptimization/invalidation on not-yet-seen receiver
            repeat(100, () -> call(new C() {}));
            assertCompiled();

            // 2. No dependency invalidation
            initialize(DJ1.class,
                       DJ2.class,
                       K1.class,
                       K2.class,
                       K3.class);
            assertCompiled();

            // 3. Dependency invalidation
            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; }});
            assertCompiled(); // no inlining
        }

        @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();
        }
    }
}
