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.f3
58 static final MethodHandle defaultMH; // invokevirtual T.f3
59 static final MethodHandle specialMH; // invokespecial T.f4 T
60 static final MethodHandle privateMH; // invokespecial I.f4 T
61 static final MethodHandle basicMH;
62
63 static final WhiteBox WB = WhiteBox.getWhiteBox();
64
65 static volatile boolean doDeopt = false;
66
67 static {
68 try {
69 MethodType mtype = MethodType.methodType(Class.class);
70
71 virtualMH = LOOKUP.findVirtual(T.class, "f1", mtype);
72 staticMH = LOOKUP.findStatic (T.class, "f2", mtype);
73 intfMH = LOOKUP.findVirtual(I.class, "f3", mtype);
74 defaultMH = LOOKUP.findVirtual(T.class, "f3", mtype);
75 specialMH = LOOKUP.findSpecial(T.class, "f4", mtype, T.class);
76 privateMH = LOOKUP.findSpecial(I.class, "f4", mtype, I.class);
77 basicMH = NonInlinedReinvoker.make(staticMH);
78 } catch (Exception e) {
79 throw new Error(e);
80 }
81 }
82
83 static class T implements I {
84 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
85 @DontInline public static Class<?> f2() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
86 @DontInline private Class<?> f4() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
87 }
88
89 static class P1 extends T {
90 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P1.class; }
91 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P1.class; }
92 }
93
94 static class P2 extends T {
95 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P2.class; }
96 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P2.class; }
97 }
100 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return I.class; }
101 @DontInline private Class<?> f4() { if (doDeopt) WB.deoptimizeAll(); return I.class; }
102 }
103
104 interface J1 extends I {
105 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return J1.class; }
106 }
107
108 interface J2 extends I {
109 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return J2.class; }
110 }
111
112 interface J3 extends I {
113 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return J3.class; }
114 }
115
116 static class Q1 extends T implements J1 {}
117 static class Q2 extends T implements J2 {}
118 static class Q3 extends T implements J3 {}
119
120 @DontInline
121 static void linkToVirtual(T recv, Class<?> expected) {
122 try {
123 Class<?> cls = (Class<?>)virtualMH.invokeExact(recv);
124 assertEquals(cls, expected);
125 } catch (Throwable e) {
126 throw new Error(e);
127 }
128 }
129
130 @DontInline
131 static void linkToVirtualDefault(T recv, Class<?> expected) {
132 try {
133 Class<?> cls = (Class<?>)defaultMH.invokeExact(recv);
134 assertEquals(cls, expected);
135 } catch (Throwable e) {
136 throw new Error(e);
137 }
138 }
139
140 @DontInline
141 static void linkToInterface(I recv, Class<?> expected) {
142 try {
143 Class<?> cls = (Class<?>)intfMH.invokeExact(recv);
144 assertEquals(cls, expected);
145 } catch (Throwable e) {
146 throw new Error(e);
147 }
148 }
149
150 @DontInline
151 static void linkToStatic() {
152 try {
153 Class<?> cls = (Class<?>)staticMH.invokeExact();
154 assertEquals(cls, T.class);
155 } catch (Throwable e) {
156 throw new Error(e);
157 }
158 }
159
160 @DontInline
161 static void linkToSpecial(T recv, Class<?> expected) {
162 try {
163 Class<?> cls = (Class<?>)specialMH.invokeExact(recv);
164 assertEquals(cls, expected);
165 } catch (Throwable e) {
166 throw new Error(e);
167 }
168 }
169
170 @DontInline
171 static void linkToSpecialIntf(I recv, Class<?> expected) {
172 try {
173 Class<?> cls = (Class<?>)privateMH.invokeExact(recv);
174 assertEquals(cls, expected);
175 } catch (Throwable e) {
176 throw new Error(e);
177 }
178 }
179
180
181 @DontInline
182 static void invokeBasic() {
183 try {
184 Class<?> cls = (Class<?>)MethodHandleHelper.invokeBasicL(basicMH);
185 assertEquals(cls, T.class);
186 } catch (Throwable e) {
187 throw new Error(e);
188 }
189 }
190
191 static void run(Runnable r) {
192 for (int i = 0; i < 20_000; i++) {
193 r.run();
194 }
195
196 doDeopt = true;
197 r.run();
198 doDeopt = false;
199
200 WB.clearInlineCaches();
201
202 for (int i = 0; i < 20_000; i++) {
203 r.run();
204 }
205
206 doDeopt = true;
207 r.run();
208 doDeopt = false;
209 }
210
211 static void testVirtual() {
212 System.out.println("linkToVirtual");
213
214 // Monomorphic case (optimized virtual call)
215 run(() -> linkToVirtual(new T(), T.class));
216 run(() -> linkToVirtualDefault(new T(), I.class));
217
218 // Megamorphic case (optimized virtual call)
219 run(() -> {
220 linkToVirtual(new T() {}, T.class);
221 linkToVirtual(new T() {}, T.class);
222 linkToVirtual(new T() {}, T.class);
223 });
224
225 run(() -> {
226 linkToVirtualDefault(new T(){}, I.class);
227 linkToVirtualDefault(new T(){}, I.class);
228 linkToVirtualDefault(new T(){}, I.class);
229 });
230
231 // Megamorphic case (virtual call), multiple implementations
232 run(() -> {
233 linkToVirtual(new T(), T.class);
234 linkToVirtual(new P1(), P1.class);
235 linkToVirtual(new P2(), P2.class);
236 });
237
|
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.f3
58 static final MethodHandle defaultMH; // invokevirtual T.f3
59 static final MethodHandle specialMH; // invokespecial T.f4 T
60 static final MethodHandle privateMH; // invokespecial I.f4 T
61 static final MethodHandle basicMH;
62
63 static final MethodHandle intrinsicMH; // invokevirtual Object.hashCode
64
65 static final WhiteBox WB = WhiteBox.getWhiteBox();
66
67 static volatile boolean doDeopt = false;
68
69 static {
70 try {
71 MethodType mtype = MethodType.methodType(Class.class);
72
73 virtualMH = LOOKUP.findVirtual(T.class, "f1", mtype);
74 staticMH = LOOKUP.findStatic (T.class, "f2", mtype);
75 intfMH = LOOKUP.findVirtual(I.class, "f3", mtype);
76 defaultMH = LOOKUP.findVirtual(T.class, "f3", mtype);
77 specialMH = LOOKUP.findSpecial(T.class, "f4", mtype, T.class);
78 privateMH = LOOKUP.findSpecial(I.class, "f4", mtype, I.class);
79 basicMH = NonInlinedReinvoker.make(staticMH);
80 intrinsicMH = LOOKUP.findVirtual(Object.class, "hashCode", MethodType.methodType(int.class));
81 } catch (Exception e) {
82 throw new Error(e);
83 }
84 }
85
86 static class T implements I {
87 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
88 @DontInline public static Class<?> f2() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
89 @DontInline private Class<?> f4() { if (doDeopt) WB.deoptimizeAll(); return T.class; }
90 }
91
92 static class P1 extends T {
93 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P1.class; }
94 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P1.class; }
95 }
96
97 static class P2 extends T {
98 @DontInline public Class<?> f1() { if (doDeopt) WB.deoptimizeAll(); return P2.class; }
99 @DontInline public Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return P2.class; }
100 }
103 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return I.class; }
104 @DontInline private Class<?> f4() { if (doDeopt) WB.deoptimizeAll(); return I.class; }
105 }
106
107 interface J1 extends I {
108 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return J1.class; }
109 }
110
111 interface J2 extends I {
112 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return J2.class; }
113 }
114
115 interface J3 extends I {
116 @DontInline default Class<?> f3() { if (doDeopt) WB.deoptimizeAll(); return J3.class; }
117 }
118
119 static class Q1 extends T implements J1 {}
120 static class Q2 extends T implements J2 {}
121 static class Q3 extends T implements J3 {}
122
123 static class H {
124 public int hashCode() { return 0; }
125 }
126
127 @DontInline
128 static void linkToVirtual(T recv, Class<?> expected) {
129 try {
130 Class<?> cls = (Class<?>)virtualMH.invokeExact(recv);
131 assertEquals(cls, expected);
132 } catch (Throwable e) {
133 throw new Error(e);
134 }
135 }
136
137 @DontInline
138 static void linkToVirtualDefault(T recv, Class<?> expected) {
139 try {
140 Class<?> cls = (Class<?>)defaultMH.invokeExact(recv);
141 assertEquals(cls, expected);
142 } catch (Throwable e) {
143 throw new Error(e);
144 }
145 }
146
147 @DontInline
148 static void linkToVirtualIntrinsic(Object recv, int expected) {
149 try {
150 int v = (int)intrinsicMH.invokeExact(recv);
151 assertEquals(v, expected);
152 } catch (Throwable e) {
153 throw new Error(e);
154 }
155 }
156
157 @DontInline
158 static void linkToInterface(I recv, Class<?> expected) {
159 try {
160 Class<?> cls = (Class<?>)intfMH.invokeExact(recv);
161 assertEquals(cls, expected);
162 } catch (Throwable e) {
163 throw new Error(e);
164 }
165 }
166
167 @DontInline
168 static void linkToStatic() {
169 try {
170 Class<?> cls = (Class<?>)staticMH.invokeExact();
171 assertEquals(cls, T.class);
172 } catch (Throwable e) {
173 throw new Error(e);
174 }
175 }
176
177 @DontInline
178 static void linkToSpecial(T recv, Class<?> expected) {
179 try {
180 Class<?> cls = (Class<?>)specialMH.invokeExact(recv);
181 assertEquals(cls, expected);
182 } catch (Throwable e) {
183 throw new Error(e);
184 }
185 }
186
187 @DontInline
188 static void linkToSpecialIntf(I recv, Class<?> expected) {
189 try {
190 Class<?> cls = (Class<?>)privateMH.invokeExact(recv);
191 assertEquals(cls, expected);
192 } catch (Throwable e) {
193 throw new Error(e);
194 }
195 }
196
197 @DontInline
198 static void invokeBasic() {
199 try {
200 Class<?> cls = (Class<?>)MethodHandleHelper.invokeBasicL(basicMH);
201 assertEquals(cls, T.class);
202 } catch (Throwable e) {
203 throw new Error(e);
204 }
205 }
206
207 static void run(Runnable r) {
208 for (int i = 0; i < 20_000; i++) {
209 r.run();
210 }
211
212 doDeopt = true;
213 r.run();
214 doDeopt = false;
215
216 WB.clearInlineCaches();
217
218 for (int i = 0; i < 20_000; i++) {
219 r.run();
220 }
221
222 doDeopt = true;
223 r.run();
224 doDeopt = false;
225 }
226
227 static void testVirtual() {
228 System.out.println("linkToVirtual");
229
230 // Monomorphic case (optimized virtual call)
231 run(() -> linkToVirtual(new T(), T.class));
232 run(() -> linkToVirtualDefault(new T(), I.class));
233
234 run(() -> linkToVirtualIntrinsic(new H(), 0));
235
236 // Megamorphic case (optimized virtual call)
237 run(() -> {
238 linkToVirtual(new T() {}, T.class);
239 linkToVirtual(new T() {}, T.class);
240 linkToVirtual(new T() {}, T.class);
241 });
242
243 run(() -> {
244 linkToVirtualDefault(new T(){}, I.class);
245 linkToVirtualDefault(new T(){}, I.class);
246 linkToVirtualDefault(new T(){}, I.class);
247 });
248
249 // Megamorphic case (virtual call), multiple implementations
250 run(() -> {
251 linkToVirtual(new T(), T.class);
252 linkToVirtual(new P1(), P1.class);
253 linkToVirtual(new P2(), P2.class);
254 });
255
|