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 17import java.lang.invoke.MethodHandle; 18import java.lang.invoke.MethodHandles; 19import java.lang.invoke.MethodHandles.Lookup; 20import java.lang.invoke.MethodType; 21import java.lang.invoke.WrongMethodTypeException; 22import java.lang.reflect.Constructor; 23import java.lang.reflect.Field; 24import java.lang.reflect.Method; 25import java.nio.charset.Charset; 26import java.nio.charset.StandardCharsets; 27import java.util.ArrayList; 28import java.util.Arrays; 29import java.util.List; 30 31public class Main { 32 public static void assertTrue(boolean value) { 33 if (!value) { 34 throw new AssertionError("assertTrue value: " + value); 35 } 36 } 37 38 public static void assertFalse(boolean value) { 39 if (value) { 40 throw new AssertionError("assertTrue value: " + value); 41 } 42 } 43 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 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 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 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 72 public static void fail() { 73 System.out.println("fail"); 74 Thread.dumpStack(); 75 } 76 77 public static void fail(String message) { 78 System.out.println("fail: " + message); 79 Thread.dumpStack(); 80 } 81 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 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 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 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 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 182 private static boolean And(boolean lhs, boolean rhs) { 183 return lhs & rhs; 184 } 185 186 private static boolean Xor(boolean lhs, boolean rhs) { 187 return lhs ^ rhs; 188 } 189 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 198 private static byte Multiply(byte value, byte n) { 199 return (byte)(value * n); 200 } 201 202 private static short Multiply(short value, short n) { 203 return (short)(value * n); 204 } 205 206 private static int Multiply(int value, int n) { 207 return value * n; 208 } 209 210 private static long Multiply(long value, long n) { 211 return value * n; 212 } 213 214 private static float Multiply(float value, float n) { 215 return value * n; 216 } 217 218 private static double Multiply(double value, double n) { 219 return value * n; 220 } 221 222 private static char Next(char c) { 223 return (char)(c + 1); 224 } 225 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 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 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 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 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 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 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 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 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 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 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 369 public static void main(String[] args) throws Throwable { 370 $opt$BasicTest(); 371 ReturnValuesTest(); 372 $opt$AccessorsTest(); 373 } 374} 375