blob: 5368a22b21a647f97dcbea15adcdc8e2a79081aa [file] [log] [blame]
Orion Hodson8430e772018-03-15 15:13:43 +00001/*
2 * Copyright (C) 2018 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 annotations.ConstantMethodHandle;
18import annotations.ConstantMethodType;
19import java.lang.invoke.MethodHandle;
20import java.lang.invoke.MethodType;
Orion Hodsonecd58562018-09-24 11:27:33 +010021import java.lang.invoke.WrongMethodTypeException;
22
23import java.io.StreamTokenizer;
24import java.io.StringReader;
25import java.util.Stack;
Orion Hodson8430e772018-03-15 15:13:43 +000026
27class Main {
Orion Hodsondbaa5c72018-05-10 08:22:46 +010028 /**
29 * Number of iterations run to attempt to trigger JIT compilation. These tests run on ART and
30 * the RI so they iterate rather than using the ART only native method ensureJitCompiled().
31 */
32 private static final int ITERATIONS_FOR_JIT = 12000;
33
34 /** A static field updated by method handle getters and setters. */
Orion Hodson8430e772018-03-15 15:13:43 +000035 private static String name = "default";
36
37 private static void unreachable() {
38 throw new Error("Unreachable");
39 }
40
Orion Hodsondbaa5c72018-05-10 08:22:46 +010041 private static void assertEquals(Object expected, Object actual) {
42 if (!expected.equals(actual)) {
43 throw new AssertionError("Assertion failure: " + expected + " != " + actual);
44 }
45 }
46
Orion Hodson18259d72018-04-12 11:18:23 +010047 private static class LocalClass {
48 public LocalClass() {}
49
50 private int field;
51 }
52
Orion Hodsonecd58562018-09-24 11:27:33 +010053 private static class TestTokenizer extends StreamTokenizer {
54 public TestTokenizer(String message) {
55 super(new StringReader(message));
56 }
57 }
58
Orion Hodson8430e772018-03-15 15:13:43 +000059 @ConstantMethodType(
Orion Hodson18259d72018-04-12 11:18:23 +010060 returnType = String.class,
61 parameterTypes = {int.class, Integer.class, System.class})
Orion Hodson8430e772018-03-15 15:13:43 +000062 private static MethodType methodType0() {
63 unreachable();
64 return null;
65 }
66
Orion Hodson18259d72018-04-12 11:18:23 +010067 @ConstantMethodType(
68 returnType = void.class,
69 parameterTypes = {LocalClass.class})
70 private static MethodType methodType1() {
71 unreachable();
72 return null;
73 }
74
75 private static void repeatConstMethodType0(MethodType expected) {
76 System.out.print("repeatConstMethodType0(");
77 System.out.print(expected);
78 System.out.println(")");
Orion Hodsondbaa5c72018-05-10 08:22:46 +010079 for (int i = 0; i < ITERATIONS_FOR_JIT; ++i) {
Orion Hodson18259d72018-04-12 11:18:23 +010080 MethodType actual = methodType0();
Orion Hodsondbaa5c72018-05-10 08:22:46 +010081 assertEquals(expected, actual);
Orion Hodson18259d72018-04-12 11:18:23 +010082 }
83 }
84
85 private static void repeatConstMethodType1(MethodType expected) {
86 System.out.print("repeatConstMethodType1(");
87 System.out.print(expected);
88 System.out.println(")");
Orion Hodsondbaa5c72018-05-10 08:22:46 +010089 for (int i = 0; i < ITERATIONS_FOR_JIT; ++i) {
Orion Hodson18259d72018-04-12 11:18:23 +010090 MethodType actual = methodType1();
Orion Hodsondbaa5c72018-05-10 08:22:46 +010091 assertEquals(expected, actual);
Orion Hodson18259d72018-04-12 11:18:23 +010092 }
93 }
94
Orion Hodson8430e772018-03-15 15:13:43 +000095 static void helloWorld(String who) {
96 System.out.print("Hello World! And Hello ");
97 System.out.println(who);
98 }
99
100 @ConstantMethodHandle(
Orion Hodson18259d72018-04-12 11:18:23 +0100101 kind = ConstantMethodHandle.INVOKE_STATIC,
102 owner = "Main",
103 fieldOrMethodName = "helloWorld",
104 descriptor = "(Ljava/lang/String;)V")
Orion Hodson8430e772018-03-15 15:13:43 +0000105 private static MethodHandle printHelloHandle() {
106 unreachable();
107 return null;
108 }
109
110 @ConstantMethodHandle(
Orion Hodson18259d72018-04-12 11:18:23 +0100111 kind = ConstantMethodHandle.STATIC_PUT,
112 owner = "Main",
113 fieldOrMethodName = "name",
114 descriptor = "Ljava/lang/String;")
Orion Hodson8430e772018-03-15 15:13:43 +0000115 private static MethodHandle setNameHandle() {
116 unreachable();
117 return null;
118 }
119
120 @ConstantMethodHandle(
Orion Hodson18259d72018-04-12 11:18:23 +0100121 kind = ConstantMethodHandle.STATIC_GET,
Orion Hodsondbaa5c72018-05-10 08:22:46 +0100122 owner = "Main",
123 fieldOrMethodName = "name",
124 descriptor = "Ljava/lang/String;")
125 private static MethodHandle getNameHandle() {
126 unreachable();
127 return null;
128 }
129
130 @ConstantMethodHandle(
131 kind = ConstantMethodHandle.STATIC_GET,
Orion Hodson18259d72018-04-12 11:18:23 +0100132 owner = "java/lang/Math",
133 fieldOrMethodName = "E",
134 descriptor = "D")
Orion Hodson8430e772018-03-15 15:13:43 +0000135 private static MethodHandle getMathE() {
136 unreachable();
137 return null;
138 }
139
Orion Hodsonfd7b2c22018-03-15 15:38:38 +0000140 @ConstantMethodHandle(
Orion Hodson18259d72018-04-12 11:18:23 +0100141 kind = ConstantMethodHandle.STATIC_PUT,
142 owner = "java/lang/Math",
143 fieldOrMethodName = "E",
144 descriptor = "D")
Orion Hodsonfd7b2c22018-03-15 15:38:38 +0000145 private static MethodHandle putMathE() {
146 unreachable();
147 return null;
148 }
149
Orion Hodsonecd58562018-09-24 11:27:33 +0100150 @ConstantMethodHandle(
151 kind = ConstantMethodHandle.INSTANCE_GET,
152 owner = "java/io/StreamTokenizer",
153 fieldOrMethodName = "sval",
154 descriptor = "Ljava/lang/String;")
155 private static MethodHandle getSval() {
156 unreachable();
157 return null;
158 }
159
160 // This constant-method-handle references a private instance field. If
161 // referenced in bytecode it raises IAE at load time.
162 @ConstantMethodHandle(
163 kind = ConstantMethodHandle.INSTANCE_PUT,
164 owner = "java/io/StreamTokenizer",
165 fieldOrMethodName = "peekc",
166 descriptor = "I")
167 private static MethodHandle putPeekc() {
168 unreachable();
169 return null;
170 }
171
172 @ConstantMethodHandle(
173 kind = ConstantMethodHandle.INVOKE_VIRTUAL,
174 owner = "java/util/Stack",
175 fieldOrMethodName = "pop",
176 descriptor = "()Ljava/lang/Object;")
177 private static MethodHandle stackPop() {
178 unreachable();
179 return null;
180 }
181
182 @ConstantMethodHandle(
183 kind = ConstantMethodHandle.INVOKE_VIRTUAL,
184 owner = "java/util/Stack",
185 fieldOrMethodName = "trimToSize",
186 descriptor = "()V")
187 private static MethodHandle stackTrim() {
188 unreachable();
189 return null;
190 }
191
Orion Hodsondbaa5c72018-05-10 08:22:46 +0100192 private static void repeatConstMethodHandle() throws Throwable {
193 System.out.println("repeatConstMethodHandle()");
194 String[] values = {"A", "B", "C"};
195 for (int i = 0; i < ITERATIONS_FOR_JIT; ++i) {
196 String value = values[i % values.length];
197 setNameHandle().invoke(value);
198 String actual = (String) getNameHandle().invokeExact();
199 assertEquals(value, actual);
200 assertEquals(value, name);
201 }
202 }
203
Orion Hodson8430e772018-03-15 15:13:43 +0000204 public static void main(String[] args) throws Throwable {
205 System.out.println(methodType0());
Orion Hodson18259d72018-04-12 11:18:23 +0100206 repeatConstMethodType0(
207 MethodType.methodType(String.class, int.class, Integer.class, System.class));
208 repeatConstMethodType1(MethodType.methodType(void.class, LocalClass.class));
Orion Hodson8430e772018-03-15 15:13:43 +0000209 printHelloHandle().invokeExact("Zog");
210 printHelloHandle().invokeExact("Zorba");
211 setNameHandle().invokeExact("HoverFly");
212 System.out.print("name is ");
213 System.out.println(name);
214 System.out.println(getMathE().invoke());
Orion Hodsondbaa5c72018-05-10 08:22:46 +0100215 repeatConstMethodHandle();
Orion Hodsonfd7b2c22018-03-15 15:38:38 +0000216 try {
217 putMathE().invokeExact(Math.PI);
218 unreachable();
219 } catch (IllegalAccessError expected) {
220 System.out.println("Attempting to set Math.E raised IAE");
221 }
Orion Hodsonecd58562018-09-24 11:27:33 +0100222
223 StreamTokenizer st = new StreamTokenizer(new StringReader("Quack Moo Woof"));
224 while (st.nextToken() != StreamTokenizer.TT_EOF) {
225 System.out.println((String) getSval().invokeExact(st));
226 }
227
228 TestTokenizer tt = new TestTokenizer("Test message 123");
229 tt.nextToken();
230 System.out.println((String) getSval().invoke(tt));
231 try {
232 System.out.println((String) getSval().invokeExact(tt));
233 } catch (WrongMethodTypeException wmte) {
234 System.out.println("Getting field in TestTokenizer raised WMTE (woohoo!)");
235 }
236
237 Stack stack = new Stack();
238 stack.push(Integer.valueOf(3));
239 stack.push(Integer.valueOf(5));
240 stack.push(Integer.valueOf(7));
241 Object tos = stackPop().invokeExact(stack);
242 System.out.println("Stack: tos was " + tos);
243 System.out.println("Stack: capacity was " + stack.capacity());
244 stackTrim().invokeExact(stack);
245 System.out.println("Stack: capacity is " + stack.capacity());
Orion Hodson8430e772018-03-15 15:13:43 +0000246 }
247}