1 /*
2  * Copyright (C) 2016 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 java.lang.invoke.MethodHandle;
18 import java.lang.invoke.MethodHandles;
19 import java.lang.invoke.MethodHandles.Lookup;
20 import java.lang.invoke.MethodType;
21 import java.lang.invoke.WrongMethodTypeException;
22 import java.lang.reflect.Constructor;
23 import java.lang.reflect.Field;
24 import java.lang.reflect.Method;
25 import java.nio.charset.Charset;
26 import java.nio.charset.StandardCharsets;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 
31 public class Main {
assertTrue(boolean value)32   public static void assertTrue(boolean value) {
33     if (!value) {
34       throw new AssertionError("assertTrue value: " + value);
35     }
36   }
37 
assertFalse(boolean value)38   public static void assertFalse(boolean value) {
39     if (value) {
40       throw new AssertionError("assertTrue value: " + value);
41     }
42   }
43 
assertEquals(int i1, int i2)44   public static void assertEquals(int i1, int i2) {
45     if (i1 == i2) { return; }
46     throw new AssertionError("assertEquals i1: " + i1 + ", i2: " + i2);
47   }
48 
assertEquals(long i1, long i2)49   public static void assertEquals(long i1, long i2) {
50     if (i1 == i2) { return; }
51     throw new AssertionError("assertEquals l1: " + i1 + ", l2: " + i2);
52   }
53 
assertEquals(Object o, Object p)54   public static void assertEquals(Object o, Object p) {
55     if (o == p) { return; }
56     if (o != null && p != null && o.equals(p)) { return; }
57     throw new AssertionError("assertEquals: o1: " + o + ", o2: " + p);
58   }
59 
assertEquals(String s1, String s2)60   public static void assertEquals(String s1, String s2) {
61     if (s1 == s2) {
62       return;
63     }
64 
65     if (s1 != null && s2 != null && s1.equals(s2)) {
66       return;
67     }
68 
69     throw new AssertionError("assertEquals s1: " + s1 + ", s2: " + s2);
70   }
71 
fail()72   public static void fail() {
73     System.out.println("fail");
74     Thread.dumpStack();
75   }
76 
fail(String message)77   public static void fail(String message) {
78     System.out.println("fail: " + message);
79     Thread.dumpStack();
80   }
81 
Min2Print2(int a, int b)82   public static int Min2Print2(int a, int b) {
83     int[] values = new int[] { a, b };
84     System.out.println("Running Main.Min2Print2(" + Arrays.toString(values) + ")");
85     return a > b ? a : b;
86   }
87 
Min2Print3(int a, int b, int c)88   public static int Min2Print3(int a, int b, int c) {
89     int[] values = new int[] { a, b, c };
90     System.out.println("Running Main.Min2Print3(" + Arrays.toString(values) + ")");
91     return a > b ? a : b;
92   }
93 
Min2Print6(int a, int b, int c, int d, int e, int f)94   public static int Min2Print6(int a, int b, int c, int d, int e, int f) {
95     int[] values = new int[] { a, b, c, d, e, f };
96     System.out.println("Running Main.Min2Print6(" + Arrays.toString(values) + ")");
97     return a > b ? a : b;
98   }
99 
Min2Print26(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l, int m, int n, int o, int p, int q, int r, int s, int t, int u, int v, int w, int x, int y, int z)100   public static int Min2Print26(int a, int b, int c, int d,
101                                 int e, int f, int g, int h,
102                                 int i, int j, int k, int l,
103                                 int m, int n, int o, int p,
104                                 int q, int r, int s, int t,
105                                 int u, int v, int w, int x,
106                                 int y, int z) {
107     int[] values = new int[] { a, b, c, d, e, f, g, h, i, j, k, l, m,
108                                n, o, p, q, r, s, t, u, v, w, x, y, z };
109     System.out.println("Running Main.Min2Print26(" + Arrays.toString(values) + ")");
110     return a > b ? a : b;
111   }
112 
$opt$BasicTest()113   public static void $opt$BasicTest() throws Throwable {
114     MethodHandle mh;
115     mh = MethodHandles.lookup().findStatic(
116         Main.class, "Min2Print2", MethodType.methodType(int.class, int.class, int.class));
117     assertEquals((int) mh.invokeExact(33, -4), 33);
118     assertEquals((int) mh.invokeExact(-4, 33), 33);
119 
120     mh = MethodHandles.lookup().findStatic(
121         Main.class, "Min2Print3",
122         MethodType.methodType(int.class, int.class, int.class, int.class));
123     assertEquals((int) mh.invokeExact(33, -4, 17), 33);
124     assertEquals((int) mh.invokeExact(-4, 17, 33), 17);
125     assertEquals((int) mh.invokeExact(17, 33, -4), 33);
126 
127     mh = MethodHandles.lookup().findStatic(
128         Main.class, "Min2Print6",
129         MethodType.methodType(
130             int.class, int.class, int.class, int.class, int.class, int.class, int.class));
131     assertEquals((int) mh.invokeExact(33, -4, 77, 88, 99, 111), 33);
132     try {
133         // Too few arguments
134         assertEquals((int) mh.invokeExact(33, -4, 77, 88), 33);
135         fail("No WMTE for too few arguments");
136     } catch (WrongMethodTypeException e) {}
137     try {
138         // Too many arguments
139         assertEquals((int) mh.invokeExact(33, -4, 77, 88, 89, 90, 91), 33);
140         fail("No WMTE for too many arguments");
141     } catch (WrongMethodTypeException e) {}
142     assertEquals((int) mh.invokeExact(-4, 77, 88, 99, 111, 33), 77);
143     assertEquals((int) mh.invokeExact(77, 88, 99, 111, 33, -4), 88);
144     assertEquals((int) mh.invokeExact(88, 99, 111, 33, -4, 77), 99);
145     assertEquals((int) mh.invokeExact(99, 111, 33, -4, 77, 88), 111);
146     assertEquals((int) mh.invokeExact(111, 33, -4, 77, 88, 99), 111);
147 
148     // A preposterous number of arguments.
149     mh = MethodHandles.lookup().findStatic(
150         Main.class, "Min2Print26",
151         MethodType.methodType(
152             // Return-type
153             int.class,
154             // Arguments
155             int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
156             int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
157             int.class, int.class, int.class, int.class, int.class, int.class, int.class, int.class,
158             int.class, int.class));
159     assertEquals(1, (int) mh.invokeExact(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
160                                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25));
161     assertEquals(25, (int) mh.invokeExact(25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
162                                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24));
163     assertEquals(25, (int) mh.invokeExact(24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
164                                          13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23));
165 
166     try {
167         // Wrong argument type
168         mh.invokeExact("a");
169         fail("No WMTE for wrong arguments");
170     } catch (WrongMethodTypeException wmte) {}
171 
172     try {
173         // Invoke on null handle.
174         MethodHandle mh0 = null;
175         mh0.invokeExact("bad");
176         fail("No NPE for you");
177     } catch (NullPointerException npe) {}
178 
179     System.out.println("BasicTest done.");
180   }
181 
And(boolean lhs, boolean rhs)182   private static boolean And(boolean lhs, boolean rhs) {
183     return lhs & rhs;
184   }
185 
Xor(boolean lhs, boolean rhs)186   private static boolean Xor(boolean lhs, boolean rhs) {
187     return lhs ^ rhs;
188   }
189 
Multiply(String value, int n)190   private static String Multiply(String value, int n) {
191     String result = "";
192     for (int i = 0; i < n; ++i) {
193       result = value + result;
194     }
195     return result;
196   }
197 
Multiply(byte value, byte n)198   private static byte Multiply(byte value, byte n) {
199     return (byte)(value * n);
200   }
201 
Multiply(short value, short n)202   private static short Multiply(short value, short n) {
203     return (short)(value * n);
204   }
205 
Multiply(int value, int n)206   private static int Multiply(int value, int n) {
207     return value * n;
208   }
209 
Multiply(long value, long n)210   private static long Multiply(long value, long n) {
211     return value * n;
212   }
213 
Multiply(float value, float n)214   private static float Multiply(float value, float n) {
215     return value * n;
216   }
217 
Multiply(double value, double n)218   private static double Multiply(double value, double n) {
219     return value * n;
220   }
221 
Next(char c)222   private static char Next(char c) {
223     return (char)(c + 1);
224   }
225 
$opt$ReturnBooleanTest()226   public static void $opt$ReturnBooleanTest() throws Throwable {
227     MethodHandles.Lookup lookup = MethodHandles.lookup();
228     MethodHandle mh =
229             lookup.findStatic(Main.class, "And",
230                               MethodType.methodType(boolean.class, boolean.class, boolean.class));
231     assertEquals(true, (boolean) mh.invokeExact(true, true));
232     assertEquals(false, (boolean) mh.invokeExact(true, false));
233     assertEquals(false, (boolean) mh.invokeExact(false, true));
234     assertEquals(false, (boolean) mh.invokeExact(false, false));
235     assertEquals(true, (boolean) mh.invoke(true, true));
236     assertEquals(false, (boolean) mh.invoke(true, false));
237     assertEquals(false, (boolean) mh.invoke(false, true));
238     assertEquals(false, (boolean) mh.invoke(false, false));
239 
240     mh = lookup.findStatic(Main.class, "Xor",
241                            MethodType.methodType(boolean.class, boolean.class, boolean.class));
242     assertEquals(false, (boolean) mh.invokeExact(true, true));
243     assertEquals(true, (boolean) mh.invokeExact(true, false));
244     assertEquals(true, (boolean) mh.invokeExact(false, true));
245     assertEquals(false, (boolean) mh.invokeExact(false, false));
246     assertEquals(false, (boolean) mh.invoke(true, true));
247     assertEquals(true, (boolean) mh.invoke(true, false));
248     assertEquals(true, (boolean) mh.invoke(false, true));
249     assertEquals(false, (boolean) mh.invoke(false, false));
250 
251     System.out.println("$opt$ReturnBooleanTest done.");
252   }
253 
$opt$ReturnCharTest()254   public static void $opt$ReturnCharTest() throws Throwable {
255     MethodHandles.Lookup lookup = MethodHandles.lookup();
256     MethodHandle mh = lookup.findStatic(Main.class, "Next",
257                            MethodType.methodType(char.class, char.class));
258     assertEquals('B', (char) mh.invokeExact('A'));
259     assertEquals((char) -55, (char) mh.invokeExact((char) -56));
260     System.out.println("$opt$ReturnCharTest done.");
261   }
262 
$opt$ReturnByteTest()263   public static void $opt$ReturnByteTest() throws Throwable {
264     MethodHandles.Lookup lookup = MethodHandles.lookup();
265     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
266                                          MethodType.methodType(byte.class, byte.class, byte.class));
267     assertEquals((byte) 30, (byte) mh.invokeExact((byte) 10, (byte) 3));
268     assertEquals((byte) -90, (byte) mh.invoke((byte) -10, (byte) 9));
269     System.out.println("$opt$ReturnByteTest done.");
270   }
271 
$opt$ReturnShortTest()272   public static void $opt$ReturnShortTest() throws Throwable {
273     MethodHandles.Lookup lookup = MethodHandles.lookup();
274     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
275                            MethodType.methodType(short.class, short.class, short.class));
276     assertEquals((short) 3000, (short) mh.invokeExact((short) 1000, (short) 3));
277     assertEquals((short) -3000, (short) mh.invoke((short) -1000, (short) 3));
278     System.out.println("$opt$ReturnShortTest done.");
279   }
280 
$opt$ReturnIntTest()281   public static void $opt$ReturnIntTest() throws Throwable {
282     MethodHandles.Lookup lookup = MethodHandles.lookup();
283     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
284                            MethodType.methodType(int.class, int.class, int.class));
285     assertEquals(3_000_000, (int) mh.invokeExact(1_000_000, 3));
286     assertEquals(-3_000_000, (int) mh.invoke(-1_000, 3_000));
287     System.out.println("$opt$ReturnIntTest done.");
288   }
289 
$opt$ReturnLongTest()290   public static void $opt$ReturnLongTest() throws Throwable {
291     MethodHandles.Lookup lookup = MethodHandles.lookup();
292     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
293                            MethodType.methodType(long.class, long.class, long.class));
294     assertEquals(4_294_967_295_000L, (long) mh.invokeExact(1000L, 4_294_967_295L));
295     assertEquals(-4_294_967_295_000L, (long) mh.invoke(-1000L, 4_294_967_295L));
296     System.out.println("$opt$ReturnLongTest done.");
297   }
298 
$opt$ReturnFloatTest()299   public static void $opt$ReturnFloatTest() throws Throwable {
300     MethodHandles.Lookup lookup = MethodHandles.lookup();
301     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
302                            MethodType.methodType(float.class, float.class, float.class));
303     assertEquals(3.0F, (float) mh.invokeExact(1000.0F, 3e-3F));
304     assertEquals(-3.0F, (float) mh.invoke(-1000.0F, 3e-3F));
305     System.out.println("$opt$ReturnFloatTest done.");
306   }
307 
$opt$ReturnDoubleTest()308   public static void $opt$ReturnDoubleTest() throws Throwable {
309     MethodHandles.Lookup lookup = MethodHandles.lookup();
310     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
311                            MethodType.methodType(double.class, double.class, double.class));
312     assertEquals(3033000.0, (double) mh.invokeExact(1000.0, 3.033e3));
313     assertEquals(-3033000.0, (double) mh.invoke(-1000.0, 3.033e3));
314     System.out.println("$opt$ReturnDoubleTest done.");
315   }
316 
$opt$ReturnStringTest()317   public static void $opt$ReturnStringTest() throws Throwable {
318     MethodHandles.Lookup lookup = MethodHandles.lookup();
319     MethodHandle mh = lookup.findStatic(Main.class, "Multiply",
320                            MethodType.methodType(String.class, String.class, int.class));
321     assertEquals("100010001000", (String) mh.invokeExact("1000", 3));
322     assertEquals("100010001000", (String) mh.invoke("1000", 3));
323     System.out.println("$opt$ReturnStringTest done.");
324   }
325 
ReturnValuesTest()326   public static void ReturnValuesTest() throws Throwable {
327     $opt$ReturnBooleanTest();
328     $opt$ReturnCharTest();
329     $opt$ReturnByteTest();
330     $opt$ReturnShortTest();
331     $opt$ReturnIntTest();
332     $opt$ReturnLongTest();
333     $opt$ReturnFloatTest();
334     $opt$ReturnDoubleTest();
335     $opt$ReturnStringTest();
336     System.out.println("ReturnValuesTest done.");
337   }
338 
339   static class ValueHolder {
340     public boolean m_z;
341     public static boolean s_z;
342   }
343 
$opt$AccessorsTest()344   public static void $opt$AccessorsTest() throws Throwable {
345     ValueHolder valueHolder = new ValueHolder();
346     MethodHandles.Lookup lookup = MethodHandles.lookup();
347 
348     MethodHandle setMember = lookup.findSetter(ValueHolder.class, "m_z", boolean.class);
349     MethodHandle getMember = lookup.findGetter(ValueHolder.class, "m_z", boolean.class);
350     MethodHandle setStatic = lookup.findStaticSetter(ValueHolder.class, "s_z", boolean.class);
351     MethodHandle getStatic = lookup.findStaticGetter(ValueHolder.class, "s_z", boolean.class);
352 
353     boolean [] values = { false, true, false, true, false };
354     for (boolean value : values) {
355       assertEquals((boolean) getStatic.invoke(), ValueHolder.s_z);
356       setStatic.invoke(value);
357       ValueHolder.s_z = value;
358       assertEquals(ValueHolder.s_z, value);
359       assertEquals((boolean) getStatic.invoke(), value);
360 
361       assertEquals((boolean) getMember.invoke(valueHolder), valueHolder.m_z);
362       setMember.invoke(valueHolder, value);
363       valueHolder.m_z = value;
364       assertEquals(valueHolder.m_z, value);
365       assertEquals((boolean) getMember.invoke(valueHolder), value);
366     }
367   }
368 
main(String[] args)369   public static void main(String[] args) throws Throwable {
370     $opt$BasicTest();
371     ReturnValuesTest();
372     $opt$AccessorsTest();
373   }
374 }
375