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