1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 import annotations.BootstrapMethod;
18 import annotations.CalledByIndy;
19 import java.lang.invoke.CallSite;
20 import java.lang.invoke.ConstantCallSite;
21 import java.lang.invoke.MethodHandle;
22 import java.lang.invoke.MethodHandles;
23 import java.lang.invoke.MethodType;
24 
25 class TestReturnValues extends TestBase {
bsm(MethodHandles.Lookup lookup, String name, MethodType methodType)26     static CallSite bsm(MethodHandles.Lookup lookup, String name, MethodType methodType)
27             throws Throwable {
28         MethodHandle mh = lookup.findStatic(TestReturnValues.class, name, methodType);
29         return new ConstantCallSite(mh);
30     }
31 
32     //
33     // Methods that pass through a single argument.
34     // Used to check return path.
35     //
passThrough(byte value)36     static byte passThrough(byte value) {
37         return value;
38     }
39 
passThrough(char value)40     static char passThrough(char value) {
41         return value;
42     }
43 
passThrough(double value)44     static double passThrough(double value) {
45         return value;
46     }
47 
passThrough(float value)48     static float passThrough(float value) {
49         return value;
50     }
51 
passThrough(int value)52     static int passThrough(int value) {
53         return value;
54     }
55 
passThrough(Object value)56     static Object passThrough(Object value) {
57         return value;
58     }
59 
passThrough(Object[] value)60     static Object[] passThrough(Object[] value) {
61         return value;
62     }
63 
passThrough(long value)64     static long passThrough(long value) {
65         return value;
66     }
67 
passThrough(short value)68     static short passThrough(short value) {
69         return value;
70     }
71 
passThrough()72     static void passThrough() {}
73 
passThrough(boolean value)74     static boolean passThrough(boolean value) {
75         return value;
76     }
77 
78     // byte
79     @CalledByIndy(
80             bootstrapMethod =
81                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
82             fieldOrMethodName = "passThrough",
83             returnType = byte.class,
84             parameterTypes = {byte.class})
passThroughCallSite(byte value)85     private static byte passThroughCallSite(byte value) {
86         assertNotReached();
87         return (byte) 0;
88     }
89 
90     // char
91     @CalledByIndy(
92             bootstrapMethod =
93                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
94             fieldOrMethodName = "passThrough",
95             returnType = char.class,
96             parameterTypes = {char.class})
passThroughCallSite(char value)97     private static char passThroughCallSite(char value) {
98         assertNotReached();
99         return 'Z';
100     }
101 
102     // double
103     @CalledByIndy(
104             bootstrapMethod =
105                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
106             fieldOrMethodName = "passThrough",
107             returnType = double.class,
108             parameterTypes = {double.class})
passThroughCallSite(double value)109     private static double passThroughCallSite(double value) {
110         assertNotReached();
111         return Double.NaN;
112     }
113 
114     // float
115     @CalledByIndy(
116             bootstrapMethod =
117                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
118             fieldOrMethodName = "passThrough",
119             returnType = float.class,
120             parameterTypes = {float.class})
passThroughCallSite(float value)121     private static float passThroughCallSite(float value) {
122         assertNotReached();
123         return Float.NaN;
124     }
125 
126     // int
127     @CalledByIndy(
128             bootstrapMethod =
129                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
130             fieldOrMethodName = "passThrough",
131             returnType = int.class,
132             parameterTypes = {int.class})
passThroughCallSite(int value)133     private static int passThroughCallSite(int value) {
134         assertNotReached();
135         return 0;
136     }
137 
138     // long
139     @CalledByIndy(
140             bootstrapMethod =
141                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
142             fieldOrMethodName = "passThrough",
143             returnType = long.class,
144             parameterTypes = {long.class})
passThroughCallSite(long value)145     private static long passThroughCallSite(long value) {
146         assertNotReached();
147         return Long.MIN_VALUE;
148     }
149 
150     // Object
151     @CalledByIndy(
152             bootstrapMethod =
153                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
154             fieldOrMethodName = "passThrough",
155             returnType = Object.class,
156             parameterTypes = {Object.class})
passThroughCallSite(Object value)157     private static Object passThroughCallSite(Object value) {
158         assertNotReached();
159         return null;
160     }
161 
162     // Object[]
163     @CalledByIndy(
164             bootstrapMethod =
165                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
166             fieldOrMethodName = "passThrough",
167             returnType = Object[].class,
168             parameterTypes = {Object[].class})
passThroughCallSite(Object[] value)169     private static Object[] passThroughCallSite(Object[] value) {
170         assertNotReached();
171         return null;
172     }
173 
174     // short
175     @CalledByIndy(
176             bootstrapMethod =
177                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
178             fieldOrMethodName = "passThrough",
179             returnType = short.class,
180             parameterTypes = {short.class})
passThroughCallSite(short value)181     private static short passThroughCallSite(short value) {
182         assertNotReached();
183         return (short) 0;
184     }
185 
186     // void
187     @CalledByIndy(
188             bootstrapMethod =
189                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
190             fieldOrMethodName = "passThrough",
191             returnType = void.class,
192             parameterTypes = {})
passThroughCallSite()193     private static void passThroughCallSite() {
194         assertNotReached();
195     }
196 
197     // boolean
198     @CalledByIndy(
199             bootstrapMethod =
200                     @BootstrapMethod(enclosingType = TestReturnValues.class, name = "bsm"),
201             fieldOrMethodName = "passThrough",
202             returnType = boolean.class,
203             parameterTypes = {boolean.class})
passThroughCallSite(boolean value)204     private static boolean passThroughCallSite(boolean value) {
205         assertNotReached();
206         return false;
207     }
208 
testByteReturnValues()209     private static void testByteReturnValues() {
210         byte[] values = {Byte.MIN_VALUE, Byte.MAX_VALUE};
211         for (byte value : values) {
212             assertEquals(value, (byte) passThroughCallSite(value));
213         }
214     }
215 
testCharReturnValues()216     private static void testCharReturnValues() {
217         char[] values = {
218             Character.MIN_VALUE,
219             Character.MAX_HIGH_SURROGATE,
220             Character.MAX_LOW_SURROGATE,
221             Character.MAX_VALUE
222         };
223         for (char value : values) {
224             assertEquals(value, (char) passThroughCallSite(value));
225         }
226     }
227 
testDoubleReturnValues()228     private static void testDoubleReturnValues() {
229         double[] values = {
230             Double.MIN_VALUE,
231             Double.MIN_NORMAL,
232             Double.NaN,
233             Double.POSITIVE_INFINITY,
234             Double.NEGATIVE_INFINITY,
235             Double.MAX_VALUE
236         };
237         for (double value : values) {
238             assertEquals(value, (double) passThroughCallSite(value));
239         }
240     }
241 
testFloatReturnValues()242     private static void testFloatReturnValues() {
243         float[] values = {
244             Float.MIN_VALUE,
245             Float.MIN_NORMAL,
246             Float.NaN,
247             Float.POSITIVE_INFINITY,
248             Float.NEGATIVE_INFINITY,
249             Float.MAX_VALUE
250         };
251         for (float value : values) {
252             assertEquals(value, (float) passThroughCallSite(value));
253         }
254     }
255 
testIntReturnValues()256     private static void testIntReturnValues() {
257         int[] values = {Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.SIZE, -Integer.SIZE};
258         for (int value : values) {
259             assertEquals(value, (int) passThroughCallSite(value));
260         }
261     }
262 
testLongReturnValues()263     private static void testLongReturnValues() {
264         long[] values = {Long.MIN_VALUE, Long.MAX_VALUE, (long) Long.SIZE, (long) -Long.SIZE};
265         for (long value : values) {
266             assertEquals(value, (long) passThroughCallSite(value));
267         }
268     }
269 
testObjectReturnValues()270     private static void testObjectReturnValues() {
271         Object[] values = {null, "abc", Integer.valueOf(123)};
272         for (Object value : values) {
273             assertEquals(value, (Object) passThroughCallSite(value));
274         }
275 
276         Object[] otherValues = (Object[]) passThroughCallSite(values);
277         assertEquals(values.length, otherValues.length);
278         for (int i = 0; i < otherValues.length; ++i) {
279             assertEquals(values[i], otherValues[i]);
280         }
281     }
282 
testShortReturnValues()283     private static void testShortReturnValues() {
284         short[] values = {
285             Short.MIN_VALUE, Short.MAX_VALUE, (short) Short.SIZE, (short) -Short.SIZE
286         };
287         for (short value : values) {
288             assertEquals(value, (short) passThroughCallSite(value));
289         }
290     }
291 
testVoidReturnValues()292     private static void testVoidReturnValues() {
293         long l = Long.MIN_VALUE;
294         double d = Double.MIN_VALUE;
295         passThroughCallSite(); // Initializes call site
296         assertEquals(Long.MIN_VALUE, l);
297         assertEquals(Double.MIN_VALUE, d);
298 
299         l = Long.MAX_VALUE;
300         d = Double.MAX_VALUE;
301         passThroughCallSite(); // re-uses existing call site
302         assertEquals(Long.MAX_VALUE, l);
303         assertEquals(Double.MAX_VALUE, d);
304     }
305 
testBooleanReturnValues()306     private static void testBooleanReturnValues() {
307         boolean[] values = {true, false, true, false, false};
308         for (boolean value : values) {
309             assertEquals(value, (boolean) passThroughCallSite(value));
310         }
311     }
312 
test()313     public static void test() {
314         System.out.println(TestReturnValues.class.getName());
315         // Two passes here - the first is for the call site creation and invoke path, the second
316         // for the lookup and invoke path.
317         for (int pass = 0; pass < 2; ++pass) {
318             testByteReturnValues(); // B
319             testCharReturnValues(); // C
320             testDoubleReturnValues(); // D
321             testFloatReturnValues(); // F
322             testIntReturnValues(); // I
323             testLongReturnValues(); // J
324             testObjectReturnValues(); // L
325             testShortReturnValues(); // S
326             testVoidReturnValues(); // S
327             testBooleanReturnValues(); // Z
328         }
329     }
330 }
331