blob: e9d313b874421db520d516aeb4196785101d199e [file] [log] [blame]
Narayan Kamath000e1882016-10-24 17:14:25 +01001/*
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.invoke.Transformers.Transformer;
23
24import dalvik.system.EmulatedStackFrame;
25
26public class Main {
27
28 public static void testDelegate_allTypes(boolean z, char a, short b, int c, long d,
29 float e, double f, String g, Object h) {
30 System.out.println("boolean: " + z);
31 System.out.println("char: " + a);
32 System.out.println("short: " + b);
33 System.out.println("int: " + c);
34 System.out.println("long: " + d);
35 System.out.println("float: " + e);
36 System.out.println("double: " + f);
37 System.out.println("String: " + g);
38 System.out.println("Object: " + h);
39 }
40
41 public static boolean testDelegate_returnBoolean() {
42 return true;
43 }
44
45 public static char testDelegate_returnChar() {
46 return 'a';
47 }
48
49 public static int testDelegate_returnInt() {
50 return 42;
51 }
52
53 public static long testDelegate_returnLong() {
54 return 43;
55 }
56
57 public static float testDelegate_returnFloat() {
58 return 43.0f;
59 }
60
61 public static double testDelegate_returnDouble() {
62 return 43.0;
63 }
64
65 public static String testDelegate_returnString() {
66 return "plank";
67 }
68
69 public static class DelegatingTransformer extends Transformer {
70 private final MethodHandle delegate;
71
72 public DelegatingTransformer(MethodHandle delegate) {
73 super(delegate.type());
74 this.delegate = delegate;
75 }
76
77 @Override
78 public void transform(EmulatedStackFrame stackFrame) throws Throwable {
79 delegate.invoke(stackFrame);
80 }
81 }
82
83 public static void main(String[] args) throws Throwable {
84 testThrowException();
85
86 testDelegation();
87 }
88
89 public static void testDelegation() throws Throwable {
90 System.out.println("---");
91 System.out.println("-- testDelegation");
92 System.out.println("---");
93
94 MethodHandle specialFunctionHandle = MethodHandles.lookup().findStatic(
95 Main.class, "testDelegate_allTypes", MethodType.methodType(void.class,
96 new Class<?>[] { boolean.class, char.class, short.class, int.class, long.class,
97 float.class, double.class, String.class, Object.class }));
98
99 DelegatingTransformer delegate = new DelegatingTransformer(specialFunctionHandle);
100
101 // Test an exact invoke.
Narayan Kamathb24b0262016-10-31 12:58:45 +0000102 //
103 // Note that the shorter form below doesn't work and must be
104 // investigated on the jack side : b/32536744
105 //
106 // delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l,
107 // 0.56f, 100.0d, "hello", (Object) "goodbye");
108
109 Object obj = "goodbye";
Narayan Kamath000e1882016-10-24 17:14:25 +0100110 delegate.invokeExact(false, 'h', (short) 56, 72, Integer.MAX_VALUE + 42l,
Narayan Kamathb24b0262016-10-31 12:58:45 +0000111 0.56f, 100.0d, "hello", obj);
Narayan Kamath000e1882016-10-24 17:14:25 +0100112
113 // Test a non exact invoke with one int -> long conversion and a float -> double
114 // conversion.
115 delegate.invoke(false, 'h', (short) 56, 72, 73,
116 0.56f, 100.0f, "hello", "goodbye");
117
118 // Should throw a WrongMethodTypeException if the types don't align.
119 try {
120 delegate.invoke(false);
121 throw new AssertionError("Call to invoke unexpectedly succeeded");
122 } catch (WrongMethodTypeException expected) {
123 }
124
125 // Test return values.
126
127 // boolean.
128 MethodHandle returner = MethodHandles.lookup().findStatic(
129 Main.class, "testDelegate_returnBoolean", MethodType.methodType(boolean.class));
130 delegate = new DelegatingTransformer(returner);
131
132 System.out.println((boolean) delegate.invoke());
133 System.out.println((boolean) delegate.invokeExact());
134
135 // char.
136 returner = MethodHandles.lookup().findStatic(
137 Main.class, "testDelegate_returnChar", MethodType.methodType(char.class));
138 delegate = new DelegatingTransformer(returner);
139
140 System.out.println((char) delegate.invoke());
141 System.out.println((char) delegate.invokeExact());
142
143 // int.
144 returner = MethodHandles.lookup().findStatic(
145 Main.class, "testDelegate_returnInt", MethodType.methodType(int.class));
146 delegate = new DelegatingTransformer(returner);
147
148 System.out.println((int) delegate.invoke());
149 System.out.println((int) delegate.invokeExact());
150
151 // long.
152 returner = MethodHandles.lookup().findStatic(
153 Main.class, "testDelegate_returnLong", MethodType.methodType(long.class));
154 delegate = new DelegatingTransformer(returner);
155
156 System.out.println((long) delegate.invoke());
157 System.out.println((long) delegate.invokeExact());
158
159 // float.
160 returner = MethodHandles.lookup().findStatic(
161 Main.class, "testDelegate_returnFloat", MethodType.methodType(float.class));
162 delegate = new DelegatingTransformer(returner);
163
164 System.out.println((float) delegate.invoke());
165 System.out.println((float) delegate.invokeExact());
166
167 // double.
168 returner = MethodHandles.lookup().findStatic(
169 Main.class, "testDelegate_returnDouble", MethodType.methodType(double.class));
170 delegate = new DelegatingTransformer(returner);
171
172 System.out.println((double) delegate.invoke());
173 System.out.println((double) delegate.invokeExact());
174
175 // references.
176 returner = MethodHandles.lookup().findStatic(
177 Main.class, "testDelegate_returnString", MethodType.methodType(String.class));
178 delegate = new DelegatingTransformer(returner);
179
180 System.out.println((String) delegate.invoke());
181 System.out.println((String) delegate.invokeExact());
182 }
183
184 public static void testThrowException() throws Throwable {
185 MethodHandle handle = MethodHandles.throwException(String.class,
186 IllegalArgumentException.class);
187
188 if (handle.type().returnType() != String.class) {
189 System.out.println("Unexpected return type for handle: " + handle +
190 " [ " + handle.type() + "]");
191 }
192
193 try {
194 handle.invoke();
195 System.out.println("Expected an exception of type: java.lang.IllegalArgumentException");
196 } catch (IllegalArgumentException expected) {
197 }
198 }
199}
200
201