test/hotspot/jtreg/compiler/cha/StrengthReduceInterfaceCall.java
author vlivanov
Thu, 14 Feb 2019 15:27:12 -0800
changeset 53764 8bf7e0823202
parent 53595 8462b295c08b
permissions -rw-r--r--
8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event Reviewed-by: iignatyev
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
53595
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     1
/*
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     2
 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     4
 *
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     7
 * published by the Free Software Foundation.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     8
 *
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    13
 * accompanied this code).
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    14
 *
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    18
 *
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    21
 * questions.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    22
 */
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    23
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    24
/*
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    25
 * @test
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    26
 * @requires !vm.graal.enabled
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    27
 * @modules java.base/jdk.internal.org.objectweb.asm
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    28
 *          java.base/jdk.internal.misc
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    29
 *          java.base/jdk.internal.vm.annotation
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    30
 * @library /test/lib /
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    31
 * @build sun.hotspot.WhiteBox
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    32
 * @run driver ClassFileInstaller sun.hotspot.WhiteBox
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    33
 *                                sun.hotspot.WhiteBox$WhiteBoxPermission
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    34
 *
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    35
 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    36
 *                   -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    37
 *                   -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=compileonly,*::m -XX:CompileCommand=dontinline,*::test
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    38
 *                   -Xbatch -XX:+WhiteBoxAPI -Xmixed
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    39
 *                   -XX:-TieredCompilation
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    40
 *                      compiler.cha.StrengthReduceInterfaceCall
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    41
 *
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    42
 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    43
 *                   -XX:+PrintCompilation -XX:+PrintInlining -XX:+TraceDependencies -verbose:class -XX:CompileCommand=quiet
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    44
 *                   -XX:CompileCommand=compileonly,*::test -XX:CompileCommand=compileonly,*::m -XX:CompileCommand=dontinline,*::test
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    45
 *                   -Xbatch -XX:+WhiteBoxAPI -Xmixed
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    46
 *                   -XX:+TieredCompilation -XX:TieredStopAtLevel=1
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    47
 *                      compiler.cha.StrengthReduceInterfaceCall
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    48
 */
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    49
package compiler.cha;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    50
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    51
import jdk.internal.misc.Unsafe;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    52
import jdk.internal.org.objectweb.asm.ClassWriter;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    53
import jdk.internal.org.objectweb.asm.MethodVisitor;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    54
import jdk.internal.vm.annotation.DontInline;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    55
import sun.hotspot.WhiteBox;
53764
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
    56
import sun.hotspot.code.NMethod;
53595
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    57
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    58
import java.io.IOException;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    59
import java.lang.annotation.Retention;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    60
import java.lang.annotation.RetentionPolicy;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    61
import java.lang.invoke.MethodHandle;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    62
import java.lang.invoke.MethodHandles;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    63
import java.lang.reflect.Method;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    64
import java.util.HashMap;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    65
import java.util.concurrent.Callable;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    66
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    67
import static jdk.test.lib.Asserts.*;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    68
import static jdk.internal.org.objectweb.asm.ClassWriter.*;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    69
import static jdk.internal.org.objectweb.asm.Opcodes.*;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    70
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    71
public class StrengthReduceInterfaceCall {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    72
    public static void main(String[] args) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    73
        run(ObjectToString.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    74
        run(ObjectHashCode.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    75
        run(TwoLevelHierarchyLinear.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    76
        run(ThreeLevelHierarchyLinear.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    77
        run(ThreeLevelHierarchyAbstractVsDefault.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    78
        run(ThreeLevelDefaultHierarchy.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    79
        run(ThreeLevelDefaultHierarchy1.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    80
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    81
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    82
    public static class ObjectToString extends ATest<ObjectToString.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    83
        public ObjectToString() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    84
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    85
        interface J           { String toString(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    86
        interface I extends J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    87
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    88
        static class C implements I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    89
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    90
        interface K1 extends I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    91
        interface K2 extends I { String toString(); } // K2.tS() ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    92
        // interface K3 extends I { default String toString() { return "K3"; } // K2.tS() DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    93
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    94
        static class D implements I { public String toString() { return "D"; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    95
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    96
        static class DJ1 implements J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    97
        static class DJ2 implements J { public String toString() { return "DJ2"; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    98
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
    99
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   100
        public Object test(I i) { return ObjectToStringHelper.test(i); /* invokeinterface I.toString() */ }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   101
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   102
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   103
        public void testMono() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   104
            // 0. Trigger compilation of a monomorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   105
            compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.toString()
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   106
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   107
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   108
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   109
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   110
            call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   111
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   112
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   113
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   114
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   115
        public void testBi() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   116
            // 0. Trigger compilation of a bimorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   117
            compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   118
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   119
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   120
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   121
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   122
            call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   123
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   124
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   125
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   126
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   127
        public void testMega() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   128
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   129
            compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.toString()
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   130
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   131
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   132
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   133
            // compiler.cha.StrengthReduceInterfaceCall$ObjectToString::test (5 bytes)
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   134
            //     @ 1   compiler.cha.StrengthReduceInterfaceCall$ObjectToStringHelper::test (7 bytes)   inline (hot)
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   135
            //       @ 1   java.lang.Object::toString (36 bytes)   virtual call
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   136
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   137
            // No dependency - no invalidation
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   138
            repeat(100, () -> call(new C(){})); // Cn <: C <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   139
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   140
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   141
            initialize(K1.class,   // intf  K1             <: intf I <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   142
                       K2.class,   // intf  K2.tS ABSTRACT <: intf I <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   143
                       DJ1.class,  //      DJ1                       <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   144
                       DJ2.class); //      DJ2.tS                    <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   145
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   146
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   147
            initialize(D.class); // D.tS <: intf I <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   148
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   149
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   150
            call(new C() { public String toString() { return "Cn"; }}); // Cn.tS <: C.tS <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   151
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   152
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   153
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   154
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   155
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   156
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   157
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   158
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   159
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   160
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   161
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   162
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   163
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   164
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   165
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   166
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   167
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   168
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   169
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   170
    public static class ObjectHashCode extends ATest<ObjectHashCode.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   171
        public ObjectHashCode() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   172
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   173
        interface J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   174
        interface I extends J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   175
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   176
        static class C implements I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   177
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   178
        interface K1 extends I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   179
        interface K2 extends I { int hashCode(); } // K2.hC() ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   180
        // interface K3 extends I { default int hashCode() { return CORRECT; } // K2.hC() DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   181
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   182
        static class D implements I { public int hashCode() { return super.hashCode(); }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   183
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   184
        static class DJ1 implements J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   185
        static class DJ2 implements J { public int hashCode() { return super.hashCode(); }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   186
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   187
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   188
        public Object test(I i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   189
            return ObjectHashCodeHelper.test(i); /* invokeinterface I.hashCode() */
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   190
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   191
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   192
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   193
        public void testMono() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   194
            // 0. Trigger compilation of a monomorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   195
            compile(monomophic()); // C1 <: C <: intf I <: intf J <: Object.hashCode()
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   196
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   197
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   198
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   199
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   200
            call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   201
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   202
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   203
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   204
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   205
        public void testBi() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   206
            // 0. Trigger compilation of a bimorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   207
            compile(bimorphic()); // C1 <: C <: intf I <: intf J <: Object.toString()
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   208
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   209
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   210
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   211
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   212
            call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   213
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   214
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   215
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   216
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   217
        public void testMega() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   218
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   219
            compile(megamorphic()); // C1,C2,C3 <: C <: intf I <: intf J <: Object.hashCode()
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   220
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   221
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   222
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   223
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   224
            // No dependency - no invalidation
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   225
            repeat(100, () -> call(new C(){})); // Cn <: C <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   226
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   227
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   228
            initialize(K1.class,   // intf  K1             <: intf I <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   229
                       K2.class,   // intf  K2.hC ABSTRACT <: intf I <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   230
                       DJ1.class,  //      DJ1                       <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   231
                       DJ2.class); //      DJ2.hC                    <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   232
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   233
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   234
            initialize(D.class); // D.hC <: intf I <: intf J
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   235
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   236
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   237
            call(new C() { public int hashCode() { return super.hashCode(); }}); // Cn.hC <: C.hC <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   238
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   239
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   240
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   241
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   242
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   243
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   244
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   245
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   246
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   247
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   248
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   249
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   250
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   251
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   252
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   253
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   254
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   255
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   256
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   257
    public static class TwoLevelHierarchyLinear extends ATest<TwoLevelHierarchyLinear.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   258
        public TwoLevelHierarchyLinear() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   259
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   260
        interface J { default Object m() { return WRONG; } }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   261
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   262
        interface I extends J { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   263
        static class C implements I { public Object m() { return CORRECT; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   264
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   265
        interface K1 extends I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   266
        interface K2 extends I { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   267
        interface K3 extends I { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   268
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   269
        static class D implements I { public Object m() { return WRONG;   }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   270
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   271
        static class DJ1 implements J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   272
        static class DJ2 implements J { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   273
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   274
        @DontInline
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   275
        public Object test(I i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   276
            return i.m();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   277
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   278
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   279
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   280
        public void testMega1() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   281
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   282
            compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   283
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   284
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   285
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   286
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   287
            checkInvalidReceiver(); // ensure proper type check is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   288
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   289
            // 1. No deoptimization/invalidation on not-yet-seen receiver
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   290
            repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   291
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   292
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   293
            // 2. No dependency invalidation on class loading of unrelated classes: different context
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   294
            initialize(K1.class,   // intf  K1            <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   295
                       K2.class,   // intf  K2.m ABSTRACT <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   296
                       DJ1.class,  //      DJ1                                 <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   297
                       DJ2.class); //      DJ2.m                               <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   298
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   299
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   300
            // 3. Dependency invalidation on D <: I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   301
            initialize(D.class); // D.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   302
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   303
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   304
            // 4. Recompilation: no inlining, no dependencies
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   305
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   306
            call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   307
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   308
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   309
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   310
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   311
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   312
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   313
        public void testMega2() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   314
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   315
            compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   316
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   317
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   318
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   319
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   320
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   321
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   322
            // 1. Dependency invalidation
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   323
            initialize(K3.class); // intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   324
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   325
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   326
            // 2. Recompilation: still inlines
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   327
            // FIXME: no default method support in CHA yet
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   328
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   329
            call(new K3() { public Object m() { return CORRECT; }}); // K3n.m <: intf K3.m DEFAULT <: intf I.m ABSTRACT <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   330
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   331
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   332
            // 3. Recompilation: no inlining, no dependencies
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   333
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   334
            call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: intf K3.m DEFAULT  <: intf I.m ABSTRACT <: intf J.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   335
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   336
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   337
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   338
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   339
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   340
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   341
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   342
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   343
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   344
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   345
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   346
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   347
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   348
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   349
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   350
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   351
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   352
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   353
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   354
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   355
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   356
    public static class ThreeLevelHierarchyLinear extends ATest<ThreeLevelHierarchyLinear.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   357
        public ThreeLevelHierarchyLinear() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   358
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   359
        interface J           { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   360
        interface I extends J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   361
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   362
        interface K1 extends I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   363
        interface K2 extends I { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   364
        interface K3 extends I { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   365
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   366
        static class C  implements I { public Object m() { return CORRECT; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   367
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   368
        static class DI implements I { public Object m() { return WRONG;   }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   369
        static class DJ implements J { public Object m() { return WRONG;   }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   370
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   371
        @DontInline
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   372
        public Object test(I i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   373
            return i.m(); // I <: J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   374
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   375
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   376
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   377
        public void testMega1() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   378
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   379
            compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   380
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   381
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   382
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   383
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   384
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   385
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   386
            // 1. No deoptimization/invalidation on not-yet-seen receiver
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   387
            repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   388
            assertCompiled(); // No deopt on not-yet-seen receiver
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   389
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   390
            // 2. No dependency invalidation: different context
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   391
            initialize(DJ.class,  //      DJ.m                    <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   392
                       K1.class,  // intf K1            <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   393
                       K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   394
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   395
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   396
            // 3. Dependency invalidation: DI.m <: I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   397
            initialize(DI.class); //      DI.m          <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   398
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   399
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   400
            // 4. Recompilation w/o a dependency
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   401
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   402
            call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   403
            assertCompiled(); // no dependency
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   404
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   405
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   406
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   407
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   408
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   409
        public void testMega2() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   410
            compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   411
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   412
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   413
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   414
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   415
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   416
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   417
            // Dependency invalidation
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   418
            initialize(K3.class); // intf K3.m DEFAULT <: intf I;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   419
            assertNotCompiled(); // FIXME: default methods in sub-interfaces shouldn't be taken into account by CHA
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   420
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   421
            // Recompilation with a dependency
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   422
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   423
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   424
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   425
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   426
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   427
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   428
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   429
            call(new K3() { public Object m() { return CORRECT; }}); // Kn.m <: K3.m DEFAULT <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   430
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   431
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   432
            // Recompilation w/o a dependency
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   433
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   434
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   435
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   436
            call(new C() { public Object m() { return CORRECT; }}); // Cn.m <: C.m <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   437
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   438
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   439
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   440
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   441
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   442
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   443
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   444
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   445
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   446
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   447
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   448
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   449
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() { public Object m() { return WRONG; }}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   450
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   451
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   452
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   453
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   454
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   455
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   456
    public static class ThreeLevelHierarchyAbstractVsDefault extends ATest<ThreeLevelHierarchyAbstractVsDefault.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   457
        public ThreeLevelHierarchyAbstractVsDefault() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   458
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   459
        interface J1                { default Object m() { return WRONG; } } // intf J1.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   460
        interface J2 extends J1     { Object m(); }                          // intf J2.m ABSTRACT <: intf J1
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   461
        interface I  extends J1, J2 {}                                       // intf  I.m OVERPASS <: intf J1,J2
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   462
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   463
        static class C  implements I { public Object m() { return CORRECT; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   464
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   465
        @DontInline
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   466
        public Object test(I i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   467
            return i.m(); // intf I.m OVERPASS
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   468
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   469
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   470
        static class DI implements I { public Object m() { return WRONG;   }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   471
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   472
        static class DJ11 implements J1 {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   473
        static class DJ12 implements J1 { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   474
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   475
        static class DJ2 implements J2 { public Object m() { return WRONG;   }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   476
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   477
        interface K11 extends J1 {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   478
        interface K12 extends J1 { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   479
        interface K13 extends J1 { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   480
        interface K21 extends J2 {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   481
        interface K22 extends J2 { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   482
        interface K23 extends J2 { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   483
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   484
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   485
        public void testMega1() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   486
            // 0. Trigger compilation of megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   487
            compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   488
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   489
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   490
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   491
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   492
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   493
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   494
            // 1. No deopt/invalidation on not-yet-seen receiver
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   495
            repeat(100, () -> call(new C(){})); // Cn <: C.m <: intf I.m OVERPASS <: intf J2.m ABSTRACT <: intf J1.m DEFAULT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   496
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   497
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   498
            // 2. No dependency invalidation: different context
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   499
            initialize(K11.class, K12.class, K13.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   500
                       K21.class, K22.class, K23.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   501
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   502
            // 3. Dependency invalidation: Cn.m <: C <: I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   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
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   504
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   505
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   506
            // 4. Recompilation w/o a dependency
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   507
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   508
            call(new C() { public Object m() { return CORRECT; }});
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   509
            assertCompiled(); // no inlining
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   510
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   511
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   512
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   513
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   514
        public void testMega2() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   515
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   516
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   517
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   518
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   519
            // Dependency: type = unique_concrete_method, context = I, method = C.m
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   520
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   521
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   522
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   523
            // 1. No dependency invalidation: different context
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   524
            initialize(DJ11.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   525
                       DJ12.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   526
                       DJ2.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   527
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   528
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   529
            // 2. Dependency invalidation: DI.m <: I
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   530
            initialize(DI.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   531
            assertNotCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   532
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   533
            // 3. Recompilation w/o a dependency
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   534
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   535
            call(new C() { public Object m() { return CORRECT; }});
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   536
            assertCompiled(); // no inlining
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   537
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   538
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   539
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   540
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   541
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   542
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   543
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   544
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   545
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   546
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   547
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   548
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   549
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   550
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() {}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   551
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   552
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   553
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   554
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   555
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   556
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() { public Object m() { return WRONG; }}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   557
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   558
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   559
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   560
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   561
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   562
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   563
    public static class ThreeLevelDefaultHierarchy extends ATest<ThreeLevelDefaultHierarchy.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   564
        public ThreeLevelDefaultHierarchy() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   565
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   566
        interface J           { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   567
        interface I extends J {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   568
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   569
        static class C  implements I { public Object m() { return CORRECT; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   570
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   571
        interface K1 extends I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   572
        interface K2 extends I { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   573
        interface K3 extends I { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   574
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   575
        static class DI implements I { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   576
        static class DJ implements J { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   577
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   578
        @DontInline
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   579
        public Object test(I i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   580
            return i.m(); // no inlining since J.m is a default method
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   581
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   582
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   583
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   584
        public void testMega() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   585
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   586
            compile(megamorphic()); // C1,C2,C3 <: C.m <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   587
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   588
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   589
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   590
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   591
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   592
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   593
            // 1. No deoptimization/invalidation on not-yet-seen receiver
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   594
            repeat(100, () -> call(new C() {}));
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   595
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   596
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   597
            // 2. No dependency and no inlining
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   598
            initialize(DJ.class,  //      DJ.m                    <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   599
                       DI.class,  //      DI.m          <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   600
                       K1.class,  // intf K1            <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   601
                       K2.class); // intf K2.m ABSTRACT <: intf I <: intf J.m ABSTRACT
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   602
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   603
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   604
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   605
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   606
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   607
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   608
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   609
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   610
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   611
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   612
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   613
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   614
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J() {}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   615
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   616
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   617
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   618
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   619
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   620
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   621
    public static class ThreeLevelDefaultHierarchy1 extends ATest<ThreeLevelDefaultHierarchy1.I> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   622
        public ThreeLevelDefaultHierarchy1() { super(I.class, C.class); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   623
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   624
        interface J1                { Object m();}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   625
        interface J2 extends J1     { default Object m() { return WRONG; }  }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   626
        interface I  extends J1, J2 {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   627
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   628
        static class C  implements I { public Object m() { return CORRECT; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   629
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   630
        interface K1 extends I {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   631
        interface K2 extends I { Object m(); }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   632
        interface K3 extends I { default Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   633
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   634
        static class DI implements I { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   635
        static class DJ1 implements J1 { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   636
        static class DJ2 implements J2 { public Object m() { return WRONG; }}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   637
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   638
        @DontInline
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   639
        public Object test(I i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   640
            return i.m(); // no inlining since J.m is a default method
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   641
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   642
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   643
        @TestCase
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   644
        public void testMega() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   645
            // 0. Trigger compilation of a megamorphic call site
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   646
            compile(megamorphic());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   647
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   648
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   649
            // Dependency: none
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   650
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   651
            checkInvalidReceiver(); // ensure proper type check on receiver is preserved
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   652
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   653
            // 1. No deoptimization/invalidation on not-yet-seen receiver
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   654
            repeat(100, () -> call(new C() {}));
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   655
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   656
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   657
            // 2. No dependency, no inlining
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   658
            // CHA doesn't support default methods yet.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   659
            initialize(DJ1.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   660
                       DJ2.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   661
                       DI.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   662
                       K1.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   663
                       K2.class,
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   664
                       K3.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   665
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   666
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   667
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   668
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   669
        public void checkInvalidReceiver() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   670
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   671
                I o = (I) unsafeCastMH(I.class).invokeExact(new Object()); // unrelated
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   672
                test(o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   673
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   674
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   675
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   676
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   677
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J1() { public Object m() { return WRONG; } }); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   678
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   679
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   680
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   681
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   682
            shouldThrow(IncompatibleClassChangeError.class, () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   683
                I j = (I) unsafeCastMH(I.class).invokeExact((Object)new J2() {}); // super interface
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   684
                test(j);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   685
            });
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   686
            assertCompiled();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   687
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   688
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   689
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   690
    /* =========================================================== */
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   691
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   692
    interface Action {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   693
        int run();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   694
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   695
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   696
    public static final Unsafe U = Unsafe.getUnsafe();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   697
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   698
    interface Test<T> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   699
        void call(T o);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   700
        T receiver(int id);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   701
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   702
        default Runnable monomophic() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   703
            return () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   704
                call(receiver(0)); // 100%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   705
            };
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   706
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   707
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   708
        default Runnable bimorphic() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   709
            return () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   710
                call(receiver(0)); // 50%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   711
                call(receiver(1)); // 50%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   712
            };
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   713
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   714
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   715
        default Runnable polymorphic() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   716
            return () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   717
                for (int i = 0; i < 23; i++) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   718
                    call(receiver(0)); // 92%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   719
                }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   720
                call(receiver(1)); // 4%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   721
                call(receiver(2)); // 4%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   722
            };
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   723
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   724
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   725
        default Runnable megamorphic() {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   726
            return () -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   727
                call(receiver(0)); // 33%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   728
                call(receiver(1)); // 33%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   729
                call(receiver(2)); // 33%
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   730
            };
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   731
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   732
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   733
        default void initialize(Class<?>... cs) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   734
            for (Class<?> c : cs) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   735
                U.ensureClassInitialized(c);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   736
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   737
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   738
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   739
        default void repeat(int cnt, Runnable r) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   740
            for (int i = 0; i < cnt; i++) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   741
                r.run();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   742
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   743
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   744
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   745
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   746
    public static abstract class ATest<T> implements Test<T> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   747
        public static final WhiteBox WB = WhiteBox.getWhiteBox();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   748
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   749
        public static final Object CORRECT = new Object();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   750
        public static final Object WRONG   = new Object();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   751
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   752
        final Method TEST;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   753
        private final Class<T> declared;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   754
        private final Class<?> receiver;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   755
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   756
        private final HashMap<Integer, T> receivers = new HashMap<>();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   757
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   758
        public ATest(Class<T> declared, Class<?> receiver) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   759
            this.declared = declared;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   760
            this.receiver = receiver;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   761
            TEST = compute(() -> this.getClass().getDeclaredMethod("test", declared));
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   762
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   763
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   764
        @DontInline
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   765
        public abstract Object test(T i);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   766
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   767
        public abstract void checkInvalidReceiver();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   768
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   769
        public T receiver(int id) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   770
            return receivers.computeIfAbsent(id, (i -> {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   771
                try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   772
                    MyClassLoader cl = (MyClassLoader) receiver.getClassLoader();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   773
                    Class<?> sub = cl.subclass(receiver, i);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   774
                    return (T)sub.getDeclaredConstructor().newInstance();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   775
                } catch (Exception e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   776
                    throw new Error(e);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   777
                }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   778
            }));
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   779
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   780
53764
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   781
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   782
        public void compile(Runnable r) {
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   783
            while (!WB.isMethodCompiled(TEST)) {
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   784
                for (int i = 0; i < 100; i++) {
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   785
                    r.run();
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   786
                }
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   787
            }
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   788
            assertCompiled(); // record nmethod info
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   789
        }
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   790
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   791
        private NMethod prevNM = null;
53595
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   792
53764
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   793
        public void assertNotCompiled() {
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   794
            NMethod curNM = NMethod.get(TEST, false);
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   795
            assertTrue(prevNM != null); // was previously compiled
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   796
            assertTrue(curNM == null || prevNM.compile_id != curNM.compile_id); // either no nmethod present or recompiled
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   797
            prevNM = curNM; // update nmethod info
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   798
        }
53595
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   799
53764
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   800
        public void assertCompiled() {
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   801
            NMethod curNM = NMethod.get(TEST, false);
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   802
            assertTrue(curNM != null); // nmethod is present
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   803
            assertTrue(prevNM == null || prevNM.compile_id == curNM.compile_id); // no recompilations if nmethod present
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   804
            prevNM = curNM; // update nmethod info
8bf7e0823202 8218758: [TESTBUG] compiler/cha/StrengthReduceInterfaceCall.java misses recompilation event
vlivanov
parents: 53595
diff changeset
   805
        }
53595
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   806
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   807
        @Override
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   808
        public void call(T i) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   809
            assertTrue(test(i) != WRONG);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   810
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   811
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   812
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   813
    @Retention(value = RetentionPolicy.RUNTIME)
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   814
    public @interface TestCase {}
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   815
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   816
    static void run(Class<?> test) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   817
        try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   818
            for (Method m : test.getDeclaredMethods()) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   819
                if (m.isAnnotationPresent(TestCase.class)) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   820
                    System.out.println(m.toString());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   821
                    ClassLoader cl = new MyClassLoader(test);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   822
                    Class<?> c = cl.loadClass(test.getName());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   823
                    c.getMethod(m.getName()).invoke(c.getDeclaredConstructor().newInstance());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   824
                }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   825
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   826
        } catch (Exception e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   827
            throw new Error(e);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   828
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   829
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   830
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   831
    static class ObjectToStringHelper {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   832
        static Object test(Object o) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   833
            throw new Error("not used");
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   834
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   835
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   836
    static class ObjectHashCodeHelper {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   837
        static int test(Object o) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   838
        throw new Error("not used");
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   839
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   840
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   841
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   842
    static final class MyClassLoader extends ClassLoader {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   843
        private final Class<?> test;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   844
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   845
        MyClassLoader(Class<?> test) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   846
            this.test = test;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   847
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   848
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   849
        static String intl(String s) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   850
            return s.replace('.', '/');
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   851
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   852
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   853
        Class<?> subclass(Class<?> c, int id) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   854
            String name = c.getName() + id;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   855
            Class<?> sub = findLoadedClass(name);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   856
            if (sub == null) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   857
                ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   858
                cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, intl(c.getName()), null);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   859
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   860
                { // Default constructor: <init>()V
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   861
                    MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   862
                    mv.visitCode();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   863
                    mv.visitVarInsn(ALOAD, 0);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   864
                    mv.visitMethodInsn(INVOKESPECIAL, intl(c.getName()), "<init>", "()V", false);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   865
                    mv.visitInsn(RETURN);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   866
                    mv.visitMaxs(0, 0);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   867
                    mv.visitEnd();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   868
                }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   869
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   870
                byte[] classFile = cw.toByteArray();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   871
                return defineClass(name, classFile, 0, classFile.length);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   872
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   873
            return sub;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   874
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   875
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   876
        protected Class<?> loadClass(String name, boolean resolve)
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   877
                throws ClassNotFoundException
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   878
        {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   879
            // First, check if the class has already been loaded
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   880
            Class<?> c = findLoadedClass(name);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   881
            if (c == null) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   882
                try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   883
                    c = getParent().loadClass(name);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   884
                    if (name.endsWith("ObjectToStringHelper")) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   885
                        ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   886
                        cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, "java/lang/Object", null);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   887
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   888
                        {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   889
                            MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "(Ljava/lang/Object;)Ljava/lang/Object;", null, null);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   890
                            mv.visitCode();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   891
                            mv.visitVarInsn(ALOAD, 0);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   892
                            mv.visitMethodInsn(INVOKEINTERFACE, intl(test.getName()) + "$I", "toString", "()Ljava/lang/String;", true);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   893
                            mv.visitInsn(ARETURN);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   894
                            mv.visitMaxs(0, 0);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   895
                            mv.visitEnd();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   896
                        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   897
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   898
                        byte[] classFile = cw.toByteArray();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   899
                        return defineClass(name, classFile, 0, classFile.length);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   900
                    } else if (name.endsWith("ObjectHashCodeHelper")) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   901
                        ClassWriter cw = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   902
                        cw.visit(52, ACC_PUBLIC | ACC_SUPER, intl(name), null, "java/lang/Object", null);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   903
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   904
                        {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   905
                            MethodVisitor mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "test", "(Ljava/lang/Object;)I", null, null);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   906
                            mv.visitCode();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   907
                            mv.visitVarInsn(ALOAD, 0);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   908
                            mv.visitMethodInsn(INVOKEINTERFACE, intl(test.getName()) + "$I", "hashCode", "()I", true);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   909
                            mv.visitInsn(IRETURN);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   910
                            mv.visitMaxs(0, 0);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   911
                            mv.visitEnd();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   912
                        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   913
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   914
                        byte[] classFile = cw.toByteArray();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   915
                        return defineClass(name, classFile, 0, classFile.length);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   916
                    } else if (c == test || name.startsWith(test.getName())) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   917
                        try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   918
                            String path = name.replace('.', '/') + ".class";
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   919
                            byte[] classFile = getParent().getResourceAsStream(path).readAllBytes();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   920
                            return defineClass(name, classFile, 0, classFile.length);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   921
                        } catch (IOException e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   922
                            throw new Error(e);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   923
                        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   924
                    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   925
                } catch (ClassNotFoundException e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   926
                    // ClassNotFoundException thrown if class not found
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   927
                    // from the non-null parent class loader
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   928
                }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   929
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   930
                if (c == null) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   931
                    // If still not found, then invoke findClass in order
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   932
                    // to find the class.
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   933
                    c = findClass(name);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   934
                }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   935
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   936
            if (resolve) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   937
                resolveClass(c);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   938
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   939
            return c;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   940
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   941
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   942
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   943
    public interface RunnableWithException {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   944
        void run() throws Throwable;
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   945
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   946
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   947
    public static void shouldThrow(Class<? extends Throwable> expectedException, RunnableWithException r) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   948
        try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   949
            r.run();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   950
            throw new AssertionError("Exception not thrown: " + expectedException.getName());
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   951
        } catch(Throwable e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   952
            if (expectedException == e.getClass()) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   953
                // success: proper exception is thrown
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   954
            } else {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   955
                throw new Error(expectedException.getName() + " is expected", e);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   956
            }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   957
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   958
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   959
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   960
    public static MethodHandle unsafeCastMH(Class<?> cls) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   961
        try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   962
            MethodHandle mh = MethodHandles.identity(Object.class);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   963
            return MethodHandles.explicitCastArguments(mh, mh.type().changeReturnType(cls));
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   964
        } catch (Throwable e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   965
            throw new Error(e);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   966
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   967
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   968
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   969
    static <T> T compute(Callable<T> c) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   970
        try {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   971
            return c.call();
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   972
        } catch (Exception e) {
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   973
            throw new Error(e);
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   974
        }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   975
    }
8462b295c08b 6986483: CHA: optimize calls through interfaces
vlivanov
parents:
diff changeset
   976
}