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