1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @bug 8072008 27 * @library /test/lib / ../patches 28 * @modules java.base/jdk.internal.misc 29 * java.base/jdk.internal.vm.annotation 30 * 31 * @build java.base/java.lang.invoke.MethodHandleHelper 32 * sun.hotspot.WhiteBox 33 * @run main/bootclasspath/othervm -XX:+IgnoreUnrecognizedVMOptions 34 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 35 * -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 36 * compiler.jsr292.NonInlinedCall.InvokeTest 37 */ 38 39 package compiler.jsr292.NonInlinedCall; 40 41 import jdk.internal.vm.annotation.DontInline; 42 import sun.hotspot.WhiteBox; 43 44 import java.lang.invoke.MethodHandle; 45 import java.lang.invoke.MethodHandleHelper; 46 import java.lang.invoke.MethodHandleHelper.NonInlinedReinvoker; 47 import java.lang.invoke.MethodHandles; 48 import java.lang.invoke.MethodType; 49 50 import static jdk.test.lib.Asserts.assertEquals; 51 52 public class InvokeTest { 53 static MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP; 54 55 static final MethodHandle virtualMH; // invokevirtual T.f1 56 static final MethodHandle staticMH; // invokestatic T.f2 57 static final MethodHandle intfMH; // invokeinterface I.f1 58 static final MethodHandle specialMH; // invokespecial T.f4 T 59 static final MethodHandle basicMH; 60 61 static final WhiteBox WB = WhiteBox.getWhiteBox(); 62 63 static volatile boolean doDeopt = false; 64 65 static { 66 try { 67 MethodType mtype = MethodType.methodType(Class.class); 68 69 virtualMH = LOOKUP.findVirtual(T.class, "f1", mtype); 70 staticMH = LOOKUP.findStatic (T.class, "f2", mtype); 71 intfMH = LOOKUP.findVirtual(I.class, "f3", mtype); 72 specialMH = LOOKUP.findSpecial(T.class, "f4", mtype, T.class); 73 basicMH = NonInlinedReinvoker.make(staticMH); 74 } catch (Exception e) { 75 throw new Error(e); 76 } 77 } 78 79 static class T implements I { 80 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return T.class; } 81 @DontInline public static Class<?> f2() { if (doDeopt) WB.deoptimizeAll(); return T.class; } 82 @DontInline private Class<?> f4() { if (doDeopt) WB.deoptimizeAll(); return T.class; } 83 } 84 85 static class P1 extends T { 86 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P1.class; } 87 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P1.class; } 88 } 89 90 static class P2 extends T { 91 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P2.class; } 92 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P2.class; } 93 } 94 95 static interface I { 96 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return I.class; } 97 } 98 99 @DontInline 100 static void linkToVirtual(Object obj, Class<?> extecpted) { 101 try { 102 Class<?> cls = (Class<?>)virtualMH.invokeExact((T)obj); 103 assertEquals(cls, obj.getClass()); 104 } catch (Throwable e) { 105 throw new Error(e); 106 } 107 } 108 109 @DontInline 110 static void linkToInterface(Object obj, Class<?> expected) { 111 try { 112 Class<?> cls = (Class<?>)intfMH.invokeExact((I)obj); 113 assertEquals(cls, expected); 114 } catch (Throwable e) { 115 throw new Error(e); 116 } 117 } 118 119 @DontInline 120 static void linkToStatic() { 121 try { 122 Class<?> cls = (Class<?>)staticMH.invokeExact(); 123 assertEquals(cls, T.class); 124 } catch (Throwable e) { 125 throw new Error(e); 126 } 127 } 128 129 @DontInline 130 static void linkToSpecial(Object obj, Class<?> expected) { 131 try { 132 Class<?> cls = (Class<?>)specialMH.invokeExact((T)obj); 133 assertEquals(cls, expected); 134 } catch (Throwable e) { 135 throw new Error(e); 136 } 137 } 138 139 @DontInline 140 static void invokeBasic() { 141 try { 142 Class<?> cls = (Class<?>)MethodHandleHelper.invokeBasicL(basicMH); 143 assertEquals(cls, T.class); 144 } catch (Throwable e) { 145 throw new Error(e); 146 } 147 } 148 149 static void run(Runnable r) { 150 for (int i = 0; i < 20_000; i++) { 151 r.run(); 152 } 153 154 doDeopt = true; 155 r.run(); 156 doDeopt = false; 157 158 WB.clearInlineCaches(); 159 160 for (int i = 0; i < 20_000; i++) { 161 r.run(); 162 } 163 164 doDeopt = true; 165 r.run(); 166 doDeopt = false; 167 } 168 169 static void testVirtual() { 170 System.out.println("linkToVirtual"); 171 172 // Monomorphic case (optimized virtual call) 173 run(() -> linkToVirtual(new T(), T.class)); 174 175 // Megamorphic case (virtual call) 176 Object[] recv = new Object[] { new T(), new P1(), new P2() }; 177 run(() -> { 178 for (Object r : recv) { 179 linkToVirtual(r, r.getClass()); 180 }}); 181 } 182 183 static void testInterface() { 184 System.out.println("linkToInterface"); 185 186 // Monomorphic case (optimized virtual call), concrete target method 187 run(() -> linkToInterface(new P1(), P1.class)); 188 189 // Monomorphic case (optimized virtual call), default target method 190 run(() -> linkToInterface(new T(), I.class)); 191 192 // Megamorphic case (virtual call) 193 Object[][] recv = new Object[][] {{new T(), I.class}, {new P1(), P1.class}, {new P2(), P2.class}}; 194 run(() -> { 195 for (Object[] r : recv) { 196 linkToInterface(r[0], (Class<?>)r[1]); 197 }}); 198 } 199 200 static void testSpecial() { 201 System.out.println("linkToSpecial"); 202 // Monomorphic case (optimized virtual call) 203 run(() -> linkToSpecial(new T(), T.class)); 204 } 205 206 static void testStatic() { 207 System.out.println("linkToStatic"); 208 // static call 209 run(() -> linkToStatic()); 210 } 211 212 static void testBasic() { 213 System.out.println("invokeBasic"); 214 // static call 215 run(() -> invokeBasic()); 216 } 217 218 public static void main(String[] args) { 219 testVirtual(); 220 testInterface(); 221 testSpecial(); 222 testStatic(); 223 testBasic(); 224 } 225 }