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 /testlibrary /../../test/lib 28 * @build InvokeTest NonInlinedReinvoker 29 * @run main ClassFileInstaller sun.hotspot.WhiteBox 30 * sun.hotspot.WhiteBox$WhiteBoxPermission 31 * java.lang.invoke.InvokeTest 32 * java.lang.invoke.InvokeTest$T 33 * java.lang.invoke.InvokeTest$P1 34 * java.lang.invoke.InvokeTest$P2 35 * java.lang.invoke.InvokeTest$I 36 * java.lang.invoke.NonInlinedReinvoker 37 * jdk.test.lib.Asserts 38 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions 39 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 40 * -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 41 * java.lang.invoke.InvokeTest 42 */ 43 package java.lang.invoke; 44 45 import sun.hotspot.WhiteBox; 46 47 import jdk.internal.vm.annotation.DontInline; 48 49 import static jdk.test.lib.Asserts.*; 50 51 public class InvokeTest { 52 static MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP; 53 54 static final MethodHandle virtualMH; // invokevirtual T.f1 55 static final MethodHandle staticMH; // invokestatic T.f2 56 static final MethodHandle intfMH; // invokeinterface I.f1 57 static final MethodHandle specialMH; // invokespecial T.f4 T 58 static final MethodHandle basicMH; 59 60 static final WhiteBox WB = WhiteBox.getWhiteBox(); 61 62 static volatile boolean doDeopt = false; 63 64 static { 65 try { 66 MethodType mtype = MethodType.methodType(Class.class); 67 68 virtualMH = LOOKUP.findVirtual(T.class, "f1", mtype); 69 staticMH = LOOKUP.findStatic (T.class, "f2", mtype); 70 intfMH = LOOKUP.findVirtual(I.class, "f3", mtype); 71 specialMH = LOOKUP.findSpecial(T.class, "f4", mtype, T.class); 72 basicMH = NonInlinedReinvoker.make(staticMH); 73 } catch (Exception e) { 74 throw new Error(e); 75 } 76 } 77 78 static class T implements I { 79 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimize(); return T.class; } 80 @DontInline public static Class<?> f2() { if (doDeopt) WB.deoptimize(); return T.class; } 81 @DontInline private Class<?> f4() { if (doDeopt) WB.deoptimize(); return T.class; } 82 } 83 84 static class P1 extends T { 85 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimize(); return P1.class; } 86 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimize(); return P1.class; } 87 } 88 89 static class P2 extends T { 90 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimize(); return P2.class; } 91 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimize(); return P2.class; } 92 } 93 94 static interface I { 95 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimize(); return I.class; } 96 } 97 98 @DontInline 99 static void linkToVirtual(Object obj, Class<?> extecpted) { 100 try { 101 Class<?> cls = (Class<?>)virtualMH.invokeExact((T)obj); 102 assertEquals(cls, obj.getClass()); 103 } catch (Throwable e) { 104 throw new Error(e); 105 } 106 } 107 108 @DontInline 109 static void linkToInterface(Object obj, Class<?> expected) { 110 try { 111 Class<?> cls = (Class<?>)intfMH.invokeExact((I)obj); 112 assertEquals(cls, expected); 113 } catch (Throwable e) { 114 throw new Error(e); 115 } 116 } 117 118 @DontInline 119 static void linkToStatic() { 120 try { 121 Class<?> cls = (Class<?>)staticMH.invokeExact(); 122 assertEquals(cls, T.class); 123 } catch (Throwable e) { 124 throw new Error(e); 125 } 126 } 127 128 @DontInline 129 static void linkToSpecial(Object obj, Class<?> expected) { 130 try { 131 Class<?> cls = (Class<?>)specialMH.invokeExact((T)obj); 132 assertEquals(cls, expected); 133 } catch (Throwable e) { 134 throw new Error(e); 135 } 136 } 137 138 @DontInline 139 static void invokeBasic() { 140 try { 141 Class<?> cls = (Class<?>)basicMH.invokeBasic(); 142 assertEquals(cls, T.class); 143 } catch (Throwable e) { 144 throw new Error(e); 145 } 146 } 147 148 static void run(Runnable r) { 149 for (int i = 0; i < 20_000; i++) { 150 r.run(); 151 } 152 153 doDeopt = true; 154 r.run(); 155 doDeopt = false; 156 157 WB.clearInlineCaches(); 158 159 for (int i = 0; i < 20_000; i++) { 160 r.run(); 161 } 162 163 doDeopt = true; 164 r.run(); 165 doDeopt = false; 166 } 167 168 static void testVirtual() { 169 System.out.println("linkToVirtual"); 170 171 // Monomorphic case (optimized virtual call) 172 run(() -> linkToVirtual(new T(), T.class)); 173 174 // Megamorphic case (virtual call) 175 Object[] recv = new Object[] { new T(), new P1(), new P2() }; 176 run(() -> { 177 for (Object r : recv) { 178 linkToVirtual(r, r.getClass()); 179 }}); 180 } 181 182 static void testInterface() { 183 System.out.println("linkToInterface"); 184 185 // Monomorphic case (optimized virtual call) 186 run(() -> linkToInterface(new T(), I.class)); 187 188 // Megamorphic case (virtual call) 189 Object[][] recv = new Object[][] {{new T(), I.class}, {new P1(), P1.class}, {new P2(), P2.class}}; 190 run(() -> { 191 for (Object[] r : recv) { 192 linkToInterface(r[0], (Class<?>)r[1]); 193 }}); 194 } 195 196 static void testSpecial() { 197 System.out.println("linkToSpecial"); 198 // Monomorphic case (optimized virtual call) 199 run(() -> linkToSpecial(new T(), T.class)); 200 } 201 202 static void testStatic() { 203 System.out.println("linkToStatic"); 204 // static call 205 run(() -> linkToStatic()); 206 } 207 208 static void testBasic() { 209 System.out.println("invokeBasic"); 210 // static call 211 run(() -> invokeBasic()); 212 } 213 214 public static void main(String[] args) { 215 testVirtual(); 216 testInterface(); 217 testSpecial(); 218 testStatic(); 219 testBasic(); 220 } 221 }