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