xref: /aosp_15_r20/art/test/713-varhandle-invokers/src/Main.java (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2018 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker import static java.lang.invoke.MethodHandles.lookup;
18*795d594fSAndroid Build Coastguard Worker import static java.lang.invoke.MethodType.methodType;
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandle;
21*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.MethodHandles;
22*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.VarHandle;
23*795d594fSAndroid Build Coastguard Worker import java.lang.invoke.WrongMethodTypeException;
24*795d594fSAndroid Build Coastguard Worker 
25*795d594fSAndroid Build Coastguard Worker public final class Main {
26*795d594fSAndroid Build Coastguard Worker     static class TestSetupError extends Error {
TestSetupError(String message, Throwable cause)27*795d594fSAndroid Build Coastguard Worker         TestSetupError(String message, Throwable cause) {
28*795d594fSAndroid Build Coastguard Worker             super(message, cause);
29*795d594fSAndroid Build Coastguard Worker         }
30*795d594fSAndroid Build Coastguard Worker     }
31*795d594fSAndroid Build Coastguard Worker 
failAssertion(String message)32*795d594fSAndroid Build Coastguard Worker     private static void failAssertion(String message) {
33*795d594fSAndroid Build Coastguard Worker         StringBuilder sb = new StringBuilder();
34*795d594fSAndroid Build Coastguard Worker         sb.append("Test failure: ");
35*795d594fSAndroid Build Coastguard Worker         sb.append(message);
36*795d594fSAndroid Build Coastguard Worker         throw new AssertionError(sb.toString());
37*795d594fSAndroid Build Coastguard Worker     }
38*795d594fSAndroid Build Coastguard Worker 
assertUnreachable()39*795d594fSAndroid Build Coastguard Worker     private static void assertUnreachable() throws Throwable {
40*795d594fSAndroid Build Coastguard Worker         failAssertion("Unreachable");
41*795d594fSAndroid Build Coastguard Worker     }
42*795d594fSAndroid Build Coastguard Worker 
failAssertEquals(Object expected, Object actual)43*795d594fSAndroid Build Coastguard Worker     private static void failAssertEquals(Object expected, Object actual) {
44*795d594fSAndroid Build Coastguard Worker         StringBuilder sb = new StringBuilder();
45*795d594fSAndroid Build Coastguard Worker         sb.append(expected);
46*795d594fSAndroid Build Coastguard Worker         sb.append(" != ");
47*795d594fSAndroid Build Coastguard Worker         sb.append(actual);
48*795d594fSAndroid Build Coastguard Worker         failAssertion(sb.toString());
49*795d594fSAndroid Build Coastguard Worker     }
50*795d594fSAndroid Build Coastguard Worker 
assertEquals(boolean expected, boolean actual)51*795d594fSAndroid Build Coastguard Worker     private static void assertEquals(boolean expected, boolean actual) {
52*795d594fSAndroid Build Coastguard Worker         if (expected != actual) {
53*795d594fSAndroid Build Coastguard Worker             failAssertEquals(expected, actual);
54*795d594fSAndroid Build Coastguard Worker         }
55*795d594fSAndroid Build Coastguard Worker     }
56*795d594fSAndroid Build Coastguard Worker 
assertEquals(int expected, int actual)57*795d594fSAndroid Build Coastguard Worker     private static void assertEquals(int expected, int actual) {
58*795d594fSAndroid Build Coastguard Worker         if (expected != actual) {
59*795d594fSAndroid Build Coastguard Worker             failAssertEquals(expected, actual);
60*795d594fSAndroid Build Coastguard Worker         }
61*795d594fSAndroid Build Coastguard Worker     }
62*795d594fSAndroid Build Coastguard Worker 
assertEquals(long expected, long actual)63*795d594fSAndroid Build Coastguard Worker     private static void assertEquals(long expected, long actual) {
64*795d594fSAndroid Build Coastguard Worker         if (expected != actual) {
65*795d594fSAndroid Build Coastguard Worker             failAssertEquals(expected, actual);
66*795d594fSAndroid Build Coastguard Worker         }
67*795d594fSAndroid Build Coastguard Worker     }
68*795d594fSAndroid Build Coastguard Worker 
assertEquals(float expected, float actual)69*795d594fSAndroid Build Coastguard Worker     private static void assertEquals(float expected, float actual) {
70*795d594fSAndroid Build Coastguard Worker         if (expected != actual) {
71*795d594fSAndroid Build Coastguard Worker             failAssertEquals(expected, actual);
72*795d594fSAndroid Build Coastguard Worker         }
73*795d594fSAndroid Build Coastguard Worker     }
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker     static class FieldVarHandleExactInvokerTest {
76*795d594fSAndroid Build Coastguard Worker         private static final Class<?> THIS_CLASS = FieldVarHandleExactInvokerTest.class;
77*795d594fSAndroid Build Coastguard Worker         private static final VarHandle fieldVarHandle;
78*795d594fSAndroid Build Coastguard Worker 
79*795d594fSAndroid Build Coastguard Worker         int field;
80*795d594fSAndroid Build Coastguard Worker 
81*795d594fSAndroid Build Coastguard Worker         static {
82*795d594fSAndroid Build Coastguard Worker             try {
83*795d594fSAndroid Build Coastguard Worker                 fieldVarHandle = lookup().findVarHandle(THIS_CLASS, "field", int.class);
84*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
85*795d594fSAndroid Build Coastguard Worker                 throw new TestSetupError("Failed to lookup of field", e);
86*795d594fSAndroid Build Coastguard Worker             }
87*795d594fSAndroid Build Coastguard Worker         }
88*795d594fSAndroid Build Coastguard Worker 
run()89*795d594fSAndroid Build Coastguard Worker         void run() throws Throwable {
90*795d594fSAndroid Build Coastguard Worker             System.out.println(THIS_CLASS.getName());
91*795d594fSAndroid Build Coastguard Worker 
92*795d594fSAndroid Build Coastguard Worker             MethodHandle invokerMethodHandle =
93*795d594fSAndroid Build Coastguard Worker                     MethodHandles.varHandleExactInvoker(
94*795d594fSAndroid Build Coastguard Worker                             VarHandle.AccessMode.GET_AND_SET,
95*795d594fSAndroid Build Coastguard Worker                             methodType(int.class, THIS_CLASS, int.class));
96*795d594fSAndroid Build Coastguard Worker 
97*795d594fSAndroid Build Coastguard Worker             field = 3;
98*795d594fSAndroid Build Coastguard Worker             assertEquals(3, (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, 4));
99*795d594fSAndroid Build Coastguard Worker             assertEquals(4, field);
100*795d594fSAndroid Build Coastguard Worker 
101*795d594fSAndroid Build Coastguard Worker             //
102*795d594fSAndroid Build Coastguard Worker             // Check invocations with MethodHandle.invokeExact()
103*795d594fSAndroid Build Coastguard Worker             //
104*795d594fSAndroid Build Coastguard Worker             try {
105*795d594fSAndroid Build Coastguard Worker                 // Check for unboxing
106*795d594fSAndroid Build Coastguard Worker                 int i =
107*795d594fSAndroid Build Coastguard Worker                         (int)
108*795d594fSAndroid Build Coastguard Worker                                 invokerMethodHandle.invokeExact(
109*795d594fSAndroid Build Coastguard Worker                                         fieldVarHandle, this, Integer.valueOf(3));
110*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
111*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
112*795d594fSAndroid Build Coastguard Worker                 assertEquals(4, field);
113*795d594fSAndroid Build Coastguard Worker             }
114*795d594fSAndroid Build Coastguard Worker             try {
115*795d594fSAndroid Build Coastguard Worker                 // Check for widening conversion
116*795d594fSAndroid Build Coastguard Worker                 int i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, (short) 3);
117*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
118*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
119*795d594fSAndroid Build Coastguard Worker                 assertEquals(4, field);
120*795d594fSAndroid Build Coastguard Worker             }
121*795d594fSAndroid Build Coastguard Worker             try {
122*795d594fSAndroid Build Coastguard Worker                 // Check for acceptance of void return type
123*795d594fSAndroid Build Coastguard Worker                 invokerMethodHandle.invokeExact(fieldVarHandle, this, 77);
124*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
125*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
126*795d594fSAndroid Build Coastguard Worker                 assertEquals(4, field);
127*795d594fSAndroid Build Coastguard Worker             }
128*795d594fSAndroid Build Coastguard Worker             try {
129*795d594fSAndroid Build Coastguard Worker                 // Check for wider return type
130*795d594fSAndroid Build Coastguard Worker                 long l = (long) invokerMethodHandle.invokeExact(fieldVarHandle, this, 77);
131*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
132*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
133*795d594fSAndroid Build Coastguard Worker                 assertEquals(4, field);
134*795d594fSAndroid Build Coastguard Worker             }
135*795d594fSAndroid Build Coastguard Worker             try {
136*795d594fSAndroid Build Coastguard Worker                 // Check null VarHandle instance fails
137*795d594fSAndroid Build Coastguard Worker                 VarHandle vhNull = null;
138*795d594fSAndroid Build Coastguard Worker                 int i = (int) invokerMethodHandle.invokeExact(vhNull, this, 777);
139*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
140*795d594fSAndroid Build Coastguard Worker             } catch (NullPointerException expected) {
141*795d594fSAndroid Build Coastguard Worker                 assertEquals(4, field);
142*795d594fSAndroid Build Coastguard Worker             }
143*795d594fSAndroid Build Coastguard Worker 
144*795d594fSAndroid Build Coastguard Worker             //
145*795d594fSAndroid Build Coastguard Worker             // Check invocations with MethodHandle.invoke()
146*795d594fSAndroid Build Coastguard Worker             //
147*795d594fSAndroid Build Coastguard Worker 
148*795d594fSAndroid Build Coastguard Worker             // Check for unboxing
149*795d594fSAndroid Build Coastguard Worker             int i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Integer.valueOf(3));
150*795d594fSAndroid Build Coastguard Worker             assertEquals(3, field);
151*795d594fSAndroid Build Coastguard Worker 
152*795d594fSAndroid Build Coastguard Worker             // Check for unboxing
153*795d594fSAndroid Build Coastguard Worker             i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Short.valueOf((short) 4));
154*795d594fSAndroid Build Coastguard Worker             assertEquals(4, field);
155*795d594fSAndroid Build Coastguard Worker 
156*795d594fSAndroid Build Coastguard Worker             // Check for widening conversion
157*795d594fSAndroid Build Coastguard Worker             i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, (short) 23);
158*795d594fSAndroid Build Coastguard Worker             assertEquals(23, field);
159*795d594fSAndroid Build Coastguard Worker 
160*795d594fSAndroid Build Coastguard Worker             // Check for acceptance of void return type
161*795d594fSAndroid Build Coastguard Worker             invokerMethodHandle.invoke(fieldVarHandle, this, 77);
162*795d594fSAndroid Build Coastguard Worker             assertEquals(77, field);
163*795d594fSAndroid Build Coastguard Worker 
164*795d594fSAndroid Build Coastguard Worker             // Check for wider return type
165*795d594fSAndroid Build Coastguard Worker             long l = (long) invokerMethodHandle.invoke(fieldVarHandle, this, 88);
166*795d594fSAndroid Build Coastguard Worker             assertEquals(88, field);
167*795d594fSAndroid Build Coastguard Worker 
168*795d594fSAndroid Build Coastguard Worker             try {
169*795d594fSAndroid Build Coastguard Worker                 // Check null VarHandle instance fails
170*795d594fSAndroid Build Coastguard Worker                 VarHandle vhNull = null;
171*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invoke(vhNull, this, 888);
172*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
173*795d594fSAndroid Build Coastguard Worker             } catch (NullPointerException expected) {
174*795d594fSAndroid Build Coastguard Worker                 assertEquals(88, field);
175*795d594fSAndroid Build Coastguard Worker             }
176*795d594fSAndroid Build Coastguard Worker         }
177*795d594fSAndroid Build Coastguard Worker     }
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker     static class LongFieldVarHandleExactInvokerTest {
180*795d594fSAndroid Build Coastguard Worker         private static final Class<?> THIS_CLASS = LongFieldVarHandleExactInvokerTest.class;
181*795d594fSAndroid Build Coastguard Worker 
182*795d594fSAndroid Build Coastguard Worker         private static final VarHandle fieldVarHandle;
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker         private static final long CANARY = 0x0123456789abcdefL;
185*795d594fSAndroid Build Coastguard Worker 
186*795d594fSAndroid Build Coastguard Worker         long field = 0L;
187*795d594fSAndroid Build Coastguard Worker 
188*795d594fSAndroid Build Coastguard Worker         static {
189*795d594fSAndroid Build Coastguard Worker             try {
190*795d594fSAndroid Build Coastguard Worker                 fieldVarHandle = lookup().findVarHandle(THIS_CLASS, "field", long.class);
191*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
192*795d594fSAndroid Build Coastguard Worker                 throw new TestSetupError("Failed to lookup of field", e);
193*795d594fSAndroid Build Coastguard Worker             }
194*795d594fSAndroid Build Coastguard Worker         }
195*795d594fSAndroid Build Coastguard Worker 
run()196*795d594fSAndroid Build Coastguard Worker         void run() throws Throwable {
197*795d594fSAndroid Build Coastguard Worker             System.out.println(THIS_CLASS.getName());
198*795d594fSAndroid Build Coastguard Worker 
199*795d594fSAndroid Build Coastguard Worker             MethodHandle invokerMethodHandle =
200*795d594fSAndroid Build Coastguard Worker                     MethodHandles.varHandleExactInvoker(
201*795d594fSAndroid Build Coastguard Worker                             VarHandle.AccessMode.COMPARE_AND_SET,
202*795d594fSAndroid Build Coastguard Worker                             methodType(boolean.class, THIS_CLASS, long.class, long.class));
203*795d594fSAndroid Build Coastguard Worker             checkCompareAndSet(invokerMethodHandle, 0L, CANARY);
204*795d594fSAndroid Build Coastguard Worker             checkCompareAndSet(invokerMethodHandle, 1L, 1L);
205*795d594fSAndroid Build Coastguard Worker             checkCompareAndSet(invokerMethodHandle, CANARY, ~CANARY);
206*795d594fSAndroid Build Coastguard Worker             checkCompareAndSet(invokerMethodHandle, ~CANARY, 0L);
207*795d594fSAndroid Build Coastguard Worker         }
208*795d594fSAndroid Build Coastguard Worker 
checkCompareAndSet(MethodHandle compareAndSet, long oldValue, long newValue)209*795d594fSAndroid Build Coastguard Worker         private void checkCompareAndSet(MethodHandle compareAndSet, long oldValue, long newValue)
210*795d594fSAndroid Build Coastguard Worker                 throws Throwable {
211*795d594fSAndroid Build Coastguard Worker             final boolean expectSuccess = (oldValue == field);
212*795d594fSAndroid Build Coastguard Worker             final long oldFieldValue = field;
213*795d594fSAndroid Build Coastguard Worker             assertEquals(
214*795d594fSAndroid Build Coastguard Worker                     expectSuccess,
215*795d594fSAndroid Build Coastguard Worker                     (boolean) compareAndSet.invoke(fieldVarHandle, this, oldValue, newValue));
216*795d594fSAndroid Build Coastguard Worker             assertEquals(expectSuccess ? newValue : oldFieldValue, field);
217*795d594fSAndroid Build Coastguard Worker         }
218*795d594fSAndroid Build Coastguard Worker     }
219*795d594fSAndroid Build Coastguard Worker 
220*795d594fSAndroid Build Coastguard Worker     static class FieldVarHandleInvokerTest {
221*795d594fSAndroid Build Coastguard Worker         private static final Class<?> THIS_CLASS = FieldVarHandleInvokerTest.class;
222*795d594fSAndroid Build Coastguard Worker         private static final VarHandle fieldVarHandle;
223*795d594fSAndroid Build Coastguard Worker         int field;
224*795d594fSAndroid Build Coastguard Worker 
225*795d594fSAndroid Build Coastguard Worker         static {
226*795d594fSAndroid Build Coastguard Worker             try {
227*795d594fSAndroid Build Coastguard Worker                 fieldVarHandle = lookup().findVarHandle(THIS_CLASS, "field", int.class);
228*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
229*795d594fSAndroid Build Coastguard Worker                 throw new TestSetupError("Failed to lookup of field", e);
230*795d594fSAndroid Build Coastguard Worker             }
231*795d594fSAndroid Build Coastguard Worker         }
232*795d594fSAndroid Build Coastguard Worker 
run()233*795d594fSAndroid Build Coastguard Worker         void run() throws Throwable {
234*795d594fSAndroid Build Coastguard Worker             System.out.println("fieldVarHandleInvokerTest");
235*795d594fSAndroid Build Coastguard Worker             MethodHandle invokerMethodHandle =
236*795d594fSAndroid Build Coastguard Worker                     MethodHandles.varHandleInvoker(
237*795d594fSAndroid Build Coastguard Worker                             VarHandle.AccessMode.GET_AND_SET,
238*795d594fSAndroid Build Coastguard Worker                             methodType(int.class, THIS_CLASS, int.class));
239*795d594fSAndroid Build Coastguard Worker 
240*795d594fSAndroid Build Coastguard Worker             field = 3;
241*795d594fSAndroid Build Coastguard Worker             int oldField = (int) invokerMethodHandle.invoke(fieldVarHandle, this, 4);
242*795d594fSAndroid Build Coastguard Worker             assertEquals(3, oldField);
243*795d594fSAndroid Build Coastguard Worker             assertEquals(4, field);
244*795d594fSAndroid Build Coastguard Worker 
245*795d594fSAndroid Build Coastguard Worker             //
246*795d594fSAndroid Build Coastguard Worker             // Check invocations with MethodHandle.invoke()
247*795d594fSAndroid Build Coastguard Worker             //
248*795d594fSAndroid Build Coastguard Worker 
249*795d594fSAndroid Build Coastguard Worker             // Check for unboxing
250*795d594fSAndroid Build Coastguard Worker             int i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Integer.valueOf(3));
251*795d594fSAndroid Build Coastguard Worker             assertEquals(3, field);
252*795d594fSAndroid Build Coastguard Worker 
253*795d594fSAndroid Build Coastguard Worker             // Check for widening conversion
254*795d594fSAndroid Build Coastguard Worker             i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, (short) 33);
255*795d594fSAndroid Build Coastguard Worker             assertEquals(33, field);
256*795d594fSAndroid Build Coastguard Worker 
257*795d594fSAndroid Build Coastguard Worker             // Check for widening conversion
258*795d594fSAndroid Build Coastguard Worker             i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, Byte.valueOf((byte) 34));
259*795d594fSAndroid Build Coastguard Worker             assertEquals(34, field);
260*795d594fSAndroid Build Coastguard Worker 
261*795d594fSAndroid Build Coastguard Worker             // Check for acceptance of void return type
262*795d594fSAndroid Build Coastguard Worker             invokerMethodHandle.invoke(fieldVarHandle, this, 77);
263*795d594fSAndroid Build Coastguard Worker             assertEquals(77, field);
264*795d594fSAndroid Build Coastguard Worker 
265*795d594fSAndroid Build Coastguard Worker             // Check for wider return type
266*795d594fSAndroid Build Coastguard Worker             long l = (long) invokerMethodHandle.invoke(fieldVarHandle, this, 88);
267*795d594fSAndroid Build Coastguard Worker             assertEquals(88, field);
268*795d594fSAndroid Build Coastguard Worker             try {
269*795d594fSAndroid Build Coastguard Worker                 // Check narrowing conversion fails
270*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, 3.0);
271*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
272*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
273*795d594fSAndroid Build Coastguard Worker             }
274*795d594fSAndroid Build Coastguard Worker             try {
275*795d594fSAndroid Build Coastguard Worker                 // Check reference type fails
276*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invoke(fieldVarHandle, this, "Bad");
277*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
278*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
279*795d594fSAndroid Build Coastguard Worker             }
280*795d594fSAndroid Build Coastguard Worker             try {
281*795d594fSAndroid Build Coastguard Worker                 // Check null VarHandle instance fails
282*795d594fSAndroid Build Coastguard Worker                 VarHandle vhNull = null;
283*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invoke(vhNull, this, 888);
284*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
285*795d594fSAndroid Build Coastguard Worker             } catch (NullPointerException expected) {
286*795d594fSAndroid Build Coastguard Worker                 assertEquals(88, field);
287*795d594fSAndroid Build Coastguard Worker             }
288*795d594fSAndroid Build Coastguard Worker 
289*795d594fSAndroid Build Coastguard Worker             //
290*795d594fSAndroid Build Coastguard Worker             // Check invocations with MethodHandle.invokeExact()
291*795d594fSAndroid Build Coastguard Worker             //
292*795d594fSAndroid Build Coastguard Worker             field = -1;
293*795d594fSAndroid Build Coastguard Worker             try {
294*795d594fSAndroid Build Coastguard Worker                 // Check for unboxing
295*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, Integer.valueOf(3));
296*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
297*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
298*795d594fSAndroid Build Coastguard Worker                 assertEquals(-1, field);
299*795d594fSAndroid Build Coastguard Worker             }
300*795d594fSAndroid Build Coastguard Worker             try {
301*795d594fSAndroid Build Coastguard Worker                 // Check for widening conversion
302*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, (short) 33);
303*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
304*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
305*795d594fSAndroid Build Coastguard Worker                 assertEquals(-1, field);
306*795d594fSAndroid Build Coastguard Worker             }
307*795d594fSAndroid Build Coastguard Worker             try {
308*795d594fSAndroid Build Coastguard Worker                 // Check for acceptance of void return type
309*795d594fSAndroid Build Coastguard Worker                 invokerMethodHandle.invokeExact(fieldVarHandle, this, 77);
310*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
311*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
312*795d594fSAndroid Build Coastguard Worker                 assertEquals(-1, field);
313*795d594fSAndroid Build Coastguard Worker             }
314*795d594fSAndroid Build Coastguard Worker             try {
315*795d594fSAndroid Build Coastguard Worker                 // Check for wider return type
316*795d594fSAndroid Build Coastguard Worker                 l = (long) invokerMethodHandle.invokeExact(fieldVarHandle, this, 78);
317*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
318*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
319*795d594fSAndroid Build Coastguard Worker                 assertEquals(-1, field);
320*795d594fSAndroid Build Coastguard Worker             }
321*795d594fSAndroid Build Coastguard Worker             try {
322*795d594fSAndroid Build Coastguard Worker                 // Check narrowing conversion fails
323*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, 3.0);
324*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
325*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
326*795d594fSAndroid Build Coastguard Worker             }
327*795d594fSAndroid Build Coastguard Worker             try {
328*795d594fSAndroid Build Coastguard Worker                 // Check reference type fails
329*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invokeExact(fieldVarHandle, this, "Bad");
330*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
331*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
332*795d594fSAndroid Build Coastguard Worker             }
333*795d594fSAndroid Build Coastguard Worker             try {
334*795d594fSAndroid Build Coastguard Worker                 // Check null VarHandle instance fails
335*795d594fSAndroid Build Coastguard Worker                 VarHandle vhNull = null;
336*795d594fSAndroid Build Coastguard Worker                 i = (int) invokerMethodHandle.invokeExact(vhNull, this, 888);
337*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
338*795d594fSAndroid Build Coastguard Worker             } catch (NullPointerException expected) {
339*795d594fSAndroid Build Coastguard Worker                 assertEquals(-1, field);
340*795d594fSAndroid Build Coastguard Worker             }
341*795d594fSAndroid Build Coastguard Worker         }
342*795d594fSAndroid Build Coastguard Worker     }
343*795d594fSAndroid Build Coastguard Worker 
344*795d594fSAndroid Build Coastguard Worker     static class DivergenceExactInvokerTest {
345*795d594fSAndroid Build Coastguard Worker         private static final VarHandle floatsArrayVarHandle;
346*795d594fSAndroid Build Coastguard Worker 
347*795d594fSAndroid Build Coastguard Worker         static {
348*795d594fSAndroid Build Coastguard Worker             try {
349*795d594fSAndroid Build Coastguard Worker                 floatsArrayVarHandle = MethodHandles.arrayElementVarHandle(float[].class);
350*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
351*795d594fSAndroid Build Coastguard Worker                 throw new TestSetupError("Failed to create VarHandle", e);
352*795d594fSAndroid Build Coastguard Worker             }
353*795d594fSAndroid Build Coastguard Worker         }
354*795d594fSAndroid Build Coastguard Worker 
run()355*795d594fSAndroid Build Coastguard Worker         void run() throws Throwable {
356*795d594fSAndroid Build Coastguard Worker             System.out.println("DivergenceExactInvokerTest");
357*795d594fSAndroid Build Coastguard Worker             float[] floatsArray = new float[4];
358*795d594fSAndroid Build Coastguard Worker             // Exact invoker of an accessor having the form:
359*795d594fSAndroid Build Coastguard Worker             //  float accessor(float[] values, int index, Float current, float replacement)
360*795d594fSAndroid Build Coastguard Worker             MethodHandle exactInvoker =
361*795d594fSAndroid Build Coastguard Worker                     MethodHandles.varHandleExactInvoker(
362*795d594fSAndroid Build Coastguard Worker                             VarHandle.AccessMode.COMPARE_AND_EXCHANGE,
363*795d594fSAndroid Build Coastguard Worker                             methodType(
364*795d594fSAndroid Build Coastguard Worker                                     float.class,
365*795d594fSAndroid Build Coastguard Worker                                     float[].class,
366*795d594fSAndroid Build Coastguard Worker                                     int.class,
367*795d594fSAndroid Build Coastguard Worker                                     Float.class,
368*795d594fSAndroid Build Coastguard Worker                                     float.class));
369*795d594fSAndroid Build Coastguard Worker             floatsArray[2] = Float.valueOf(4.0f);
370*795d594fSAndroid Build Coastguard Worker             // Callsite that is an exact match with exactInvoker.type().
371*795d594fSAndroid Build Coastguard Worker             try {
372*795d594fSAndroid Build Coastguard Worker                 // exactInvoker.type() is not compatible with floatsArrayVarHandle accessor.
373*795d594fSAndroid Build Coastguard Worker                 float old =
374*795d594fSAndroid Build Coastguard Worker                         (float)
375*795d594fSAndroid Build Coastguard Worker                                 exactInvoker.invoke(
376*795d594fSAndroid Build Coastguard Worker                                         floatsArrayVarHandle,
377*795d594fSAndroid Build Coastguard Worker                                         floatsArray,
378*795d594fSAndroid Build Coastguard Worker                                         2,
379*795d594fSAndroid Build Coastguard Worker                                         Float.valueOf(4.0f),
380*795d594fSAndroid Build Coastguard Worker                                         8.0f);
381*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
382*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
383*795d594fSAndroid Build Coastguard Worker                 assertEquals(4.0f, floatsArray[2]);
384*795d594fSAndroid Build Coastguard Worker             }
385*795d594fSAndroid Build Coastguard Worker 
386*795d594fSAndroid Build Coastguard Worker             // Callsites that are exact matches with exactInvoker.type()
387*795d594fSAndroid Build Coastguard Worker             try {
388*795d594fSAndroid Build Coastguard Worker                 // Mismatch between exactInvoker.type() and VarHandle type (Float != float)
389*795d594fSAndroid Build Coastguard Worker                 float old =
390*795d594fSAndroid Build Coastguard Worker                         (float)
391*795d594fSAndroid Build Coastguard Worker                                 exactInvoker.invoke(
392*795d594fSAndroid Build Coastguard Worker                                         floatsArrayVarHandle, floatsArray, 2, 8.0f, 16.0f);
393*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
394*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
395*795d594fSAndroid Build Coastguard Worker                 assertEquals(4.0f, floatsArray[2]);
396*795d594fSAndroid Build Coastguard Worker             }
397*795d594fSAndroid Build Coastguard Worker             try {
398*795d594fSAndroid Build Coastguard Worker                 // short not convertible to Float
399*795d594fSAndroid Build Coastguard Worker                 float old =
400*795d594fSAndroid Build Coastguard Worker                         (float)
401*795d594fSAndroid Build Coastguard Worker                                 exactInvoker.invoke(
402*795d594fSAndroid Build Coastguard Worker                                         floatsArrayVarHandle, floatsArray, 2, (short) 4, 13.0f);
403*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
404*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
405*795d594fSAndroid Build Coastguard Worker                 assertEquals(4.0f, floatsArray[2]);
406*795d594fSAndroid Build Coastguard Worker             }
407*795d594fSAndroid Build Coastguard Worker             try {
408*795d594fSAndroid Build Coastguard Worker                 // int not convertible to Float
409*795d594fSAndroid Build Coastguard Worker                 float old =
410*795d594fSAndroid Build Coastguard Worker                         (float) exactInvoker.invoke(floatsArrayVarHandle, floatsArray, 2, 8, -8.0f);
411*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
412*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
413*795d594fSAndroid Build Coastguard Worker                 assertEquals(4.0f, floatsArray[2]);
414*795d594fSAndroid Build Coastguard Worker             }
415*795d594fSAndroid Build Coastguard Worker         }
416*795d594fSAndroid Build Coastguard Worker     }
417*795d594fSAndroid Build Coastguard Worker 
418*795d594fSAndroid Build Coastguard Worker     static class DivergenceInvokerTest {
419*795d594fSAndroid Build Coastguard Worker         private static final VarHandle floatsArrayVarHandle;
420*795d594fSAndroid Build Coastguard Worker 
421*795d594fSAndroid Build Coastguard Worker         static {
422*795d594fSAndroid Build Coastguard Worker             try {
423*795d594fSAndroid Build Coastguard Worker                 floatsArrayVarHandle = MethodHandles.arrayElementVarHandle(float[].class);
424*795d594fSAndroid Build Coastguard Worker             } catch (Exception e) {
425*795d594fSAndroid Build Coastguard Worker                 throw new TestSetupError("Failed to create VarHandle", e);
426*795d594fSAndroid Build Coastguard Worker             }
427*795d594fSAndroid Build Coastguard Worker         }
428*795d594fSAndroid Build Coastguard Worker 
run()429*795d594fSAndroid Build Coastguard Worker         void run() throws Throwable {
430*795d594fSAndroid Build Coastguard Worker             System.out.println("DivergenceInvokerTest");
431*795d594fSAndroid Build Coastguard Worker             float[] floatsArray = new float[4];
432*795d594fSAndroid Build Coastguard Worker             // Invoker of an accessor having the form:
433*795d594fSAndroid Build Coastguard Worker             //  float accessor(float[] values, int index, Float current, float replacement)
434*795d594fSAndroid Build Coastguard Worker             MethodHandle invoker =
435*795d594fSAndroid Build Coastguard Worker                     MethodHandles.varHandleInvoker(
436*795d594fSAndroid Build Coastguard Worker                             VarHandle.AccessMode.COMPARE_AND_EXCHANGE,
437*795d594fSAndroid Build Coastguard Worker                             methodType(
438*795d594fSAndroid Build Coastguard Worker                                     float.class,
439*795d594fSAndroid Build Coastguard Worker                                     float[].class,
440*795d594fSAndroid Build Coastguard Worker                                     int.class,
441*795d594fSAndroid Build Coastguard Worker                                     Float.class,
442*795d594fSAndroid Build Coastguard Worker                                     float.class));
443*795d594fSAndroid Build Coastguard Worker             floatsArray[2] = Float.valueOf(4.0f);
444*795d594fSAndroid Build Coastguard Worker             // Callsite that is an exact match with invoker.type()
445*795d594fSAndroid Build Coastguard Worker             float old =
446*795d594fSAndroid Build Coastguard Worker                     (float)
447*795d594fSAndroid Build Coastguard Worker                             invoker.invoke(
448*795d594fSAndroid Build Coastguard Worker                                     floatsArrayVarHandle,
449*795d594fSAndroid Build Coastguard Worker                                     floatsArray,
450*795d594fSAndroid Build Coastguard Worker                                     2,
451*795d594fSAndroid Build Coastguard Worker                                     Float.valueOf(4.0f),
452*795d594fSAndroid Build Coastguard Worker                                     8.0f);
453*795d594fSAndroid Build Coastguard Worker             assertEquals(4.0f, old);
454*795d594fSAndroid Build Coastguard Worker             assertEquals(8.0f, floatsArray[2]);
455*795d594fSAndroid Build Coastguard Worker 
456*795d594fSAndroid Build Coastguard Worker             // Callsite that is convertible match to invoker.type()
457*795d594fSAndroid Build Coastguard Worker             old = (float) invoker.invoke(floatsArrayVarHandle, floatsArray, 2, 8.0f, 16.0f);
458*795d594fSAndroid Build Coastguard Worker             assertEquals(8.0f, old);
459*795d594fSAndroid Build Coastguard Worker             assertEquals(16.0f, floatsArray[2]);
460*795d594fSAndroid Build Coastguard Worker 
461*795d594fSAndroid Build Coastguard Worker             // Callsites that are not convertible to invoker.type().
462*795d594fSAndroid Build Coastguard Worker             try {
463*795d594fSAndroid Build Coastguard Worker                 // short is not convertible to Float
464*795d594fSAndroid Build Coastguard Worker                 old = (float) invoker.invoke(floatsArrayVarHandle, floatsArray, 2, (short) 4, 8.0f);
465*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
466*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
467*795d594fSAndroid Build Coastguard Worker                 assertEquals(16.0f, floatsArray[2]);
468*795d594fSAndroid Build Coastguard Worker             }
469*795d594fSAndroid Build Coastguard Worker             try {
470*795d594fSAndroid Build Coastguard Worker                 // int is not convertible to Float
471*795d594fSAndroid Build Coastguard Worker                 old = (float) invoker.invoke(floatsArrayVarHandle, floatsArray, 2, 8, -8.0f);
472*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
473*795d594fSAndroid Build Coastguard Worker             } catch (WrongMethodTypeException expected) {
474*795d594fSAndroid Build Coastguard Worker                 assertEquals(16.0f, floatsArray[2]);
475*795d594fSAndroid Build Coastguard Worker             }
476*795d594fSAndroid Build Coastguard Worker 
477*795d594fSAndroid Build Coastguard Worker             try {
478*795d594fSAndroid Build Coastguard Worker                 MethodHandle unsupportedInvoker =
479*795d594fSAndroid Build Coastguard Worker                         MethodHandles.varHandleInvoker(
480*795d594fSAndroid Build Coastguard Worker                                 VarHandle.AccessMode.GET_AND_BITWISE_OR,
481*795d594fSAndroid Build Coastguard Worker                                 methodType(float.class, float[].class, int.class, float.class));
482*795d594fSAndroid Build Coastguard Worker                 old =
483*795d594fSAndroid Build Coastguard Worker                         (float)
484*795d594fSAndroid Build Coastguard Worker                                 unsupportedInvoker.invoke(
485*795d594fSAndroid Build Coastguard Worker                                         floatsArrayVarHandle, floatsArray, 0, 2.71f);
486*795d594fSAndroid Build Coastguard Worker                 assertUnreachable();
487*795d594fSAndroid Build Coastguard Worker             } catch (UnsupportedOperationException expected) {
488*795d594fSAndroid Build Coastguard Worker             }
489*795d594fSAndroid Build Coastguard Worker         }
490*795d594fSAndroid Build Coastguard Worker     }
491*795d594fSAndroid Build Coastguard Worker 
main(String[] args)492*795d594fSAndroid Build Coastguard Worker     public static void main(String[] args) throws Throwable {
493*795d594fSAndroid Build Coastguard Worker         new FieldVarHandleExactInvokerTest().run();
494*795d594fSAndroid Build Coastguard Worker         new LongFieldVarHandleExactInvokerTest().run();
495*795d594fSAndroid Build Coastguard Worker         new FieldVarHandleInvokerTest().run();
496*795d594fSAndroid Build Coastguard Worker         new DivergenceExactInvokerTest().run();
497*795d594fSAndroid Build Coastguard Worker         new DivergenceInvokerTest().run();
498*795d594fSAndroid Build Coastguard Worker     }
499*795d594fSAndroid Build Coastguard Worker }
500