Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 { |
| 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() { |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 73 | System.out.println("fail"); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 74 | Thread.dumpStack(); |
| 75 | } |
| 76 | |
| 77 | public static void fail(String message) { |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 78 | System.out.println("fail: " + message); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 79 | Thread.dumpStack(); |
| 80 | } |
| 81 | |
| 82 | public static int Min2Print2(int a, int b) { |
| 83 | int[] values = new int[] { a, b }; |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 84 | System.out.println("Running Main.Min2Print2(" + Arrays.toString(values) + ")"); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 }; |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 90 | System.out.println("Running Main.Min2Print3(" + Arrays.toString(values) + ")"); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 }; |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 96 | System.out.println("Running Main.Min2Print6(" + Arrays.toString(values) + ")"); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 }; |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 109 | System.out.println("Running Main.Min2Print26(" + Arrays.toString(values) + ")"); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 | |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 179 | System.out.println("BasicTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 | |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 251 | System.out.println("$opt$ReturnBooleanTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 260 | System.out.println("$opt$ReturnCharTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 269 | System.out.println("$opt$ReturnByteTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 278 | System.out.println("$opt$ReturnShortTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 287 | System.out.println("$opt$ReturnIntTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 296 | System.out.println("$opt$ReturnLongTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 305 | System.out.println("$opt$ReturnFloatTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 314 | System.out.println("$opt$ReturnDoubleTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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)); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 323 | System.out.println("$opt$ReturnStringTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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(); |
Kevin Brodsky | f6c66c3 | 2015-12-17 14:13:00 +0000 | [diff] [blame] | 336 | System.out.println("ReturnValuesTest done."); |
Orion Hodson | ac14139 | 2017-01-13 11:53:47 +0000 | [diff] [blame] | 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 | } |