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